Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rosa hcp deployment #10421

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion conf/deployment/aws/rosa_hcp_1az_3w_m5.12x.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
DEPLOYMENT:
allow_lower_instance_requirements: false
sts_enabled: true
force_download_ocm_cli: true
force_download_rosa_cli: true
ocm_cli_version: '0.1.67'
rosa_cli_version: '1.2.44'
RUN:
username: 'cluster-admin'
ENV_DATA:
platform: 'rosa_hcp'
deployment_type: 'managed'
rosa_mode: "auto"
region: 'us-west-2'
worker_availability_zones:
- 'us-west-2a'
worker_replicas: 3
worker_instance_type: 'm5.12xlarge'
cluster_namespace: "odf-storage"
private_link: false
machine_cidr: "10.0.0.0/16"
ms_env_type: "staging"
23 changes: 23 additions & 0 deletions ocs_ci/deployment/deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -1045,6 +1045,20 @@ def deploy_ocs_via_operator(self, image=None):
setup_local_storage(storageclass=self.DEFAULT_STORAGECLASS_LSO)

logger.info("Creating namespace and operator group.")
# patch OLM YAML with the namespace
olm_ns_op_group_data = list(templating.load_yaml(constants.OLM_YAML, True))

if self.namespace != constants.OPENSHIFT_STORAGE_NAMESPACE:

for cr in olm_ns_op_group_data:
if cr["kind"] == "Namespace":
cr["metadata"]["name"] = self.namespace
elif cr["kind"] == "OperatorGroup":
cr["metadata"]["namespace"] = self.namespace
cr["spec"]["targetNamespaces"] = [self.namespace]

templating.dump_data_to_temp_yaml(olm_ns_op_group_data, constants.OLM_YAML)

run_cmd(f"oc create -f {constants.OLM_YAML}")

# Create Multus Networks
Expand Down Expand Up @@ -1210,8 +1224,16 @@ def deploy_ocs_via_operator(self, image=None):
replace_to=config.DEPLOYMENT["csv_change_to"],
)

# change namespace of storage system if needed
storage_system_data = templating.load_yaml(constants.STORAGE_SYSTEM_ODF_YAML)
storage_system_data["metadata"]["namespace"] = self.namespace
storage_system_data["spec"]["namespace"] = self.namespace

# create storage system
if ocs_version >= version.VERSION_4_9:
templating.dump_data_to_temp_yaml(
storage_system_data, constants.STORAGE_SYSTEM_ODF_YAML
)
exec_cmd(f"oc apply -f {constants.STORAGE_SYSTEM_ODF_YAML}")

ocp_version = version.get_semantic_ocp_version_from_config()
Expand Down Expand Up @@ -1296,6 +1318,7 @@ def deploy_ocs_via_operator(self, image=None):
cluster_data["spec"]["storageDeviceSets"][0]["replica"] = 4

cluster_data["metadata"]["name"] = config.ENV_DATA["storage_cluster_name"]
cluster_data["metadata"]["namespace"] = self.namespace

deviceset_data = cluster_data["spec"]["storageDeviceSets"][0]
device_size = int(config.ENV_DATA.get("device_size", defaults.DEVICE_SIZE))
Expand Down
3 changes: 2 additions & 1 deletion ocs_ci/deployment/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,11 @@ def __init__(self):
from .openshift_dedicated import OpenshiftDedicated

self.cls_map["openshiftdedicated_managed"] = OpenshiftDedicated
elif self.deployment_platform == constants.ROSA_PLATFORM:
elif self.deployment_platform in constants.ROSA_PLATFORMS:
from .rosa import ROSA

self.cls_map["rosa_managed"] = ROSA
self.cls_map["rosa_hcp_ipi"] = ROSA
elif self.deployment_platform == constants.FUSIONAAS_PLATFORM:
from .fusion_aas import FUSIONAAS

Expand Down
1 change: 1 addition & 0 deletions ocs_ci/deployment/ocp.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ def deploy_prereq(self):
if (
not self.flexy_deployment
and config.ENV_DATA["deployment_type"] != "managed"
and config.ENV_DATA.get("platform") != "rosa_hcp"
):
self.create_config()

Expand Down
6 changes: 5 additions & 1 deletion ocs_ci/deployment/rosa.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,11 @@ def deploy_ocs(self):
return
except (IndexError, CommandFailed):
logger.info("Running OCS basic installation")
rosa.install_odf_addon(self.cluster_name)

