Skip to content

Commit

Permalink
rosa upgrade
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Osypenko <[email protected]>
  • Loading branch information
DanielOsypenko committed Jan 12, 2025
1 parent dcd0472 commit bbe073a
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 58 deletions.
46 changes: 15 additions & 31 deletions ocs_ci/utility/rosa.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from ocs_ci.ocs.exceptions import (
CommandFailed,
ManagedServiceAddonDeploymentError,
UnsupportedPlatformVersionError,
ConfigurationError,
ResourceWrongStatusException,
TimeoutExpiredError,
Expand All @@ -31,6 +30,7 @@
)
from ocs_ci.utility.retry import catch_exceptions
from ocs_ci.utility.utils import exec_cmd, TimeoutSampler
from ocs_ci.utility.version import get_latest_rosa_version

logger = logging.getLogger(name=__file__)
rosa = config.AUTH.get("rosa", {})
Expand Down Expand Up @@ -78,6 +78,7 @@ def create_cluster(cluster_name, version, region):
f"is not valid ROSA OCP version. "
f"Selecting latest rosa version for deployment"
)
logger.info(f"Looking for z-stream version of {version}")
rosa_ocp_version = get_latest_rosa_version(version)
logger.info(f"Using OCP version {rosa_ocp_version}")

Expand Down Expand Up @@ -344,36 +345,6 @@ def get_rosa_service_details(cluster):
return json.loads(service_info)


def get_latest_rosa_version(version):
"""
Returns latest available z-stream version available for ROSA.
Args:
version (str): OCP version in format `x.y`
Returns:
str: Latest available z-stream version
"""
cmd = "rosa list versions"
output = utils.run_cmd(cmd, timeout=1800)
logger.info(f"Looking for z-stream version of {version}")
rosa_version = None
for line in output.splitlines():
match = re.search(f"^{version}\\.(\\d+) ", line)
if match:
rosa_version = match.group(0).rstrip()
break
if rosa_version is None:
logger.error(f"Could not find any version of {version} available for ROSA")
logger.info("Try providing an older version of OCP with --ocp-version")
logger.info("Latest OCP versions available for ROSA are:")
for i in range(3):
logger.info(f"{output.splitlines()[i + 1]}")
raise UnsupportedPlatformVersionError
return rosa_version


