247 lines
12 KiB
Diff
247 lines
12 KiB
Diff
From 3c74cd2e237df1646b73238de51bd0d4e019ec82 Mon Sep 17 00:00:00 2001
|
|
From: Matej Matuska <mmatuska@redhat.com>
|
|
Date: Tue, 7 Oct 2025 17:57:19 +0200
|
|
Subject: [PATCH 65/69] cs->rhel: Handle potentially unreleased target version
|
|
|
|
On CS to RHEL upgrades, particularly on 9->10, there is only one upgrade
|
|
path defined, CS 9 -> latest RHEL 10 (10.X). However a situation may occur,
|
|
in which the latest RHEL version has not yet been publicly released, e.g.
|
|
in pre-release builds.
|
|
|
|
This is problematic because the upgrade fails if the content is not yet
|
|
available. If this happens the user is informed via a hint in the error
|
|
message to specify the latest available RHEL version (the previous minor
|
|
version) manually using the --target-version CLI option.
|
|
|
|
To make leapp consider the previous minor version as supported without
|
|
adding it to upgrade_paths.json (which would affect RHEL->RHEL
|
|
upgrades), it is added to the IPUConfig message after processing the
|
|
json.
|
|
|
|
Also, in the error message, move the existing proxy hints from 'details'
|
|
to 'hint', otherwise the original exeception message, which is in
|
|
'details' is overwritten.
|
|
|
|
Jira: RHEL-110563
|
|
---
|
|
.../libraries/ipuworkflowconfig.py | 50 +++++++++++++++++++
|
|
.../tests/test_ipuworkflowconfig.py | 47 ++++++++++++++++-
|
|
.../libraries/userspacegen.py | 46 +++++++++++------
|
|
3 files changed, 127 insertions(+), 16 deletions(-)
|
|
|
|
diff --git a/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py b/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py
|
|
index 0c05640a..828eee88 100644
|
|
--- a/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py
|
|
+++ b/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py
|
|
@@ -189,6 +189,53 @@ def construct_models_for_paths_matching_source_major(
|
|
return multipaths_matching_source
|
|
|
|
|
|
+def _centos_to_rhel_supported_version_workaround(exposed_supported_paths):
|
|
+ """
|
|
+ Add target version one minor version lower than the latest version
|
|
+
|
|
+ On CS to RHEL upgrades, particularly on 9->10, there is only one upgrade
|
|
+ path defined, CS 9 -> latest RHEL 10 (10.X). However a situation may occur,
|
|
+ in which the latest RHEL version has not yet been publicly released, e.g.
|
|
+ in pre-release builds.
|
|
+
|
|
+ This is problematic because the upgrade fails if the content is not yet
|
|
+ available. If this happens the user is informed (by code elsewhere) to
|
|
+ specify the latest available RHEL version (the previous minor version)
|
|
+ manually using the --target-version CLI option.
|
|
+ However the previous minor version is not a supported target version. This
|
|
+ function adds it as one by appending it to exposed_supported_paths[0].target_versions.
|
|
+ The version is not appended if already present or if the defined latest is X.0.
|
|
+
|
|
+ :param exposed_supported_paths: The supported upgrade paths. Length is expected to be 1.
|
|
+ :type exposed_supported_paths: list[IPUSourceToPossibleTargets]
|
|
+ """
|
|
+
|
|
+ if len(exposed_supported_paths) != 1:
|
|
+ raise StopActorExecutionError(
|
|
+ "Expected only 1 IPUSourceToPossibleTargets model on CS->RHEL upgrade"
|
|
+ )
|
|
+ path = exposed_supported_paths[0]
|
|
+
|
|
+ major, minor = max(path.target_versions).split('.')
|
|
+ if not minor or minor == '0':
|
|
+ api.current_logger().debug(
|
|
+ "Skipping centos->rhel supported versions workaround, the latest target minor version is 0."
|
|
+ )
|
|
+ return
|
|
+
|
|
+ new_minor = int(minor) - 1
|
|
+ to_add = "{}.{}".format(major, new_minor)
|
|
+
|
|
+ if to_add not in path.target_versions:
|
|
+ msg = "Adding {} as a supported target version for centos->rhel upgrade.".format(to_add)
|
|
+ path.target_versions.append(to_add)
|
|
+ else:
|
|
+ msg = "Skipping adding {} as a target version for centos->rhel upgrade, already present.".format(
|
|
+ to_add
|
|
+ )
|
|
+ api.current_logger().debug(msg)
|
|
+
|
|
+
|
|
def produce_ipu_config(actor):
|
|
flavour = os.environ.get('LEAPP_UPGRADE_PATH_FLAVOUR')
|
|
target_version = os.environ.get('LEAPP_UPGRADE_PATH_TARGET_RELEASE')
|
|
@@ -219,6 +266,9 @@ def produce_ipu_config(actor):
|
|
raw_upgrade_paths, source_major_version
|
|
)
|
|
|
|
+ if exposed_supported_paths and os_release.release_id == 'centos' and target_distro == 'rhel':
|
|
+ _centos_to_rhel_supported_version_workaround(exposed_supported_paths)
|
|
+
|
|
actor.produce(IPUConfig(
|
|
leapp_env_vars=get_env_vars(),
|
|
os_release=os_release,
|
|
diff --git a/repos/system_upgrade/common/actors/ipuworkflowconfig/tests/test_ipuworkflowconfig.py b/repos/system_upgrade/common/actors/ipuworkflowconfig/tests/test_ipuworkflowconfig.py
|
|
index c0deaf0e..583cdfc5 100644
|
|
--- a/repos/system_upgrade/common/actors/ipuworkflowconfig/tests/test_ipuworkflowconfig.py
|
|
+++ b/repos/system_upgrade/common/actors/ipuworkflowconfig/tests/test_ipuworkflowconfig.py
|
|
@@ -1,10 +1,12 @@
|
|
import os
|
|
+from copy import deepcopy
|
|
|
|
import pytest
|
|
|
|
from leapp.exceptions import StopActorExecutionError
|
|
from leapp.libraries.actor import ipuworkflowconfig
|
|
-from leapp.libraries.stdlib import CalledProcessError
|
|
+from leapp.libraries.common.testutils import logger_mocked
|
|
+from leapp.libraries.stdlib import api, CalledProcessError
|
|
from leapp.models import IPUSourceToPossibleTargets, OSRelease
|
|
|
|
CUR_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
@@ -260,3 +262,46 @@ def test_load_raw_upgrade_paths_for_distro_and_flavour(monkeypatch, distro, flav
|
|
def test_virtual_version_construction(construction_params, expected_versions):
|
|
result = ipuworkflowconfig.get_virtual_version(TEST_UPGRADE_PATHS, *construction_params)
|
|
assert result == expected_versions
|
|
+
|
|
+
|
|
+def _make_path(source_ver, target_vers):
|
|
+ return IPUSourceToPossibleTargets(source_version=source_ver, target_versions=target_vers)
|
|
+
|
|
+
|
|
+@pytest.mark.parametrize(
|
|
+ "paths,to_add,logmsg",
|
|
+ [
|
|
+ (
|
|
+ [_make_path("9.8", ["10.2"])],
|
|
+ ["10.1"],
|
|
+ "Adding 10.1 as a supported target version for centos->rhel upgrade."
|
|
+ ),
|
|
+ (
|
|
+ [_make_path("9.10", ["10.10"])],
|
|
+ ["10.9"],
|
|
+ "Adding 10.9 as a supported target version for centos->rhel upgrade."
|
|
+ ),
|
|
+ # already present
|
|
+ (
|
|
+ [_make_path("8.10", ["9.6", "9.7"])],
|
|
+ [],
|
|
+ "Skipping adding 9.6 as a target version for centos->rhel upgrade, already present."
|
|
+ ),
|
|
+ # lowest minor
|
|
+ (
|
|
+ [_make_path("9.6", ["10.0"])],
|
|
+ [],
|
|
+ "Skipping centos->rhel supported versions workaround, the latest target minor version is 0."
|
|
+ ),
|
|
+ ],
|
|
+)
|
|
+def test_centos_to_rhel_supported_version_workaround(monkeypatch, paths, to_add, logmsg):
|
|
+ logger = logger_mocked()
|
|
+ monkeypatch.setattr(api, 'current_logger', logger)
|
|
+
|
|
+ original = deepcopy(paths[0])
|
|
+ ipuworkflowconfig._centos_to_rhel_supported_version_workaround(paths)
|
|
+
|
|
+ assert paths[0].source_version == original.source_version
|
|
+ assert paths[0].target_versions == original.target_versions + to_add
|
|
+ assert logmsg in logger.dbgmsg[0]
|
|
diff --git a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
|
|
index 9df83ef8..c825c731 100644
|
|
--- a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
|
|
+++ b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
|
|
@@ -7,8 +7,8 @@ from leapp import reporting
|
|
from leapp.exceptions import StopActorExecution, StopActorExecutionError
|
|
from leapp.libraries.actor import constants
|
|
from leapp.libraries.common import distro, dnfplugin, mounting, overlaygen, repofileutils, rhsm, utils
|
|
-from leapp.libraries.common.config import get_env, get_product_type, get_target_distro_id
|
|
-from leapp.libraries.common.config.version import get_target_major_version
|
|
+from leapp.libraries.common.config import get_env, get_product_type, get_source_distro_id, get_target_distro_id
|
|
+from leapp.libraries.common.config.version import get_target_major_version, get_target_version
|
|
from leapp.libraries.common.gpg import get_path_to_gpg_certs, is_nogpgcheck_set
|
|
from leapp.libraries.stdlib import api, CalledProcessError, config, run
|
|
from leapp.models import RequiredTargetUserspacePackages # deprecated
|
|
@@ -250,7 +250,9 @@ def prepare_target_userspace(context, userspace_dir, enabled_repos, packages):
|
|
try:
|
|
context.call(cmd, callback_raw=utils.logging_handler)
|
|
except CalledProcessError as exc:
|
|
- message = 'Unable to install RHEL {} userspace packages.'.format(target_major_version)
|
|
+ message = 'Unable to install target \'{}\' {} userspace packages.'.format(
|
|
+ get_target_distro_id(), target_major_version
|
|
+ )
|
|
details = {'details': str(exc), 'stderr': exc.stderr}
|
|
|
|
if 'more space needed on the' in exc.stderr:
|
|
@@ -263,26 +265,40 @@ def prepare_target_userspace(context, userspace_dir, enabled_repos, packages):
|
|
# failed since leapp does not support updates behind proxy yet.
|
|
for manager_info in api.consume(PkgManagerInfo):
|
|
if manager_info.configured_proxies:
|
|
- details['details'] = (
|
|
- "DNF failed to install userspace packages, likely due to the proxy "
|
|
- "configuration detected in the YUM/DNF configuration file. "
|
|
- "Make sure the proxy is properly configured in /etc/dnf/dnf.conf. "
|
|
- "It's also possible the proxy settings in the DNF configuration file are "
|
|
- "incompatible with the target system. A compatible configuration can be "
|
|
- "placed in /etc/leapp/files/dnf.conf which, if present, will be used during "
|
|
- "the upgrade instead of /etc/dnf/dnf.conf. "
|
|
- "In such case the configuration will also be applied to the target system."
|
|
+ details['hint'] = (
|
|
+ 'DNF failed to install userspace packages, likely due to the proxy '
|
|
+ 'configuration detected in the YUM/DNF configuration file. '
|
|
+ 'Make sure the proxy is properly configured in /etc/dnf/dnf.conf. '
|
|
+ 'It\'s also possible the proxy settings in the DNF configuration file are '
|
|
+ 'incompatible with the target system. A compatible configuration can be '
|
|
+ 'placed in /etc/leapp/files/dnf.conf which, if present, will be used during '
|
|
+ 'the upgrade instead of /etc/dnf/dnf.conf. '
|
|
+ 'In such case the configuration will also be applied to the target system.'
|
|
)
|
|
|
|
# Similarly if a proxy was set specifically for one of the repositories.
|
|
for repo_facts in api.consume(RepositoriesFacts):
|
|
for repo_file in repo_facts.repositories:
|
|
if any(repo_data.proxy and repo_data.enabled for repo_data in repo_file.data):
|
|
- details['details'] = (
|
|
- "DNF failed to install userspace packages, likely due to the proxy "
|
|
- "configuration detected in a repository configuration file."
|
|
+ details['hint'] = (
|
|
+ 'DNF failed to install userspace packages, likely due to the proxy '
|
|
+ 'configuration detected in a repository configuration file.'
|
|
)
|
|
|
|
+ if get_source_distro_id() == 'centos' and get_target_distro_id() == 'rhel':
|
|
+ check_rhel_release_hint = (
|
|
+ 'When upgrading and converting from Centos Stream to Red Hat Enterprise Linux'
|
|
+ ' (RHEL), the automatically determined latest target version of RHEL \'{}\' might'
|
|
+ ' not yet have been released. If so, specify the latest released RHEL version'
|
|
+ ' manually using the --target-version commandline option.'
|
|
+ ).format(get_target_version())
|
|
+
|
|
+ if details.get('hint'):
|
|
+ # keep the proxy hint, we don't know which one is the problem
|
|
+ details['hint'] = f"{details['hint']}\n\n{check_rhel_release_hint}"
|
|
+ else:
|
|
+ details['hint'] = check_rhel_release_hint
|
|
+
|
|
raise StopActorExecutionError(message=message, details=details)
|
|
|
|
|
|
--
|
|
2.51.1
|
|
|