# rosa hp is self-managed and doesn't support ODF addon
if config.ENV_DATA.get("platform") != "rosa_hcp":
rosa.install_odf_addon(self.cluster_name)

pod = ocp.OCP(kind=constants.POD, namespace=self.namespace)

if config.ENV_DATA.get("cluster_type") != "consumer":
Expand Down
1 change: 1 addition & 0 deletions ocs_ci/ocs/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -1403,6 +1403,7 @@
ROSA_PLATFORM = "rosa"
FUSIONAAS_PLATFORM = "fusion_aas"
ROSA_HCP_PLATFORM = "rosa_hcp"
ROSA_PLATFORMS = [ROSA_PLATFORM, ROSA_HCP_PLATFORM]
HCI_BAREMETAL = "hci_baremetal"
HCI_VSPHERE = "hci_vsphere"
ACM_OCP_DEPLOYMENT = "acm_ocp_deployment"
Expand Down
141 changes: 136 additions & 5 deletions ocs_ci/utility/rosa.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
generate_onboarding_token,
get_storage_provider_endpoint,
)
from ocs_ci.utility.utils import exec_cmd, TimeoutSampler

logger = logging.getLogger(name=__file__)
rosa = config.AUTH.get("rosa", {})
rosa_hcp = config.ENV_DATA.get("platform") == "rosa_hcp"


def login():
Expand Down Expand Up @@ -66,6 +68,10 @@ def create_cluster(cluster_name, version, region):
logger.info(f"Using OCP version {rosa_ocp_version}")

create_account_roles()
oidc_config_id = None
if rosa_hcp:
oidc_config_id = create_oidc_config()

compute_nodes = config.ENV_DATA["worker_replicas"]
compute_machine_type = config.ENV_DATA["worker_instance_type"]
multi_az = "--multi-az " if config.ENV_DATA.get("multi_availability_zones") else ""
Expand All @@ -75,12 +81,18 @@ def create_cluster(cluster_name, version, region):
subnet_section_name = "ms_subnet_ids_per_region_" + config.ENV_DATA.get(
"subnet_type", "default"
)
if rosa_hcp:
# For ROSA HCP we have only one subnet id's pair. Hence we can use default subnet id's.
subnet_section_name = "rosahcp_subnet_ids_per_region_default"
cmd = (
f"rosa create cluster --cluster-name {cluster_name} --region {region} "
f"--machine-cidr {machine_cidr} --replicas {compute_nodes} "
f"--compute-machine-type {compute_machine_type} "
f"--version {rosa_ocp_version} {multi_az}--sts --yes"
)

if oidc_config_id:
cmd += f" --oidc-config-id {oidc_config_id}"
if rosa_mode == "auto":
cmd += " --mode auto"

