5
5
import logging
6
6
import tempfile
7
7
8
- from ocs_ci .framework import config
9
- from ocs_ci .ocs . resources . ocs import OCS
8
+ from ocs_ci .deployment . qe_app_registry import QeAppRegistry
9
+ from ocs_ci .ocs import ocp
10
10
from ocs_ci .ocs .ocp import OCP
11
+ from ocs_ci .ocs .resources .ocs import OCS
12
+ from ocs_ci .framework import config
11
13
from ocs_ci .utility import templating
12
14
from ocs_ci .ocs import constants
13
15
from ocs_ci .utility .utils import (
14
16
run_cmd ,
15
17
exec_cmd ,
16
18
)
17
19
from ocs_ci .ocs .resources .catalog_source import CatalogSource
18
- from ocs_ci .ocs import ocp
20
+ from ocs_ci .ocs . resources . deployment import Deployment
19
21
from ocs_ci .utility .utils import get_running_ocp_version
20
22
from ocs_ci .ocs .exceptions import CommandFailed , UnavailableResourceException
21
23
@@ -28,22 +30,30 @@ class MCEInstaller(object):
28
30
"""
29
31
30
32
def __init__ (self ):
31
- self .namespace = constants .MCE_NAMESPACE
33
+ self .mce_namespace = constants .MCE_NAMESPACE
32
34
self .ns_obj = ocp .OCP (kind = constants .NAMESPACES )
33
35
self .hypershift_override_image_cm = "hypershift-override-images-new"
34
36
self .multicluster_engine = ocp .OCP (
35
37
kind = "MultiClusterEngine" ,
36
38
resource_name = constants .MULTICLUSTER_ENGINE ,
39
+ namespace = self .mce_namespace ,
37
40
)
38
41
self .catsrc = ocp .OCP (
39
42
kind = constants .CATSRC , namespace = constants .MARKETPLACE_NAMESPACE
40
43
)
41
44
self .subs = ocp .OCP (kind = constants .PROVIDER_SUBSCRIPTION )
42
45
43
- def create_mce_catalog_source (self ):
46
+ def _create_mce_catalog_source (self ):
44
47
"""
45
48
Creates a catalogsource for mce operator.
46
49
50
+ We use qe-app-registry catalog source to install latest version
51
+ In future if we want to install particular image we can use subscription.spec.startingCSV:<image> like
52
+ quay.io:443/acm-d/mce-custom-registry:2.13.0-DOWNSTREAM-2025-03-02-02-49-35
53
+ In this case we don't need another channel in subscription but may reuse stable-2.8 channel
54
+
55
+ ! Important. This catalog source does not work without ICSP, this catsrc is not used in a moment.
56
+ ! This method was left for reference only.
47
57
"""
48
58
if not self .catsrc .is_exist (
49
59
resource_name = constants .MCE_CATSRC_NAME ,
@@ -79,15 +89,13 @@ def create_mce_namespace(self):
79
89
CommandFailed: If the 'oc create' command fails.
80
90
"""
81
91
if not self .ns_obj .is_exist (
82
- resource_name = self .namespace ,
92
+ resource_name = self .mce_namespace ,
83
93
):
84
- logger .info (f"Creating namespace { self .namespace } for mce resources" )
94
+ logger .info (f"Creating namespace { self .mce_namespace } for mce resources" )
85
95
namespace_yaml_file = templating .load_yaml (constants .MCE_NAMESPACE_YAML )
86
96
namespace_yaml = OCS (** namespace_yaml_file )
87
97
namespace_yaml .create ()
88
- logger .info (f"MCE namespace { self .namespace } was created successfully" )
89
- else :
90
- logger .info (f"{ self .namespace } already exists" )
98
+ logger .info (f"MCE namespace { self .mce_namespace } was created successfully" )
91
99
92
100
def create_multiclusterengine_operatorgroup (self ):
93
101
"""
@@ -98,14 +106,12 @@ def create_multiclusterengine_operatorgroup(self):
98
106
if not self .multicluster_engine .is_exist (
99
107
resource_name = constants .MULTICLUSTER_ENGINE
100
108
):
101
-
102
109
operatorgroup_yaml_file = templating .load_yaml (
103
110
constants .MCE_OPERATOR_GROUP_YAML
104
111
)
105
112
operatorgroup_yaml = OCS (** operatorgroup_yaml_file )
106
113
operatorgroup_yaml .create ()
107
114
logger .info ("mce OperatorGroup created successfully" )
108
- self .multicluster_engine .wait_for_phase ("Available" )
109
115
110
116
def create_multiclusterengine_resource (self ):
111
117
"""
@@ -128,26 +134,23 @@ def create_mce_subscription(self):
128
134
constants .MCE_SUBSCRIPTION_YAML
129
135
)
130
136
131
- if config .DEPLOYMENT .get ("mce_latest_stable" ):
132
- mce_subscription_yaml_data ["spec" ][
133
- "source"
134
- ] = constants .OPERATOR_CATALOG_SOURCE_NAME
135
- mce_channel = "stable"
136
- else :
137
- mce_channel = config .DEPLOYMENT .get ("mce_channel" )
137
+ # ! Important, channel-2.8 becomes available after OCP 4.18 release
138
+ if config .DEPLOYMENT .get ("mce_channel" ):
139
+ mce_subscription_yaml_data ["spec" ]["channel" ] = config .DEPLOYMENT .get (
140
+ "mce_channel"
141
+ )
138
142
139
- mce_subscription_yaml_data ["spec" ]["channel" ] = mce_channel
140
143
mce_subscription_manifest = tempfile .NamedTemporaryFile (
141
144
mode = "w+" , prefix = "mce_subscription_manifest" , delete = False
142
145
)
143
146
templating .dump_data_to_temp_yaml (
144
147
mce_subscription_yaml_data , mce_subscription_manifest .name
145
148
)
146
- logger .info ("Creating subscription for mce operator" )
147
- run_cmd (f"oc create -f { mce_subscription_manifest .name } " )
149
+ logger .info ("Creating subscription for the mce operator" )
150
+ exec_cmd (f"oc create -f { mce_subscription_manifest .name } " )
148
151
OCP (
149
152
kind = constants .SUBSCRIPTION_COREOS ,
150
- namespace = self .namespace ,
153
+ namespace = self .mce_namespace ,
151
154
resource_name = constants .MCE_OPERATOR ,
152
155
).check_resource_existence (
153
156
should_exist = True , resource_name = constants .MCE_OPERATOR
@@ -160,7 +163,9 @@ def check_hypershift_namespace(self):
160
163
Check hypershift namespace created
161
164
162
165
"""
163
- logger .info (f"hypershift namespace { self .namespace } was created successfully" )
166
+ logger .info (
167
+ f"hypershift namespace { self .mce_namespace } was created successfully"
168
+ )
164
169
is_hypershift_ns_available = self .ns_obj .is_exist (
165
170
resource_name = constants .HYPERSHIFT_NAMESPACE ,
166
171
)
@@ -176,15 +181,20 @@ def check_supported_versions(self):
176
181
namespace = constants .HYPERSHIFT_NAMESPACE ,
177
182
)
178
183
179
- if not configmaps_obj .is_exist (
180
- resource_name = constants .SUPPORTED_VERSIONS_CONFIGMAP
184
+ if not configmaps_obj .check_resource_existence (
185
+ should_exist = True ,
186
+ timeout = 60 ,
187
+ resource_name = constants .SUPPORTED_VERSIONS_CONFIGMAP ,
181
188
):
182
189
raise UnavailableResourceException (
183
- f"Configmap { constants .SUPPORTED_VERSIONS_CONFIGMAP } does not exist in hypershift namespace"
190
+ f"Configmap { constants .SUPPORTED_VERSIONS_CONFIGMAP } does not exist "
191
+ f"in { constants .HYPERSHIFT_NAMESPACE } namespace"
184
192
)
185
193
186
- cmd = "oc get cm -n hypershift supported-versions -o jsonpath='{.data.supported-versions}'"
194
+ cmd = f"oc get cm -n { constants .HYPERSHIFT_NAMESPACE } supported-versions "
195
+ cmd += "-o jsonpath='{.data.supported-versions}'"
187
196
cmd_res = exec_cmd (cmd , shell = True )
197
+ supported_versions = ""
188
198
if cmd_res .returncode == 0 :
189
199
supported_versions = cmd_res .stdout .decode ("utf-8" )
190
200
logger .info (f"Supported versions: { supported_versions } " )
@@ -199,7 +209,7 @@ def create_image_override(self):
199
209
# Create image override configmap using the image override json
200
210
cmd = (
201
211
f"oc create cm { self .hypershift_override_image_cm } --from-file={ constants .IMAGE_OVERRIDE_JSON } "
202
- "-n {self.namespace }"
212
+ f "-n { self .mce_namespace } "
203
213
)
204
214
cmd_res = exec_cmd (cmd , shell = True )
205
215
if cmd_res .returncode :
@@ -211,43 +221,36 @@ def create_image_override(self):
211
221
)
212
222
self .multicluster_engine .wait_until_running ()
213
223
214
- def deploy_mce (self , check_mce_deployed = False , check_mce_ready = False ):
224
+ def deploy_mce (self ):
215
225
"""
216
226
Installs mce enabling software emulation.
217
227
218
- Args:
219
- check_mce_deployed (bool): If True, check if mce is already deployed. If so, skip the deployment.
220
- check_mce_ready (bool): If True, check if mce is ready. If so, skip the deployment.
221
228
"""
222
- if check_mce_deployed :
223
- if self .mce_installed ():
224
- logger .info ("mce operator is already deployed, skipping the deployment" )
225
- return
226
-
227
- if check_mce_ready :
228
- if self .post_install_verification (raise_exception = False ):
229
- logger .info ("mce operator ready, skipping the deployment" )
230
- return
231
-
232
- logger .info ("Installing mce" )
233
- # we create catsrc with nightly builds only if config.DEPLOYMENT does not have mce_latest_stable
234
- if not config .DEPLOYMENT .get ("mce_latest_stable" ):
235
- # Create mce catalog source
236
- self .create_mce_catalog_source ()
237
- # Create multicluster-engine namespace
238
- self .create_mce_namespace ()
239
- # create mce subscription
240
- self .create_mce_subscription ()
241
- # Deploy the multiclusterengine operatorgroup
242
- self .create_multiclusterengine_operatorgroup ()
243
- # Create mce resource
244
- self .create_multiclusterengine_resource ()
245
- # Check hypershift ns created
246
- if not self .check_hypershift_namespace ():
247
- cmd = f"oc create namespace { constants .HYPERSHIFT_NAMESPACE } "
248
- cmd_res = exec_cmd (cmd , shell = True )
249
- if cmd_res .returncode :
250
- raise CommandFailed ("Failed to create hypershift namespace" )
229
+
230
+ if not self .mce_installed ():
231
+ logger .info ("Installing mce" )
232
+ # we create catsrc with nightly builds only if config.DEPLOYMENT does not have mce_latest_stable
233
+ qe_app_registry = QeAppRegistry ()
234
+ qe_app_registry .icsp ()
235
+ qe_app_registry .catalog_source ()
236
+ self .create_mce_namespace ()
237
+ self .create_mce_subscription ()
238
+ self .create_multiclusterengine_operatorgroup ()
239
+
240
+ # check whether mce instance is created, if it is installed but mce don't pass validation we can not heal it in
241
+ # script here, hence no sense for full validation of mce
242
+ if not self .mce_exists ():
243
+
244
+ # Create mce resource
245
+ self .create_multiclusterengine_resource ()
246
+ # Check hypershift ns created
247
+ if not self .check_hypershift_namespace ():
248
+ cmd = f"oc create namespace { constants .HYPERSHIFT_NAMESPACE } "
249
+ cmd_res = exec_cmd (cmd , shell = True )
250
+ if cmd_res .returncode :
251
+ raise CommandFailed ("Failed to create hypershift namespace" )
252
+
253
+ self .wait_mce_resources ()
251
254
# Check supported versions in supported-versions configmap
252
255
self .check_supported_versions ()
253
256
@@ -258,36 +261,48 @@ def mce_installed(self):
258
261
Returns:
259
262
bool: True if MCE is installed, False otherwise
260
263
"""
261
- ocp = OCP (kind = constants .ROOK_OPERATOR , namespace = self .namespace )
262
- return ocp .check_resource_existence (
263
- timeout = 12 , should_exist = True , resource_name = constants .MCE_OPERATOR
264
+ ocp_obj = OCP (kind = constants .ROOK_OPERATOR )
265
+ # unlike other k8s resources, operators are OLM manager resources that identified by merged name.namespace
266
+ return ocp_obj .check_resource_existence (
267
+ timeout = 12 ,
268
+ should_exist = True ,
269
+ resource_name = constants .MCE_OPERATOR_OPERATOR_NAME_WITH_NS ,
264
270
)
265
271
266
- def post_install_verification (self , raise_exception = False ):
272
+ def mce_exists (self ):
267
273
"""
268
- Performs MCE post-installation verification, with raise_exception = False may be used safely to run on
269
- clusters with MCE installed or not installed.
270
-
271
- Args:
272
- raise_exception: If True, allow function to fail the job and raise an exception. If false, return False
273
- instead of raising an exception.
274
+ Check if MCE exists
274
275
275
276
Returns:
276
- bool: True if the verification conditions are met, False otherwise
277
- Raises:
278
- TimeoutExpiredError: If the verification conditions are not met within the timeout
279
- and raise_exception is True.
280
- ResourceNotFoundError if the namespace does not exist and raise_exception is True.
281
- ResourceWrongStatusException if the nodes are not ready, verification fails and raise_exception
282
- is True.
277
+ bool: True if MCE exists, False otherwise
283
278
"""
284
- # TODO: implement
285
- pass
279
+ return self .multicluster_engine .is_exist (
280
+ resource_name = constants .MULTICLUSTER_ENGINE
281
+ )
286
282
287
- def validate_mce_deployment (self ):
283
+ def wait_mce_resources (self ):
288
284
"""
289
- Validate mce operator installation
285
+ Wait for mce Available state and deployments Ready state
286
+
287
+ Raises:
288
+ TimeoutExpiredError: If the deployment is not in the 'Available' state within the timeout
290
289
"""
291
- if self .mce_hyperconverged_installed ():
292
- logger .info ("mce operator is already deployed" )
293
- return
290
+ if not self .mce_exists ():
291
+ raise UnavailableResourceException ("MCE resource is not created" )
292
+ deployments = [
293
+ "multicluster-engine-operator" ,
294
+ "ocm-controller" ,
295
+ "cluster-manager" ,
296
+ "ocm-webhook" ,
297
+ ]
298
+
299
+ for resource_name in deployments :
300
+ depl_ocp_obj = OCP (
301
+ kind = constants .DEPLOYMENT ,
302
+ namespace = self .mce_namespace ,
303
+ resource_name = resource_name ,
304
+ )
305
+ deployment_obj = Deployment (
306
+ ** depl_ocp_obj .get (retry = 60 , wait = 10 , dont_raise = True )
307
+ )
308
+ deployment_obj .wait_for_available_replicas (timeout = 600 )
0 commit comments