leapp-repository/SOURCES/0032-models-ipuconfig-extend-Version-class-to-contain-vir.patch
eabdullin b1bd6e77a6 Import from CS git
(cherry picked from commit 5bdc5cf293)
2025-05-15 11:55:21 +03:00

335 lines
16 KiB
Diff

From 5f569408469d4e43ff559c5b90c3cc068d59d3a4 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Fri, 2 May 2025 16:35:18 +0200
Subject: [PATCH 32/37] models(ipuconfig): extend Version class to contain
virtual versions
Add virtual_{source,target}_version fields to the Version model. These
fields store a virtual MAJOR.MINOR CentOS version so that
version-specific checks originally written for RHEL can work as expected
also on CentOS. On non-CentOS system, the value of these fields should
be the same as source/target versions. The ipuworkflowconfig actor is
modified accordingly to populate the newly added fields.
Jira-ref: RHEL-80334
---
.../checksaphana/tests/test_checksaphana.py | 4 ++
.../libraries/ipuworkflowconfig.py | 51 +++++++++++++++++--
.../tests/test_ipuworkflowconfig.py | 41 ++++++++++++++-
.../common/libraries/config/mock_configs.py | 16 ++++--
.../libraries/config/tests/test_version.py | 12 +++--
.../common/libraries/testutils.py | 13 ++++-
.../system_upgrade/common/models/ipuconfig.py | 15 ++++++
7 files changed, 137 insertions(+), 15 deletions(-)
diff --git a/repos/system_upgrade/common/actors/checksaphana/tests/test_checksaphana.py b/repos/system_upgrade/common/actors/checksaphana/tests/test_checksaphana.py
index 1417b00a..1e43f403 100644
--- a/repos/system_upgrade/common/actors/checksaphana/tests/test_checksaphana.py
+++ b/repos/system_upgrade/common/actors/checksaphana/tests/test_checksaphana.py
@@ -181,6 +181,8 @@ class MockSAPHanaVersionInstance(object):
)
)
def test_checksaphana__fullfills_rhel86_hana_min_version(monkeypatch, major, rev, patchlevel, result):
+ monkeypatch.setattr(checksaphana.api, 'current_actor', testutils.CurrentActorMocked())
+
monkeypatch.setattr(version, 'get_target_major_version', lambda: '8')
monkeypatch.setattr(version, 'get_target_version', lambda: '8.6')
monkeypatch.setattr(checksaphana, 'SAP_HANA_RHEL86_REQUIRED_PATCH_LEVELS', ((4, 48, 2), (5, 52, 0)))
@@ -213,6 +215,8 @@ def test_checksaphana__fullfills_rhel86_hana_min_version(monkeypatch, major, rev
)
)
def test_checksaphana__fullfills_hana_rhel90_min_version(monkeypatch, major, rev, patchlevel, result):
+ monkeypatch.setattr(checksaphana.api, 'current_actor', testutils.CurrentActorMocked())
+
monkeypatch.setattr(version, 'get_target_major_version', lambda: '9')
monkeypatch.setattr(version, 'get_target_version', lambda: '9.0')
monkeypatch.setattr(checksaphana, 'SAP_HANA_RHEL90_REQUIRED_PATCH_LEVELS', ((5, 59, 4), (6, 63, 0)))
diff --git a/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py b/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py
index 35f61669..f76677fd 100644
--- a/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py
+++ b/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py
@@ -10,6 +10,7 @@ ENV_IGNORE = ('LEAPP_CURRENT_PHASE', 'LEAPP_CURRENT_ACTOR', 'LEAPP_VERBOSE',
'LEAPP_DEBUG')
ENV_MAPPING = {'LEAPP_DEVEL_DM_DISABLE_UDEV': 'DM_DISABLE_UDEV'}
+CENTOS_VIRTUAL_VERSIONS_KEY = '_virtual_versions'
def get_env_vars():
@@ -92,8 +93,7 @@ def load_upgrade_paths_definitions(paths_definition_file):
return definitions
-def load_raw_upgrade_paths_for_distro_and_flavour(distro_id, flavour, paths_definition_file='upgrade_paths.json'):
- all_definitions = load_upgrade_paths_definitions(paths_definition_file)
+def extract_upgrade_paths_for_distro_and_flavour(all_definitions, distro_id, flavour):
raw_upgrade_paths_for_distro = all_definitions.get(distro_id, {})
if not raw_upgrade_paths_for_distro:
@@ -117,6 +117,39 @@ def construct_models_for_paths_matching_source_major(raw_paths, src_major_versio
return multipaths_matching_source
+def construct_virtual_versions(all_upgrade_path_defs, distro_id, source_version, target_version):
+ if distro_id.lower() != 'centos':
+ return (source_version, target_version)
+
+ centos_upgrade_paths = all_upgrade_path_defs.get('centos', {})
+ if not centos_upgrade_paths:
+ raise StopActorExecutionError('There are no upgrade paths defined for CentOS.')
+
+ virtual_versions = centos_upgrade_paths.get(CENTOS_VIRTUAL_VERSIONS_KEY, {})
+ if not virtual_versions: # Unlikely, only if using old upgrade_paths.json, but the user should not touch the file
+ details = {'details': 'The file does not contain any information about virtual versions of CentOS'}
+ raise StopActorExecutionError('The internal upgrade_paths.json file is malformed.')
+
+ source_virtual_version = virtual_versions.get(source_version)
+ target_virtual_version = virtual_versions.get(target_version)
+
+ if not source_virtual_version or not target_virtual_version:
+ if not source_virtual_version and not target_virtual_version:
+ what_is_missing = 'CentOS {} (source) and CentOS {} (target)'.format(source_virtual_version,
+ target_virtual_version)
+ elif not source_virtual_version:
+ what_is_missing = 'CentOS {} (source)'.format(source_virtual_version)
+ else:
+ what_is_missing = 'CentOS {} (target)'.format(target_virtual_version)
+
+ details_msg = 'The {} field in upgrade path definitions does not provide any information for {}'
+ details = {'details': details_msg.format(CENTOS_VIRTUAL_VERSIONS_KEY, what_is_missing)}
+ raise StopActorExecutionError('Failed to identify virtual minor version number for the system.',
+ details=details)
+
+ return (source_virtual_version, target_virtual_version)
+
+
def produce_ipu_config(actor):
flavour = os.environ.get('LEAPP_UPGRADE_PATH_FLAVOUR')
target_version = os.environ.get('LEAPP_UPGRADE_PATH_TARGET_RELEASE')
@@ -125,17 +158,27 @@ def produce_ipu_config(actor):
check_target_major_version(source_version, target_version)
- raw_upgrade_paths = load_raw_upgrade_paths_for_distro_and_flavour(os_release.release_id, flavour)
+ all_upgrade_path_defs = load_upgrade_paths_definitions('upgrade_paths.json')
+ raw_upgrade_paths = extract_upgrade_paths_for_distro_and_flavour(all_upgrade_path_defs,
+ os_release.release_id,
+ flavour)
source_major_version = source_version.split('.')[0]
exposed_supported_paths = construct_models_for_paths_matching_source_major(raw_upgrade_paths, source_major_version)
+ virtual_source_version, virtual_target_version = construct_virtual_versions(all_upgrade_path_defs,
+ os_release.release_id,
+ source_version,
+ target_version)
+
actor.produce(IPUConfig(
leapp_env_vars=get_env_vars(),
os_release=os_release,
architecture=platform.machine(),
version=Version(
source=source_version,
- target=target_version
+ target=target_version,
+ virtual_source_version=virtual_source_version,
+ virtual_target_version=virtual_target_version,
),
kernel=get_booted_kernel(),
flavour=flavour,
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 d88424ce..6184121b 100644
--- a/repos/system_upgrade/common/actors/ipuworkflowconfig/tests/test_ipuworkflowconfig.py
+++ b/repos/system_upgrade/common/actors/ipuworkflowconfig/tests/test_ipuworkflowconfig.py
@@ -149,7 +149,44 @@ def test_load_raw_upgrade_paths_for_distro_and_flavour(monkeypatch, distro, flav
}
}
}
- monkeypatch.setattr(ipuworkflowconfig, 'load_upgrade_paths_definitions', lambda *args: defined_upgrade_paths)
- result = ipuworkflowconfig.load_raw_upgrade_paths_for_distro_and_flavour(distro, flavour)
+ result = ipuworkflowconfig.extract_upgrade_paths_for_distro_and_flavour(defined_upgrade_paths,
+ distro, flavour)
assert result == expected_result
+
+
+@pytest.mark.parametrize(
+ ('construction_params', 'expected_versions'),
+ [
+ (('centos', '8', '9'), ('8.10', '9.5')),
+ (('rhel', '8.10', '9.4'), ('8.10', '9.4')),
+ ]
+)
+def test_virtual_version_construction(construction_params, expected_versions):
+ defined_upgrade_paths = {
+ 'rhel': {
+ 'default': {
+ '8.10': ['9.4', '9.5', '9.6'],
+ '8.4': ['9.2'],
+ '9.6': ['10.0'],
+ '8': ['9.4', '9.5', '9.6'],
+ '9': ['10.0']
+ },
+ 'saphana': {
+ '8.10': ['9.6', '9.4'],
+ '8': ['9.6', '9.4'],
+ '9.6': ['10.0'],
+ '9': ['10.0']
+ }
+ },
+ 'centos': {
+ '8': ['9'],
+ '_virtual_versions': {
+ '8': '8.10',
+ '9': '9.5',
+ }
+ },
+ }
+
+ result = ipuworkflowconfig.construct_virtual_versions(defined_upgrade_paths, *construction_params)
+ assert result == expected_versions
diff --git a/repos/system_upgrade/common/libraries/config/mock_configs.py b/repos/system_upgrade/common/libraries/config/mock_configs.py
index a1c9c0fd..a7ee0000 100644
--- a/repos/system_upgrade/common/libraries/config/mock_configs.py
+++ b/repos/system_upgrade/common/libraries/config/mock_configs.py
@@ -19,7 +19,9 @@ CONFIG = IPUConfig(
),
version=Version(
source='7.6',
- target='8.0'
+ target='8.0',
+ virtual_source_version='7.6',
+ virtual_target_version='8.0'
),
architecture='x86_64',
kernel='3.10.0-957.43.1.el7.x86_64',
@@ -39,7 +41,9 @@ CONFIG_NO_NETWORK_RENAMING = IPUConfig(
),
version=Version(
source='7.6',
- target='8.0'
+ target='8.0',
+ virtual_source_version='7.6',
+ virtual_target_version='8.0'
),
architecture='x86_64',
kernel='3.10.0-957.43.1.el7.x86_64',
@@ -59,7 +63,9 @@ CONFIG_ALL_SIGNED = IPUConfig(
),
version=Version(
source='7.6',
- target='8.0'
+ target='8.0',
+ virtual_source_version='7.6',
+ virtual_target_version='8.0'
),
architecture='x86_64',
kernel='3.10.0-957.43.1.el7.x86_64',
@@ -78,7 +84,9 @@ CONFIG_S390X = IPUConfig(
),
version=Version(
source='7.6',
- target='8.0'
+ target='8.0',
+ virtual_source_version='7.6',
+ virtual_target_version='8.0'
),
architecture='s390x',
kernel='3.10.0-957.43.1.el7.x86_64',
diff --git a/repos/system_upgrade/common/libraries/config/tests/test_version.py b/repos/system_upgrade/common/libraries/config/tests/test_version.py
index 3cb6479c..a8a1023e 100644
--- a/repos/system_upgrade/common/libraries/config/tests/test_version.py
+++ b/repos/system_upgrade/common/libraries/config/tests/test_version.py
@@ -27,7 +27,9 @@ def test_cmp_versions():
assert not version._cmp_versions(['>= 7.6', '& 7.7'])
-def test_matches_version_wrong_args():
+def test_matches_version_wrong_args(monkeypatch):
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked())
+
with pytest.raises(TypeError):
version.matches_version('>= 7.6', '7.7')
with pytest.raises(TypeError):
@@ -42,7 +44,9 @@ def test_matches_version_wrong_args():
version.matches_version(['>= 7.6', '& 7.7'], '7.7')
-def test_matches_version_fail():
+def test_matches_version_fail(monkeypatch):
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked())
+
assert not version.matches_version(['> 7.6', '< 7.7'], '7.6')
assert not version.matches_version(['> 7.6', '< 7.7'], '7.7')
assert not version.matches_version(['> 7.6', '< 7.10'], '7.6')
@@ -50,7 +54,9 @@ def test_matches_version_fail():
assert not version.matches_version(['7.6', '7.7', '7.10'], '7.8')
-def test_matches_version_pass():
+def test_matches_version_pass(monkeypatch):
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked())
+
assert version.matches_version(['7.6', '7.7', '7.10'], '7.7')
assert version.matches_version(['> 7.6', '< 7.10'], '7.7')
diff --git a/repos/system_upgrade/common/libraries/testutils.py b/repos/system_upgrade/common/libraries/testutils.py
index 1b3c3683..3e145d91 100644
--- a/repos/system_upgrade/common/libraries/testutils.py
+++ b/repos/system_upgrade/common/libraries/testutils.py
@@ -74,15 +74,24 @@ def _make_default_config(actor_config_schema):
return _normalize_config({}, merged_schema) # Will fill default values during normalization
+# Note: The constructor of the following class takes in too many arguments (R0913). A builder-like
+# pattern would be nice here. Ideally, the builder should actively prevent the developer from setting fields
+# that do not affect actor's behavior in __setattr__.
class CurrentActorMocked(object): # pylint:disable=R0904
- def __init__(self, arch=architecture.ARCH_X86_64, envars=None, kernel='3.10.0-957.43.1.el7.x86_64',
+ def __init__(self, arch=architecture.ARCH_X86_64, envars=None, # pylint:disable=R0913
+ kernel='3.10.0-957.43.1.el7.x86_64',
release_id='rhel', src_ver='7.8', dst_ver='8.1', msgs=None, flavour='default', config=None,
+ virtual_source_version=None, virtual_target_version=None,
supported_upgrade_paths=None):
"""
:param List[IPUSourceToPossibleTargets] supported_upgrade_paths: List of supported upgrade paths.
"""
envarsList = [EnvVar(name=k, value=v) for k, v in envars.items()] if envars else []
- version = namedtuple('Version', ['source', 'target'])(src_ver, dst_ver)
+
+ version_fields = ['source', 'target', 'virtual_source_version', 'virtual_target_version']
+ version_values = [src_ver, dst_ver, virtual_source_version or src_ver, virtual_target_version or dst_ver]
+ version = namedtuple('Version', version_fields)(*version_values)
+
release = namedtuple('OS_release', ['release_id', 'version_id'])(release_id, src_ver)
self._common_folder = '../../files'
diff --git a/repos/system_upgrade/common/models/ipuconfig.py b/repos/system_upgrade/common/models/ipuconfig.py
index 0a16b603..379ac13f 100644
--- a/repos/system_upgrade/common/models/ipuconfig.py
+++ b/repos/system_upgrade/common/models/ipuconfig.py
@@ -33,6 +33,21 @@ class Version(Model):
target = fields.String()
"""Version of the target system. E.g. '8.2.'."""
+ virtual_source_version = fields.String()
+ """
+ Source OS version used when checking whether to execute version-dependent code.
+
+ On RHEL and other systems that have version of the form MINOR.MAJOR, `virtual_source_version`
+ matches `source_version`.
+
+ CentOS has version of the form MAJOR, lacking the minor version number. The
+ `virtual_source_version` value is obtained by combining CentOS major
+ version number with a minor version number stored internally in the upgrade_paths.json file.
+ """
+
+ virtual_target_version = fields.String()
+ """ See :py:attr:`virtual_source_version` """
+
class IPUSourceToPossibleTargets(Model):
"""
--
2.49.0