def __init__(self, driver): super().__init__(driver) self.ocp_version = get_ocp_version() self.ocp_version_full = version.get_semantic_ocp_version_from_config() self.page_nav = locators[self.ocp_version]["page"] self.ocs_version_semantic = version.get_semantic_ocs_version_from_config() self.ocp_version_semantic = version.get_semantic_ocp_version_from_config() self.operator_name = ( ODF_OPERATOR if self.ocs_version_semantic >= version.VERSION_4_9 else OCS_OPERATOR ) if Version.coerce(self.ocp_version) >= Version.coerce("4.8"): self.generic_locators = locators[self.ocp_version]["generic"] if config.ENV_DATA["platform"].lower() == constants.VSPHERE_PLATFORM: self.storage_class = "thin_sc" elif config.ENV_DATA["platform"].lower() == constants.AWS_PLATFORM: aws_sc = config.DEPLOYMENT.get("customized_deployment_storage_class") if aws_sc == "gp3-csi": self.storage_class = "gp3-csi_sc" elif aws_sc == "gp2-csi": self.storage_class = "gp2-csi_sc" else: self.storage_class = "gp2_sc" elif config.ENV_DATA["platform"].lower() == constants.AZURE_PLATFORM: if self.ocp_version_semantic >= version.VERSION_4_11: self.storage_class = "managed-csi_sc" else: self.storage_class = "managed-premium_sc" elif config.ENV_DATA["platform"].lower() == constants.GCP_PLATFORM: self.storage_class = "standard_sc"
def add_deployment_dependencies(): """ Adding dependencies for IBM Cloud deployment """ ocp_version = util_version.get_semantic_ocp_version_from_config() if ocp_version >= util_version.VERSION_4_9: logger.info( "IBM Cloud dependencies like volumesnapshot CRs will not be created" ) return cr_base_url = ( "https://raw.githubusercontent.com/openshift/csi-external-snapshotter/" f"release-{ocp_version}/" ) if ocp_version < util_version.VERSION_4_6: cr_base_url = f"{cr_base_url}config/crd/" else: cr_base_url = f"{cr_base_url}client/config/crd/" # This works only for OCP >= 4.6 and till IBM Cloud guys will resolve the issue wa_crs = [ f"{cr_base_url}snapshot.storage.k8s.io_volumesnapshotclasses.yaml", f"{cr_base_url}snapshot.storage.k8s.io_volumesnapshotcontents.yaml", f"{cr_base_url}snapshot.storage.k8s.io_volumesnapshots.yaml", ] for cr in wa_crs: run_cmd(f"oc apply -f {cr}")
def verify_storage_system(): """ Verify storage system status """ managed_service = (config.ENV_DATA["platform"].lower() in constants.MANAGED_SERVICE_PLATFORMS) live_deployment = config.DEPLOYMENT.get("live_deployment") ocp_version = version.get_semantic_ocp_version_from_config() ocs_version = version.get_semantic_ocs_version_from_config() if (live_deployment and ocs_version == version.VERSION_4_9 and ocp_version == version.VERSION_4_10): log.warning( "Because of the BZ 2075422, we are skipping storage system validation!" ) return if ocs_version >= version.VERSION_4_9 and not managed_service: log.info("Verifying storage system status") storage_system = OCP(kind=constants.STORAGESYSTEM, namespace=config.ENV_DATA["cluster_namespace"]) storage_system_data = storage_system.get() storage_system_status = {} for condition in storage_system_data["items"][0]["status"][ "conditions"]: storage_system_status[condition["type"]] = condition["status"] log.debug(f"storage system status: {storage_system_status}") assert storage_system_status == constants.STORAGE_SYSTEM_STATUS, ( f"Storage System status is not in expected state. Expected {constants.STORAGE_SYSTEM_STATUS}" f" but found {storage_system_status}")
def install_logging(): csv = ocp.OCP( kind=constants.CLUSTER_SERVICE_VERSION, namespace=constants.OPENSHIFT_LOGGING_NAMESPACE, ) logging_csv = csv.get().get("items") if logging_csv: logger.info("Logging is already configured, Skipping Installation") return logger.info("Configuring Openshift-logging") # Gets OCP version to align logging version to OCP version ocp_version = version.get_semantic_ocp_version_from_config() logging_channel = "stable" if ocp_version >= version.VERSION_4_7 else ocp_version # Creates namespace openshift-operators-redhat ocp_logging_obj.create_namespace(yaml_file=constants.EO_NAMESPACE_YAML) # Creates an operator-group for elasticsearch assert ocp_logging_obj.create_elasticsearch_operator_group( yaml_file=constants.EO_OG_YAML, resource_name=constants.OPENSHIFT_OPERATORS_REDHAT_NAMESPACE, ) # Set RBAC policy on the project assert ocp_logging_obj.set_rbac( yaml_file=constants.EO_RBAC_YAML, resource_name="prometheus-k8s" ) # Creates subscription for elastic-search operator subscription_yaml = templating.load_yaml(constants.EO_SUB_YAML) subscription_yaml["spec"]["channel"] = logging_channel helpers.create_resource(**subscription_yaml) assert ocp_logging_obj.get_elasticsearch_subscription() # Creates a namespace openshift-logging ocp_logging_obj.create_namespace(yaml_file=constants.CL_NAMESPACE_YAML) # Creates an operator-group for cluster-logging assert ocp_logging_obj.create_clusterlogging_operator_group( yaml_file=constants.CL_OG_YAML ) # Creates subscription for cluster-logging cl_subscription = templating.load_yaml(constants.CL_SUB_YAML) cl_subscription["spec"]["channel"] = logging_channel helpers.create_resource(**cl_subscription) assert ocp_logging_obj.get_clusterlogging_subscription() # Creates instance in namespace openshift-logging cluster_logging_operator = OCP( kind=constants.POD, namespace=constants.OPENSHIFT_LOGGING_NAMESPACE ) logger.info(f"The cluster-logging-operator {cluster_logging_operator.get()}") ocp_logging_obj.create_instance()
def deploy_ocp(self, log_cli_level="DEBUG"): super(AWSBase, self).deploy_ocp(log_cli_level) ocp_version = version.get_semantic_ocp_version_from_config() ocs_version = version.get_semantic_ocs_version_from_config() if ocs_version >= version.VERSION_4_10 and ocp_version >= version.VERSION_4_9: # If we don't customize the storage class, we will use the default one self.DEFAULT_STORAGECLASS = config.DEPLOYMENT.get( "customized_deployment_storage_class", self.DEFAULT_STORAGECLASS )
class AZUREBase(CloudDeploymentBase): """ Azure deployment base class, with code common to both IPI and UPI. Having this base class separate from AZUREIPI even when we have implemented IPI only makes adding UPI class later easier, moreover code structure is comparable with other platforms. """ # default storage class for StorageCluster CRD on Azure platform # From OCP 4.11, default storage class is managed-csi if version.get_semantic_ocp_version_from_config() >= version.VERSION_4_11: DEFAULT_STORAGECLASS = "managed-csi" else: DEFAULT_STORAGECLASS = "managed-premium" def __init__(self): super(AZUREBase, self).__init__() self.azure_util = AzureUtil() def add_node(self): # TODO: implement later super(AZUREBase, self).add_node() def check_cluster_existence(self, cluster_name_prefix): """ Check cluster existence based on a cluster name prefix. Returns: bool: True if a cluster with the same name prefix already exists, False otherwise """ logger.info("checking existence of cluster with prefix %s", cluster_name_prefix) # ask about all azure resource groups, and filter it by cluster name # prefix (there is azure resource group for each cluster, which # contains all other azure resources of the cluster) resource_groups = self.azure_util.resource_client.resource_groups.list( ) for rg in resource_groups: if rg.name.startswith(cluster_name_prefix): logger.info( "For given cluster name prefix %s, there is a resource group %s already.", cluster_name_prefix, rg.name, ) return True logger.info( "For given cluster name prefix %s, there is no resource group.", cluster_name_prefix, ) return False
def create_optional_operators_catalogsource_non_ga(force=False): """ Creating optional operators CatalogSource and ImageContentSourcePolicy for non-ga OCP. Args: force (bool): enable/disable lso catalog setup """ ocp_version = version.get_semantic_ocp_version_from_config() ocp_ga_version = get_ocp_ga_version(ocp_version) if ocp_ga_version and not force: return optional_operators_data = list( templating.load_yaml(constants.LOCAL_STORAGE_OPTIONAL_OPERATORS, multi_document=True)) optional_operators_yaml = tempfile.NamedTemporaryFile( mode="w+", prefix="optional_operators", delete=False) if config.DEPLOYMENT.get("optional_operators_image"): for _dict in optional_operators_data: if _dict.get("kind").lower() == "catalogsource": _dict["spec"]["image"] = config.DEPLOYMENT.get( "optional_operators_image") if config.DEPLOYMENT.get("disconnected"): # in case of disconnected environment, we have to mirror all the # optional_operators images icsp = None for _dict in optional_operators_data: if _dict.get("kind").lower() == "catalogsource": index_image = _dict["spec"]["image"] if _dict.get("kind").lower() == "imagecontentsourcepolicy": icsp = _dict mirrored_index_image = (f"{config.DEPLOYMENT['mirror_registry']}/" f"{index_image.split('/', 1)[-1]}") prune_and_mirror_index_image( index_image, mirrored_index_image, constants.DISCON_CL_REQUIRED_PACKAGES, icsp, ) _dict["spec"]["image"] = mirrored_index_image templating.dump_data_to_temp_yaml(optional_operators_data, optional_operators_yaml.name) with open(optional_operators_yaml.name, "r") as f: logger.info(f.read()) logger.info( "Creating optional operators CatalogSource and ImageContentSourcePolicy" ) run_cmd(f"oc create -f {optional_operators_yaml.name}") wait_for_machineconfigpool_status("all")
def check_filecount_in_project(self, project): """ Check the files in the project Args: project (str): The project name """ elasticsearch_pod_obj = self.get_elasticsearch_pod_obj() cmd = f"es_util --query=project.{project}.*/_count" if version.get_semantic_ocp_version_from_config() >= version.VERSION_4_5: cmd = ( 'es_util --query=*/_count?pretty -d \'{"query": {"match":' f'{{"kubernetes.namespace_name": "{project}"}}}}}}\'' ) project_filecount = elasticsearch_pod_obj.exec_cmd_on_pod(command=cmd) assert ( project_filecount["_shards"]["successful"] != 0 ), f"No files found in project {project}" logger.info(f"Total number of files and shards in project {project_filecount}")
def validate_project_exists(self, project): """ This function checks whether the new project exists in the EFK stack Args: project (str): The project """ elasticsearch_pod_obj = self.get_elasticsearch_pod_obj() if version.get_semantic_ocp_version_from_config() <= version.VERSION_4_4: project_index = elasticsearch_pod_obj.exec_cmd_on_pod( command="indices", out_yaml_format=False ) if project in project_index: logger.info(f"The project {project} exists in the EFK stack") for item in project_index.split("\n"): if project in item: logger.info(item.strip()) assert ( "green" in item.strip() ), f"Project {project} is Unhealthy" else: raise ModuleNotFoundError else: cmd = ( 'es_util --query=*/_search?pretty -d \'{"query": {"match":' f' {{"kubernetes.namespace_name": "{project}"}}}}}}\'' ) project_out = elasticsearch_pod_obj.exec_cmd_on_pod( command=cmd, out_yaml_format=True ) logger.info(project_out) if project_out["_shards"]["successful"]: logger.info("The Project exists on the EFK stack") else: raise ModuleNotFoundError
def create_pvc_snapshot(pvc_name, snap_yaml, snap_name, namespace, sc_name=None, wait=False): """ Create snapshot of a PVC Args: pvc_name (str): Name of the PVC snap_yaml (str): The path of snapshot yaml snap_name (str): The name of the snapshot to be created namespace (str): The namespace for the snapshot creation sc_name (str): The name of the snapshot class wait (bool): True to wait for snapshot to be ready, False otherwise Returns: OCS object """ ocp_version = version.get_semantic_ocp_version_from_config() snapshot_data = templating.load_yaml(snap_yaml) if ocp_version >= version.VERSION_4_11: snapshot_data["apiVersion"] = "snapshot.storage.k8s.io/v1" snapshot_data["metadata"]["name"] = snap_name snapshot_data["metadata"]["namespace"] = namespace if sc_name: snapshot_data["spec"]["volumeSnapshotClassName"] = sc_name snapshot_data["spec"]["source"]["persistentVolumeClaimName"] = pvc_name ocs_obj = OCS(**snapshot_data) created_snap = ocs_obj.create(do_reload=True) assert created_snap, f"Failed to create snapshot {snap_name}" if wait: ocs_obj.ocp.wait_for_resource( condition="true", resource_name=ocs_obj.name, column=constants.STATUS_READYTOUSE, timeout=60, ) return ocs_obj
def setup_local_storage(storageclass): """ Setup the necessary resources for enabling local storage. Args: storageclass (string): storageClassName value to be used in LocalVolume CR based on LOCAL_VOLUME_YAML """ # Get the worker nodes workers = get_nodes(node_type="worker") worker_names = [worker.name for worker in workers] logger.debug("Workers: %s", worker_names) ocp_version = version.get_semantic_ocp_version_from_config() ocs_version = version.get_semantic_ocs_version_from_config() ocp_ga_version = get_ocp_ga_version(ocp_version) if not ocp_ga_version: optional_operators_data = list( templating.load_yaml(constants.LOCAL_STORAGE_OPTIONAL_OPERATORS, multi_document=True)) optional_operators_yaml = tempfile.NamedTemporaryFile( mode="w+", prefix="optional_operators", delete=False) if config.DEPLOYMENT.get("optional_operators_image"): for _dict in optional_operators_data: if _dict.get("kind").lower() == "catalogsource": _dict["spec"]["image"] = config.DEPLOYMENT.get( "optional_operators_image") if config.DEPLOYMENT.get("disconnected"): # in case of disconnected environment, we have to mirror all the # optional_operators images icsp = None for _dict in optional_operators_data: if _dict.get("kind").lower() == "catalogsource": index_image = _dict["spec"]["image"] if _dict.get("kind").lower() == "imagecontentsourcepolicy": icsp = _dict mirrored_index_image = (f"{config.DEPLOYMENT['mirror_registry']}/" f"{index_image.split('/', 1)[-1]}") prune_and_mirror_index_image( index_image, mirrored_index_image, constants.DISCON_CL_REQUIRED_PACKAGES, icsp, ) _dict["spec"]["image"] = mirrored_index_image templating.dump_data_to_temp_yaml(optional_operators_data, optional_operators_yaml.name) with open(optional_operators_yaml.name, "r") as f: logger.info(f.read()) logger.info( "Creating optional operators CatalogSource and ImageContentSourcePolicy" ) run_cmd(f"oc create -f {optional_operators_yaml.name}") logger.info( "Sleeping for 60 sec to start update machineconfigpool status") # sleep here to start update machineconfigpool status time.sleep(60) wait_for_machineconfigpool_status("all") logger.info("Retrieving local-storage-operator data from yaml") lso_data = list( templating.load_yaml(constants.LOCAL_STORAGE_OPERATOR, multi_document=True)) # ensure namespace is correct lso_namespace = config.ENV_DATA["local_storage_namespace"] for data in lso_data: if data["kind"] == "Namespace": data["metadata"]["name"] = lso_namespace else: data["metadata"]["namespace"] = lso_namespace if data["kind"] == "OperatorGroup": data["spec"]["targetNamespaces"] = [lso_namespace] # Update local-storage-operator subscription data with channel for data in lso_data: if data["kind"] == "Subscription": data["spec"]["channel"] = get_lso_channel() if not ocp_ga_version: if data["kind"] == "Subscription": data["spec"]["source"] = "optional-operators" # Create temp yaml file and create local storage operator logger.info( "Creating temp yaml file with local-storage-operator data:\n %s", lso_data) lso_data_yaml = tempfile.NamedTemporaryFile( mode="w+", prefix="local_storage_operator", delete=False) templating.dump_data_to_temp_yaml(lso_data, lso_data_yaml.name) with open(lso_data_yaml.name, "r") as f: logger.info(f.read()) logger.info("Creating local-storage-operator") run_cmd(f"oc create -f {lso_data_yaml.name}") local_storage_operator = ocp.OCP(kind=constants.POD, namespace=lso_namespace) assert local_storage_operator.wait_for_resource( condition=constants.STATUS_RUNNING, selector=constants.LOCAL_STORAGE_OPERATOR_LABEL, timeout=600, ), "Local storage operator did not reach running phase" # Add disks for vSphere/RHV platform platform = config.ENV_DATA.get("platform").lower() lso_type = config.DEPLOYMENT.get("type") if platform == constants.VSPHERE_PLATFORM: add_disk_for_vsphere_platform() if platform == constants.RHV_PLATFORM: add_disk_for_rhv_platform() if (ocp_version >= version.VERSION_4_6) and (ocs_version >= version.VERSION_4_6): # Pull local volume discovery yaml data logger.info("Pulling LocalVolumeDiscovery CR data from yaml") lvd_data = templating.load_yaml(constants.LOCAL_VOLUME_DISCOVERY_YAML) # Set local-volume-discovery namespace lvd_data["metadata"]["namespace"] = lso_namespace worker_nodes = get_compute_node_names(no_replace=True) # Update local volume discovery data with Worker node Names logger.info( "Updating LocalVolumeDiscovery CR data with worker nodes Name: %s", worker_nodes, ) lvd_data["spec"]["nodeSelector"]["nodeSelectorTerms"][0][ "matchExpressions"][0]["values"] = worker_nodes lvd_data_yaml = tempfile.NamedTemporaryFile( mode="w+", prefix="local_volume_discovery", delete=False) templating.dump_data_to_temp_yaml(lvd_data, lvd_data_yaml.name) logger.info("Creating LocalVolumeDiscovery CR") run_cmd(f"oc create -f {lvd_data_yaml.name}") # Pull local volume set yaml data logger.info("Pulling LocalVolumeSet CR data from yaml") lvs_data = templating.load_yaml(constants.LOCAL_VOLUME_SET_YAML) # Since we don't have datastore with SSD on our current VMware machines, localvolumeset doesn't detect # NonRotational disk. As a workaround we are setting Rotational to device MechanicalProperties to detect # HDD disk if platform == constants.VSPHERE_PLATFORM or config.ENV_DATA.get( "local_storage_allow_rotational_disks"): logger.info("Adding Rotational for deviceMechanicalProperties spec" " to detect HDD disk") lvs_data["spec"]["deviceInclusionSpec"][ "deviceMechanicalProperties"].append("Rotational") # Update local volume set data with Worker node Names logger.info( "Updating LocalVolumeSet CR data with worker nodes Name: %s", worker_nodes) lvs_data["spec"]["nodeSelector"]["nodeSelectorTerms"][0][ "matchExpressions"][0]["values"] = worker_nodes # Set storage class logger.info( "Updating LocalVolumeSet CR data with LSO storageclass: %s", storageclass) lvs_data["spec"]["storageClassName"] = storageclass # set volumeMode to Filesystem for MCG only deployment if config.ENV_DATA["mcg_only_deployment"]: lvs_data["spec"]["volumeMode"] = constants.VOLUME_MODE_FILESYSTEM lvs_data_yaml = tempfile.NamedTemporaryFile(mode="w+", prefix="local_volume_set", delete=False) templating.dump_data_to_temp_yaml(lvs_data, lvs_data_yaml.name) logger.info("Creating LocalVolumeSet CR") run_cmd(f"oc create -f {lvs_data_yaml.name}") else: # Retrieve NVME device path ID for each worker node device_paths = get_device_paths(worker_names) # Pull local volume yaml data logger.info("Pulling LocalVolume CR data from yaml") lv_data = templating.load_yaml(constants.LOCAL_VOLUME_YAML) # Set local-volume namespace lv_data["metadata"]["namespace"] = lso_namespace # Set storage class logger.info("Updating LocalVolume CR data with LSO storageclass: %s", storageclass) for scd in lv_data["spec"]["storageClassDevices"]: scd["storageClassName"] = storageclass # Update local volume data with NVME IDs logger.info("Updating LocalVolume CR data with device paths: %s", device_paths) lv_data["spec"]["storageClassDevices"][0]["devicePaths"] = device_paths # Create temp yaml file and create local volume lv_data_yaml = tempfile.NamedTemporaryFile(mode="w+", prefix="local_volume", delete=False) templating.dump_data_to_temp_yaml(lv_data, lv_data_yaml.name) logger.info("Creating LocalVolume CR") run_cmd(f"oc create -f {lv_data_yaml.name}") logger.info("Waiting 30 seconds for PVs to create") storage_class_device_count = 1 if platform == constants.AWS_PLATFORM and not lso_type == constants.AWS_EBS: storage_class_device_count = 2 elif platform == constants.IBM_POWER_PLATFORM: numberofstoragedisks = config.ENV_DATA.get("number_of_storage_disks", 1) storage_class_device_count = numberofstoragedisks elif platform == constants.VSPHERE_PLATFORM: # extra_disks is used in vSphere attach_disk() method storage_class_device_count = config.ENV_DATA.get("extra_disks", 1) expected_pvs = len(worker_names) * storage_class_device_count verify_pvs_created(expected_pvs, storageclass)
def run_ocs_upgrade(operation=None, *operation_args, **operation_kwargs): """ Run upgrade procedure of OCS cluster Args: operation: (function): Function to run operation_args: (iterable): Function's arguments operation_kwargs: (map): Function's keyword arguments """ ceph_cluster = CephCluster() original_ocs_version = config.ENV_DATA.get("ocs_version") upgrade_in_current_source = config.UPGRADE.get("upgrade_in_current_source", False) upgrade_ocs = OCSUpgrade( namespace=config.ENV_DATA["cluster_namespace"], version_before_upgrade=original_ocs_version, ocs_registry_image=config.UPGRADE.get("upgrade_ocs_registry_image"), upgrade_in_current_source=upgrade_in_current_source, ) upgrade_version = upgrade_ocs.get_upgrade_version() assert ( upgrade_ocs.get_parsed_versions()[1] >= upgrade_ocs.get_parsed_versions()[0] ), ( f"Version you would like to upgrade to: {upgrade_version} " f"is not higher or equal to the version you currently running: " f"{upgrade_ocs.version_before_upgrade}" ) # For external cluster , create the secrets if upgraded version is 4.8 if ( config.DEPLOYMENT["external_mode"] and original_ocs_version == "4.7" and upgrade_version == "4.8" ): access_key = config.EXTERNAL_MODE.get("access_key_rgw-admin-ops-user", "") secret_key = config.EXTERNAL_MODE.get("secret_key_rgw-admin-ops-user", "") if not (access_key and secret_key): raise ExternalClusterRGWAdminOpsUserException( "Access and secret key for rgw-admin-ops-user not found" ) cmd = ( f'oc create secret generic --type="kubernetes.io/rook"' f' "rgw-admin-ops-user" --from-literal=accessKey={access_key} --from-literal=secretKey={secret_key}' ) exec_cmd(cmd) csv_name_pre_upgrade = upgrade_ocs.get_csv_name_pre_upgrade() pre_upgrade_images = upgrade_ocs.get_pre_upgrade_image(csv_name_pre_upgrade) upgrade_ocs.load_version_config_file(upgrade_version) if config.DEPLOYMENT.get("disconnected"): upgrade_ocs.ocs_registry_image = prepare_disconnected_ocs_deployment( upgrade=True ) log.info(f"Disconnected upgrade - new image: {upgrade_ocs.ocs_registry_image}") with CephHealthMonitor(ceph_cluster): channel = upgrade_ocs.set_upgrade_channel() upgrade_ocs.set_upgrade_images() ui_upgrade_supported = False if config.UPGRADE.get("ui_upgrade"): if ( version.get_semantic_ocp_version_from_config() == version.VERSION_4_9 and original_ocs_version == "4.8" and upgrade_version == "4.9" ): ui_upgrade_supported = True else: log.warning( "UI upgrade combination is not supported. It will fallback to CLI upgrade" ) if ui_upgrade_supported: ocs_odf_upgrade_ui() else: if upgrade_version != "4.9": # In the case of upgrade to ODF 4.9, the ODF operator should upgrade # OCS automatically. upgrade_ocs.update_subscription(channel) if original_ocs_version == "4.8" and upgrade_version == "4.9": deployment = Deployment() deployment.subscribe_ocs() else: # In the case upgrade is not from 4.8 to 4.9 and we have manual approval strategy # we need to wait and approve install plan, otherwise it's approved in the # subscribe_ocs method. subscription_plan_approval = config.DEPLOYMENT.get( "subscription_plan_approval" ) if subscription_plan_approval == "Manual": wait_for_install_plan_and_approve( config.ENV_DATA["cluster_namespace"] ) if (config.ENV_DATA["platform"] == constants.IBMCLOUD_PLATFORM) and not ( upgrade_in_current_source ): create_ocs_secret(config.ENV_DATA["cluster_namespace"]) for attempt in range(2): # We need to do it twice, because some of the SA are updated # after the first load of OCS pod after upgrade. So we need to # link updated SA again. log.info( f"Sleep 1 minute before attempt: {attempt + 1}/2 " "of linking secret/SAs" ) time.sleep(60) link_all_sa_and_secret_and_delete_pods( constants.OCS_SECRET, config.ENV_DATA["cluster_namespace"] ) if operation: log.info(f"Calling test function: {operation}") _ = operation(*operation_args, **operation_kwargs) # Workaround for issue #2531 time.sleep(30) # End of workaround for sample in TimeoutSampler( timeout=725, sleep=5, func=upgrade_ocs.check_if_upgrade_completed, channel=channel, csv_name_pre_upgrade=csv_name_pre_upgrade, ): try: if sample: log.info("Upgrade success!") break except TimeoutException: raise TimeoutException("No new CSV found after upgrade!") old_image = upgrade_ocs.get_images_post_upgrade( channel, pre_upgrade_images, upgrade_version ) verify_image_versions( old_image, upgrade_ocs.get_parsed_versions()[1], upgrade_ocs.version_before_upgrade, ) ocs_install_verification( timeout=600, skip_osd_distribution_check=True, ocs_registry_image=upgrade_ocs.ocs_registry_image, post_upgrade_verification=True, version_before_upgrade=upgrade_ocs.version_before_upgrade, )
def run_ocs_upgrade(operation=None, *operation_args, **operation_kwargs): """ Run upgrade procedure of OCS cluster Args: operation: (function): Function to run operation_args: (iterable): Function's arguments operation_kwargs: (map): Function's keyword arguments """ ceph_cluster = CephCluster() original_ocs_version = config.ENV_DATA.get("ocs_version") upgrade_in_current_source = config.UPGRADE.get("upgrade_in_current_source", False) upgrade_ocs = OCSUpgrade( namespace=config.ENV_DATA["cluster_namespace"], version_before_upgrade=original_ocs_version, ocs_registry_image=config.UPGRADE.get("upgrade_ocs_registry_image"), upgrade_in_current_source=upgrade_in_current_source, ) upgrade_version = upgrade_ocs.get_upgrade_version() assert ( upgrade_ocs.get_parsed_versions()[1] >= upgrade_ocs.get_parsed_versions()[0]), ( f"Version you would like to upgrade to: {upgrade_version} " f"is not higher or equal to the version you currently running: " f"{upgrade_ocs.version_before_upgrade}") # create external cluster object if config.DEPLOYMENT["external_mode"]: host, user, password = get_external_cluster_client() external_cluster = ExternalCluster(host, user, password) # For external cluster , create the secrets if upgraded version is 4.8 if (config.DEPLOYMENT["external_mode"] and original_ocs_version == "4.7" and upgrade_version == "4.8"): external_cluster.create_object_store_user() access_key = config.EXTERNAL_MODE.get("access_key_rgw-admin-ops-user", "") secret_key = config.EXTERNAL_MODE.get("secret_key_rgw-admin-ops-user", "") if not (access_key and secret_key): raise ExternalClusterRGWAdminOpsUserException( "Access and secret key for rgw-admin-ops-user not found") cmd = ( f'oc create secret generic --type="kubernetes.io/rook"' f' "rgw-admin-ops-user" --from-literal=accessKey={access_key} --from-literal=secretKey={secret_key}' ) exec_cmd(cmd) csv_name_pre_upgrade = upgrade_ocs.get_csv_name_pre_upgrade() pre_upgrade_images = upgrade_ocs.get_pre_upgrade_image( csv_name_pre_upgrade) upgrade_ocs.load_version_config_file(upgrade_version) if config.DEPLOYMENT.get("disconnected") and not config.DEPLOYMENT.get( "disconnected_env_skip_image_mirroring"): upgrade_ocs.ocs_registry_image = prepare_disconnected_ocs_deployment( upgrade=True) log.info( f"Disconnected upgrade - new image: {upgrade_ocs.ocs_registry_image}" ) with CephHealthMonitor(ceph_cluster): channel = upgrade_ocs.set_upgrade_channel() upgrade_ocs.set_upgrade_images() live_deployment = config.DEPLOYMENT["live_deployment"] disable_addon = config.DEPLOYMENT.get("ibmcloud_disable_addon") if (config.ENV_DATA["platform"] == constants.IBMCLOUD_PLATFORM and live_deployment and not disable_addon): clustername = config.ENV_DATA.get("cluster_name") cmd = f"ibmcloud ks cluster addon disable openshift-data-foundation --cluster {clustername} -f" run_ibmcloud_cmd(cmd) time.sleep(120) cmd = ( f"ibmcloud ks cluster addon enable openshift-data-foundation --cluster {clustername} -f --version " f"{upgrade_version}.0 --param ocsUpgrade=true") run_ibmcloud_cmd(cmd) time.sleep(120) else: ui_upgrade_supported = False if config.UPGRADE.get("ui_upgrade"): if (version.get_semantic_ocp_version_from_config() == version.VERSION_4_9 and original_ocs_version == "4.8" and upgrade_version == "4.9"): ui_upgrade_supported = True else: log.warning( "UI upgrade combination is not supported. It will fallback to CLI upgrade" ) if ui_upgrade_supported: ocs_odf_upgrade_ui() else: if (config.ENV_DATA["platform"] == constants.IBMCLOUD_PLATFORM ) and not (upgrade_in_current_source): create_ocs_secret(config.ENV_DATA["cluster_namespace"]) if upgrade_version != "4.9": # In the case of upgrade to ODF 4.9, the ODF operator should upgrade # OCS automatically. upgrade_ocs.update_subscription(channel) if original_ocs_version == "4.8" and upgrade_version == "4.9": deployment = Deployment() deployment.subscribe_ocs() else: # In the case upgrade is not from 4.8 to 4.9 and we have manual approval strategy # we need to wait and approve install plan, otherwise it's approved in the # subscribe_ocs method. subscription_plan_approval = config.DEPLOYMENT.get( "subscription_plan_approval") if subscription_plan_approval == "Manual": wait_for_install_plan_and_approve( config.ENV_DATA["cluster_namespace"]) if (config.ENV_DATA["platform"] == constants.IBMCLOUD_PLATFORM ) and not (upgrade_in_current_source): for attempt in range(2): # We need to do it twice, because some of the SA are updated # after the first load of OCS pod after upgrade. So we need to # link updated SA again. log.info( f"Sleep 1 minute before attempt: {attempt + 1}/2 " "of linking secret/SAs") time.sleep(60) link_all_sa_and_secret_and_delete_pods( constants.OCS_SECRET, config.ENV_DATA["cluster_namespace"]) if operation: log.info(f"Calling test function: {operation}") _ = operation(*operation_args, **operation_kwargs) # Workaround for issue #2531 time.sleep(30) # End of workaround for sample in TimeoutSampler( timeout=725, sleep=5, func=upgrade_ocs.check_if_upgrade_completed, channel=channel, csv_name_pre_upgrade=csv_name_pre_upgrade, ): try: if sample: log.info("Upgrade success!") break except TimeoutException: raise TimeoutException("No new CSV found after upgrade!") old_image = upgrade_ocs.get_images_post_upgrade( channel, pre_upgrade_images, upgrade_version) verify_image_versions( old_image, upgrade_ocs.get_parsed_versions()[1], upgrade_ocs.version_before_upgrade, ) # update external secrets if config.DEPLOYMENT["external_mode"]: upgrade_version = version.get_semantic_version(upgrade_version, True) if upgrade_version >= version.VERSION_4_10: external_cluster.update_permission_caps() else: external_cluster.update_permission_caps(EXTERNAL_CLUSTER_USER) external_cluster.get_external_cluster_details() # update the external cluster details in secrets log.info("updating external cluster secret") external_cluster_details = NamedTemporaryFile( mode="w+", prefix="external-cluster-details-", delete=False, ) with open(external_cluster_details.name, "w") as fd: decoded_external_cluster_details = decode( config.EXTERNAL_MODE["external_cluster_details"]) fd.write(decoded_external_cluster_details) cmd = ( f"oc set data secret/rook-ceph-external-cluster-details -n {constants.OPENSHIFT_STORAGE_NAMESPACE} " f"--from-file=external_cluster_details={external_cluster_details.name}" ) exec_cmd(cmd) if config.ENV_DATA.get("mcg_only_deployment"): mcg_only_install_verification( ocs_registry_image=upgrade_ocs.ocs_registry_image) else: ocs_install_verification( timeout=600, skip_osd_distribution_check=True, ocs_registry_image=upgrade_ocs.ocs_registry_image, post_upgrade_verification=True, version_before_upgrade=upgrade_ocs.version_before_upgrade, )
def modify_scaleup_repo(self): """ Modify the scale-up repo. Considering the user experience, removing the access and secret keys and variable from appropriate location in the scale-up repo """ # importing here to avoid circular dependancy from ocs_ci.deployment.vmware import change_vm_root_disk_size if self.folder_structure: logger.info("Modifying scaleup repo for folder structure") # modify default_map.yaml default_map_path = os.path.join( constants.CLUSTER_LAUNCHER_VSPHERE_DIR, f"aos-{self.ocp_version}", "default_map.yaml", ) dict_data = load_yaml(default_map_path) dict_data["cluster_domain"] = config.ENV_DATA["base_domain"] dict_data["vsphere"]["vcsa-qe"]["datacenter"] = config.ENV_DATA[ "vsphere_datacenter"] dict_data["vsphere"]["vcsa-qe"]["datastore"] = config.ENV_DATA[ "vsphere_datastore"] dict_data["vsphere"]["vcsa-qe"]["network"] = config.ENV_DATA[ "vm_network"] dict_data["vsphere"]["vcsa-qe"]["cpus"] = config.ENV_DATA[ "rhel_num_cpus"] dict_data["vsphere"]["vcsa-qe"]["memory"] = config.ENV_DATA[ "rhel_memory"] dict_data["vsphere"]["vcsa-qe"][ "root_volume_size"] = config.ENV_DATA.get( "root_disk_size", "120") if version.get_semantic_ocp_version_from_config( ) >= version.VERSION_4_9: dict_data["vsphere"]["vcsa-qe"]["image_7"] = config.ENV_DATA[ "rhel_template"] else: dict_data["vsphere"]["vcsa-qe"]["image"] = config.ENV_DATA[ "rhel_template"] dump_data_to_temp_yaml(dict_data, default_map_path) else: # remove access and secret key from constants.SCALEUP_VSPHERE_MAIN access_key = 'access_key = "${var.aws_access_key}"' secret_key = 'secret_key = "${var.aws_secret_key}"' replace_content_in_file(constants.SCALEUP_VSPHERE_MAIN, f"{access_key}", " ") replace_content_in_file(constants.SCALEUP_VSPHERE_MAIN, f"{secret_key}", " ") # remove access and secret key from constants.SCALEUP_VSPHERE_ROUTE53 route53_access_key = 'access_key = "${var.access_key}"' route53_secret_key = 'secret_key = "${var.secret_key}"' replace_content_in_file(constants.SCALEUP_VSPHERE_ROUTE53, f"{route53_access_key}", " ") replace_content_in_file(constants.SCALEUP_VSPHERE_ROUTE53, f"{route53_secret_key}", " ") replace_content_in_file( constants.SCALEUP_VSPHERE_ROUTE53, "us-east-1", f"{config.ENV_DATA.get('region')}", ) # remove access and secret variables from scale-up repo remove_keys_from_tf_variable_file( constants.SCALEUP_VSPHERE_VARIABLES, ["aws_access_key", "aws_secret_key"], ) remove_keys_from_tf_variable_file( constants.SCALEUP_VSPHERE_ROUTE53_VARIABLES, ["access_key", "secret_key"], ) # change root disk size change_vm_root_disk_size(constants.SCALEUP_VSPHERE_MACHINE_CONF)
def deploy_ocs_via_operator(self, image=None): """ Method for deploy OCS via OCS operator Args: image (str): Image of ocs registry. """ ui_deployment = config.DEPLOYMENT.get("ui_deployment") live_deployment = config.DEPLOYMENT.get("live_deployment") arbiter_deployment = config.DEPLOYMENT.get("arbiter_deployment") if ui_deployment and ui_deployment_conditions(): self.deployment_with_ui() # Skip the rest of the deployment when deploy via UI return else: logger.info("Deployment of OCS via OCS operator") self.label_and_taint_nodes() if config.DEPLOYMENT.get("local_storage"): setup_local_storage(storageclass=self.DEFAULT_STORAGECLASS_LSO) logger.info("Creating namespace and operator group.") run_cmd(f"oc create -f {constants.OLM_YAML}") # create multus network if config.ENV_DATA.get("is_multus_enabled"): logger.info("Creating multus network") multus_data = templating.load_yaml(constants.MULTUS_YAML) multus_config_str = multus_data["spec"]["config"] multus_config_dct = json.loads(multus_config_str) if config.ENV_DATA.get("multus_public_network_interface"): multus_config_dct["master"] = config.ENV_DATA.get( "multus_public_network_interface" ) multus_data["spec"]["config"] = json.dumps(multus_config_dct) multus_data_yaml = tempfile.NamedTemporaryFile( mode="w+", prefix="multus", delete=False ) templating.dump_data_to_temp_yaml(multus_data, multus_data_yaml.name) run_cmd(f"oc create -f {multus_data_yaml.name}") if config.ENV_DATA["platform"] == constants.IBMCLOUD_PLATFORM: ibmcloud.add_deployment_dependencies() if not live_deployment: create_ocs_secret(self.namespace) if not live_deployment: create_catalog_source(image) self.subscribe_ocs() operator_selector = get_selector_for_ocs_operator() subscription_plan_approval = config.DEPLOYMENT.get("subscription_plan_approval") ocs_version = version.get_semantic_ocs_version_from_config() if ocs_version >= version.VERSION_4_9: ocs_operator_names = [ defaults.ODF_OPERATOR_NAME, defaults.OCS_OPERATOR_NAME, defaults.NOOBAA_OPERATOR, ] else: ocs_operator_names = [defaults.OCS_OPERATOR_NAME] channel = config.DEPLOYMENT.get("ocs_csv_channel") is_ibm_sa_linked = False for ocs_operator_name in ocs_operator_names: package_manifest = PackageManifest( resource_name=ocs_operator_name, selector=operator_selector, subscription_plan_approval=subscription_plan_approval, ) package_manifest.wait_for_resource(timeout=300) csv_name = package_manifest.get_current_csv(channel=channel) csv = CSV(resource_name=csv_name, namespace=self.namespace) if ( config.ENV_DATA["platform"] == constants.IBMCLOUD_PLATFORM and not live_deployment ): if not is_ibm_sa_linked: logger.info("Sleeping for 60 seconds before applying SA") time.sleep(60) link_all_sa_and_secret_and_delete_pods( constants.OCS_SECRET, self.namespace ) is_ibm_sa_linked = True csv.wait_for_phase("Succeeded", timeout=720) ocp_version = version.get_semantic_ocp_version_from_config() if config.ENV_DATA["platform"] == constants.IBMCLOUD_PLATFORM: config_map = ocp.OCP( kind="configmap", namespace=self.namespace, resource_name=constants.ROOK_OPERATOR_CONFIGMAP, ) config_map.get(retry=10, wait=5) config_map_patch = ( '\'{"data": {"ROOK_CSI_KUBELET_DIR_PATH": "/var/data/kubelet"}}\'' ) logger.info("Patching config map to change KUBLET DIR PATH") exec_cmd( f"oc patch configmap -n {self.namespace} " f"{constants.ROOK_OPERATOR_CONFIGMAP} -p {config_map_patch}" ) if config.DEPLOYMENT.get("create_ibm_cos_secret", True): logger.info("Creating secret for IBM Cloud Object Storage") with open(constants.IBM_COS_SECRET_YAML, "r") as cos_secret_fd: cos_secret_data = yaml.load(cos_secret_fd, Loader=yaml.SafeLoader) key_id = config.AUTH["ibmcloud"]["ibm_cos_access_key_id"] key_secret = config.AUTH["ibmcloud"]["ibm_cos_secret_access_key"] cos_secret_data["data"]["IBM_COS_ACCESS_KEY_ID"] = key_id cos_secret_data["data"]["IBM_COS_SECRET_ACCESS_KEY"] = key_secret cos_secret_data_yaml = tempfile.NamedTemporaryFile( mode="w+", prefix="cos_secret", delete=False ) templating.dump_data_to_temp_yaml( cos_secret_data, cos_secret_data_yaml.name ) exec_cmd(f"oc create -f {cos_secret_data_yaml.name}") # Modify the CSV with custom values if required if all( key in config.DEPLOYMENT for key in ("csv_change_from", "csv_change_to") ): modify_csv( csv=csv_name, replace_from=config.DEPLOYMENT["csv_change_from"], replace_to=config.DEPLOYMENT["csv_change_to"], ) # create custom storage class for StorageCluster CR if necessary if self.CUSTOM_STORAGE_CLASS_PATH is not None: with open(self.CUSTOM_STORAGE_CLASS_PATH, "r") as custom_sc_fo: custom_sc = yaml.load(custom_sc_fo, Loader=yaml.SafeLoader) # set value of DEFAULT_STORAGECLASS to mach the custom storage cls self.DEFAULT_STORAGECLASS = custom_sc["metadata"]["name"] run_cmd(f"oc create -f {self.CUSTOM_STORAGE_CLASS_PATH}") # create storage system if ocs_version >= version.VERSION_4_9: exec_cmd(f"oc create -f {constants.STORAGE_SYSTEM_ODF_YAML}") # Set rook log level self.set_rook_log_level() # creating StorageCluster if config.DEPLOYMENT.get("kms_deployment"): kms = KMS.get_kms_deployment() kms.deploy() cluster_data = templating.load_yaml(constants.STORAGE_CLUSTER_YAML) # Figure out all the OCS modules enabled/disabled # CLI parameter --disable-components takes the precedence over # anything which comes from config file if config.ENV_DATA.get("disable_components"): for component in config.ENV_DATA["disable_components"]: config.COMPONENTS[f"disable_{component}"] = True logger.warning(f"disabling: {component}") # Update cluster_data with respective component enable/disable for key in config.COMPONENTS.keys(): comp_name = constants.OCS_COMPONENTS_MAP[key.split("_")[1]] if config.COMPONENTS[key]: if "noobaa" in key: merge_dict( cluster_data, { "spec": { "multiCloudGateway": {"reconcileStrategy": "ignore"} } }, ) else: merge_dict( cluster_data, { "spec": { "managedResources": { f"{comp_name}": {"reconcileStrategy": "ignore"} } } }, ) if arbiter_deployment: cluster_data["spec"]["arbiter"] = {} cluster_data["spec"]["nodeTopologies"] = {} cluster_data["spec"]["arbiter"]["enable"] = True cluster_data["spec"]["nodeTopologies"][ "arbiterLocation" ] = self.get_arbiter_location() cluster_data["spec"]["storageDeviceSets"][0]["replica"] = 4 cluster_data["metadata"]["name"] = config.ENV_DATA["storage_cluster_name"] deviceset_data = cluster_data["spec"]["storageDeviceSets"][0] device_size = int(config.ENV_DATA.get("device_size", defaults.DEVICE_SIZE)) logger.info( "Flexible scaling is available from version 4.7 on LSO cluster with less than 3 zones" ) zone_num = get_az_count() if ( config.DEPLOYMENT.get("local_storage") and ocs_version >= version.VERSION_4_7 and zone_num < 3 and not config.DEPLOYMENT.get("arbiter_deployment") ): cluster_data["spec"]["flexibleScaling"] = True # https://bugzilla.redhat.com/show_bug.cgi?id=1921023 cluster_data["spec"]["storageDeviceSets"][0]["count"] = 3 cluster_data["spec"]["storageDeviceSets"][0]["replica"] = 1 # set size of request for storage if self.platform.lower() == constants.BAREMETAL_PLATFORM: pv_size_list = helpers.get_pv_size( storageclass=self.DEFAULT_STORAGECLASS_LSO ) pv_size_list.sort() deviceset_data["dataPVCTemplate"]["spec"]["resources"]["requests"][ "storage" ] = f"{pv_size_list[0]}" else: deviceset_data["dataPVCTemplate"]["spec"]["resources"]["requests"][ "storage" ] = f"{device_size}Gi" # set storage class to OCS default on current platform if self.DEFAULT_STORAGECLASS: deviceset_data["dataPVCTemplate"]["spec"][ "storageClassName" ] = self.DEFAULT_STORAGECLASS # StorageCluster tweaks for LSO if config.DEPLOYMENT.get("local_storage"): cluster_data["spec"]["manageNodes"] = False cluster_data["spec"]["monDataDirHostPath"] = "/var/lib/rook" deviceset_data["name"] = constants.DEFAULT_DEVICESET_LSO_PVC_NAME deviceset_data["portable"] = False deviceset_data["dataPVCTemplate"]["spec"][ "storageClassName" ] = self.DEFAULT_STORAGECLASS_LSO lso_type = config.DEPLOYMENT.get("type") if ( self.platform.lower() == constants.AWS_PLATFORM and not lso_type == constants.AWS_EBS ): deviceset_data["count"] = 2 # setting resource limits for AWS i3 # https://access.redhat.com/documentation/en-us/red_hat_openshift_container_storage/4.6/html-single/deploying_openshift_container_storage_using_amazon_web_services/index#creating-openshift-container-storage-cluster-on-amazon-ec2_local-storage if ( ocs_version >= version.VERSION_4_5 and config.ENV_DATA.get("worker_instance_type") == constants.AWS_LSO_WORKER_INSTANCE ): deviceset_data["resources"] = { "limits": {"cpu": 2, "memory": "5Gi"}, "requests": {"cpu": 1, "memory": "5Gi"}, } if (ocp_version >= version.VERSION_4_6) and ( ocs_version >= version.VERSION_4_6 ): cluster_data["metadata"]["annotations"] = { "cluster.ocs.openshift.io/local-devices": "true" } count = config.DEPLOYMENT.get("local_storage_storagedeviceset_count") if count is not None: deviceset_data["count"] = count # Allow lower instance requests and limits for OCS deployment # The resources we need to change can be found here: # https://github.com/openshift/ocs-operator/blob/release-4.5/pkg/deploy-manager/storagecluster.go#L88-L116 if config.DEPLOYMENT.get("allow_lower_instance_requirements"): none_resources = {"Requests": None, "Limits": None} deviceset_data["resources"] = deepcopy(none_resources) resources = [ "mon", "mds", "rgw", "mgr", "noobaa-core", "noobaa-db", ] if ocs_version >= version.VERSION_4_5: resources.append("noobaa-endpoint") cluster_data["spec"]["resources"] = { resource: deepcopy(none_resources) for resource in resources } if ocs_version >= version.VERSION_4_5: cluster_data["spec"]["resources"]["noobaa-endpoint"] = { "limits": {"cpu": "100m", "memory": "100Mi"}, "requests": {"cpu": "100m", "memory": "100Mi"}, } else: local_storage = config.DEPLOYMENT.get("local_storage") platform = config.ENV_DATA.get("platform", "").lower() if local_storage and platform == "aws": resources = { "mds": { "limits": {"cpu": 3, "memory": "8Gi"}, "requests": {"cpu": 1, "memory": "8Gi"}, } } if ocs_version < version.VERSION_4_5: resources["noobaa-core"] = { "limits": {"cpu": 2, "memory": "8Gi"}, "requests": {"cpu": 1, "memory": "8Gi"}, } resources["noobaa-db"] = { "limits": {"cpu": 2, "memory": "8Gi"}, "requests": {"cpu": 1, "memory": "8Gi"}, } cluster_data["spec"]["resources"] = resources # Enable host network if enabled in config (this require all the # rules to be enabled on underlaying platform). if config.DEPLOYMENT.get("host_network"): cluster_data["spec"]["hostNetwork"] = True cluster_data["spec"]["storageDeviceSets"] = [deviceset_data] if self.platform == constants.IBMCLOUD_PLATFORM: mon_pvc_template = { "spec": { "accessModes": ["ReadWriteOnce"], "resources": {"requests": {"storage": "20Gi"}}, "storageClassName": self.DEFAULT_STORAGECLASS, "volumeMode": "Filesystem", } } cluster_data["spec"]["monPVCTemplate"] = mon_pvc_template # Need to check if it's needed for ibm cloud to set manageNodes cluster_data["spec"]["manageNodes"] = False if config.ENV_DATA.get("encryption_at_rest"): if ocs_version < version.VERSION_4_6: error_message = "Encryption at REST can be enabled only on OCS >= 4.6!" logger.error(error_message) raise UnsupportedFeatureError(error_message) logger.info("Enabling encryption at REST!") cluster_data["spec"]["encryption"] = { "enable": True, } if config.DEPLOYMENT.get("kms_deployment"): cluster_data["spec"]["encryption"]["kms"] = { "enable": True, } if config.DEPLOYMENT.get("ceph_debug"): setup_ceph_debug() cluster_data["spec"]["managedResources"] = { "cephConfig": {"reconcileStrategy": "ignore"} } if config.ENV_DATA.get("is_multus_enabled"): cluster_data["spec"]["network"] = { "provider": "multus", "selectors": { "public": f"{defaults.ROOK_CLUSTER_NAMESPACE}/ocs-public" }, } cluster_data_yaml = tempfile.NamedTemporaryFile( mode="w+", prefix="cluster_storage", delete=False ) templating.dump_data_to_temp_yaml(cluster_data, cluster_data_yaml.name) run_cmd(f"oc create -f {cluster_data_yaml.name}", timeout=1200) if config.DEPLOYMENT["infra_nodes"]: _ocp = ocp.OCP(kind="node") _ocp.exec_oc_cmd( command=f"annotate namespace {defaults.ROOK_CLUSTER_NAMESPACE} " f"{constants.NODE_SELECTOR_ANNOTATION}" )
def create_catalog_source(image=None, ignore_upgrade=False): """ This prepare catalog source manifest for deploy OCS operator from quay registry. Args: image (str): Image of ocs registry. ignore_upgrade (bool): Ignore upgrade parameter. """ logger.info("Adding CatalogSource") if not image: image = config.DEPLOYMENT.get("ocs_registry_image", "") if config.DEPLOYMENT.get("stage_rh_osbs"): image = config.DEPLOYMENT.get("stage_index_image", constants.OSBS_BOUNDLE_IMAGE) ocp_version = version.get_semantic_ocp_version_from_config() osbs_image_tag = config.DEPLOYMENT.get( "stage_index_image_tag", f"v{ocp_version}" ) image += f":{osbs_image_tag}" run_cmd( "oc patch image.config.openshift.io/cluster --type merge -p '" '{"spec": {"registrySources": {"insecureRegistries": ' '["registry-proxy.engineering.redhat.com"]}}}\'' ) run_cmd(f"oc apply -f {constants.STAGE_IMAGE_CONTENT_SOURCE_POLICY_YAML}") logger.info("Sleeping for 60 sec to start update machineconfigpool status") time.sleep(60) wait_for_machineconfigpool_status("all", timeout=1800) if not ignore_upgrade: upgrade = config.UPGRADE.get("upgrade", False) else: upgrade = False image_and_tag = image.rsplit(":", 1) image = image_and_tag[0] image_tag = image_and_tag[1] if len(image_and_tag) == 2 else None if not image_tag and config.REPORTING.get("us_ds") == "DS": image_tag = get_latest_ds_olm_tag( upgrade, latest_tag=config.DEPLOYMENT.get("default_latest_tag", "latest") ) catalog_source_data = templating.load_yaml(constants.CATALOG_SOURCE_YAML) if config.ENV_DATA["platform"] == constants.IBMCLOUD_PLATFORM: create_ocs_secret(constants.MARKETPLACE_NAMESPACE) catalog_source_data["spec"]["secrets"] = [constants.OCS_SECRET] cs_name = constants.OPERATOR_CATALOG_SOURCE_NAME change_cs_condition = ( (image or image_tag) and catalog_source_data["kind"] == "CatalogSource" and catalog_source_data["metadata"]["name"] == cs_name ) if change_cs_condition: default_image = config.DEPLOYMENT["default_ocs_registry_image"] image = image if image else default_image.rsplit(":", 1)[0] catalog_source_data["spec"][ "image" ] = f"{image}:{image_tag if image_tag else 'latest'}" catalog_source_manifest = tempfile.NamedTemporaryFile( mode="w+", prefix="catalog_source_manifest", delete=False ) templating.dump_data_to_temp_yaml(catalog_source_data, catalog_source_manifest.name) run_cmd(f"oc apply -f {catalog_source_manifest.name}", timeout=2400) catalog_source = CatalogSource( resource_name=constants.OPERATOR_CATALOG_SOURCE_NAME, namespace=constants.MARKETPLACE_NAMESPACE, ) # Wait for catalog source is ready catalog_source.wait_for_state("READY")