leapp-repository/0061-Introduce-deprecated-IPUPaths-msg-temporary-solution.patch
Petr Stodulka 74a92adf20 IPU 9.6-10.0: CTC 2 candidate 2
- Detect XFS file systems with problematic parameters
- Raise an inhibitor if unsupported target version supplied instead of error
- Prevent a possible crash with LiveMode when adding the upgrade boot entry on systems with LVM
- Resolves: RHEL-57043, RHEL-52309, RHEL-60034
2025-01-29 15:26:03 +01:00

304 lines
11 KiB
Diff

From a6438828415c094c600de80e2e05409a4ccd5822 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Wed, 29 Jan 2025 04:43:33 +0100
Subject: [PATCH 61/63] Introduce deprecated IPUPaths msg (temporary solution)
This is hackish precursor to move checking of the specified
target system versions into actors to be able to create report
when unsupported target version is specified.
The problem is that currently there is no information about the
supported upgrade paths in messages. Also, the information about
supported source and target versions are stored in two different
places (in system upgrade common repo):
* shared configs.version library
* files/upgrade_paths.json
As a temporary solution let's introduce IPUPaths message which
will contain filtered data from the json file based on:
* the upgrade flavour (default, saphana)
* and source major version
There is no value to print information to users about different
upgrade paths for other flavours and OS major versions. The model
is marked as deprecated so we can remove it in the next release when
we redesign this solution to unify how actors get this data
(and define them just in one place).
jira: RHEL-51072
---
.../actors/scandefinedipupaths/actor.py | 31 ++++++
.../libraries/scandefinedipupaths.py | 43 ++++++++
.../tests/files/upgrade_paths.json | 15 +++
.../tests/test_scandefinedipupaths.py | 97 +++++++++++++++++++
.../system_upgrade/common/models/ipupaths.py | 43 ++++++++
5 files changed, 229 insertions(+)
create mode 100644 repos/system_upgrade/common/actors/scandefinedipupaths/actor.py
create mode 100644 repos/system_upgrade/common/actors/scandefinedipupaths/libraries/scandefinedipupaths.py
create mode 100644 repos/system_upgrade/common/actors/scandefinedipupaths/tests/files/upgrade_paths.json
create mode 100644 repos/system_upgrade/common/actors/scandefinedipupaths/tests/test_scandefinedipupaths.py
create mode 100644 repos/system_upgrade/common/models/ipupaths.py
diff --git a/repos/system_upgrade/common/actors/scandefinedipupaths/actor.py b/repos/system_upgrade/common/actors/scandefinedipupaths/actor.py
new file mode 100644
index 00000000..a84c85f2
--- /dev/null
+++ b/repos/system_upgrade/common/actors/scandefinedipupaths/actor.py
@@ -0,0 +1,31 @@
+from leapp.actors import Actor
+from leapp.libraries.actor import scandefinedipupaths
+from leapp.models import IPUPaths
+from leapp.tags import FactsPhaseTag, IPUWorkflowTag
+
+
+class ScanDefinedIPUPaths(Actor):
+ """
+ Load defined IPU paths for the current major source system version
+ and defined upgrade flavour.
+
+ The upgrade paths are defined inside `files/upgrade_paths.json`.
+ Based on the defined upgrade flavour (default, saphana, ..) loads particular
+ definitions and filter out all upgrade paths from other system major versions.
+ I.e. for RHEL 8.10 system with the default upgrade flavour, load all upgrade
+ paths from any RHEL 8 system defined under the 'default' flavour.
+
+ The code is mostly taken from the CLI command_utils. The duplicate solution
+ is not so problematic now as it will be unified next time.
+
+ Note the deprecation suppression is expected here as this is considered as
+ temporary solution now.
+ """
+
+ name = 'scan_defined_ipu_paths'
+ consumes = ()
+ produces = (IPUPaths,)
+ tags = (IPUWorkflowTag, FactsPhaseTag)
+
+ def process(self):
+ scandefinedipupaths.process()
diff --git a/repos/system_upgrade/common/actors/scandefinedipupaths/libraries/scandefinedipupaths.py b/repos/system_upgrade/common/actors/scandefinedipupaths/libraries/scandefinedipupaths.py
new file mode 100644
index 00000000..1e39f2c8
--- /dev/null
+++ b/repos/system_upgrade/common/actors/scandefinedipupaths/libraries/scandefinedipupaths.py
@@ -0,0 +1,43 @@
+import json
+
+from leapp.libraries.common.config.version import get_source_major_version
+from leapp.libraries.stdlib import api
+from leapp.models import IPUPath, IPUPaths
+from leapp.utils.deprecation import suppress_deprecation
+
+
+def load_ipu_paths_for_flavour(flavour, _filename='upgrade_paths.json'):
+ """
+ Load defined IPU paths from the upgrade_paths.json file for the specified
+ flavour.
+
+ Note the file is required to be always present, so skipping any test
+ for the missing file. Crash hard and terribly if the file is missing
+ or the content is invalid.
+
+ We expect the flavour to be always good as it is under our control
+ (already sanitized in IPUConfig), but return empty dict and log it if missing.
+ """
+ with open(api.get_common_file_path(_filename)) as fp:
+ data = json.loads(fp.read())
+ if flavour not in data:
+ api.current_logger().warning(
+ 'Cannot discover any upgrade paths for flavour: {}'
+ .format(flavour)
+ )
+ return data.get(flavour, {})
+
+
+def get_filtered_ipu_paths(ipu_paths, src_major_version):
+ result = []
+ for src_version, tgt_versions in ipu_paths.items():
+ if src_version.split('.')[0] == src_major_version:
+ result.append(IPUPath(source_version=src_version, target_versions=tgt_versions))
+ return result
+
+
+@suppress_deprecation(IPUPaths)
+def process():
+ flavour = api.current_actor().configuration.flavour
+ ipu_paths = load_ipu_paths_for_flavour(flavour)
+ api.produce(IPUPaths(data=get_filtered_ipu_paths(ipu_paths, get_source_major_version())))
diff --git a/repos/system_upgrade/common/actors/scandefinedipupaths/tests/files/upgrade_paths.json b/repos/system_upgrade/common/actors/scandefinedipupaths/tests/files/upgrade_paths.json
new file mode 100644
index 00000000..edd32224
--- /dev/null
+++ b/repos/system_upgrade/common/actors/scandefinedipupaths/tests/files/upgrade_paths.json
@@ -0,0 +1,15 @@
+{
+ "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"]
+ }
+}
diff --git a/repos/system_upgrade/common/actors/scandefinedipupaths/tests/test_scandefinedipupaths.py b/repos/system_upgrade/common/actors/scandefinedipupaths/tests/test_scandefinedipupaths.py
new file mode 100644
index 00000000..9ffc9829
--- /dev/null
+++ b/repos/system_upgrade/common/actors/scandefinedipupaths/tests/test_scandefinedipupaths.py
@@ -0,0 +1,97 @@
+import json
+import os
+
+import pytest
+
+from leapp.libraries.actor import scandefinedipupaths
+from leapp.libraries.common.testutils import CurrentActorMocked, produce_mocked
+from leapp.models import IPUPath, IPUPaths
+from leapp.utils.deprecation import suppress_deprecation
+
+CUR_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+class CurrentActorMockedModified(CurrentActorMocked):
+ def get_common_file_path(self, fname):
+ fpath = os.path.join(CUR_DIR, 'files', fname)
+ assert os.path.exists(fpath)
+ if os.path.exists(fpath):
+ return fpath
+ return None
+
+
+@pytest.mark.parametrize(('flavour', 'expected_result'), (
+ ('nonsense', {}),
+ (
+ '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']
+ }
+ ),
+))
+def test_load_ipu_paths_for_flavour(monkeypatch, flavour, expected_result):
+ monkeypatch.setattr(scandefinedipupaths.api, 'current_actor', CurrentActorMockedModified())
+
+ result = scandefinedipupaths.load_ipu_paths_for_flavour(flavour=flavour)
+ assert result == expected_result
+
+
+_DATA_IPU_PATHS = {
+ '8.10': ['9.4', '9.5', '9.6'],
+ '8.4': ['9.2'],
+ '9.6': ['10.0'],
+ '8': ['9.4', '9.5', '9.6'],
+ '80.0': ['81.0']
+}
+
+
+@suppress_deprecation(IPUPaths)
+@pytest.mark.parametrize(('maj_version', 'expected_result'), (
+ ('7', []),
+ (
+ '8',
+ [
+ IPUPath(source_version='8.10', target_versions=['9.4', '9.5', '9.6']),
+ IPUPath(source_version='8.4', target_versions=['9.2']),
+ IPUPath(source_version='8', target_versions=['9.4', '9.5', '9.6']),
+ ]
+ ),
+ (
+ '80',
+ [
+ IPUPath(source_version='80.0', target_versions=['81.0']),
+ ]
+ ),
+
+
+))
+def test_get_filtered_ipu_paths(monkeypatch, maj_version, expected_result):
+ result = scandefinedipupaths.get_filtered_ipu_paths(_DATA_IPU_PATHS, maj_version)
+ result = sorted(result, key=lambda x: x.source_version)
+ assert result == sorted(expected_result, key=lambda x: x.source_version)
+
+
+def test_scan_defined_ipu_paths(monkeypatch):
+ # let's try one 'full' happy run
+ monkeypatch.setattr(scandefinedipupaths.api, 'current_actor', CurrentActorMockedModified(src_ver='9.6'))
+ monkeypatch.setattr(scandefinedipupaths.api, 'produce', produce_mocked())
+ scandefinedipupaths.process()
+
+ assert scandefinedipupaths.api.produce.called == 1
+ msg = scandefinedipupaths.api.produce.model_instances[0]
+ assert isinstance(msg, IPUPaths)
+ assert len(msg.data) == 2
+ assert {i.source_version for i in msg.data} == {'9', '9.6'}
diff --git a/repos/system_upgrade/common/models/ipupaths.py b/repos/system_upgrade/common/models/ipupaths.py
new file mode 100644
index 00000000..5469f25e
--- /dev/null
+++ b/repos/system_upgrade/common/models/ipupaths.py
@@ -0,0 +1,43 @@
+from leapp.models import fields, Model
+from leapp.topics import SystemInfoTopic
+from leapp.utils.deprecation import deprecated
+
+
+class IPUPath(Model):
+ """
+ Represent upgrade paths from a source system version.
+
+ This model is not supposed to be produced nor consumed directly by any actor.
+ See `IPUPaths` instead.
+ """
+ topic = SystemInfoTopic
+
+ source_version = fields.String()
+ """Version of a particular source system."""
+
+ target_versions = fields.List(fields.String())
+ """List of defined target system versions for the `source_version` system."""
+
+
+@deprecated(
+ since="2025-02-01",
+ message="This model is temporary and not assumed to be used in any actors."
+)
+class IPUPaths(Model):
+ """
+ Defined Upgrade paths from the source system major version and used upgrade flavour.
+
+ In example for the RHEL 8.10 system with the 'default' upgrade flavour it will
+ contain information about all defined upgrade paths from any RHEL 8 system
+ for the 'default' flavour (other flavour can be e.g. 'saphana' for systems
+ with SAP HANA installed.
+
+ Note this model is marked as deprecated now as it is considered as a temporary
+ solution. It can be removed in any future release!
+ """
+ topic = SystemInfoTopic
+
+ data = fields.List(fields.Model(IPUPath))
+ """
+ List of defined (filtered) upgrade paths.
+ """
--
2.48.1