Expand All @@ -92,6 +104,17 @@ def create_cluster(cluster_name, version, region):
# if parameters are not defined then existing byo-vpc will be used
if config.ENV_DATA.get("subnet_ids", ""):
subnet_ids = config.ENV_DATA.get("subnet_ids")
elif rosa_hcp:
# we have only one subnet id's pair, for ROSA HCP we need a pair of public and private subnet-ids
# ROSA CLI identifies public vs. private subnets based on routing
# in future we may want to change indexes and pick-up approach
public_subnet = config.ENV_DATA["rosahcp_subnet_ids_per_region_default"][
"us-west-2"
]["public_subnet"].split(",")[0]
private_subnet = config.ENV_DATA["rosahcp_subnet_ids_per_region_default"][
"us-west-2"
]["private_subnet"].split(",")[0]
subnet_ids = f"{public_subnet},{private_subnet}"
elif config.ENV_DATA.get("vpc_name", ""):
aws = AWSUtil()
subnet_ids = ",".join(
Expand All @@ -109,8 +132,15 @@ def create_cluster(cluster_name, version, region):

if private_link:
cmd += " --private-link "

if rosa_hcp:
# with rosa hcp we need operator roles to be created before cluster creation
prefix = f"operatorRoles{cluster_name}"
create_operator_roles(cluster_name, prefix)
cmd += f" --operator-roles-prefix {prefix} "

utils.run_cmd(cmd, timeout=1200)
if rosa_mode != "auto":
if rosa_mode != "auto" and not rosa_hcp:
logger.info(
"Waiting for ROSA cluster status changed to waiting or pending state"
)
Expand Down Expand Up @@ -343,20 +373,29 @@ def create_account_roles(prefix="ManagedOpenShift"):
prefix (str): role prefix

"""
cmd = f"rosa create account-roles --mode auto" f" --prefix {prefix} --yes"
if config.ENV_DATA.get("platform") == "rosa_hcp":
prefix = "RosaHCP"
hosted_cp_param = "--hosted-cp"
else:
hosted_cp_param = ""

cmd = f"rosa create account-roles {hosted_cp_param} --mode auto --prefix {prefix} --yes"
utils.run_cmd(cmd, timeout=1200)


def create_operator_roles(cluster):
def create_operator_roles(cluster, prefix=""):
"""
Create the cluster-specific Operator IAM roles. The roles created include the
relevant prefix for the cluster name

Args:
cluster (str): cluster name or cluster id

prefix (str): role prefix
"""
cmd = f"rosa create operator-roles --cluster {cluster}" f" --mode auto --yes"

cmd = f"rosa create operator-roles --cluster {cluster} --mode auto --yes"
if prefix:
cmd += f" --prefix {prefix}"
utils.run_cmd(cmd, timeout=1200)


Expand All @@ -373,6 +412,98 @@ def create_oidc_provider(cluster):
utils.run_cmd(cmd, timeout=1200)


def create_oidc_config():
"""
Create OIDC config and wait for it to appear in the list
! In a very extreme case, other OIDC config can be created in the same time failing TimeoutSampler and
raising TimeoutExpiredError exception

Returns:
str: OIDC config id

Raises:
TimeoutExpiredError: If OIDC config is not created in time
"""
cmd = "rosa create oidc-config --mode=auto --yes"
proc = utils.exec_cmd(cmd, timeout=1200)
if proc.returncode != 0:
raise CommandFailed(f"Failed to create oidc config: {proc.stderr}")

for sample in TimeoutSampler(
timeout=300,
sleep=10,
func=get_oidc_config_ids,
latest=True,
):
if sample[0] in proc.stdout:
logger.info("OIDC config created successfully")
return sample


def delete_oidc_config(oidc_config_id):
"""
Delete OIDC config

Args:
oidc_config_id (str): OIDC config id

"""
# check if requested oidc config persisted
if oidc_config_id not in get_oidc_config_ids():
logger.warning(
f"OIDC config {oidc_config_id} is not found in the list of available configs"
)
return

cmd = f"rosa delete oidc-config {oidc_config_id} --mode auto --yes"
utils.exec_cmd(cmd, timeout=1200)
for sample in TimeoutSampler(
timeout=300,
sleep=10,
func=get_oidc_config_ids,
latest=False,
):
if oidc_config_id not in sample:
logger.info("OIDC config deleted successfully")
return


def get_latest_oidc_config_id():
cmd = "rosa list oidc-config -o json | jq -r 'max_by(.creation_timestamp) | .id'"
cmd_res = exec_cmd(cmd, shell=True)
if cmd_res.returncode != 0:
raise CommandFailed(f"Failed to get latest oidc config id: {cmd_res.stderr}")
logger.info(f"Latest OIDC config id: {cmd_res.stdout}")
return cmd_res.stdout.strip()


def get_oidc_config_ids(latest=False):
"""
Get OIDC config ids. If latest is True, return only the latest OIDC config id.

Args:
latest (bool): If True, return only the latest OIDC config id

Returns:
list: List of OIDC config ids
"""
if latest:
cmd = (
"rosa list oidc-config -o json | jq -r 'max_by(.creation_timestamp) | .id'"
)
else:
cmd = (
"rosa list oidc-config -o json | jq -r 'map(select(has(\"id\"))) | .[].id'"
)

cmd_res = exec_cmd(cmd, shell=True)
if cmd_res.returncode != 0:
raise CommandFailed(f"Failed to get OIDC config ids: {cmd_res.stderr}")

logger.info(f"OIDC config id(s), latest='{latest}': {cmd_res.stdout}")
return cmd_res.stdout.strip().splitlines()


def download_rosa_cli():
"""
Method to download OCM cli
Expand Down
Loading