From 9ba5eb1857420235ef8aa06ea530404d6690ca22 Mon Sep 17 00:00:00 2001 From: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> Date: Wed, 11 Dec 2024 20:37:46 +0530 Subject: [PATCH 01/11] Added mce.py file for mce installation related methods and created libtest to check mce installation and hcp cluster creation without acm operator Signed-off-by: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> --- ocs_ci/deployment/hosted_cluster.py | 12 +- ocs_ci/deployment/mce.py | 243 ++++++++++++++++++ ocs_ci/ocs/constants.py | 12 + .../mce-deployment/image-override.json | 8 + .../templates/mce-deployment/mce_catsrc.yaml | 8 + .../mce-deployment/mce_namespace.yaml | 6 + .../mce-deployment/mce_operator.yaml | 10 + .../mce-deployment/mce_subscription.yaml | 11 + .../test_provider_create_hosted_cluster.py | 26 ++ 9 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 ocs_ci/deployment/mce.py create mode 100644 ocs_ci/templates/mce-deployment/image-override.json create mode 100644 ocs_ci/templates/mce-deployment/mce_catsrc.yaml create mode 100644 ocs_ci/templates/mce-deployment/mce_namespace.yaml create mode 100644 ocs_ci/templates/mce-deployment/mce_operator.yaml create mode 100644 ocs_ci/templates/mce-deployment/mce_subscription.yaml diff --git a/ocs_ci/deployment/hosted_cluster.py b/ocs_ci/deployment/hosted_cluster.py index b855dabaaef..ea2f44429af 100644 --- a/ocs_ci/deployment/hosted_cluster.py +++ b/ocs_ci/deployment/hosted_cluster.py @@ -5,6 +5,7 @@ import time from concurrent.futures import ThreadPoolExecutor from ocs_ci.deployment.cnv import CNVInstaller +from ocs_ci.deployment.mce import MCEInstaller from ocs_ci.deployment.deployment import Deployment from ocs_ci.deployment.helpers.hypershift_base import ( HyperShiftBase, @@ -365,6 +366,7 @@ def __init__(self, name): HyperShiftBase.__init__(self) MetalLBInstaller.__init__(self) CNVInstaller.__init__(self) + MCEInstaller.__init__(self) self.name = name if config.ENV_DATA.get("clusters", {}).get(self.name): cluster_path = ( @@ -450,7 +452,12 @@ def deploy_ocp( ) def deploy_dependencies( - self, deploy_acm_hub, deploy_cnv, deploy_metallb, download_hcp_binary + self, + deploy_acm_hub, + deploy_cnv, + deploy_metallb, + download_hcp_binary, + deploy_mce, ): """ Deploy dependencies for hosted OCP cluster @@ -459,6 +466,7 @@ def deploy_dependencies( deploy_cnv: bool Deploy CNV deploy_metallb: bool Deploy MetalLB download_hcp_binary: bool Download HCP binary + deploy_mce: bool Deploy mce """ initial_default_sc = helpers.get_default_storage_class() @@ -480,6 +488,8 @@ def deploy_dependencies( self.deploy_lb() if download_hcp_binary: self.update_hcp_binary() + if deploy_mce: + self.deploy_mce() provider_ocp_version = str( get_semantic_version(get_ocp_version(), only_major_minor=True) diff --git a/ocs_ci/deployment/mce.py b/ocs_ci/deployment/mce.py new file mode 100644 index 00000000000..b3d001c9a9f --- /dev/null +++ b/ocs_ci/deployment/mce.py @@ -0,0 +1,243 @@ +""" +This module contains functionality required for mce installation. +""" + +import logging +import tempfile + +from ocs_ci.framework import config +from ocs_ci.ocs.resources.ocs import OCS +from ocs_ci.ocs.ocp import OCP +from ocs_ci.utility import templating +from ocs_ci.ocs import constants +from ocs_ci.utility.utils import ( + run_cmd, + exec_cmd, +) +from ocs_ci.ocs import exceptions +from ocs_ci.ocs.resources.catalog_source import CatalogSource +from ocs_ci.ocs import ocp +from ocs_ci.utility.utils import get_running_ocp_version + +logger = logging.getLogger(__name__) + + +class MCEInstaller(object): + """ + mce Installer class for mce deployment + """ + + def __init__(self): + self.namespace = constants.MCE_NAMESPACE + self.ns_obj = ocp.OCP(kind=constants.NAMESPACES) + self.hypershift_override_image_cm = "hypershift-override-images-new" + self.multicluster_engine = ocp.OCP( + kind="MultiClusterEngine", + resource_name=constants.MULTICLUSTER_ENGINE, + ) + + def create_mce_catalog_source(self): + """ + Creates a catalogsource for mce operator. + + """ + logger.info("Adding CatalogSource for MCE") + mce_catalog_source_data = templating.load_yaml(constants.MCE_CATSRC_YAML) + mce_catalog_source_name = mce_catalog_source_data.get("metadata").get("name") + if config.ENV_DATA.get("mce_image"): + mce_image_tag = config.ENV_DATA.get("mce_image") + mce_catalog_source_data["spec"]["image"] = mce_image_tag + mce_catalog_source_manifest = tempfile.NamedTemporaryFile( + mode="w+", prefix="mce_catalog_source_manifest", delete=False + ) + templating.dump_data_to_temp_yaml( + mce_catalog_source_data, mce_catalog_source_manifest.name + ) + run_cmd(f"oc apply -f {mce_catalog_source_manifest.name}", timeout=2400) + mce_catalog_source = CatalogSource( + resource_name=mce_catalog_source_name, + namespace=constants.MARKETPLACE_NAMESPACE, + ) + + # Wait for catalog source is ready + mce_catalog_source.wait_for_state("READY") + + def create_mce_namespace(self): + """ + Creates the namespace for mce resources + + Raises: + CommandFailed: If the 'oc create' command fails. + """ + try: + logger.info(f"Creating namespace {self.namespace} for mce resources") + namespace_yaml_file = templating.load_yaml(constants.MCE_NAMESPACE_YAML) + namespace_yaml = OCS(**namespace_yaml_file) + namespace_yaml.create() + logger.info(f"MCE namespace {self.namespace} was created successfully") + except exceptions.CommandFailed as ef: + if ( + f'project.project.openshift.io "{self.namespace}" already exists' + in str(ef) + ): + logger.info(f"Namespace {self.namespace} already present") + raise ef + + def create_multiclusterengine_operator(self): + """ + Creates multiclusterengine operator + + """ + operatorgroup_yaml_file = templating.load_yaml(constants.MCE_OPERATOR_YAM) + operatorgroup_yaml = OCS(**operatorgroup_yaml_file) + try: + operatorgroup_yaml.create() + logger.info("mce OperatorGroup created successfully") + except exceptions.CommandFailed as ef: + if "multiclusterengine exists" in str(ef): + logger.info("multiclusterengine already exists") + + cmd = "oc get mce multiclusterengine -o jsonpath='{.status}'" + cmd_res = exec_cmd(cmd, shell=True) + if cmd_res.returncode != 0: + logger.error(f"Failed to get multicluster engine status\n{cmd_res.stderr}") + else: + logger.info( + f"Multicluster engine version: {cmd_res.stdout.decode('utf-8')}" + ) + assert ( + cmd_res.stdout.decode("utf-8") == "Available" + ), "multiclusterengine is not is 'Available' status" + + def create_mce_subscription(self): + """ + Creates subscription for mce operator + + """ + mce_subscription_yaml_data = templating.load_yaml( + constants.MCE_SUBSCRIPTION_YAML + ) + + if config.DEPLOYMENT.get("mce_latest_stable"): + mce_subscription_yaml_data["spec"][ + "source" + ] = constants.OPERATOR_CATALOG_SOURCE_NAME + mce_sub_channel = "stable-2.7" + + mce_subscription_yaml_data["spec"]["channel"] = f"{mce_sub_channel}" + mce_subscription_manifest = tempfile.NamedTemporaryFile( + mode="w+", prefix="mce_subscription_manifest", delete=False + ) + templating.dump_data_to_temp_yaml( + mce_subscription_yaml_data, mce_subscription_manifest.name + ) + logger.info("Creating subscription for mce operator") + run_cmd(f"oc create -f {mce_subscription_manifest.name}") + OCP( + kind=constants.SUBSCRIPTION_COREOS, + namespace=self.namespace, + resource_name=constants.MCE_OPERATOR, + ).check_resource_existence( + should_exist=True, resource_name=constants.MCE_OPERATOR + ) + + def check_hypershift_namespace(self): + """ + Check hypershift namespace created + + """ + logger.info(f"hypershift namespace {self.namespace} was created successfully") + is_hypershift_ns_available = self.ns_obj.is_exist( + resource_name=constants.HYPERSHIFT_NAMESPACE, + ) + return is_hypershift_ns_available + + def check_supported_versions(self): + """ + Check supported ocp versions for hcp cluster creation + + """ + configmaps_obj = OCP( + kind=constants.CONFIGMAP, + namespace=constants.HYPERSHIFT_NAMESPACE, + ) + + assert configmaps_obj.is_exist( + resource_name=constants.SUPPORTED_VERSIONS_CONFIGMAP + ), f"Configmap {constants.SUPPORTED_VERSIONS_CONFIGMAP} does not exist in hypershift namespace" + + cmd = "oc get cm -n hypershift supported-versions -o jsonpath='{.data.supported-versions}'" + cmd_res = exec_cmd(cmd, shell=True) + if cmd_res.returncode == 0: + supported_versions = cmd_res.stdout.decode("utf-8") + logger.info(f"Supported versions: {supported_versions}") + + if not get_running_ocp_version() in supported_versions: + self.create_image_override() + + def create_image_override(self): + """ + Create hypershift image override cm + """ + # Create image override configmap using the image override json + cmd = ( + f"oc create cm {self.hypershift_override_image_cm} --from-file={constants.IMAGE_OVERRIDE_JSON}" + "-n {self.namespace}" + ) + cmd_res = exec_cmd(cmd, shell=True) + assert cmd_res.returncode == 0 + + configmaps_obj = OCP( + kind=constants.CONFIGMAP, + namespace=constants.HYPERSHIFT_NAMESPACE, + ) + + assert configmaps_obj.is_exist( + resource_name=self.hypershift_override_image_cm + ), f"Configmap {self.hypershift_override_image_cm} does not exist in hypershift namespace" + + # annotate multicluster engine operator with the override cm + self.multicluster_engine.annotate( + annotation=f"imageOverridesCM={self.hypershift_override_image_cm}" + ) + self.multicluster_engine.wait_until_running() + + def deploy_mce(self, check_mce_deployed=False, check_mce_ready=False): + """ + Installs mce enabling software emulation. + + Args: + check_mce_deployed (bool): If True, check if mce is already deployed. If so, skip the deployment. + check_mce_ready (bool): If True, check if mce is ready. If so, skip the deployment. + """ + if check_mce_deployed: + if self.mce_hyperconverged_installed(): + logger.info("mce operator is already deployed, skipping the deployment") + return + + if check_mce_ready: + if self.post_install_verification(raise_exception=False): + logger.info("mce operator ready, skipping the deployment") + return + + logger.info("Installing mce") + # we create catsrc with nightly builds only if config.DEPLOYMENT does not have mce_latest_stable + if not config.DEPLOYMENT.get("mce_latest_stable"): + # Create mce catalog source + self.create_mce_catalog_source() + # Create multicluster-engine namespace + self.create_mce_namespace() + # create mce subscription + self.create_mce_subscription() + # Deploy the multiclusterengine CR + self.create_multiclusterengine_operator() + # Check hypershift ns created + if not self.check_hypershift_namespace(): + cmd = ( + "oc patch mce multiclusterengine " + '-p \'{"spec":{"overrides":{"components":[' + '{"enabled":true, "name":"hypershift"}' + "]}}}' --type=merge" + ) + cmd_res = exec_cmd(cmd, shell=True) + assert cmd_res.returncode == 0 diff --git a/ocs_ci/ocs/constants.py b/ocs_ci/ocs/constants.py index 97c62d4db6e..a3526da5810 100644 --- a/ocs_ci/ocs/constants.py +++ b/ocs_ci/ocs/constants.py @@ -33,6 +33,7 @@ TEMPLATE_DEPLOYMENT_DIR_LVMO = os.path.join(TEMPLATE_DIR, "lvmo-deployment") TEMPLATE_MULTICLUSTER_DIR = os.path.join(TEMPLATE_DEPLOYMENT_DIR, "multicluster") TEMPLATE_DEPLOYMENT_DIR_CNV = os.path.join(TEMPLATE_DIR, "cnv-deployment") +TEMPLATE_DEPLOYMENT_DIR_MCE = os.path.join(TEMPLATE_DIR, "mce-deployment") TEMPLATE_DEPLOYMENT_DIR_METALLB = os.path.join(TEMPLATE_DIR, "metallb-deployment") TEMPLATE_DEPLOYMENT_DIR_NMSTATE = os.path.join(TEMPLATE_DIR, "nmstate-deployment") TEMPLATE_DEPLOYMENT_DIR_INF = os.path.join( @@ -2733,6 +2734,17 @@ ACM_BREW_REPO = SUBMARINER_BREW_REPO # Multicluster related +MCE_NAMESPACE = "multicluster-engine" +MCE_NAMESPACE_YAML = os.path.join(TEMPLATE_DEPLOYMENT_DIR_MCE, "mce_namespace.yaml") +MCE_CATSRC_YAML = os.path.join(TEMPLATE_DEPLOYMENT_DIR_MCE, "mce_catsrc.yaml") +MCE_SUBSCRIPTION_YAML = os.path.join( + TEMPLATE_DEPLOYMENT_DIR_MCE, "mce_subscription.yaml" +) +MCE_OPERATOR = "multicluster-engine-operator" +MCE_OPERATOR_YAML = os.path.join(TEMPLATE_DEPLOYMENT_DIR_MCE, "mce_operator.yaml") +HYPERSHIFT_NAMESPACE = "hypershift" +SUPPORTED_VERSIONS_CONFIGMAP = "supported-versions" +IMAGE_OVERRIDE_JSON = os.path.join(TEMPLATE_DEPLOYMENT_DIR_MCE, "image-override.json") # OpenSSL Certificate parameters OPENSSL_KEY_SIZE = 2048 diff --git a/ocs_ci/templates/mce-deployment/image-override.json b/ocs_ci/templates/mce-deployment/image-override.json new file mode 100644 index 00000000000..724a4e68445 --- /dev/null +++ b/ocs_ci/templates/mce-deployment/image-override.json @@ -0,0 +1,8 @@ +[ + { + "image-name": "rhtap-hypershift-operator", + "image-tag": "17a958f", + "image-remote": "quay.io/acm-d", + "image-key": "hypershift_operator" + } + ] diff --git a/ocs_ci/templates/mce-deployment/mce_catsrc.yaml b/ocs_ci/templates/mce-deployment/mce_catsrc.yaml new file mode 100644 index 00000000000..98fdae0e33d --- /dev/null +++ b/ocs_ci/templates/mce-deployment/mce_catsrc.yaml @@ -0,0 +1,8 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: CatalogSource +metadata: + name: mce-catalogsource + namespace: openshift-marketplace +spec: + image: PLACE_HOLDER2.13.0-DOWNSTREAM-2024-12-09-22-26-41 + sourceType: grpc diff --git a/ocs_ci/templates/mce-deployment/mce_namespace.yaml b/ocs_ci/templates/mce-deployment/mce_namespace.yaml new file mode 100644 index 00000000000..1c6928bf0a6 --- /dev/null +++ b/ocs_ci/templates/mce-deployment/mce_namespace.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: multicluster-engine + labels: + openshift.io/cluster-monitoring: "true" diff --git a/ocs_ci/templates/mce-deployment/mce_operator.yaml b/ocs_ci/templates/mce-deployment/mce_operator.yaml new file mode 100644 index 00000000000..a3afc5d5e4a --- /dev/null +++ b/ocs_ci/templates/mce-deployment/mce_operator.yaml @@ -0,0 +1,10 @@ +apiVersion: multicluster.openshift.io/v1 +kind: MultiClusterEngine +metadata: + name: multiclusterengine +spec: + overrides: + components: + - name: local-cluster + enabled: true + availabilityConfig: High diff --git a/ocs_ci/templates/mce-deployment/mce_subscription.yaml b/ocs_ci/templates/mce-deployment/mce_subscription.yaml new file mode 100644 index 00000000000..32b15714637 --- /dev/null +++ b/ocs_ci/templates/mce-deployment/mce_subscription.yaml @@ -0,0 +1,11 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: Subscription +metadata: + name: multicluster-engine + namespace: multicluster-engine +spec: + channel: stable + installPlanApproval: Automatic + name: multicluster-engine + source: mce-catalogsource + sourceNamespace: openshift-marketplace diff --git a/tests/libtest/test_provider_create_hosted_cluster.py b/tests/libtest/test_provider_create_hosted_cluster.py index 7e9c564cb09..3203d004d4c 100644 --- a/tests/libtest/test_provider_create_hosted_cluster.py +++ b/tests/libtest/test_provider_create_hosted_cluster.py @@ -312,3 +312,29 @@ def test_verify_native_storage(self): assert ( storage_class in storage_class_classes ), "Storage classes ae not created as expected" + + @runs_on_provider + @hci_provider_required + def test_deploy_mce(self): + """ + Test deploy mce without installting acm + """ + logger.info("Test deploy mce without deploying ACM") + HypershiftHostedOCP("dummy").deploy_dependencies( + deploy_acm_hub=False, + deploy_cnv=False, + deploy_metallb=False, + download_hcp_binary=False, + deploy_mce=True, + ) + assert validate_acm_hub_install(), "ACM not installed or MCE not configured" + + @hci_provider_required + def test_provider_deploy_OCP_hosted_skip_acm(self): + """ + Test deploy hosted OCP on provider platform with cnv ready beforehand + """ + logger.info("Test deploy hosted OCP on provider platform with cnv ready") + cluster_name = list(config.ENV_DATA["clusters"].keys())[-1] + + HypershiftHostedOCP(cluster_name).deploy_ocp(deploy_acm_hub=False) From 47b5f6d0a601c27c11ea9ef669c63649e5f06b80 Mon Sep 17 00:00:00 2001 From: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> Date: Thu, 12 Dec 2024 12:42:49 +0530 Subject: [PATCH 02/11] Updated odf installation on provider using ocs-catalogsource Signed-off-by: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> --- ocs_ci/deployment/hosted_cluster.py | 7 +++++-- .../storage_client_deployment.py | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/ocs_ci/deployment/hosted_cluster.py b/ocs_ci/deployment/hosted_cluster.py index ea2f44429af..af37a4227d6 100644 --- a/ocs_ci/deployment/hosted_cluster.py +++ b/ocs_ci/deployment/hosted_cluster.py @@ -360,7 +360,9 @@ def deploy_multiple_odf_clients(self): hosted_odf.do_deploy() -class HypershiftHostedOCP(HyperShiftBase, MetalLBInstaller, CNVInstaller, Deployment): +class HypershiftHostedOCP( + HyperShiftBase, MetalLBInstaller, CNVInstaller, Deployment, MCEInstaller +): def __init__(self, name): Deployment.__init__(self) HyperShiftBase.__init__(self) @@ -388,6 +390,7 @@ def deploy_ocp( deploy_acm_hub=True, deploy_metallb=True, download_hcp_binary=True, + deploy_mce=True, ): """ Deploy hosted OCP cluster on provisioned Provider platform @@ -408,7 +411,7 @@ def deploy_ocp( deploy_acm_hub = False self.deploy_dependencies( - deploy_acm_hub, deploy_cnv, deploy_metallb, download_hcp_binary + deploy_acm_hub, deploy_cnv, deploy_metallb, download_hcp_binary, deploy_mce ) ocp_version = str(config.ENV_DATA["clusters"][self.name].get("ocp_version")) diff --git a/ocs_ci/deployment/provider_client/storage_client_deployment.py b/ocs_ci/deployment/provider_client/storage_client_deployment.py index 2af97a2205d..4153e7ca8bf 100644 --- a/ocs_ci/deployment/provider_client/storage_client_deployment.py +++ b/ocs_ci/deployment/provider_client/storage_client_deployment.py @@ -4,6 +4,7 @@ import logging import time +import tempfile from ocs_ci.framework import config @@ -41,6 +42,7 @@ verify_block_pool_exists, ) from ocs_ci.ocs.exceptions import CommandFailed +from ocs_ci.ocs.resources.catalog_source import CatalogSource log = logging.getLogger(__name__) @@ -322,6 +324,22 @@ def odf_subscription_on_provider(self): live_deployment = config.DEPLOYMENT.get("live_deployment") if not live_deployment: create_catalog_source() + catalog_data = templating.load_yaml(constants.PROVIDER_MODE_CATALOGSOURCE) + catalog_data["spec"]["image"] = config.DEPLOYMENT.get( + "ocs_registry_image", "" + ) + catalog_data_yaml = tempfile.NamedTemporaryFile( + mode="w+", prefix="catalog_data", delete=False + ) + templating.dump_data_to_temp_yaml(catalog_data, catalog_data_yaml.name) + self.ocp_obj.exec_oc_cmd(f"apply -f {catalog_data_yaml.name}") + + catalog_source = CatalogSource( + resource_name=constants.OCS_CATALOG_SOURCE_NAME, + namespace=constants.MARKETPLACE_NAMESPACE, + ) + # Wait for catalog source is ready + catalog_source.wait_for_state("READY") log.info("Creating namespace and operator group.") olm_data = templating.load_yaml(constants.OLM_YAML, multi_document=True) From 3beb8aa195ca84323452770f9e316ee4f2286d22 Mon Sep 17 00:00:00 2001 From: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> Date: Thu, 12 Dec 2024 19:58:55 +0530 Subject: [PATCH 03/11] Added a temporary test will remove later Signed-off-by: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> --- tests/functional/test_temp.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/functional/test_temp.py diff --git a/tests/functional/test_temp.py b/tests/functional/test_temp.py new file mode 100644 index 00000000000..f49d6186b19 --- /dev/null +++ b/tests/functional/test_temp.py @@ -0,0 +1,10 @@ +from ocs_ci.deployment.baremetal import clean_disk +from ocs_ci.ocs.node import get_nodes +from ocs_ci.ocs import constants + + +def test_fun(): + worker_node_objs = get_nodes(node_type=constants.WORKER_MACHINE) + print(f"worker nodes: {worker_node_objs}") + for worker in worker_node_objs: + clean_disk(worker) From 9cfe114796289d1c0adc23c064dab4f77b55dc26 Mon Sep 17 00:00:00 2001 From: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> Date: Mon, 6 Jan 2025 13:14:35 +0530 Subject: [PATCH 04/11] Addressed review comments Signed-off-by: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> --- conf/README.md | 4 +- ocs_ci/deployment/hosted_cluster.py | 2 +- ocs_ci/deployment/mce.py | 97 +++++++++++++++-------------- ocs_ci/ocs/constants.py | 4 +- 4 files changed, 57 insertions(+), 50 deletions(-) diff --git a/conf/README.md b/conf/README.md index b4fdcad163c..cb7d97bad26 100644 --- a/conf/README.md +++ b/conf/README.md @@ -105,7 +105,9 @@ anywhere else. * `mirror_registry` - Hostname of the mirror registry * `mirror_registry_user` - Username for disconnected cluster mirror registry * `mirror_registry_password` - Password for disconnected cluster mirror registry -* `opm_index_prune_binary_image` - Required only for IBM Power Systems and IBM Z images: Operator Registry base image with the tag that matches the target OpenShift Container Platform cluster major and minor version. +* `opm_index_prune_binary_image` - Required only for IBM Power Systems and IBM Z images: Operator Registry base image with the tag that matches the target OpenShift Container Platform cluster major and minor +* `deploy_mce`- Boolean, Deploy mce if True +version. (for example: `registry.redhat.io/openshift4/ose-operator-registry:v4.9`) [doc](https://access.redhat.com/documentation/en-us/openshift_container_platform/4.9/html/operators/administrator-tasks#olm-pruning-index-image_olm-managing-custom-catalogs) * `min_noobaa_endpoints` - Sets minimum noobaa endpoints (Workaround for https://github.com/red-hat-storage/ocs-ci/issues/2861) diff --git a/ocs_ci/deployment/hosted_cluster.py b/ocs_ci/deployment/hosted_cluster.py index af37a4227d6..fd1c498f88f 100644 --- a/ocs_ci/deployment/hosted_cluster.py +++ b/ocs_ci/deployment/hosted_cluster.py @@ -491,7 +491,7 @@ def deploy_dependencies( self.deploy_lb() if download_hcp_binary: self.update_hcp_binary() - if deploy_mce: + if deploy_mce and not deploy_acm_hub(): self.deploy_mce() provider_ocp_version = str( diff --git a/ocs_ci/deployment/mce.py b/ocs_ci/deployment/mce.py index b3d001c9a9f..9e472c5736e 100644 --- a/ocs_ci/deployment/mce.py +++ b/ocs_ci/deployment/mce.py @@ -14,7 +14,6 @@ run_cmd, exec_cmd, ) -from ocs_ci.ocs import exceptions from ocs_ci.ocs.resources.catalog_source import CatalogSource from ocs_ci.ocs import ocp from ocs_ci.utility.utils import get_running_ocp_version @@ -35,29 +34,44 @@ def __init__(self): kind="MultiClusterEngine", resource_name=constants.MULTICLUSTER_ENGINE, ) + self.catsrc = ocp.OCP( + kind=constants.CATSRC, namespace=constants.MARKETPLACE_NAMESPACE + ) + self.subs = ocp.OCP(kind=constants.PROVIDER_SUBSCRIPTION) def create_mce_catalog_source(self): """ Creates a catalogsource for mce operator. """ - logger.info("Adding CatalogSource for MCE") - mce_catalog_source_data = templating.load_yaml(constants.MCE_CATSRC_YAML) - mce_catalog_source_name = mce_catalog_source_data.get("metadata").get("name") - if config.ENV_DATA.get("mce_image"): - mce_image_tag = config.ENV_DATA.get("mce_image") - mce_catalog_source_data["spec"]["image"] = mce_image_tag - mce_catalog_source_manifest = tempfile.NamedTemporaryFile( - mode="w+", prefix="mce_catalog_source_manifest", delete=False - ) - templating.dump_data_to_temp_yaml( - mce_catalog_source_data, mce_catalog_source_manifest.name - ) - run_cmd(f"oc apply -f {mce_catalog_source_manifest.name}", timeout=2400) - mce_catalog_source = CatalogSource( - resource_name=mce_catalog_source_name, - namespace=constants.MARKETPLACE_NAMESPACE, - ) + if not self.catsrc.is_exist( + resource_name=constants.MCE_CATSRC_NAME, + ): + logger.info("Adding CatalogSource for MCE") + mce_catalog_source_data = templating.load_yaml(constants.MCE_CATSRC_YAML) + if config.ENV_DATA.get("mce_image"): + mce_image_tag = config.ENV_DATA.get("mce_image") + mce_catalog_source_data["spec"]["image"] = mce_image_tag + mce_catalog_source_manifest = tempfile.NamedTemporaryFile( + mode="w+", prefix="mce_catalog_source_manifest", delete=False + ) + templating.dump_data_to_temp_yaml( + mce_catalog_source_data, mce_catalog_source_manifest.name + ) + run_cmd(f"oc apply -f {mce_catalog_source_manifest.name}", timeout=2400) + mce_catalog_source = CatalogSource( + resource_name=constants.MCE_CATSRC_NAME, + namespace=constants.MARKETPLACE_NAMESPACE, + ) + else: + logger.info("catalogsource exists") + logger.info("Check the image for MCE") + if not mce_catalog_source_data["spec"]["image"] == config.ENV_DATA.get( + "mce_image" + ): + mce_catalog_source_data["spec"]["image"] = config.ENV_DATA.get( + "mce_image" + ) # Wait for catalog source is ready mce_catalog_source.wait_for_state("READY") @@ -69,54 +83,43 @@ def create_mce_namespace(self): Raises: CommandFailed: If the 'oc create' command fails. """ - try: + if not self.ns_obj.is_exist( + resource_name=self.namespace, + ): logger.info(f"Creating namespace {self.namespace} for mce resources") namespace_yaml_file = templating.load_yaml(constants.MCE_NAMESPACE_YAML) namespace_yaml = OCS(**namespace_yaml_file) namespace_yaml.create() logger.info(f"MCE namespace {self.namespace} was created successfully") - except exceptions.CommandFailed as ef: - if ( - f'project.project.openshift.io "{self.namespace}" already exists' - in str(ef) - ): - logger.info(f"Namespace {self.namespace} already present") - raise ef + else: + logger.info(f"{self.namespace} already exists") def create_multiclusterengine_operator(self): """ Creates multiclusterengine operator """ - operatorgroup_yaml_file = templating.load_yaml(constants.MCE_OPERATOR_YAM) - operatorgroup_yaml = OCS(**operatorgroup_yaml_file) - try: + logger.info("Check if mce operator already exist") + if not self.multicluster_engine.is_exist( + resource_name=constants.MULTICLUSTER_ENGINE + ): + + operatorgroup_yaml_file = templating.load_yaml(constants.MCE_OPERATOR_YAML) + operatorgroup_yaml = OCS(**operatorgroup_yaml_file) operatorgroup_yaml.create() logger.info("mce OperatorGroup created successfully") - except exceptions.CommandFailed as ef: - if "multiclusterengine exists" in str(ef): - logger.info("multiclusterengine already exists") - - cmd = "oc get mce multiclusterengine -o jsonpath='{.status}'" - cmd_res = exec_cmd(cmd, shell=True) - if cmd_res.returncode != 0: - logger.error(f"Failed to get multicluster engine status\n{cmd_res.stderr}") - else: - logger.info( - f"Multicluster engine version: {cmd_res.stdout.decode('utf-8')}" - ) - assert ( - cmd_res.stdout.decode("utf-8") == "Available" - ), "multiclusterengine is not is 'Available' status" + self.multicluster_engine.wait_for_phase("Available") def create_mce_subscription(self): """ Creates subscription for mce operator """ - mce_subscription_yaml_data = templating.load_yaml( - constants.MCE_SUBSCRIPTION_YAML - ) + logger.info("Check if mce subscription already exist") + if not self.subs.is_exist(resource_name=constants.MCE_OPERATOR): + mce_subscription_yaml_data = templating.load_yaml( + constants.MCE_SUBSCRIPTION_YAML + ) if config.DEPLOYMENT.get("mce_latest_stable"): mce_subscription_yaml_data["spec"][ diff --git a/ocs_ci/ocs/constants.py b/ocs_ci/ocs/constants.py index a3526da5810..546e1ba1211 100644 --- a/ocs_ci/ocs/constants.py +++ b/ocs_ci/ocs/constants.py @@ -401,6 +401,7 @@ "storagesystems", "storagesystem", ] +PROVIDER_SUBSCRIPTION = "subs" OCS_CLIENT_OPERATOR_CONTROLLER_MANAGER_PREFIX = "ocs-client-operator-controller-manager" OCS_CLIENT_OPERATOR_CONSOLE = "ocs-client-operator-console" @@ -2737,10 +2738,11 @@ MCE_NAMESPACE = "multicluster-engine" MCE_NAMESPACE_YAML = os.path.join(TEMPLATE_DEPLOYMENT_DIR_MCE, "mce_namespace.yaml") MCE_CATSRC_YAML = os.path.join(TEMPLATE_DEPLOYMENT_DIR_MCE, "mce_catsrc.yaml") +MCE_CATSRC_NAME = "mce-catalogsource" MCE_SUBSCRIPTION_YAML = os.path.join( TEMPLATE_DEPLOYMENT_DIR_MCE, "mce_subscription.yaml" ) -MCE_OPERATOR = "multicluster-engine-operator" +MCE_OPERATOR = "multicluster-engine" MCE_OPERATOR_YAML = os.path.join(TEMPLATE_DEPLOYMENT_DIR_MCE, "mce_operator.yaml") HYPERSHIFT_NAMESPACE = "hypershift" SUPPORTED_VERSIONS_CONFIGMAP = "supported-versions" From c57871e1d1eb1b1c0aac5a8ca11b488dc46ecdb1 Mon Sep 17 00:00:00 2001 From: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> Date: Mon, 6 Jan 2025 13:53:42 +0530 Subject: [PATCH 05/11] Addressed review comments and synced the branch with master Signed-off-by: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> --- ocs_ci/deployment/mce.py | 32 ++++++++----------- .../mce-deployment/image-override.json | 2 +- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/ocs_ci/deployment/mce.py b/ocs_ci/deployment/mce.py index 9e472c5736e..624cc16dfe9 100644 --- a/ocs_ci/deployment/mce.py +++ b/ocs_ci/deployment/mce.py @@ -17,6 +17,7 @@ from ocs_ci.ocs.resources.catalog_source import CatalogSource from ocs_ci.ocs import ocp from ocs_ci.utility.utils import get_running_ocp_version +from ocs_ci.ocs.exceptions import CommandFailed, UnavailableResourceException logger = logging.getLogger(__name__) @@ -165,9 +166,12 @@ def check_supported_versions(self): namespace=constants.HYPERSHIFT_NAMESPACE, ) - assert configmaps_obj.is_exist( + if not configmaps_obj.is_exist( resource_name=constants.SUPPORTED_VERSIONS_CONFIGMAP - ), f"Configmap {constants.SUPPORTED_VERSIONS_CONFIGMAP} does not exist in hypershift namespace" + ): + raise UnavailableResourceException( + f"Configmap {constants.SUPPORTED_VERSIONS_CONFIGMAP} does not exist in hypershift namespace" + ) cmd = "oc get cm -n hypershift supported-versions -o jsonpath='{.data.supported-versions}'" cmd_res = exec_cmd(cmd, shell=True) @@ -188,16 +192,8 @@ def create_image_override(self): "-n {self.namespace}" ) cmd_res = exec_cmd(cmd, shell=True) - assert cmd_res.returncode == 0 - - configmaps_obj = OCP( - kind=constants.CONFIGMAP, - namespace=constants.HYPERSHIFT_NAMESPACE, - ) - - assert configmaps_obj.is_exist( - resource_name=self.hypershift_override_image_cm - ), f"Configmap {self.hypershift_override_image_cm} does not exist in hypershift namespace" + if cmd_res.returncode: + raise CommandFailed("override configmap not created successfully") # annotate multicluster engine operator with the override cm self.multicluster_engine.annotate( @@ -236,11 +232,9 @@ def deploy_mce(self, check_mce_deployed=False, check_mce_ready=False): self.create_multiclusterengine_operator() # Check hypershift ns created if not self.check_hypershift_namespace(): - cmd = ( - "oc patch mce multiclusterengine " - '-p \'{"spec":{"overrides":{"components":[' - '{"enabled":true, "name":"hypershift"}' - "]}}}' --type=merge" - ) + cmd = f"oc create namespace {constants.HYPERSHIFT_NAMESPACE}" cmd_res = exec_cmd(cmd, shell=True) - assert cmd_res.returncode == 0 + if cmd_res.returncode: + raise CommandFailed("Failed to create hypershift namespace") + # Check supported versions in supported-versions configmap + self.check_supported_versions() diff --git a/ocs_ci/templates/mce-deployment/image-override.json b/ocs_ci/templates/mce-deployment/image-override.json index 724a4e68445..5c8fe6d8718 100644 --- a/ocs_ci/templates/mce-deployment/image-override.json +++ b/ocs_ci/templates/mce-deployment/image-override.json @@ -1,7 +1,7 @@ [ { "image-name": "rhtap-hypershift-operator", - "image-tag": "17a958f", + "image-tag": "latest", "image-remote": "quay.io/acm-d", "image-key": "hypershift_operator" } From 3af94f5c145f8e6ab5bbaf75e098fc9f7658abe0 Mon Sep 17 00:00:00 2001 From: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> Date: Mon, 6 Jan 2025 14:56:00 +0530 Subject: [PATCH 06/11] Removed temporary test file Signed-off-by: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> --- tests/functional/test_temp.py | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 tests/functional/test_temp.py diff --git a/tests/functional/test_temp.py b/tests/functional/test_temp.py deleted file mode 100644 index f49d6186b19..00000000000 --- a/tests/functional/test_temp.py +++ /dev/null @@ -1,10 +0,0 @@ -from ocs_ci.deployment.baremetal import clean_disk -from ocs_ci.ocs.node import get_nodes -from ocs_ci.ocs import constants - - -def test_fun(): - worker_node_objs = get_nodes(node_type=constants.WORKER_MACHINE) - print(f"worker nodes: {worker_node_objs}") - for worker in worker_node_objs: - clean_disk(worker) From 74581e2d835c48156e384dcf114771bb36e641eb Mon Sep 17 00:00:00 2001 From: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:04:48 +0530 Subject: [PATCH 07/11] Updated the testcase Signed-off-by: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> --- ocs_ci/deployment/hosted_cluster.py | 1 + ocs_ci/deployment/mce.py | 8 ++++++++ tests/libtest/test_provider_create_hosted_cluster.py | 4 ++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ocs_ci/deployment/hosted_cluster.py b/ocs_ci/deployment/hosted_cluster.py index fd1c498f88f..03201873301 100644 --- a/ocs_ci/deployment/hosted_cluster.py +++ b/ocs_ci/deployment/hosted_cluster.py @@ -493,6 +493,7 @@ def deploy_dependencies( self.update_hcp_binary() if deploy_mce and not deploy_acm_hub(): self.deploy_mce() + self.validate_mce_deployment() provider_ocp_version = str( get_semantic_version(get_ocp_version(), only_major_minor=True) diff --git a/ocs_ci/deployment/mce.py b/ocs_ci/deployment/mce.py index 624cc16dfe9..b46f9b8dcb8 100644 --- a/ocs_ci/deployment/mce.py +++ b/ocs_ci/deployment/mce.py @@ -238,3 +238,11 @@ def deploy_mce(self, check_mce_deployed=False, check_mce_ready=False): raise CommandFailed("Failed to create hypershift namespace") # Check supported versions in supported-versions configmap self.check_supported_versions() + + def validate_mce_deployment(self): + """ + Validate mce operator installation + """ + if self.mce_hyperconverged_installed(): + logger.info("mce operator is already deployed") + return diff --git a/tests/libtest/test_provider_create_hosted_cluster.py b/tests/libtest/test_provider_create_hosted_cluster.py index 3203d004d4c..14dd367db78 100644 --- a/tests/libtest/test_provider_create_hosted_cluster.py +++ b/tests/libtest/test_provider_create_hosted_cluster.py @@ -320,14 +320,14 @@ def test_deploy_mce(self): Test deploy mce without installting acm """ logger.info("Test deploy mce without deploying ACM") - HypershiftHostedOCP("dummy").deploy_dependencies( + hypershift_hosted = HypershiftHostedOCP("dummy") + hypershift_hosted.deploy_dependencies( deploy_acm_hub=False, deploy_cnv=False, deploy_metallb=False, download_hcp_binary=False, deploy_mce=True, ) - assert validate_acm_hub_install(), "ACM not installed or MCE not configured" @hci_provider_required def test_provider_deploy_OCP_hosted_skip_acm(self): From 4c18c3a32116ae2a3e091a0dce6db3deaf492746 Mon Sep 17 00:00:00 2001 From: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> Date: Tue, 7 Jan 2025 15:04:16 +0530 Subject: [PATCH 08/11] Corrected typo Signed-off-by: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> --- ocs_ci/deployment/hosted_cluster.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ocs_ci/deployment/hosted_cluster.py b/ocs_ci/deployment/hosted_cluster.py index 03201873301..2c84e5c1d71 100644 --- a/ocs_ci/deployment/hosted_cluster.py +++ b/ocs_ci/deployment/hosted_cluster.py @@ -491,7 +491,7 @@ def deploy_dependencies( self.deploy_lb() if download_hcp_binary: self.update_hcp_binary() - if deploy_mce and not deploy_acm_hub(): + if deploy_mce and not deploy_acm_hub: self.deploy_mce() self.validate_mce_deployment() From d04ca790b955c66e358dcfc7df6def906db80d2f Mon Sep 17 00:00:00 2001 From: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> Date: Tue, 7 Jan 2025 15:30:02 +0530 Subject: [PATCH 09/11] Corrected typo Signed-off-by: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> --- ocs_ci/deployment/mce.py | 2 +- ocs_ci/templates/mce-deployment/mce_catsrc.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ocs_ci/deployment/mce.py b/ocs_ci/deployment/mce.py index b46f9b8dcb8..54ed99e406f 100644 --- a/ocs_ci/deployment/mce.py +++ b/ocs_ci/deployment/mce.py @@ -52,7 +52,7 @@ def create_mce_catalog_source(self): mce_catalog_source_data = templating.load_yaml(constants.MCE_CATSRC_YAML) if config.ENV_DATA.get("mce_image"): mce_image_tag = config.ENV_DATA.get("mce_image") - mce_catalog_source_data["spec"]["image"] = mce_image_tag + mce_catalog_source_data["spec"]["image"] = mce_image_tag mce_catalog_source_manifest = tempfile.NamedTemporaryFile( mode="w+", prefix="mce_catalog_source_manifest", delete=False ) diff --git a/ocs_ci/templates/mce-deployment/mce_catsrc.yaml b/ocs_ci/templates/mce-deployment/mce_catsrc.yaml index 98fdae0e33d..10475109b37 100644 --- a/ocs_ci/templates/mce-deployment/mce_catsrc.yaml +++ b/ocs_ci/templates/mce-deployment/mce_catsrc.yaml @@ -4,5 +4,5 @@ metadata: name: mce-catalogsource namespace: openshift-marketplace spec: - image: PLACE_HOLDER2.13.0-DOWNSTREAM-2024-12-09-22-26-41 + image: 2.13.0-DOWNSTREAM-2024-12-09-22-26-41 sourceType: grpc From b94bacb822ad10d71f1ff221ea3fa0730050db18 Mon Sep 17 00:00:00 2001 From: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> Date: Tue, 7 Jan 2025 16:30:13 +0530 Subject: [PATCH 10/11] Corrected mce image details Signed-off-by: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> --- ocs_ci/deployment/mce.py | 4 +++- ocs_ci/templates/mce-deployment/mce_catsrc.yaml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ocs_ci/deployment/mce.py b/ocs_ci/deployment/mce.py index 54ed99e406f..7736a632017 100644 --- a/ocs_ci/deployment/mce.py +++ b/ocs_ci/deployment/mce.py @@ -52,7 +52,9 @@ def create_mce_catalog_source(self): mce_catalog_source_data = templating.load_yaml(constants.MCE_CATSRC_YAML) if config.ENV_DATA.get("mce_image"): mce_image_tag = config.ENV_DATA.get("mce_image") - mce_catalog_source_data["spec"]["image"] = mce_image_tag + mce_catalog_source_data["spec"]["image"] = ( + "quay.io:443/acm-d/mce-custom-registry:" + mce_image_tag + ) mce_catalog_source_manifest = tempfile.NamedTemporaryFile( mode="w+", prefix="mce_catalog_source_manifest", delete=False ) diff --git a/ocs_ci/templates/mce-deployment/mce_catsrc.yaml b/ocs_ci/templates/mce-deployment/mce_catsrc.yaml index 10475109b37..2d8750f0443 100644 --- a/ocs_ci/templates/mce-deployment/mce_catsrc.yaml +++ b/ocs_ci/templates/mce-deployment/mce_catsrc.yaml @@ -4,5 +4,5 @@ metadata: name: mce-catalogsource namespace: openshift-marketplace spec: - image: 2.13.0-DOWNSTREAM-2024-12-09-22-26-41 + image: quay.io:443/acm-d/mce-custom-registry:2.13.0-DOWNSTREAM-2025-01-05-19-09-28 sourceType: grpc From 2250b234f21fbb850916e94fd6b8a919156477da Mon Sep 17 00:00:00 2001 From: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> Date: Tue, 7 Jan 2025 17:02:27 +0530 Subject: [PATCH 11/11] Corrected typo Signed-off-by: Amrita Mahapatra <49347640+amr1ta@users.noreply.github.com> --- ocs_ci/deployment/mce.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/ocs_ci/deployment/mce.py b/ocs_ci/deployment/mce.py index 7736a632017..ed78f83e66d 100644 --- a/ocs_ci/deployment/mce.py +++ b/ocs_ci/deployment/mce.py @@ -66,18 +66,10 @@ def create_mce_catalog_source(self): resource_name=constants.MCE_CATSRC_NAME, namespace=constants.MARKETPLACE_NAMESPACE, ) + # Wait for catalog source is ready + mce_catalog_source.wait_for_state("READY") else: logger.info("catalogsource exists") - logger.info("Check the image for MCE") - if not mce_catalog_source_data["spec"]["image"] == config.ENV_DATA.get( - "mce_image" - ): - mce_catalog_source_data["spec"]["image"] = config.ENV_DATA.get( - "mce_image" - ) - - # Wait for catalog source is ready - mce_catalog_source.wait_for_state("READY") def create_mce_namespace(self): """ @@ -128,9 +120,11 @@ def create_mce_subscription(self): mce_subscription_yaml_data["spec"][ "source" ] = constants.OPERATOR_CATALOG_SOURCE_NAME - mce_sub_channel = "stable-2.7" + mce_channel = "stable" + else: + mce_channel = config.DEPLOYMENT.get("mce_channel") - mce_subscription_yaml_data["spec"]["channel"] = f"{mce_sub_channel}" + mce_subscription_yaml_data["spec"]["channel"] = mce_channel mce_subscription_manifest = tempfile.NamedTemporaryFile( mode="w+", prefix="mce_subscription_manifest", delete=False )