From 37f6e616843a9441a6a79fecbffa94c238d987aa Mon Sep 17 00:00:00 2001 From: Matej Matuska Date: Thu, 18 Sep 2025 19:12:41 +0200 Subject: [PATCH 60/69] ipuconfig: Map source to target distro paths when converting Jira: RHEL-110563 --- .../libraries/ipuworkflowconfig.py | 112 +++++++++++----- .../tests/test_ipuworkflowconfig.py | 123 ++++++++++++------ 2 files changed, 167 insertions(+), 68 deletions(-) diff --git a/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py b/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py index afc139a1..0c05640a 100644 --- a/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py +++ b/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py @@ -93,31 +93,7 @@ def load_upgrade_paths_definitions(paths_definition_file): return definitions -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: - api.current_logger().warning('No upgrade paths defined for distro \'{}\''.format(distro_id)) - - raw_upgrade_paths_for_flavour = raw_upgrade_paths_for_distro.get(flavour, {}) - - if not raw_upgrade_paths_for_flavour: - api.current_logger().warning('Cannot discover any upgrade paths for flavour: {}/{}'.format(distro_id, flavour)) - - return raw_upgrade_paths_for_flavour - - -def construct_models_for_paths_matching_source_major(raw_paths, src_major_version): - multipaths_matching_source = [] - for src_version, target_versions in raw_paths.items(): - if src_version.split('.')[0] == src_major_version: - source_to_targets = IPUSourceToPossibleTargets(source_version=src_version, - target_versions=target_versions) - multipaths_matching_source.append(source_to_targets) - return multipaths_matching_source - - -def construct_virtual_version(all_upgrade_path_defs, distro, version): +def get_virtual_version(all_upgrade_path_defs, distro, version): if distro.lower() != 'centos': return version @@ -147,11 +123,78 @@ def construct_virtual_version(all_upgrade_path_defs, distro, version): return virtual_version +def extract_upgrade_paths_for_distro_and_flavour(all_definitions, distro, flavour): + distro_paths = all_definitions.get(distro, {}) + if not distro_paths: + api.current_logger().warning( + "No upgrade paths defined for distro '{}'".format(distro) + ) + + distro_paths = distro_paths.get(flavour, {}) + if not distro_paths: + api.current_logger().warning( + "Cannot discover any upgrade paths for flavour: {}/{}".format( + distro, flavour + ) + ) + return distro_paths + + +def make_cross_distro_paths(all_paths, source_distro, target_distro, flavour): + """ + Make paths for upgrade + conversion. + + :param all_paths: The raw upgrade paths retrieved from upgrade_paths.json + :type all_paths: dict + :param source_distro: The source distro. + :type source_distro: str + :param target_distro: The target distro. + :type target_distro: str + :param flavour: The flavour to find paths for. + :type target_distro: str + :return: A dictionary with conversion paths for upgrade + conversion between + source and target distro. + :rtype: dict + """ + # using source and target for both distro and version gets confusing, using + # a and b for distro instead + paths_a = extract_upgrade_paths_for_distro_and_flavour( + all_paths, source_distro, flavour + ) + paths_b = extract_upgrade_paths_for_distro_and_flavour( + all_paths, target_distro, flavour + ) + + conversion_paths = {} + for source_ver_a, _ in paths_a.items(): + virt_source_ver_a = get_virtual_version(all_paths, source_distro, source_ver_a) + + for source_ver_b, target_ver_b in paths_b.items(): + virt_source_ver_b = get_virtual_version(all_paths, target_distro, source_ver_b) + if virt_source_ver_a == virt_source_ver_b: + conversion_paths[source_ver_a] = target_ver_b + + return conversion_paths + + +def construct_models_for_paths_matching_source_major( + raw_paths, src_major_version +): + multipaths_matching_source = [] + for src_version, target_versions in raw_paths.items(): + if src_version.split('.')[0] == src_major_version: + source_to_targets = IPUSourceToPossibleTargets(source_version=src_version, + target_versions=target_versions) + multipaths_matching_source.append(source_to_targets) + return multipaths_matching_source + + def produce_ipu_config(actor): flavour = os.environ.get('LEAPP_UPGRADE_PATH_FLAVOUR') target_version = os.environ.get('LEAPP_UPGRADE_PATH_TARGET_RELEASE') os_release = get_os_release('/etc/os-release') source_version = os_release.version_id + target_distro = os.environ.get('LEAPP_TARGET_OS') check_target_major_version(source_version, target_version) @@ -159,13 +202,22 @@ def produce_ipu_config(actor): 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) + if os_release.release_id == target_distro: + raw_upgrade_paths = extract_upgrade_paths_for_distro_and_flavour( + all_upgrade_path_defs, os_release.release_id, flavour + ) + else: + raw_upgrade_paths = make_cross_distro_paths( + all_upgrade_path_defs, os_release.release_id, target_distro, flavour + ) - target_distro = os.environ.get('LEAPP_TARGET_OS') + virtual_source_version = get_virtual_version(all_upgrade_path_defs, os_release.release_id, source_version) + virtual_target_version = get_virtual_version(all_upgrade_path_defs, target_distro, target_version) - virtual_source_version = construct_virtual_version(all_upgrade_path_defs, os_release.release_id, source_version) - virtual_target_version = construct_virtual_version(all_upgrade_path_defs, target_distro, target_version) + source_major_version = source_version.split('.')[0] + exposed_supported_paths = construct_models_for_paths_matching_source_major( + raw_upgrade_paths, source_major_version + ) actor.produce(IPUConfig( leapp_env_vars=get_env_vars(), 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 96b63666..c0deaf0e 100644 --- a/repos/system_upgrade/common/actors/ipuworkflowconfig/tests/test_ipuworkflowconfig.py +++ b/repos/system_upgrade/common/actors/ipuworkflowconfig/tests/test_ipuworkflowconfig.py @@ -1,6 +1,4 @@ -import json import os -import tempfile import pytest @@ -42,6 +40,43 @@ def _get_os_release(version='7.9', codename='Maipo'): return release +TEST_UPGRADE_PATHS = { + 'rhel': { + 'default': { + '8.10': ['9.4', '9.6', '9.7'], + '8.4': ['9.2'], + '9.6': ['10.0'], + '9.7': ['10.1'], + '8': ['9.4', '9.6'], + '9': ['10.1'], + }, + 'saphana': { + '8.10': ['9.6', '9.4'], + '8': ['9.6', '9.4'], + '9.6': ['10.0'], + '9': ['10.0'], + }, + }, + 'centos': { + 'default': { + '8': ['9'], + '9': ['10'], + }, + '_virtual_versions': { + '8': '8.10', + '9': '9.7', + '10': '10.1', + }, + }, + 'almalinux': { + 'default': { + '8.10': ['9.0', '9.1', '9.2', '9.3', '9.4', '9.5', '9.6', '9.7'], + '9.7': ['10.0', '10.1'], + }, + }, +} + + def test_leapp_env_vars(monkeypatch): _clean_leapp_envs(monkeypatch) monkeypatch.setenv('LEAPP_WHATEVER', '0') @@ -82,6 +117,7 @@ def test_get_booted_kernel(monkeypatch): IPUSourceToPossibleTargets(source_version='8.10', target_versions=['9.4', '9.5', '9.6']), IPUSourceToPossibleTargets(source_version='8.4', target_versions=['9.2']), IPUSourceToPossibleTargets(source_version='8', target_versions=['9.4', '9.5', '9.6']), + IPUSourceToPossibleTargets(source_version='8.6', target_versions=['9']), ] ), ( @@ -90,6 +126,13 @@ def test_get_booted_kernel(monkeypatch): IPUSourceToPossibleTargets(source_version='80.0', target_versions=['81.0']), ] ), + ( + '9', + [ + IPUSourceToPossibleTargets(source_version='9', target_versions=['10']), + IPUSourceToPossibleTargets(source_version='9.6', target_versions=['10.0']), + ] + ), ) ) def test_construct_models_for_paths_matching_source_major(source_major_version, expected_result): @@ -98,7 +141,9 @@ def test_construct_models_for_paths_matching_source_major(source_major_version, '8.4': ['9.2'], '9.6': ['10.0'], '8': ['9.4', '9.5', '9.6'], - '80.0': ['81.0'] + '80.0': ['81.0'], + '8.6': ['9'], + '9': ['10'], } result = ipuworkflowconfig.construct_models_for_paths_matching_source_major(RAW_PATHS, source_major_version) @@ -106,6 +151,38 @@ def test_construct_models_for_paths_matching_source_major(source_major_version, assert result == sorted(expected_result, key=lambda x: x.source_version) +@pytest.mark.parametrize( + "src_distro,dst_distro,expected", + [ + ("centos", "rhel", {"8": ["9.4", "9.6", "9.7"], "9": ["10.1"]}), + ("almalinux", "rhel", {"8.10": ["9.4", "9.6", "9.7"], "9.7": ["10.1"]}), + ("rhel", "centos", {"8.10": ["9"], "9.7": ["10"]}), + ("almalinux", "centos", {"8.10": ["9"], "9.7": ["10"]}), + ( + "rhel", + "almalinux", + { + "8.10": ["9.0", "9.1", "9.2", "9.3", "9.4", "9.5", "9.6", "9.7"], + "9.7": ["10.0", "10.1"], + }, + ), + ( + "centos", + "almalinux", + { + "8": ["9.0", "9.1", "9.2", "9.3", "9.4", "9.5", "9.6", "9.7"], + "9": ["10.0", "10.1"], + }, + ), + ], +) +def test_make_cross_distro_paths(src_distro, dst_distro, expected): + res = ipuworkflowconfig.make_cross_distro_paths( + TEST_UPGRADE_PATHS, src_distro, dst_distro, 'default' + ) + assert res == expected + + @pytest.mark.parametrize( ('distro', 'flavour', 'expected_result'), ( @@ -163,8 +240,9 @@ def test_load_raw_upgrade_paths_for_distro_and_flavour(monkeypatch, distro, flav } } - result = ipuworkflowconfig.extract_upgrade_paths_for_distro_and_flavour(defined_upgrade_paths, - distro, flavour) + result = ipuworkflowconfig.extract_upgrade_paths_for_distro_and_flavour( + defined_upgrade_paths, distro, flavour + ) assert result == expected_result @@ -172,7 +250,7 @@ def test_load_raw_upgrade_paths_for_distro_and_flavour(monkeypatch, distro, flav ('construction_params', 'expected_versions'), [ (('centos', '8'), '8.10'), - (('centos', '9'), '9.5'), + (('centos', '9'), '9.7'), (('rhel', '8.10'), '8.10'), (('rhel', '9.4'), '9.4'), (('almalinux', '8.10'), '8.10'), @@ -180,36 +258,5 @@ def test_load_raw_upgrade_paths_for_distro_and_flavour(monkeypatch, distro, flav ] ) 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', - } - }, - 'almalinux': { - 'default': { - '8.10': ['9.0', '9.1', '9.2', '9.3', '9.4', '9.5', '9.6'], - '9.6': ['10.0'] - } - }, - } - - result = ipuworkflowconfig.construct_virtual_version(defined_upgrade_paths, *construction_params) + result = ipuworkflowconfig.get_virtual_version(TEST_UPGRADE_PATHS, *construction_params) assert result == expected_versions -- 2.51.1