Пример #1
0
 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"
Пример #2
0
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}")
Пример #3
0
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}")
Пример #4
0
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()
Пример #5
0
    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
            )
Пример #6
0
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
Пример #7
0
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
Пример #10
0
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
Пример #11
0
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)
Пример #12
0
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,
    )
Пример #13
0
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,
        )
Пример #14
0
    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)
Пример #15
0
    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}"
            )
Пример #16
0
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")