def validate_ocp_version(version):
"""
Validate the version whether given version is z-stream version available for ROSA.
Expand Down Expand Up @@ -1151,3 +1122,16 @@ def label_nodes(cluster_name, machinepool_id, labels, rewrite=False):
)
machine_pool.refresh()
return machine_pool.labels


def upgrade_rosa_cluster(cluster_name, version):
"""
Upgrade the ROSA cluster to the given version
Args:
cluster_name (str): The cluster name
version (str): The version to upgrade the cluster
"""
cmd = f"rosa upgrade cluster --cluster {cluster_name} --version {version} --mode auto --yes"
utils.run_cmd(cmd, timeout=2400)
112 changes: 111 additions & 1 deletion ocs_ci/utility/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@

from ocs_ci.framework import config
from ocs_ci.ocs import defaults
from ocs_ci.ocs.exceptions import WrongVersionExpression
from ocs_ci.ocs.exceptions import (
WrongVersionExpression,
UnsupportedPlatformVersionError,
)
from ocs_ci.ocs import constants


Expand Down Expand Up @@ -292,3 +295,110 @@ def get_volsync_operator_version(namespace=constants.SUBMARINER_OPERATOR_NAMESPA
if "volsync" in csv["metadata"]["name"]:
# extract version string
return csv["spec"]["version"]


def get_ocp_versions_rosa():
"""
Get the list of available versions for ROSA.
Returns:
str: a list of available versions for ROSA in string format
"""
from ocs_ci.utility.utils import exec_cmd

cmd = "rosa list versions"
output = exec_cmd(cmd, timeout=1800)
return output.stdout.decode()


def ocp_version_available_on_rosa(version):
"""
Check if requested version is available on ROSA for upgrade
Args:
version (str): OCP version in format `x.y.z`
Returns:
bool: True if version is supported, False otherwise
"""
output = get_ocp_versions_rosa()
return True if version in output else False


def get_next_ocp_version_rosa(version):
"""
Get the next available minor version for ROSA.
Args:
version (str): OCP version in format `x.y.z`
Returns:
str: Next available version for ROSA
"""
# This should return a list of versions in `x.y.z` format in string representation
output = get_ocp_versions_rosa()

current_version = Version(version)
next_version = None

for line in output.splitlines():
try:
available_version = Version(line.split()[0])
if available_version > current_version:
next_version = available_version
break
except ValueError:
# Skipping invalid version
pass

if next_version is None:
raise UnsupportedPlatformVersionError(
f"Could not find any next version after {version} available for ROSA"
)

return str(next_version)


def get_latest_rosa_version(version):
"""
Returns latest available z-stream version available for ROSA.
Args:
version (str): OCP version in format `x.y`
Returns:
str: Latest available z-stream version
"""
output = get_ocp_versions_rosa()
rosa_version = None
for line in output.splitlines():
match = re.search(f"^{version}\\.(\\d+) ", line)
if match:
rosa_version = match.group(0).rstrip()
break
if rosa_version is None:
error_msg = (
f"Could not find any version of {version} available for ROSA. "
f"Try providing an older version of OCP with --ocp-version. "
f"Latest OCP versions available for ROSA are: \n"
)
for i in range(3):
error_msg += f"{output.splitlines()[i + 1]}"
raise UnsupportedPlatformVersionError(error_msg)
return rosa_version


def drop_z_version(version_str):
"""
Drops the z (patch) version from a semantic version string.
Args:
version_str (str): Version string in the format `x.y.z` or `x.y`
Returns:
str: Version string in the format `x.y`
"""
version = Version.coerce(version_str)
return f"{version.major}.{version.minor}"
85 changes: 59 additions & 26 deletions tests/functional/upgrade/test_upgrade_ocp.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from ocs_ci.ocs.resources.pod import get_ceph_tools_pod
from ocs_ci.deployment.disconnected import mirror_ocp_release_images
from ocs_ci.framework import config
from ocs_ci.utility.rosa import upgrade_rosa_cluster
from ocs_ci.utility.utils import (
archive_ceph_crashes,
ceph_crash_info_display,
Expand All @@ -28,6 +29,9 @@
from ocs_ci.utility.version import (
get_semantic_ocp_running_version,
VERSION_4_8,
get_latest_rosa_version,
ocp_version_available_on_rosa,
drop_z_version,
)
from ocs_ci.framework.pytest_customization.marks import (
purple_squad,
Expand Down Expand Up @@ -92,17 +96,42 @@ def test_upgrade_ocp(self, reduce_and_resume_cluster_load):
ocp_channel = config.UPGRADE.get(
"ocp_channel", ocp.get_ocp_upgrade_channel()
)
logger.info(f"OCP Channel: {ocp_channel}")

ocp_upgrade_version = config.UPGRADE.get("ocp_upgrade_version")
if ocp_upgrade_version:
target_image = ocp_upgrade_version
if not ocp_upgrade_version:
ocp_upgrade_version = get_latest_ocp_version(channel=ocp_channel)
ocp_arch = config.UPGRADE["ocp_arch"]
target_image = f"{ocp_upgrade_version}-{ocp_arch}"
elif ocp_upgrade_version.endswith(".nightly"):
target_image = expose_ocp_version(ocp_upgrade_version)
logger.info(f"OCP upgrade version: {ocp_upgrade_version}")

logger.info(f"Target image: {target_image}")
rosa_platform = (
config.ENV_DATA["platform"].lower() in constants.ROSA_PLATFORMS
)

if rosa_platform:
# Handle ROSA-specific upgrade logic
# If ROSA environment, Nightly builds are not supported
# If not provided ocp_upgrade_version - get the latest released version of the channel.
# If provided - check availability and use the provided version in format "X.Y.Z"
if ocp_upgrade_version and ocp_version_available_on_rosa(
ocp_upgrade_version
):
target_image = ocp_upgrade_version
else:
latest_ocp_ver = get_latest_ocp_version(channel=ocp_channel)
if not ocp_version_available_on_rosa(latest_ocp_ver):
version_major_minor = drop_z_version(latest_ocp_ver)
target_image = get_latest_rosa_version(version_major_minor)
else:
# Handle non-ROSA upgrade logic
if ocp_upgrade_version:
target_image = (
expose_ocp_version(ocp_upgrade_version)
if ocp_upgrade_version.endswith(".nightly")
else ocp_upgrade_version
)
else:
ocp_upgrade_version = get_latest_ocp_version(channel=ocp_channel)
ocp_arch = config.UPGRADE["ocp_arch"]
target_image = f"{ocp_upgrade_version}-{ocp_arch}"
logger.info(f"Target image: {target_image}")

image_path = config.UPGRADE["ocp_upgrade_path"]
cluster_operators = ocp.get_all_cluster_operators()
Expand All @@ -115,24 +144,28 @@ def test_upgrade_ocp(self, reduce_and_resume_cluster_load):
)

# Verify Upgrade subscription channel:
ocp.patch_ocp_upgrade_channel(ocp_channel)
for sampler in TimeoutSampler(
timeout=250,
sleep=15,
func=ocp.verify_ocp_upgrade_channel,
channel_variable=ocp_channel,
):
if sampler:
logger.info(f"OCP Channel:{ocp_channel}")
break
if not rosa_platform:
ocp.patch_ocp_upgrade_channel(ocp_channel)
for sampler in TimeoutSampler(
timeout=250,
sleep=15,
func=ocp.verify_ocp_upgrade_channel,
channel_variable=ocp_channel,
):
if sampler:
logger.info(f"OCP Channel:{ocp_channel}")
break

# pause a MachineHealthCheck resource
if get_semantic_ocp_running_version() > VERSION_4_8:
pause_machinehealthcheck()
# pause a MachineHealthCheck resource
# no machinehealthcheck on ROSA
if get_semantic_ocp_running_version() > VERSION_4_8:
pause_machinehealthcheck()

# Upgrade OCP
logger.info(f"full upgrade path: {image_path}:{target_image}")
ocp.upgrade_ocp(image=target_image, image_path=image_path)
logger.info(f"full upgrade path: {image_path}:{target_image}")
ocp.upgrade_ocp(image=target_image, image_path=image_path)
else:
logger.info(f"upgrade rosa cluster to target version: '{target_image}'")
upgrade_rosa_cluster(config.ENV_DATA["cluster_name"], target_image)

# Wait for upgrade
for ocp_operator in cluster_operators:
Expand Down Expand Up @@ -167,7 +200,7 @@ def test_upgrade_ocp(self, reduce_and_resume_cluster_load):
logger.info(f"{ocp_operator} upgrade did not completed yet!")

# resume a MachineHealthCheck resource
if get_semantic_ocp_running_version() > VERSION_4_8:
if get_semantic_ocp_running_version() > VERSION_4_8 and not rosa_platform:
resume_machinehealthcheck()

# post upgrade validation: check cluster operator status
Expand Down

0 comments on commit bbe073a

Please sign in to comment.