Import from CS git

(cherry picked from commit 5bdc5cf293)
This commit is contained in:
eabdullin 2025-05-15 07:48:12 +00:00 committed by Yuriy Kohut
parent f0c47bb5a3
commit b1bd6e77a6
38 changed files with 98729 additions and 5 deletions

View File

@ -0,0 +1,49 @@
From 092ea5e7c5b8a453bcd30be5fefb0e2ecab752c4 Mon Sep 17 00:00:00 2001
From: Yuriy Kohut <yura.kohut@gmail.com>
Date: Mon, 3 Mar 2025 15:36:43 +0200
Subject: [PATCH 01/37] Use leapp.libraries.common.rpms.get_leapp_packages
(which is backward compatible) to get the list of leapp and leapp-repository
rpms, that should be preserved during the 9to10 upgrade
Do not import get_source_major_version as it isn't used anywhere
---
.../common/libraries/dnfconfig.py | 22 +------------------
1 file changed, 1 insertion(+), 21 deletions(-)
diff --git a/repos/system_upgrade/common/libraries/dnfconfig.py b/repos/system_upgrade/common/libraries/dnfconfig.py
index 5b8180f0..4b5afeb5 100644
--- a/repos/system_upgrade/common/libraries/dnfconfig.py
+++ b/repos/system_upgrade/common/libraries/dnfconfig.py
@@ -1,28 +1,8 @@
from leapp.exceptions import StopActorExecutionError
-from leapp.libraries.common.config.version import get_source_major_version
+from leapp.libraries.common.rpms import get_leapp_packages
from leapp.libraries.stdlib import api, CalledProcessError
-def get_leapp_packages():
- """
- Return the list of leapp and leapp-repository rpms that should be preserved
- during the upgrade.
-
- It's list of packages that should be preserved, not what is really
- installed.
-
- The snactor RPM doesn't have to be installed, but if so, we have to take
- care about that too as well to prevent broken dnf transaction.
- """
- # TODO: should we set the seatbelt and exclude leapp RPMs from the target
- # system too?
- generic = ['leapp', 'snactor']
- if get_source_major_version() == '7':
- return generic + ['python2-leapp', 'leapp-upgrade-el7toel8']
-
- return generic + ['python3-leapp', 'leapp-upgrade-el8toel9']
-
-
def _strip_split(data, sep, maxsplit=-1):
"""
Just like str.split(), but remove ambient whitespaces from all items
--
2.49.0

View File

@ -0,0 +1,38 @@
From 1be52a6430b878bd4984bcf2577f3c7c847d2e48 Mon Sep 17 00:00:00 2001
From: Joe Ashcraft <joeashcraft@gmail.com>
Date: Tue, 4 Mar 2025 16:31:14 -0600
Subject: [PATCH 02/37] fix - spell AllowZoneDrifting correctly
resolves #1354
---
.../actors/firewalldcheckallowzonedrifting/actor.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/repos/system_upgrade/el8toel9/actors/firewalldcheckallowzonedrifting/actor.py b/repos/system_upgrade/el8toel9/actors/firewalldcheckallowzonedrifting/actor.py
index 0002f6aa..6f1c8f43 100644
--- a/repos/system_upgrade/el8toel9/actors/firewalldcheckallowzonedrifting/actor.py
+++ b/repos/system_upgrade/el8toel9/actors/firewalldcheckallowzonedrifting/actor.py
@@ -7,9 +7,9 @@ from leapp.tags import ChecksPhaseTag, IPUWorkflowTag
class FirewalldCheckAllowZoneDrifting(Actor):
"""
- This actor will check if AllowZoneDrifiting=yes in firewalld.conf. This
+ This actor will check if AllowZoneDrifting=yes in firewalld.conf. This
option has been removed in RHEL-9 and behavior is as if
- AllowZoneDrifiting=no.
+ AllowZoneDrifting=no.
"""
name = 'firewalld_check_allow_zone_drifting'
@@ -37,7 +37,7 @@ class FirewalldCheckAllowZoneDrifting(Actor):
reporting.Summary('Firewalld has enabled configuration option '
'"{conf_key}" which has been removed in RHEL-9. '
'New behavior is as if "{conf_key}" was set to "no".'.format(
- conf_key='AllowZoneDrifiting')),
+ conf_key='AllowZoneDrifting')),
reporting.Severity(reporting.Severity.HIGH),
reporting.Groups([reporting.Groups.SANITY, reporting.Groups.FIREWALL]),
reporting.Groups([reporting.Groups.INHIBITOR]),
--
2.49.0

View File

@ -0,0 +1,134 @@
From 9ea195e84dbc70e4539efe86b6d8f8ca597e2661 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Thu, 27 Feb 2025 09:36:45 +0100
Subject: [PATCH 03/37] cli(upgrade): allow users to enable entire experimental
features
Introduce a new CLI option --enable-experimental-feature that allows
users to enable entire features that might be facilitated by a large
number of experimental actors. Previously, the used had to
remember/figure out the names of all of these actors and list them
manually using `--whitelist-experimental`. Using
`--enable-experimental-feature` therefore lifts this burden from the
user, and the user simply needs to know what experimental feature to
enable. The help for the new options includes a list of all supported
experimental feature - at the moment, the list contains only 'livemode'.
Jira-ref: RHELMISC-10648
---
commands/preupgrade/__init__.py | 4 ++++
commands/rerun/__init__.py | 1 +
commands/upgrade/__init__.py | 4 ++++
commands/upgrade/util.py | 35 ++++++++++++++++++++++++++++++++-
4 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/commands/preupgrade/__init__.py b/commands/preupgrade/__init__.py
index c1fabbbd..e52b6561 100644
--- a/commands/preupgrade/__init__.py
+++ b/commands/preupgrade/__init__.py
@@ -14,6 +14,10 @@ from leapp.utils.output import beautify_actor_exception, report_errors, report_i
@command('preupgrade', help='Generate preupgrade report')
@command_opt('whitelist-experimental', action='append', metavar='ActorName', help='Enables experimental actors')
+@command_opt('enable-experimental-feature', action='append', metavar='Feature',
+ help=('Enable experimental feature. '
+ 'Available experimental features: {}').format(util.get_help_str_with_avail_experimental_features()),
+ choices=list(util.EXPERIMENTAL_FEATURES), default=[])
@command_opt('debug', is_flag=True, help='Enable debug mode', inherit=False)
@command_opt('verbose', is_flag=True, help='Enable verbose logging', inherit=False)
@command_opt('no-rhsm', is_flag=True, help='Use only custom repositories and skip actions'
diff --git a/commands/rerun/__init__.py b/commands/rerun/__init__.py
index a06dd266..842178af 100644
--- a/commands/rerun/__init__.py
+++ b/commands/rerun/__init__.py
@@ -71,6 +71,7 @@ def rerun(args):
nogpgcheck=False,
channel=None,
report_schema='1.1.0',
+ enable_experimental_feature=[],
whitelist_experimental=[],
enablerepo=[]))
diff --git a/commands/upgrade/__init__.py b/commands/upgrade/__init__.py
index 608099ac..6f7504bf 100644
--- a/commands/upgrade/__init__.py
+++ b/commands/upgrade/__init__.py
@@ -20,6 +20,10 @@ from leapp.utils.output import beautify_actor_exception, report_errors, report_i
@command_opt('resume', is_flag=True, help='Continue the last execution after it was stopped (e.g. after reboot)')
@command_opt('reboot', is_flag=True, help='Automatically performs reboot when requested.')
@command_opt('whitelist-experimental', action='append', metavar='ActorName', help='Enable experimental actors')
+@command_opt('enable-experimental-feature', action='append', metavar='Feature',
+ help=('Enable experimental feature. '
+ 'Available experimental features: {}').format(util.get_help_str_with_avail_experimental_features()),
+ choices=list(util.EXPERIMENTAL_FEATURES), default=[])
@command_opt('debug', is_flag=True, help='Enable debug mode', inherit=False)
@command_opt('verbose', is_flag=True, help='Enable verbose logging', inherit=False)
@command_opt('no-rhsm', is_flag=True, help='Use only custom repositories and skip actions'
diff --git a/commands/upgrade/util.py b/commands/upgrade/util.py
index b20c316d..bfdbc4fa 100644
--- a/commands/upgrade/util.py
+++ b/commands/upgrade/util.py
@@ -17,6 +17,25 @@ from leapp.utils.output import report_unsupported
from leapp.utils.report import fetch_upgrade_report_messages, generate_report_file
+EXPERIMENTAL_FEATURES = {
+ 'livemode': [
+ 'live_image_generator',
+ 'live_mode_config_scanner',
+ 'live_mode_reporter',
+ 'prepare_live_image',
+ 'emit_livemode_requirements',
+ 'remove_live_image',
+ ]
+}
+""" Maps experimental features to a set of experimental actors that need to be enabled. """
+
+
+def get_help_str_with_avail_experimental_features():
+ if EXPERIMENTAL_FEATURES:
+ return ', '.join(EXPERIMENTAL_FEATURES)
+ return 'There are no experimental features available'
+
+
def disable_database_sync():
def disable_db_sync_decorator(f):
@functools.wraps(f)
@@ -184,11 +203,25 @@ def handle_output_level(args):
# the latest supported release because of target_version discovery attempt.
def prepare_configuration(args):
"""Returns a configuration dict object while setting a few env vars as a side-effect"""
+
if args.whitelist_experimental:
args.whitelist_experimental = list(itertools.chain(*[i.split(',') for i in args.whitelist_experimental]))
os.environ['LEAPP_EXPERIMENTAL'] = '1'
else:
os.environ['LEAPP_EXPERIMENTAL'] = '0'
+ args.whitelist_experimental = []
+
+ for experimental_feature in set(args.enable_experimental_feature):
+ # It might happen that there are no experimental features, which would allow user
+ # to pass us any string as an experimental feature.
+ if experimental_feature not in EXPERIMENTAL_FEATURES:
+ continue
+
+ actors_needed_for_feature = EXPERIMENTAL_FEATURES[experimental_feature]
+ args.whitelist_experimental.extend(actors_needed_for_feature)
+ if args.enable_experimental_feature:
+ os.environ['LEAPP_EXPERIMENTAL'] = '1'
+
os.environ['LEAPP_UNSUPPORTED'] = '0' if os.getenv('LEAPP_UNSUPPORTED', '0') == '0' else '1'
if args.no_rhsm:
os.environ['LEAPP_NO_RHSM'] = '1'
@@ -235,7 +268,7 @@ def prepare_configuration(args):
configuration = {
'debug': os.getenv('LEAPP_DEBUG', '0'),
'verbose': os.getenv('LEAPP_VERBOSE', '0'),
- 'whitelist_experimental': args.whitelist_experimental or (),
+ 'whitelist_experimental': args.whitelist_experimental or (), # Modified to also contain exp. features
'environment': {env: os.getenv(env) for env in os.environ if env.startswith('LEAPP_')},
'cmd': sys.argv,
}
--
2.49.0

View File

@ -0,0 +1,91 @@
From 11b9733cfe1c7cc10db675fba24d94c0c30f6b6e Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Thu, 27 Feb 2025 10:18:17 +0100
Subject: [PATCH 04/37] feat(livemode): exclude DNF cache from the created
squashfs image
Exclude /var/cache/dnf from the generated squashfs image. The DNF
cache is not needed for the live system that we boot into, since leapp
will always use DNF cache stored within target userspace container
(/sysroot/var/lib/leapp/...). Therefore, this optimization saves
a lot of disk space for the user (2GB->700mb).
---
.../libraries/liveimagegenerator.py | 22 ++++++++++++++-----
.../tests/test_image_generation.py | 6 +++--
2 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/repos/system_upgrade/common/actors/livemode/liveimagegenerator/libraries/liveimagegenerator.py b/repos/system_upgrade/common/actors/livemode/liveimagegenerator/libraries/liveimagegenerator.py
index af8981d8..46118630 100644
--- a/repos/system_upgrade/common/actors/livemode/liveimagegenerator/libraries/liveimagegenerator.py
+++ b/repos/system_upgrade/common/actors/livemode/liveimagegenerator/libraries/liveimagegenerator.py
@@ -24,7 +24,7 @@ def lighten_target_userpace(context):
tree_to_prune, error)
-def build_squashfs(livemode_config, userspace_info):
+def build_squashfs(livemode_config, userspace_info, paths_to_exclude=None):
"""
Generate the live rootfs image based on the target userspace
@@ -34,8 +34,11 @@ def build_squashfs(livemode_config, userspace_info):
target_userspace_fullpath = userspace_info.path
squashfs_fullpath = livemode_config.squashfs_fullpath
- api.current_logger().info('Building the squashfs image %s from target userspace located at %s',
- squashfs_fullpath, target_userspace_fullpath)
+ if not paths_to_exclude:
+ paths_to_exclude = []
+
+ api.current_logger().info('Building the squashfs image %s from target userspace located at %s with excludes: %s',
+ squashfs_fullpath, target_userspace_fullpath, ', '.join(paths_to_exclude))
try:
if os.path.exists(squashfs_fullpath):
@@ -44,8 +47,13 @@ def build_squashfs(livemode_config, userspace_info):
api.current_logger().warning('Failed to remove already existing %s. Full error: %s',
squashfs_fullpath, error)
+ mksquashfs_command = ['mksquashfs', target_userspace_fullpath, squashfs_fullpath]
+ if paths_to_exclude:
+ mksquashfs_command.append('-e')
+ mksquashfs_command.extend(paths_to_exclude)
+
try:
- run(['mksquashfs', target_userspace_fullpath, squashfs_fullpath])
+ run(mksquashfs_command)
except CalledProcessError as error:
raise StopActorExecutionError(
'Cannot pack the target userspace into a squash image. ',
@@ -68,5 +76,9 @@ def generate_live_image_if_enabled():
with mounting.NspawnActions(base_dir=userspace_info.path) as context:
lighten_target_userpace(context)
- squashfs_path = build_squashfs(livemode_config, userspace_info)
+
+ # Exclude the DNF cache - we do not need it, leapp mounts /sysroot and uses userspace's dnf cache from there
+ paths_to_exclude = [os.path.join(userspace_info.path, 'var/cache/dnf')]
+
+ squashfs_path = build_squashfs(livemode_config, userspace_info, paths_to_exclude=paths_to_exclude)
api.produce(LiveModeArtifacts(squashfs_path=squashfs_path))
diff --git a/repos/system_upgrade/common/actors/livemode/liveimagegenerator/tests/test_image_generation.py b/repos/system_upgrade/common/actors/livemode/liveimagegenerator/tests/test_image_generation.py
index 5c434a6b..16ae0a09 100644
--- a/repos/system_upgrade/common/actors/livemode/liveimagegenerator/tests/test_image_generation.py
+++ b/repos/system_upgrade/common/actors/livemode/liveimagegenerator/tests/test_image_generation.py
@@ -78,10 +78,12 @@ def test_generate_live_image_if_enabled(monkeypatch, livemode_config, should_pro
def __exit__(self, *args, **kwargs):
pass
+ def build_squashfs_image_mock(livemode_config, userspace_info, *args, **kwargs):
+ return '/squashfs'
+
monkeypatch.setattr(mounting, 'NspawnActions', NspawnMock)
monkeypatch.setattr(live_image_generator_lib, 'lighten_target_userpace', lambda context: None)
- monkeypatch.setattr(live_image_generator_lib, 'build_squashfs',
- lambda livemode_config, userspace_info: '/squashfs')
+ monkeypatch.setattr(live_image_generator_lib, 'build_squashfs', build_squashfs_image_mock)
monkeypatch.setattr(api, 'produce', produce_mocked())
live_image_generator_lib.generate_live_image_if_enabled()
--
2.49.0

View File

@ -0,0 +1,156 @@
From 36d245e59bab8f392c163c01a77f0ea9b210d0a2 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Fri, 28 Feb 2025 11:02:32 +0100
Subject: [PATCH 05/37] livemode(cfg): add declaration of livemode config
fields
Add definitions of all config classes that describe configuration of the
livemode feature using the configurability provided by the leapp
framework. The list of configuration options remains unchanged (except
for the `is_enabled` field that is removed) when compared to the
current implementation that relies on an ad-hoc INI file. The next step
is to drop the INI-based implementation in favour of using
framework-based configs relying on the field definitions from this PR.
Jira-ref: RHELMISC-10648
---
.../configs/livemode.py | 127 ++++++++++++++++++
1 file changed, 127 insertions(+)
create mode 100644 repos/system_upgrade/common/actors/livemode/livemode_config_scanner/configs/livemode.py
diff --git a/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/configs/livemode.py b/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/configs/livemode.py
new file mode 100644
index 00000000..eeef03f8
--- /dev/null
+++ b/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/configs/livemode.py
@@ -0,0 +1,127 @@
+"""
+Configuration keys for the 'livemode' feature.
+"""
+
+from leapp.actors.config import Config
+from leapp.models import fields
+
+LIVEMODE_CONFIG_SECTION = 'livemode'
+
+
+class SquashfsImagePath(Config):
+ section = LIVEMODE_CONFIG_SECTION
+ name = "squashfs_image_path"
+ type_ = fields.String()
+ default = '/var/lib/leapp/live-upgrade.img'
+ description = """
+ Location where the squashfs image of the minimal target system will be placed.
+ """
+
+
+class AdditionalPackages(Config):
+ section = LIVEMODE_CONFIG_SECTION
+ name = "additional_packages"
+ type_ = fields.List(fields.String())
+ default = []
+ description = """
+ Additional packages to be installed into the squashfs image.
+
+ Can be used to install various debugging utilities when connecting to the upgrade environment.
+ """
+
+
+class AutostartUpgradeAfterReboot(Config):
+ section = LIVEMODE_CONFIG_SECTION
+ name = "autostart_upgrade_after_reboot"
+ type_ = fields.Boolean()
+ default = True
+ description = """
+ If set to True, the upgrade will start automatically after the reboot. Otherwise a manual trigger is required.
+ """
+
+
+class SetupNetworkManager(Config):
+ section = LIVEMODE_CONFIG_SECTION
+ name = "setup_network_manager"
+ type_ = fields.Boolean()
+ default = False
+ description = """
+ Try enabling Network Manager in the squashfs image.
+
+ If set to True, leapp will copy source system's Network Manager profiles into the squashfs image and
+ enable the Network Manager service.
+ """
+
+
+class DracutNetwork(Config):
+ section = LIVEMODE_CONFIG_SECTION
+ name = "dracut_network"
+ type_ = fields.String()
+ default = ''
+ description = """
+ Dracut network arguments, required if the `url_to_load_squashfs_from` option is set.
+
+ Example:
+ ip=192.168.122.146::192.168.122.1:255.255.255.0:foo::none
+ """
+
+
+class URLToLoadSquashfsImageFrom(Config):
+ section = LIVEMODE_CONFIG_SECTION
+ name = "url_to_load_squashfs_image_from"
+ type_ = fields.String()
+ default = ''
+ description = """
+ Url pointing to the squashfs image that should be used for the upgrade environment.
+
+ Example:
+ http://192.168.122.1/live-upgrade.img
+ """
+
+
+class SetupPasswordlessRoot(Config):
+ section = LIVEMODE_CONFIG_SECTION
+ name = "setup_passwordless_root"
+ type_ = fields.Boolean()
+ default = False
+ description = """
+ If set to True, the root account of the squashfs image will have empty password. Use with caution.
+ """
+
+
+class SetupOpenSSHDUsingAuthKeys(Config):
+ section = LIVEMODE_CONFIG_SECTION
+ name = "setup_opensshd_using_auth_keys"
+ type_ = fields.String()
+ default = ''
+ description = """
+ If set to a non-empty string, openssh daemon will be setup within the squashfs image using the provided
+ authorized keys.
+
+ Example:
+ /root/.ssh/authorized_keys
+ """
+
+
+class CaptureSTraceInfoInto(Config):
+ section = LIVEMODE_CONFIG_SECTION
+ name = "capture_strace_info_into"
+ type_ = fields.String()
+ default = ''
+ description = """
+ If set to a non-empty string, leapp will be executed under strace and results will be stored within
+ the provided file path.
+ """
+
+
+livemode_cfg_fields = (
+ AdditionalPackages,
+ AutostartUpgradeAfterReboot,
+ CaptureSTraceInfoInto,
+ DracutNetwork,
+ SetupNetworkManager,
+ SetupOpenSSHDUsingAuthKeys,
+ SetupPasswordlessRoot,
+ SquashfsImagePath,
+ URLToLoadSquashfsImageFrom,
+)
--
2.49.0

View File

@ -0,0 +1,250 @@
From 849a8f2fcd04ee6d419b3856562fbff5b85577f5 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Thu, 6 Mar 2025 11:33:05 +0100
Subject: [PATCH 06/37] livemode(cfg): use framework's configurability instead
of ad-hoc INI
Drop the ad-hoc INI-based config for livemode in favour and replace it
with configuration facilitated by the leapp framework. The list of
configuration options remains (and their semantics) remains almost
unchanged, save for some field names that are renamed in a way that
better reveals their effect to the user.
Jira-ref: RHELMISC-10648
---
commands/upgrade/util.py | 1 -
etc/leapp/files/devel-livemode.ini | 9 --
.../livemode/livemode_config_scanner/actor.py | 2 +
.../libraries/scan_livemode_config.py | 101 +++++-------------
.../tests/test_config_scanner.py | 40 +++----
5 files changed, 44 insertions(+), 109 deletions(-)
delete mode 100644 etc/leapp/files/devel-livemode.ini
diff --git a/commands/upgrade/util.py b/commands/upgrade/util.py
index bfdbc4fa..6cdfa6d8 100644
--- a/commands/upgrade/util.py
+++ b/commands/upgrade/util.py
@@ -16,7 +16,6 @@ from leapp.utils.audit import get_checkpoints, get_connection, get_messages
from leapp.utils.output import report_unsupported
from leapp.utils.report import fetch_upgrade_report_messages, generate_report_file
-
EXPERIMENTAL_FEATURES = {
'livemode': [
'live_image_generator',
diff --git a/etc/leapp/files/devel-livemode.ini b/etc/leapp/files/devel-livemode.ini
deleted file mode 100644
index b79ed4df..00000000
--- a/etc/leapp/files/devel-livemode.ini
+++ /dev/null
@@ -1,9 +0,0 @@
-# Configuration for the *experimental* livemode feature
-# It is likely that this entire configuration file will be replaced by some
-# other mechanism/file in the future. For the full list of configuration options,
-# see models/livemode.py
-[livemode]
-squashfs_fullpath=/var/lib/leapp/live-upgrade.img
-setup_network_manager=no
-autostart_upgrade_after_reboot=yes
-setup_passwordless_root=no
diff --git a/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/actor.py b/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/actor.py
index dc79ecff..bd909736 100644
--- a/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/actor.py
+++ b/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/actor.py
@@ -1,4 +1,5 @@
from leapp.actors import Actor
+from leapp.configs.actor import livemode as livemode_config_lib
from leapp.libraries.actor import scan_livemode_config as scan_livemode_config_lib
from leapp.models import InstalledRPM, LiveModeConfig
from leapp.tags import ExperimentalTag, FactsPhaseTag, IPUWorkflowTag
@@ -10,6 +11,7 @@ class LiveModeConfigScanner(Actor):
"""
name = 'live_mode_config_scanner'
+ config_schemas = livemode_config_lib.livemode_cfg_fields
consumes = (InstalledRPM,)
produces = (LiveModeConfig,)
tags = (ExperimentalTag, FactsPhaseTag, IPUWorkflowTag,)
diff --git a/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/libraries/scan_livemode_config.py b/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/libraries/scan_livemode_config.py
index b2f0af7f..57408c23 100644
--- a/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/libraries/scan_livemode_config.py
+++ b/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/libraries/scan_livemode_config.py
@@ -1,14 +1,9 @@
-try:
- import configparser
-except ImportError:
- import ConfigParser as configparser
-
+from leapp.configs.actor import livemode as livemode_config_lib
from leapp.exceptions import StopActorExecutionError
from leapp.libraries.common.config import architecture, get_env
from leapp.libraries.common.rpms import has_package
from leapp.libraries.stdlib import api
from leapp.models import InstalledRPM, LiveModeConfig
-from leapp.models.fields import ModelViolationError
LIVEMODE_CONFIG_LOCATION = '/etc/leapp/files/devel-livemode.ini'
DEFAULT_SQUASHFS_PATH = '/var/lib/leapp/live-upgrade.img'
@@ -50,76 +45,32 @@ def scan_config_and_emit_message():
return
api.current_logger().info('Loading livemode config from %s', LIVEMODE_CONFIG_LOCATION)
- parser = configparser.ConfigParser()
- try:
- parser.read((LIVEMODE_CONFIG_LOCATION, ))
- except configparser.ParsingError as error:
- api.current_logger().error('Failed to parse live mode configuration due to the following error: %s', error)
+ config = api.current_actor().config[livemode_config_lib.LIVEMODE_CONFIG_SECTION]
+
+ # Mapping from model field names to configuration fields - because we might have
+ # changed some configuration field names for configuration to be more
+ # comprehensible for our users.
+ model_fields_to_config_options_map = {
+ 'url_to_load_squashfs_from': livemode_config_lib.URLToLoadSquashfsImageFrom,
+ 'squashfs_fullpath': livemode_config_lib.SquashfsImagePath,
+ 'dracut_network': livemode_config_lib.DracutNetwork,
+ 'setup_network_manager': livemode_config_lib.SetupNetworkManager,
+ 'additional_packages': livemode_config_lib.AdditionalPackages,
+ 'autostart_upgrade_after_reboot': livemode_config_lib.AutostartUpgradeAfterReboot,
+ 'setup_opensshd_with_auth_keys': livemode_config_lib.SetupOpenSSHDUsingAuthKeys,
+ 'setup_passwordless_root': livemode_config_lib.SetupPasswordlessRoot,
+ 'capture_upgrade_strace_into': livemode_config_lib.CaptureSTraceInfoInto
+ }
- details = 'Failed to read livemode configuration due to the following error: {0}.'
- raise StopActorExecutionError(
- 'Failed to read livemode configuration',
- details={'Problem': details.format(error)}
- )
+ # Read values of model fields from user-supplied configuration according to the above mapping
+ config_msg_init_kwargs = {}
+ for model_field_name, config_field in model_fields_to_config_options_map.items():
+ config_msg_init_kwargs[model_field_name] = config[config_field.name]
- livemode_section = 'livemode'
- if not parser.has_section(livemode_section):
- details = 'The configuration is missing the \'[{0}]\' section'.format(livemode_section)
- raise StopActorExecutionError(
- 'Live mode configuration does not have the required structure',
- details={'Problem': details}
- )
-
- config_kwargs = {
- 'is_enabled': True,
- 'url_to_load_squashfs_from': None,
- 'squashfs_fullpath': DEFAULT_SQUASHFS_PATH,
- 'dracut_network': None,
- 'setup_network_manager': False,
- 'additional_packages': [],
- 'autostart_upgrade_after_reboot': True,
- 'setup_opensshd_with_auth_keys': None,
- 'setup_passwordless_root': False,
- 'capture_upgrade_strace_into': None
- }
+ # Some fields of the LiveModeConfig are historical and can no longer be changed by the user
+ # in the config. Therefore, we just hard-code them here.
+ config_msg_init_kwargs['is_enabled'] = True
- config_str_options = (
- 'url_to_load_squashfs_from',
- 'squashfs_fullpath',
- 'dracut_network',
- 'setup_opensshd_with_auth_keys',
- 'capture_upgrade_strace_into'
- )
-
- config_list_options = (
- 'additional_packages',
- )
-
- config_bool_options = (
- 'setup_network_manager',
- 'setup_passwordless_root',
- 'autostart_upgrade_after_reboot',
- )
-
- for config_option in config_str_options:
- if parser.has_option(livemode_section, config_option):
- config_kwargs[config_option] = parser.get(livemode_section, config_option)
-
- for config_option in config_bool_options:
- if parser.has_option(livemode_section, config_option):
- config_kwargs[config_option] = parser.getboolean(livemode_section, config_option)
-
- for config_option in config_list_options:
- if parser.has_option(livemode_section, config_option):
- option_val = parser.get(livemode_section, config_option)
- option_list = (opt_val.strip() for opt_val in option_val.split(','))
- option_list = [opt for opt in option_list if opt]
- config_kwargs[config_option] = option_list
-
- try:
- config = LiveModeConfig(**config_kwargs)
- except ModelViolationError as error:
- raise StopActorExecutionError('Failed to parse livemode configuration.', details={'Problem': str(error)})
-
- api.produce(config)
+ config_msg = LiveModeConfig(**config_msg_init_kwargs)
+ api.produce(config_msg)
diff --git a/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/tests/test_config_scanner.py b/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/tests/test_config_scanner.py
index 016f6c04..8ddde22e 100644
--- a/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/tests/test_config_scanner.py
+++ b/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/tests/test_config_scanner.py
@@ -86,29 +86,21 @@ def test_enablement_conditions(monkeypatch, case_descr):
def test_config_scanning(monkeypatch):
""" Test whether scanning a valid config is properly transcribed into a config message. """
- config_lines = [
- '[livemode]',
- 'squashfs_fullpath=IMG',
- 'setup_network_manager=yes',
- 'autostart_upgrade_after_reboot=no',
- 'setup_opensshd_with_auth_keys=/root/.ssh/authorized_keys',
- 'setup_passwordless_root=no',
- 'additional_packages=pkgA,pkgB'
- ]
- config_content = '\n'.join(config_lines) + '\n'
-
- if sys.version[0] == '2':
- config_content = config_content.decode('utf-8') # python2 compat
-
- class ConfigParserMock(configparser.ConfigParser): # pylint: disable=too-many-ancestors
- def read(self, file_paths, *args, **kwargs):
- self.read_string(config_content)
- return file_paths
-
- monkeypatch.setattr(configparser, 'ConfigParser', ConfigParserMock)
-
+ config = {
+ 'livemode': {
+ 'squashfs_image_path': '/var/lib/leapp/live-upgrade2.img',
+ 'additional_packages': ['petri-nets'],
+ 'autostart_upgrade_after_reboot': True,
+ 'setup_network_manager': True,
+ 'setup_passwordless_root': True,
+ 'dracut_network': '',
+ 'url_to_load_squashfs_image_from': '',
+ 'setup_opensshd_using_auth_keys': '/root/.ssh/authorized_keys',
+ 'capture_strace_info_into': ''
+ }
+ }
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(config=config))
monkeypatch.setattr(scan_livemode_config_lib, 'should_scan_config', lambda: True)
-
monkeypatch.setattr(api, 'produce', produce_mocked())
scan_livemode_config_lib.scan_config_and_emit_message()
@@ -119,7 +111,7 @@ def test_config_scanning(monkeypatch):
produced_message = api.produce.model_instances[0]
assert isinstance(produced_message, LiveModeConfig)
- assert produced_message.additional_packages == ['pkgA', 'pkgB']
- assert produced_message.squashfs_fullpath == 'IMG'
+ assert produced_message.additional_packages == ['petri-nets']
+ assert produced_message.squashfs_fullpath == '/var/lib/leapp/live-upgrade2.img'
assert produced_message.setup_opensshd_with_auth_keys == '/root/.ssh/authorized_keys'
assert produced_message.setup_network_manager
--
2.49.0

View File

@ -0,0 +1,61 @@
From 96c911454e4e68a749503b644c31df3a853e8a0b Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Thu, 20 Mar 2025 22:29:36 +0100
Subject: [PATCH 07/37] fix(livemode): do not stop if dbus already appears to
be enabled
Some of the systemd units might be already enabled in the target
userspace container, causing an unhandled FileAlreadyExists error
when we attempt to enable them. This commit ignores such errors, working
on under the assumption that the services we wanted to enable are
already enabled. Hence, we ignore the possibility that the file which
unexpectedly resides at the destination of the symlink which enables the
service might contain some unexpected/incorrect content.
---
.../libraries/prepareliveimage.py | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/repos/system_upgrade/common/actors/livemode/modify_userspace_for_livemode/libraries/prepareliveimage.py b/repos/system_upgrade/common/actors/livemode/modify_userspace_for_livemode/libraries/prepareliveimage.py
index c573c84a..686c4cd6 100644
--- a/repos/system_upgrade/common/actors/livemode/modify_userspace_for_livemode/libraries/prepareliveimage.py
+++ b/repos/system_upgrade/common/actors/livemode/modify_userspace_for_livemode/libraries/prepareliveimage.py
@@ -1,3 +1,4 @@
+import errno
import grp
import os
import os.path
@@ -253,16 +254,30 @@ def enable_dbus(context):
Enable dbus-daemon into the target userspace
Looks like it's not enabled by default when installing into a container.
"""
- api.current_logger().info('Configuring the dbus services')
+ dbus_daemon_service = '/usr/lib/systemd/system/dbus-daemon.service'
links = ['/etc/systemd/system/multi-user.target.wants/dbus-daemon.service',
'/etc/systemd/system/dbus.service',
'/etc/systemd/system/messagebus.service']
+ api.current_logger().info(('Enabling dbus services. Leapp will attempt to create the following '
+ 'symlinks: {0}, all pointing to {1}').format(', '.join(links),
+ dbus_daemon_service))
+
for link in links:
+ api.current_logger().debug('Creating symlink at {0} that points to {1}'.format(link, dbus_daemon_service))
try:
os.symlink('/usr/lib/systemd/system/dbus-daemon.service', context.full_path(link))
except OSError as err:
+ if err.errno == errno.EEXIST:
+ # @Note: We are not catching FileExistsError because of python2 (there is no such error class)
+ # We are performing installations within container, so the systemd symlinks that are created
+ # during installation should have correct destination
+ api.current_logger().debug(
+ 'A file already exists at {0}, assuming it is a symlink with a correct content.'
+ )
+ continue
+
details = {'Problem': 'An error occurred while creating the systemd symlink', 'source_error': str(err)}
raise StopActorExecutionError('Cannot enable the dbus services', details=details)
--
2.49.0

View File

@ -0,0 +1,94 @@
From 6b3f6565e70290da1e02e3945851b430efb02109 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Fri, 11 Apr 2025 15:07:49 +0200
Subject: [PATCH 08/37] feat(livemode): remove the use of
LEAPP_DEVEL_ENABLE_LIVEMODE
The environmental variable has been introduced to prevent accidental
execution of livemode. However, in order for users to use the feature,
this environmental variable introduced unnecessary friction. Therefore,
this patch removes the use of the variable. Instead, whitelisting
experimental actors that facilitate livemode should be the only
mechanism that is used to enabled/disable the feature.
Jira-ref: RHELMISC-10648
---
docs/source/configuring-ipu.md | 3 ---
.../libraries/scan_livemode_config.py | 5 -----
.../tests/test_config_scanner.py | 12 ++++--------
3 files changed, 4 insertions(+), 16 deletions(-)
diff --git a/docs/source/configuring-ipu.md b/docs/source/configuring-ipu.md
index 6b838b8f..059b72c2 100644
--- a/docs/source/configuring-ipu.md
+++ b/docs/source/configuring-ipu.md
@@ -52,9 +52,6 @@ The alternative to the --channel leapp option. As a parameter accepts a channel
To use development variables, the LEAPP_UNSUPPORTED variable has to be set.
```
-#### LEAPP_DEVEL_ENABLE_LIVE_MODE
-If set to `1`, enable the use of the experimental live mode
-
#### LEAPP_DEVEL_DM_DISABLE_UDEV
Setting the environment variable provides a more convenient way of disabling udev support in libdevmapper, dmsetup and LVM2 tools globally without a need to modify any existing configuration settings. This is mostly useful if the system environment does not use udev.
diff --git a/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/libraries/scan_livemode_config.py b/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/libraries/scan_livemode_config.py
index 57408c23..26fd9d09 100644
--- a/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/libraries/scan_livemode_config.py
+++ b/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/libraries/scan_livemode_config.py
@@ -11,16 +11,11 @@ DEFAULT_SQUASHFS_PATH = '/var/lib/leapp/live-upgrade.img'
def should_scan_config():
is_unsupported = get_env('LEAPP_UNSUPPORTED', '0') == '1'
- is_livemode_enabled = get_env('LEAPP_DEVEL_ENABLE_LIVE_MODE', '0') == '1'
if not is_unsupported:
api.current_logger().debug('Will not scan livemode config - the upgrade is not unsupported.')
return False
- if not is_livemode_enabled:
- api.current_logger().debug('Will not scan livemode config - the live mode is not enabled.')
- return False
-
if not architecture.matches_architecture(architecture.ARCH_X86_64):
api.current_logger().debug('Will not scan livemode config - livemode is currently limited to x86_64.')
details = 'Live upgrades are currently limited to x86_64 only.'
diff --git a/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/tests/test_config_scanner.py b/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/tests/test_config_scanner.py
index 8ddde22e..e24aa366 100644
--- a/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/tests/test_config_scanner.py
+++ b/repos/system_upgrade/common/actors/livemode/livemode_config_scanner/tests/test_config_scanner.py
@@ -29,19 +29,16 @@ EnablementTestCase = namedtuple('EnablementTestCase', ('env_vars', 'arch', 'pkgs
@pytest.mark.parametrize(
'case_descr',
(
- EnablementTestCase(env_vars={'LEAPP_UNSUPPORTED': '1', 'LEAPP_DEVEL_ENABLE_LIVE_MODE': '1'},
+ EnablementTestCase(env_vars={'LEAPP_UNSUPPORTED': '1'},
arch=architecture.ARCH_X86_64, pkgs=('squashfs-tools', ),
result=EnablementResult.SCAN_CONFIG),
- EnablementTestCase(env_vars={'LEAPP_UNSUPPORTED': '0', 'LEAPP_DEVEL_ENABLE_LIVE_MODE': '1'},
+ EnablementTestCase(env_vars={'LEAPP_UNSUPPORTED': '0'},
arch=architecture.ARCH_X86_64, pkgs=('squashfs-tools', ),
result=EnablementResult.DO_NOTHING),
- EnablementTestCase(env_vars={'LEAPP_UNSUPPORTED': '1', 'LEAPP_DEVEL_ENABLE_LIVE_MODE': '0'},
- arch=architecture.ARCH_X86_64, pkgs=('squashfs-tools', ),
- result=EnablementResult.DO_NOTHING),
- EnablementTestCase(env_vars={'LEAPP_UNSUPPORTED': '1', 'LEAPP_DEVEL_ENABLE_LIVE_MODE': '1'},
+ EnablementTestCase(env_vars={'LEAPP_UNSUPPORTED': '1'},
arch=architecture.ARCH_ARM64, pkgs=('squashfs-tools', ),
result=EnablementResult.RAISE),
- EnablementTestCase(env_vars={'LEAPP_UNSUPPORTED': '1', 'LEAPP_DEVEL_ENABLE_LIVE_MODE': '1'},
+ EnablementTestCase(env_vars={'LEAPP_UNSUPPORTED': '1'},
arch=architecture.ARCH_ARM64, pkgs=tuple(),
result=EnablementResult.RAISE),
)
@@ -52,7 +49,6 @@ def test_enablement_conditions(monkeypatch, case_descr):
Enablement conditions:
- LEAPP_UNSUPPORTED=1
- - LEAPP_DEVEL_ENABLE_LIVE_MODE=1
Not meeting enablement conditions should prevent config message from being produced.
--
2.49.0

View File

@ -0,0 +1,29 @@
From 021f083509b074905c18b79afba4a22f8ca483f6 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Fri, 11 Apr 2025 15:12:18 +0200
Subject: [PATCH 09/37] spec: require leapp-framework 6.1 for default CLI vals
Bump framework version as we want to use default=[] for the newly
introduced `--enable-experimental-features` switch.
Jira-ref: RHELMISC-10648
---
packaging/leapp-repository.spec | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packaging/leapp-repository.spec b/packaging/leapp-repository.spec
index f45fda68..34768de1 100644
--- a/packaging/leapp-repository.spec
+++ b/packaging/leapp-repository.spec
@@ -120,7 +120,7 @@ Requires: leapp-repository-dependencies = %{leapp_repo_deps}
# IMPORTANT: this is capability provided by the leapp framework rpm.
# Check that 'version' instead of the real framework rpm version.
-Requires: leapp-framework >= 6.0, leapp-framework < 7
+Requires: leapp-framework >= 6.1, leapp-framework < 7
# Since we provide sub-commands for the leapp utility, we expect the leapp
# tool to be installed as well.
--
2.49.0

View File

@ -0,0 +1,98 @@
From 51b26776405a926882509c3f62d0bedbb4eab188 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Mon, 14 Apr 2025 10:07:53 +0200
Subject: [PATCH 10/37] docs(configuring-ipu): add experimental features
section
With the upcoming introduction of documentation of the LiveMode feature,
a question arises where to put the documentation. This patch introduces
a new subsection 'Experimental features' under the 'Configuring IPU'
section, so we have one place to where to put such features.
---
.../{ => configuring-ipu}/configuring-ipu.md | 0
.../experimental-features/index.rst | 23 +++++++++++++++++++
docs/source/configuring-ipu/index.rst | 23 +++++++++++++++++++
docs/source/index.rst | 2 +-
4 files changed, 47 insertions(+), 1 deletion(-)
rename docs/source/{ => configuring-ipu}/configuring-ipu.md (100%)
create mode 100644 docs/source/configuring-ipu/experimental-features/index.rst
create mode 100644 docs/source/configuring-ipu/index.rst
diff --git a/docs/source/configuring-ipu.md b/docs/source/configuring-ipu/configuring-ipu.md
similarity index 100%
rename from docs/source/configuring-ipu.md
rename to docs/source/configuring-ipu/configuring-ipu.md
diff --git a/docs/source/configuring-ipu/experimental-features/index.rst b/docs/source/configuring-ipu/experimental-features/index.rst
new file mode 100644
index 00000000..7a26116e
--- /dev/null
+++ b/docs/source/configuring-ipu/experimental-features/index.rst
@@ -0,0 +1,23 @@
+Experimental features
+========================================================
+
+This section provides descriptions of all available experimental
+features. Low-level details and design decisions of these features
+are provided.
+
+.. warning::
+ Actor configuration is currently a preview of the feature, it might change in future releases.
+
+.. toctree::
+ :maxdepth: 4
+ :caption: Contents:
+ :glob:
+
+
+
+.. Indices and tables
+.. ==================
+..
+.. * :ref:`genindex`
+.. * :ref:`modindex`
+.. * :ref:`search`
diff --git a/docs/source/configuring-ipu/index.rst b/docs/source/configuring-ipu/index.rst
new file mode 100644
index 00000000..1be3ebcf
--- /dev/null
+++ b/docs/source/configuring-ipu/index.rst
@@ -0,0 +1,23 @@
+Configuring the in-place upgrade
+========================================================
+
+This section covers possible ways of modifying the in-place upgrade
+without making any code changes. Leapp offers multiple mechanism
+to affect the upgrade ranging from simple environmental variables
+to more robust configuration files. This section also covers available
+experimental features.
+
+.. toctree::
+ :maxdepth: 4
+ :caption: Contents:
+ :glob:
+
+ configuring-ipu
+ experimental-features/index
+
+.. Indices and tables
+.. ==================
+..
+.. * :ref:`genindex`
+.. * :ref:`modindex`
+.. * :ref:`search`
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 33a920ec..27537ca4 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -19,7 +19,7 @@ providing Red Hat Enterprise Linux in-place upgrade functionality.
tutorials/index
project-structure/index
upgrade-architecture-and-workflow/index
- configuring-ipu
+ configuring-ipu/index
libraries-and-api/index
contrib-and-devel-guidelines
faq
--
2.49.0

View File

@ -0,0 +1,142 @@
From af35d1fd718258d37ed34be59084e7c77072096c Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Mon, 14 Apr 2025 10:14:12 +0200
Subject: [PATCH 11/37] docs(livemode): add LiveMode documentation
This commit introduces a high-level documentation of the livemode
feature. The following is documented:
- how the upgrade process differs from the standard one when using
livemode
- why is the feature useful, i.e., why would anyone use it
- how to enable and use the feature
- what configuration options are available, including an example of
configuration
Jira-ref: RHELMISC-9703
---
.github/workflows/codespell.yml | 2 +-
.../experimental-features/index.rst | 1 +
.../experimental-features/livemode.md | 86 +++++++++++++++++++
3 files changed, 88 insertions(+), 1 deletion(-)
create mode 100644 docs/source/configuring-ipu/experimental-features/livemode.md
diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml
index b8da5ebb..3e595e32 100644
--- a/.github/workflows/codespell.yml
+++ b/.github/workflows/codespell.yml
@@ -17,7 +17,7 @@ jobs:
- uses: actions/checkout@v4
- uses: codespell-project/actions-codespell@v2
with:
- ignore_words_list: ro,fo,couldn,repositor,zeor
+ ignore_words_list: ro,fo,couldn,repositor,zeor,bootup
skip: "./repos/system_upgrade/common/actors/storagescanner/tests/files/mounts,\
./repos/system_upgrade/common/actors/networkmanagerreadconfig/tests/files/nm_cfg_file_error,\
./repos/system_upgrade/el8toel9/actors/xorgdrvfact/tests/files/journalctl-xorg-intel,\
diff --git a/docs/source/configuring-ipu/experimental-features/index.rst b/docs/source/configuring-ipu/experimental-features/index.rst
index 7a26116e..37de2fed 100644
--- a/docs/source/configuring-ipu/experimental-features/index.rst
+++ b/docs/source/configuring-ipu/experimental-features/index.rst
@@ -13,6 +13,7 @@ are provided.
:caption: Contents:
:glob:
+ livemode
.. Indices and tables
diff --git a/docs/source/configuring-ipu/experimental-features/livemode.md b/docs/source/configuring-ipu/experimental-features/livemode.md
new file mode 100644
index 00000000..44200e80
--- /dev/null
+++ b/docs/source/configuring-ipu/experimental-features/livemode.md
@@ -0,0 +1,86 @@
+# LiveMode
+
+_LiveMode_ is an experimental feature that partially replaces
+leapp's custom upgrade environment with a bootable squashfs image of the target
+system. Intuitively, this squashfs-based mechanism is similar to using a live
+CD (hence the name LiveMode) from which the DNF transaction and other
+post-reboot steps will be applied. Such an upgrade environment closely
+resembles an ordinary Linux installation, making developing desired
+functionality (e.g. supporting network-based storage) much easier.
+
+## Technical details
+During an upgrade, prior to rebooting, leapp constructs a minimal target system
+container in order to obtain a version of the DNF stack expected by the new
+packages installed during the upgrade. After the container is created, the new
+DNF stack is used to download packages that will be installed during the
+upgrade. Having all necessary packages, leapp checks the RPM transaction to be
+performed during the upgrade. Finally, the upgrade environment is created - an
+initramfs containing custom dracut modules that ultimately execute leapp very
+early in the boot process. Such an upgrade environment guarantees isolation
+from other system services as there is essentially only the upgrade process
+running. However, the downside of using such an approach is that the bootup
+process of the upgrade environment is non-standard, meaning that almost none of
+the classical system initialisation services (e.g., LVM autoactivation) are
+running. Developing advanced features such as support for network-based
+storage, is, therefore demanding as only a little of the usual initialisation
+is present and executed during bootup.
+
+The LiveMode feature obtains a similar isolation level of the upgrade process
+in a different way. Instead of using an initramfs image that executes leapp
+early, the system boots into a read-only squashfs system built from the target
+system container build previously to check the upgrade RPM transaction. Since
+leapp controls the creation of the target system container, it is also in
+control of what will be running alongside the upgrade process, limiting the
+possibility of arbitrary user-defined services interfering with the upgrade.
+The upgrade environment boots into the `multi-user.target` target and leapp is
+started as an ordinary systemd service. However, the squashfs image needs to be
+stored on the disk, and, hence, the using feature **requires about 700mb of
+additional disk space**.
+
+## Using the feature
+It is possible to use the LiveMode feature by having set `LEAPP_UNSUPPORTED=1`
+and running leapp as `leapp upgrade --enable-experimental-feature livemode`.
+```
+LEAPP_UNSUPPORTED=1 leapp upgrade --enable-experimental-feature livemode
+```
+### Configuration
+The feature offers an extensive list of configuration options that can be set
+by creating a YAML file in `/etc/leapp/actor_conf.d/` with the extension
+`.yaml`. The content of the configuration file must be a mapping defining the
+`livemode` key with a value that is a mapping with (some) of the following
+keys:
+
+| Configuration field | Value type | Default | Semantics |
+|---------------------|------------|---------|-----------|
+| `squashfs_image_path` | `str` | `/var/lib/leapp/live-upgrade.img` | Location where the squashfs image of the minimal target system will be placed. |
+| `additional_packages` | `List[str]` | `[]` | Additional packages to be installed into the squashfs image. |
+| `autostart_upgrade_after_reboot` | `bool` | `True` | If set to True, the upgrade will start automatically after the reboot. Otherwise a manual trigger is required. |
+| `setup_network_manager` | `bool` | `False` | Try enabling Network Manager in the squashfs image. |
+| `dracut_network` | `str` | `''` | Dracut network arguments, required if the `url_to_load_squashfs_from` option is set. |
+| `url_to_load_squashfs_image_from` | `str` | `''` | URL pointing to the squashfs image that should be used for the upgrade environment. |
+| `setup_passwordless_root` | `bool` | `False` | If set to True, the root account of the squashfs image will have empty password. Use with caution. |
+| `setup_opensshd_using_auth_keys` | `str` | `''` | If set to a non-empty string, openssh daemon will be setup within the squashfs image using the provided authorized keys file. |
+| `capture_strace_info_into` | `str` | `''` | If set to a non-empty string, leapp will be executed under strace and results will be stored within the provided file path. |
+
+#### Configuration example
+Consider the file `/etc/leapp/actor_conf.d/livemode.yaml` with the following contents.
+```
+livemode:
+ additional_packages : [ vim ]
+ autostart_upgrade_after_reboot : false
+ setup_network_manager : true
+ setup_opensshd_using_auth_keys : /root/.ssh/authorized_keys
+```
+
+The configuration results in the following actions:
+- Leapp will install the `vim` package into the upgrade environment.
+- The upgrade will not be started automatically after reboot. Instead, user
+ needs to resume the upgrade manually. Therefore, it is possible to manually
+ inspect the system and verify that everything is in order, e.g., all of the
+ necessary storage is mounted.
+- Leapp will attempt to enable `NetworkManager` inside the upgrade environment
+ using source system's network profiles. This attempt is best-effort, meaning
+ that there is no guarantee that the network will be functional.
+- Leapp will enable the `opensshd` service. If a network access is established
+ successfully, it will be possible to login using ssh into the upgrade
+ environment using the `root` account and interact with the system.
--
2.49.0

View File

@ -0,0 +1,54 @@
From c3ec002d6ebc825c1c918e3abe9e2c849ef9ddc4 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Wed, 16 Apr 2025 13:39:28 +0200
Subject: [PATCH 12/37] DOC: rename configuring-ipu.md to envars.md
The file has bas been created before we introduced the section of
"Configuring in-place upgrade" and it contained mixture of various
stuff. We have the section now, so let's rename this file to envars
and keep here documented environments variables only.
Dropping information from this file about actors' configurations.
This needs to be anyway documented separately now and original
information has not been so helpful.
---
.../configuring-ipu/{configuring-ipu.md => envars.md} | 8 --------
docs/source/configuring-ipu/index.rst | 2 +-
2 files changed, 1 insertion(+), 9 deletions(-)
rename docs/source/configuring-ipu/{configuring-ipu.md => envars.md} (95%)
diff --git a/docs/source/configuring-ipu/configuring-ipu.md b/docs/source/configuring-ipu/envars.md
similarity index 95%
rename from docs/source/configuring-ipu/configuring-ipu.md
rename to docs/source/configuring-ipu/envars.md
index 059b72c2..61a50b82 100644
--- a/docs/source/configuring-ipu/configuring-ipu.md
+++ b/docs/source/configuring-ipu/envars.md
@@ -78,11 +78,3 @@ Change the default target RHEL version. Format: `MAJOR.MINOR`.
#### LEAPP_DEVEL_USE_PERSISTENT_PACKAGE_CACHE
Caches downloaded packages when set to `1`. This will reduce the time needed by leapp when executed multiple times, because it will not have to download already downloaded packages. However, this can lead to a random issues in case the data is not up-to-date or when setting or repositories change. The environment variable is meant to be used only for the part of the upgrade before the reboot and has no effect or use otherwise.
-
-## Actor configuration
-```{warning}
-Actor configuration is currently a preview of the feature, it might change in future releases.
-```
-The actor configuration is to be placed in the `/etc/leapp/actor_conf.d/` directory. An actor configuration is a file in YAML format.
-
-To define configuration options on your own actor refer to this tutorial TODO link.
diff --git a/docs/source/configuring-ipu/index.rst b/docs/source/configuring-ipu/index.rst
index 1be3ebcf..6490d6fd 100644
--- a/docs/source/configuring-ipu/index.rst
+++ b/docs/source/configuring-ipu/index.rst
@@ -12,7 +12,7 @@ experimental features.
:caption: Contents:
:glob:
- configuring-ipu
+ envars
experimental-features/index
.. Indices and tables
--
2.49.0

View File

@ -0,0 +1,68 @@
From 53f125b42f3e17354cc2d3e93b80fe089cf4c3b2 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Tue, 4 Mar 2025 14:42:44 +0100
Subject: [PATCH 13/37] fix(userspacegen): add exeception handling to swapping
of RHUI clients
Leapp swaps to RHUI target clients (uninstall source client+install
target client) in the scratch container to gain repository access.
To perform this step atomically, without loosing repository access
in between, `dnf shell` is invoked. The instruction as to which RPMs
should be uninstalled and which should be installed are given on
stdin of the `dnf shell` command. Currently, if we fail to swap clients
we crash with an unhandled exception `CalledProcessError` that contains
no information about what went wrong since the actual performed
transaction is hidden within the stdin of the process. This patch
adds error handling, so that we can tell that we have failed to swap
RHUI clients. Leapp's logs also contain the full DNF transaction as well
as possible explanations on why we failed.
jira-ref: RHEL-77945
---
.../libraries/userspacegen.py | 30 ++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
index 12736ab7..9fc96a52 100644
--- a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
+++ b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
@@ -1239,7 +1239,35 @@ def setup_target_rhui_access_if_needed(context, indata):
'shell'
]
- context.call(cmd, callback_raw=utils.logging_handler, stdin='\n'.join(dnf_transaction_steps))
+ try:
+ dnf_shell_instructions = '\n'.join(dnf_transaction_steps)
+ api.current_logger().debug(
+ 'Supplying the following instructions to the `dnf shell`: {}'.format(dnf_shell_instructions)
+ )
+ context.call(cmd, callback_raw=utils.logging_handler, stdin=dnf_shell_instructions)
+ except CalledProcessError as error:
+ api.current_logger().debug(
+ 'Failed to swap RHUI clients. This is likely because there are no repositories '
+ ' containing RHUI clients enabled, or we cannot access them.'
+ )
+ api.current_logger().debug(error)
+
+ swapping_clients_info_msg = 'Failed to swap `{0}` (source client{1}) with {2} (target client{3}).'
+ swapping_clients_info_msg = swapping_clients_info_msg.format(
+ ' '.join(indata.rhui_info.src_client_pkg_names),
+ '' if len(indata.rhui_info.src_client_pkg_names) == 1 else 's',
+ ' '.join(indata.rhui_info.target_client_pkg_names),
+ '' if len(indata.rhui_info.target_client_pkg_names) == 1 else 's',
+ )
+
+ details = {
+ 'details': swapping_clients_info_msg,
+ 'error': str(error)
+ }
+ raise StopActorExecutionError(
+ 'Failed to swap RHUI clients to establish content access',
+ details=details
+ )
_apply_rhui_access_postinstall_tasks(context, setup_info)
--
2.49.0

View File

@ -0,0 +1,40 @@
From 474b26cbcadc804ff50935a87ca78379999960d4 Mon Sep 17 00:00:00 2001
From: Vit Mojzis <vmojzis@redhat.com>
Date: Tue, 4 Mar 2025 11:49:05 +0100
Subject: [PATCH 14/37] selinux: do not run "semodule" when no modules are
selected
Fixes:
2025-03-04 11:21:31.550 DEBUG PID: 679 leapp.workflow.Applications.selinuxapplycustom: External command has finished: ['semodule', '-lfull']
2025-03-04 11:21:31.551 INFO PID: 679 leapp.workflow.Applications.selinuxapplycustom: Processing custom SELinux policy modules. Count: 1.
2025-03-04 11:21:31.551 INFO PID: 679 leapp.workflow.Applications.selinuxapplycustom: Skipping module permissive_rhcd_t on priority 400 because it is already installed.
2025-03-04 11:21:31.551 DEBUG PID: 679 leapp.workflow.Applications.selinuxapplycustom: External command has started: ['semodule']
2025-03-04 11:21:31.555 DEBUG PID: 679 leapp.workflow.Applications.selinuxapplycustom: At least one mode must be specified.
2025-03-04 11:21:31.555 DEBUG PID: 679 leapp.workflow.Applications.selinuxapplycustom: usage: semodule [option]... MODE...
2025-03-04 11:21:31.555 DEBUG PID: 679 leapp.workflow.Applications.selinuxapplycustom: Manage SELinux policy modules.
2025-03-04 11:21:31.556 DEBUG PID: 679 leapp.workflow.Applications.selinuxapplycustom: MODES:
2025-03-04 11:21:31.556 DEBUG PID: 679 leapp.workflow.Applications.selinuxapplycustom: -R, --reload reload policy
...
2025-03-04 11:21:31.564 WARNING PID: 679 leapp.workflow.Applications.selinuxapplycustom: Error installing modules in a single transaction:At least one mode must be specified.
---
.../common/actors/selinux/selinuxapplycustom/actor.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/repos/system_upgrade/common/actors/selinux/selinuxapplycustom/actor.py b/repos/system_upgrade/common/actors/selinux/selinuxapplycustom/actor.py
index 55c64c3e..4856f36a 100644
--- a/repos/system_upgrade/common/actors/selinux/selinuxapplycustom/actor.py
+++ b/repos/system_upgrade/common/actors/selinux/selinuxapplycustom/actor.py
@@ -92,6 +92,10 @@ class SELinuxApplyCustom(Actor):
command.extend(['-X', str(module.priority), '-i', cil_filename])
+ if command == ['semodule']:
+ # no modules selected for installation
+ continue
+
try:
run(command)
except CalledProcessError as e:
--
2.49.0

View File

@ -0,0 +1,213 @@
From 57dce775de28615260189a6612fe65e44a7d3bc9 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Sat, 29 Mar 2025 21:41:48 +0100
Subject: [PATCH 15/37] feat(ipuconfig): provide info about supported upgrade
paths
At the moment, information about supported upgrade paths is provided via
a deprecated IPUPaths message. The current solution is temporary.
This patch introduces new field in IPUConfig called
'supported_upgrade_paths' that contains a "compressed", pre-filtered,
list of upgrade paths. The decision to introduce this new field is
because we want to refactor the config.version library to not contain
its own supported upgrade paths definitions. Instead, we want to have the
information represented only once. Therefore, in order to refactor
config.version to use the information received by a message, we need
the new field on IPUConfig as we cannot force already-written actors
using config.version to add some message to their 'consumes' list.
Jira-ref: RHEL-80550
---
.../libraries/ipuworkflowconfig.py | 28 ++++++++++++++++++-
.../common/libraries/config/mock_configs.py | 14 +++++++++-
.../common/libraries/testutils.py | 20 +++++++++----
.../system_upgrade/common/models/ipuconfig.py | 22 +++++++++++++++
4 files changed, 77 insertions(+), 7 deletions(-)
diff --git a/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py b/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py
index 749b3347..86df709e 100644
--- a/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py
+++ b/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py
@@ -85,6 +85,27 @@ def check_target_major_version(curr_version, target_version):
)
+def load_raw_upgrade_paths_for_flavour(flavour='default', paths_definition_file='upgrade_paths.json'):
+ with open(api.get_common_file_path(paths_definition_file)) as fp:
+ data = json.loads(fp.read())
+
+ raw_upgrade_paths = data.get(flavour, {})
+
+ if not raw_upgrade_paths:
+ api.current_logger().warning('Cannot discover any upgrade paths for flavour: {}'.format(flavour))
+
+ return raw_upgrade_paths
+
+
+def construct_models_for_paths_matching_source_major(raw_paths, src_major_version):
+ multipaths_matching_source = []
+ for src_version, target_versions in ipu_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()
+ 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')
@@ -93,6 +114,10 @@ def produce_ipu_config(actor):
check_target_major_version(source_version, target_version)
+ raw_upgrade_paths = load_raw_upgrade_paths_for_flavour(flavour)
+ 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(),
os_release=os_release,
@@ -102,5 +127,6 @@ def produce_ipu_config(actor):
target=target_version
),
kernel=get_booted_kernel(),
- flavour=flavour
+ flavour=flavour,
+ supported_upgrade_paths=exposed_supported_paths
))
diff --git a/repos/system_upgrade/common/libraries/config/mock_configs.py b/repos/system_upgrade/common/libraries/config/mock_configs.py
index ee9dd760..a1c9c0fd 100644
--- a/repos/system_upgrade/common/libraries/config/mock_configs.py
+++ b/repos/system_upgrade/common/libraries/config/mock_configs.py
@@ -6,7 +6,7 @@ The library is supposed to be used only for testing purposes. Import of the
library is expected only inside test files.
"""
-from leapp.models import EnvVar, IPUConfig, OSRelease, Version
+from leapp.models import EnvVar, IPUConfig, IPUSourceToPossibleTargets, OSRelease, Version
CONFIG = IPUConfig(
leapp_env_vars=[EnvVar(name='LEAPP_DEVEL', value='0')],
@@ -23,6 +23,9 @@ CONFIG = IPUConfig(
),
architecture='x86_64',
kernel='3.10.0-957.43.1.el7.x86_64',
+ supported_upgrade_paths=[
+ IPUSourceToPossibleTargets(source_version='7.6', target_versions=['8.0'])
+ ]
)
CONFIG_NO_NETWORK_RENAMING = IPUConfig(
@@ -40,6 +43,9 @@ CONFIG_NO_NETWORK_RENAMING = IPUConfig(
),
architecture='x86_64',
kernel='3.10.0-957.43.1.el7.x86_64',
+ supported_upgrade_paths=[
+ IPUSourceToPossibleTargets(source_version='7.6', target_versions=['8.0'])
+ ]
)
CONFIG_ALL_SIGNED = IPUConfig(
@@ -57,6 +63,9 @@ CONFIG_ALL_SIGNED = IPUConfig(
),
architecture='x86_64',
kernel='3.10.0-957.43.1.el7.x86_64',
+ supported_upgrade_paths=[
+ IPUSourceToPossibleTargets(source_version='7.6', target_versions=['8.0'])
+ ]
)
CONFIG_S390X = IPUConfig(
@@ -73,4 +82,7 @@ CONFIG_S390X = IPUConfig(
),
architecture='s390x',
kernel='3.10.0-957.43.1.el7.x86_64',
+ supported_upgrade_paths=[
+ IPUSourceToPossibleTargets(source_version='7.6', target_versions=['8.0'])
+ ]
)
diff --git a/repos/system_upgrade/common/libraries/testutils.py b/repos/system_upgrade/common/libraries/testutils.py
index afeb360a..1b3c3683 100644
--- a/repos/system_upgrade/common/libraries/testutils.py
+++ b/repos/system_upgrade/common/libraries/testutils.py
@@ -6,7 +6,7 @@ from collections import namedtuple
from leapp import reporting
from leapp.actors.config import _normalize_config, normalize_schemas
from leapp.libraries.common.config import architecture
-from leapp.models import EnvVar
+from leapp.models import EnvVar, IPUSourceToPossibleTargets
from leapp.utils.deprecation import deprecated
@@ -76,7 +76,11 @@ def _make_default_config(actor_config_schema):
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',
- release_id='rhel', src_ver='7.8', dst_ver='8.1', msgs=None, flavour='default', config=None):
+ release_id='rhel', src_ver='7.8', dst_ver='8.1', msgs=None, flavour='default', config=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)
release = namedtuple('OS_release', ['release_id', 'version_id'])(release_id, src_ver)
@@ -85,9 +89,15 @@ class CurrentActorMocked(object): # pylint:disable=R0904
self._common_tools_folder = '../../tools'
self._actor_folder = 'files'
self._actor_tools_folder = 'tools'
- self.configuration = namedtuple(
- 'configuration', ['architecture', 'kernel', 'leapp_env_vars', 'os_release', 'version', 'flavour']
- )(arch, kernel, envarsList, release, version, flavour)
+
+ if not supported_upgrade_paths:
+ supported_upgrade_paths = [IPUSourceToPossibleTargets(source_version=src_ver, target_versions=[dst_ver])]
+
+ ipu_conf_fields = ['architecture', 'kernel', 'leapp_env_vars', 'os_release',
+ 'version', 'flavour', 'supported_upgrade_paths']
+ config_type = namedtuple('configuration', ipu_conf_fields)
+ self.configuration = config_type(arch, kernel, envarsList, release, version, flavour, supported_upgrade_paths)
+
self._msgs = msgs or []
self.config = {} if config is None else config
diff --git a/repos/system_upgrade/common/models/ipuconfig.py b/repos/system_upgrade/common/models/ipuconfig.py
index 6e7e21b5..0a16b603 100644
--- a/repos/system_upgrade/common/models/ipuconfig.py
+++ b/repos/system_upgrade/common/models/ipuconfig.py
@@ -34,6 +34,21 @@ class Version(Model):
"""Version of the target system. E.g. '8.2.'."""
+class IPUSourceToPossibleTargets(Model):
+ """
+ Represents upgrade paths from a source system version.
+
+ This model is not supposed to be produced nor consumed directly by any actor.
+ """
+ topic = SystemInfoTopic
+
+ source_version = fields.String()
+ """Source system version."""
+
+ target_versions = fields.List(fields.String())
+ """List of defined target system versions for the `source_version` system."""
+
+
class IPUConfig(Model):
"""
IPU workflow configuration model
@@ -59,3 +74,10 @@ class IPUConfig(Model):
flavour = fields.StringEnum(('default', 'saphana'), default='default')
"""Flavour of the upgrade - Used to influence changes in supported source/target release"""
+
+ supported_upgrade_paths = fields.List(fields.Model(IPUSourceToPossibleTargets))
+ """
+ List of supported upgrade paths.
+
+ The list contains only upgrade paths for the `flavour` of the source system.
+ """
--
2.49.0

View File

@ -0,0 +1,381 @@
From 6bfb0ae05f8ac05f34b5974a85ae5a703ada72b0 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Sat, 29 Mar 2025 21:56:07 +0100
Subject: [PATCH 16/37] feat(upgrade_paths): include information about distro
id
This patch tweaks upgrade_paths.json and the code reading it to contain
information about what for what distro are the upgrade paths defined.
This allows the upgrade tooling to possibly support also other distros,
such as CentOS Stream. However, this patch is only a small step towards
such a goal and further work is needed to support these systems.
Jira-ref: RHEL-80550
---
commands/command_utils.py | 28 ++++--
commands/tests/test_upgrade_paths.py | 15 ++--
.../libraries/ipuworkflowconfig.py | 35 +++++---
.../tests/test_ipuworkflowconfig.py | 85 ++++++++++++++++++-
.../tests/files/upgrade_paths.json | 29 ++++---
.../common/files/upgrade_paths.json | 36 +++++---
6 files changed, 177 insertions(+), 51 deletions(-)
diff --git a/commands/command_utils.py b/commands/command_utils.py
index 84b9de1b..a13ca59b 100644
--- a/commands/command_utils.py
+++ b/commands/command_utils.py
@@ -71,15 +71,24 @@ def get_upgrade_flavour():
return LEAPP_UPGRADE_FLAVOUR_DEFAULT
+def _retrieve_os_release_contents(_os_release_path='/etc/os-release'):
+ """
+ Retrieve the contents of /etc/os-release
+
+ :rtype: dict[str, str]
+ """
+ with open(_os_release_path) as os_release_handle:
+ lines = os_release_handle.readlines()
+ return dict(line.strip().split('=', 1) for line in lines if '=' in line)
+
+
def get_os_release_version_id(filepath):
"""
Retrieve data about System OS release from provided file.
:return: `str` version_id
"""
- with open(filepath) as f:
- data = dict(l.strip().split('=', 1) for l in f.readlines() if '=' in l)
- return data.get('VERSION_ID', '').strip('"')
+ return _retrieve_os_release_contents(_os_release_path=filepath).get('VERSION_ID', '').strip('"')
def get_upgrade_paths_config():
@@ -92,13 +101,13 @@ def get_upgrade_paths_config():
return upgrade_paths_map
-def get_target_versions_from_config(src_version_id, flavor):
+def get_target_versions_from_config(src_version_id, distro, flavor):
"""
Retrieve all possible target versions from upgrade_paths_map.
If no match is found returns empty list.
"""
upgrade_paths_map = get_upgrade_paths_config()
- return upgrade_paths_map.get(flavor, {}).get(src_version_id, [])
+ return upgrade_paths_map.get(distro, {}).get(flavor, {}).get(src_version_id, [])
def get_supported_target_versions(flavour=get_upgrade_flavour()):
@@ -107,14 +116,17 @@ def get_supported_target_versions(flavour=get_upgrade_flavour()):
The default value for `flavour` is `default`.
"""
- current_version_id = get_os_release_version_id('/etc/os-release')
- target_versions = get_target_versions_from_config(current_version_id, flavour)
+ os_release_contents = _retrieve_os_release_contents()
+ current_version_id = os_release_contents.get('VERSION_ID', '').strip('"')
+ distro_id = os_release_contents.get('ID', '').strip('"')
+
+ target_versions = get_target_versions_from_config(current_version_id, distro_id, flavour)
if not target_versions:
# If we cannot find a particular major.minor version in the map,
# we fallback to pick a target version just based on a major version.
# This can happen for example when testing not yet released versions
major_version = get_major_version(current_version_id)
- target_versions = get_target_versions_from_config(major_version, flavour)
+ target_versions = get_target_versions_from_config(major_version, distro_id, flavour)
return target_versions
diff --git a/commands/tests/test_upgrade_paths.py b/commands/tests/test_upgrade_paths.py
index f1312f66..c2cb09aa 100644
--- a/commands/tests/test_upgrade_paths.py
+++ b/commands/tests/test_upgrade_paths.py
@@ -8,19 +8,24 @@ from leapp.exceptions import CommandError
@mock.patch("leapp.cli.commands.command_utils.get_upgrade_paths_config",
- return_value={"default": {"7.9": ["8.4"], "8.6": ["9.0"], "7": ["8.4"], "8": ["9.0"]}})
+ return_value={'rhel': {"default": {"7.9": ["8.4"], "8.6": ["9.0"], "7": ["8.4"], "8": ["9.0"]}}})
def test_get_target_version(mock_open, monkeypatch):
-
- monkeypatch.setattr(command_utils, 'get_os_release_version_id', lambda x: '8.6')
+ etc_os_release_contents = {'ID': 'rhel', 'VERSION_ID': '8.6'}
+ monkeypatch.setattr(command_utils, '_retrieve_os_release_contents',
+ lambda *args, **kwargs: etc_os_release_contents)
assert command_utils.get_target_version('default') == '9.0'
monkeypatch.setenv('LEAPP_DEVEL_TARGET_RELEASE', '')
- monkeypatch.setattr(command_utils, 'get_os_release_version_id', lambda x: '8.6')
+ etc_os_release_contents = {'ID': 'rhel', 'VERSION_ID': '8.6'}
+ monkeypatch.setattr(command_utils, '_retrieve_os_release_contents',
+ lambda *args, **kwargs: etc_os_release_contents)
assert command_utils.get_target_version('default') == '9.0'
monkeypatch.delenv('LEAPP_DEVEL_TARGET_RELEASE', raising=True)
# unsupported path
- monkeypatch.setattr(command_utils, 'get_os_release_version_id', lambda x: '8.5')
+ etc_os_release_contents = {'ID': 'rhel', 'VERSION_ID': '8.5'}
+ monkeypatch.setattr(command_utils, '_retrieve_os_release_contents',
+ lambda *args, **kwargs: etc_os_release_contents)
assert command_utils.get_target_version('default') == '9.0'
diff --git a/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py b/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py
index 86df709e..35f61669 100644
--- a/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py
+++ b/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py
@@ -1,9 +1,10 @@
+import json
import os
import platform
from leapp.exceptions import StopActorExecutionError
-from leapp.libraries.stdlib import CalledProcessError, run
-from leapp.models import EnvVar, IPUConfig, OSRelease, Version
+from leapp.libraries.stdlib import api, CalledProcessError, run
+from leapp.models import EnvVar, IPUConfig, IPUSourceToPossibleTargets, OSRelease, Version
ENV_IGNORE = ('LEAPP_CURRENT_PHASE', 'LEAPP_CURRENT_ACTOR', 'LEAPP_VERBOSE',
'LEAPP_DEBUG')
@@ -85,24 +86,34 @@ def check_target_major_version(curr_version, target_version):
)
-def load_raw_upgrade_paths_for_flavour(flavour='default', paths_definition_file='upgrade_paths.json'):
+def load_upgrade_paths_definitions(paths_definition_file):
with open(api.get_common_file_path(paths_definition_file)) as fp:
- data = json.loads(fp.read())
+ definitions = json.loads(fp.read())
+ return definitions
- raw_upgrade_paths = data.get(flavour, {})
- if not raw_upgrade_paths:
- api.current_logger().warning('Cannot discover any upgrade paths for flavour: {}'.format(flavour))
+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)
+ raw_upgrade_paths_for_distro = all_definitions.get(distro_id, {})
- return raw_upgrade_paths
+ 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 ipu_paths.items():
+ 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 = IPUSourceToPossibleTargets(source_version=src_version,
+ target_versions=target_versions)
+ multipaths_matching_source.append(source_to_targets)
return multipaths_matching_source
@@ -114,7 +125,7 @@ def produce_ipu_config(actor):
check_target_major_version(source_version, target_version)
- raw_upgrade_paths = load_raw_upgrade_paths_for_flavour(flavour)
+ raw_upgrade_paths = load_raw_upgrade_paths_for_distro_and_flavour(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)
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 a5e4d03b..d88424ce 100644
--- a/repos/system_upgrade/common/actors/ipuworkflowconfig/tests/test_ipuworkflowconfig.py
+++ b/repos/system_upgrade/common/actors/ipuworkflowconfig/tests/test_ipuworkflowconfig.py
@@ -7,7 +7,7 @@ import pytest
from leapp.exceptions import StopActorExecutionError
from leapp.libraries.actor import ipuworkflowconfig
from leapp.libraries.stdlib import CalledProcessError
-from leapp.models import OSRelease
+from leapp.models import IPUSourceToPossibleTargets, OSRelease
CUR_DIR = os.path.dirname(os.path.abspath(__file__))
@@ -70,3 +70,86 @@ def test_get_booted_kernel(monkeypatch):
monkeypatch.setattr(ipuworkflowconfig, 'run', _raise_call_error)
with pytest.raises(StopActorExecutionError):
ipuworkflowconfig.get_booted_kernel()
+
+
+@pytest.mark.parametrize(
+ ('source_major_version', 'expected_result'),
+ (
+ ('7', []),
+ (
+ '8',
+ [
+ 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']),
+ ]
+ ),
+ (
+ '80',
+ [
+ IPUSourceToPossibleTargets(source_version='80.0', target_versions=['81.0']),
+ ]
+ ),
+ )
+)
+def test_construct_models_for_paths_matching_source_major(source_major_version, expected_result):
+ RAW_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']
+ }
+
+ result = ipuworkflowconfig.construct_models_for_paths_matching_source_major(RAW_PATHS, source_major_version)
+ result = sorted(result, key=lambda x: x.source_version)
+ assert result == sorted(expected_result, key=lambda x: x.source_version)
+
+
+@pytest.mark.parametrize(
+ ('distro', 'flavour', 'expected_result'),
+ (
+ ('fedora', 'default', {}),
+ (
+ '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']
+ }
+ ),
+ (
+ 'rhel', 'saphana',
+ {
+ '8.10': ['9.6', '9.4'],
+ '8': ['9.6', '9.4'],
+ '9.6': ['10.0'],
+ '9': ['10.0']
+ }
+ ),
+ )
+)
+def test_load_raw_upgrade_paths_for_distro_and_flavour(monkeypatch, distro, flavour, expected_result):
+ 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']
+ }
+ }
+ }
+ monkeypatch.setattr(ipuworkflowconfig, 'load_upgrade_paths_definitions', lambda *args: defined_upgrade_paths)
+
+ result = ipuworkflowconfig.load_raw_upgrade_paths_for_distro_and_flavour(distro, flavour)
+ assert result == expected_result
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
index edd32224..b6107376 100644
--- a/repos/system_upgrade/common/actors/scandefinedipupaths/tests/files/upgrade_paths.json
+++ b/repos/system_upgrade/common/actors/scandefinedipupaths/tests/files/upgrade_paths.json
@@ -1,15 +1,22 @@
{
- "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"]
+ "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"]
+ }
},
- "saphana": {
- "8.10": ["9.6", "9.4"],
- "8": ["9.6", "9.4"],
- "9.6": ["10.0"],
- "9": ["10.0"]
+ "centos": {
+ "default": {
+ "8": ["9"]
+ }
}
}
diff --git a/repos/system_upgrade/common/files/upgrade_paths.json b/repos/system_upgrade/common/files/upgrade_paths.json
index 1c54dae8..7ace7943 100644
--- a/repos/system_upgrade/common/files/upgrade_paths.json
+++ b/repos/system_upgrade/common/files/upgrade_paths.json
@@ -1,18 +1,26 @@
{
- "default": {
- "7.9": ["8.10"],
- "8.10": ["9.4", "9.6"],
- "9.6": ["10.0"],
- "7": ["8.10"],
- "8": ["9.4", "9.6"],
- "9": ["10.0"]
+ "rhel": {
+ "default": {
+ "7.9": ["8.10"],
+ "8.10": ["9.4", "9.6"],
+ "9.6": ["10.0"],
+ "7": ["8.10"],
+ "8": ["9.4", "9.6"],
+ "9": ["10.0"]
+ },
+ "saphana": {
+ "7.9": ["8.10"],
+ "7": ["8.10"],
+ "8.10": ["9.6", "9.4"],
+ "8": ["9.6", "9.4"],
+ "9.6": ["10.0"],
+ "9": ["10.0"]
+ }
},
- "saphana": {
- "7.9": ["8.10"],
- "7": ["8.10"],
- "8.10": ["9.6", "9.4"],
- "8": ["9.6", "9.4"],
- "9.6": ["10.0"],
- "9": ["10.0"]
+ "centos": {
+ "default": {
+ "8": ["9"],
+ "9": ["10"]
+ }
}
}
--
2.49.0

View File

@ -0,0 +1,407 @@
From 4432e62f02af820d040f45d7fc59296cf734bdc5 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Sat, 29 Mar 2025 22:00:38 +0100
Subject: [PATCH 17/37] cleanup(ipupaths): remove IPUPaths message
Drop the already deprecated IPUPaths message that was used to inform
actors about supported upgrade paths. Instead, the functionality has
been assumed by IPUConfig.
Jira-ref: RHEL-80550
---
.../common/actors/checktargetversion/actor.py | 3 +-
.../libraries/checktargetversion.py | 15 +--
.../tests/test_checktargetversion.py | 27 +++---
.../actors/scandefinedipupaths/actor.py | 31 ------
.../libraries/scandefinedipupaths.py | 43 --------
.../tests/files/upgrade_paths.json | 22 -----
.../tests/test_scandefinedipupaths.py | 97 -------------------
.../system_upgrade/common/models/ipupaths.py | 43 --------
8 files changed, 17 insertions(+), 264 deletions(-)
delete mode 100644 repos/system_upgrade/common/actors/scandefinedipupaths/actor.py
delete mode 100644 repos/system_upgrade/common/actors/scandefinedipupaths/libraries/scandefinedipupaths.py
delete mode 100644 repos/system_upgrade/common/actors/scandefinedipupaths/tests/files/upgrade_paths.json
delete mode 100644 repos/system_upgrade/common/actors/scandefinedipupaths/tests/test_scandefinedipupaths.py
delete mode 100644 repos/system_upgrade/common/models/ipupaths.py
diff --git a/repos/system_upgrade/common/actors/checktargetversion/actor.py b/repos/system_upgrade/common/actors/checktargetversion/actor.py
index 291ce3da..31375bfc 100644
--- a/repos/system_upgrade/common/actors/checktargetversion/actor.py
+++ b/repos/system_upgrade/common/actors/checktargetversion/actor.py
@@ -1,6 +1,5 @@
from leapp.actors import Actor
from leapp.libraries.actor import checktargetversion
-from leapp.models import IPUPaths
from leapp.reporting import Report
from leapp.tags import ChecksPhaseTag, IPUWorkflowTag
@@ -14,7 +13,7 @@ class CheckTargetVersion(Actor):
"""
name = 'check_target_version'
- consumes = (IPUPaths,)
+ consumes = ()
produces = (Report,)
tags = (ChecksPhaseTag, IPUWorkflowTag)
diff --git a/repos/system_upgrade/common/actors/checktargetversion/libraries/checktargetversion.py b/repos/system_upgrade/common/actors/checktargetversion/libraries/checktargetversion.py
index 0df1ece2..2369ae11 100644
--- a/repos/system_upgrade/common/actors/checktargetversion/libraries/checktargetversion.py
+++ b/repos/system_upgrade/common/actors/checktargetversion/libraries/checktargetversion.py
@@ -1,22 +1,15 @@
from leapp import reporting
-from leapp.exceptions import StopActorExecutionError
from leapp.libraries.common.config import get_env, version
from leapp.libraries.stdlib import api
-from leapp.models import IPUPaths
-from leapp.utils.deprecation import suppress_deprecation
FMT_LIST_SEPARATOR = '\n - '
-@suppress_deprecation(IPUPaths)
def get_supported_target_versions():
- ipu_paths = next(api.consume(IPUPaths), None)
src_version = version.get_source_version()
- if not ipu_paths:
- # NOTE: missing unit-tests. Unexpected situation and the solution
- # is possibly temporary
- raise StopActorExecutionError('Missing the IPUPaths message. Cannot determine defined upgrade paths.')
- for ipu_path in ipu_paths.data:
+ supported_paths = api.current_actor().configuration.supported_upgrade_paths
+
+ for ipu_path in supported_paths:
if ipu_path.source_version == src_version:
return ipu_path.target_versions
@@ -28,7 +21,7 @@ def get_supported_target_versions():
.format(src_version)
)
maj_version = version.get_source_major_version()
- for ipu_path in ipu_paths.data:
+ for ipu_path in supported_paths:
if ipu_path.source_version == maj_version:
return ipu_path.target_versions
diff --git a/repos/system_upgrade/common/actors/checktargetversion/tests/test_checktargetversion.py b/repos/system_upgrade/common/actors/checktargetversion/tests/test_checktargetversion.py
index 07391e7a..6927af23 100644
--- a/repos/system_upgrade/common/actors/checktargetversion/tests/test_checktargetversion.py
+++ b/repos/system_upgrade/common/actors/checktargetversion/tests/test_checktargetversion.py
@@ -4,36 +4,33 @@ import pytest
from leapp import reporting
from leapp.libraries.actor import checktargetversion
+from leapp.libraries.common.config import architecture
from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked, logger_mocked
from leapp.libraries.stdlib import api
-from leapp.models import IPUPath, IPUPaths
+from leapp.models import IPUSourceToPossibleTargets
from leapp.utils.deprecation import suppress_deprecation
from leapp.utils.report import is_inhibitor
-# It must be in a function so we can suppress the deprecation warning in tests.
-@suppress_deprecation(IPUPaths)
-def _get_upgrade_paths_data():
- return IPUPaths(data=[
- IPUPath(source_version='7.9', target_versions=['8.10']),
- IPUPath(source_version='8.10', target_versions=['9.4', '9.5', '9.6']),
- IPUPath(source_version='9.6', target_versions=['10.0']),
- IPUPath(source_version='7', target_versions=['8.10']),
- IPUPath(source_version='8', target_versions=['9.4', '9.5', '9.6']),
- IPUPath(source_version='9', target_versions=['10.0'])
- ])
-
-
@pytest.fixture
def setup_monkeypatch(monkeypatch):
"""Fixture to set up common monkeypatches."""
def _setup(source_version, target_version, leapp_unsupported='0'):
+ suppoted_upgrade_paths = [
+ IPUSourceToPossibleTargets(source_version='7.9', target_versions=['8.10']),
+ IPUSourceToPossibleTargets(source_version='8.10', target_versions=['9.4', '9.5', '9.6']),
+ IPUSourceToPossibleTargets(source_version='9.6', target_versions=['10.0']),
+ IPUSourceToPossibleTargets(source_version='7', target_versions=['8.10']),
+ IPUSourceToPossibleTargets(source_version='8', target_versions=['9.4', '9.5', '9.6']),
+ IPUSourceToPossibleTargets(source_version='9', target_versions=['10.0'])
+ ]
+
curr_actor_mocked = CurrentActorMocked(
src_ver=source_version,
dst_ver=target_version,
envars={'LEAPP_UNSUPPORTED': leapp_unsupported},
- msgs=[_get_upgrade_paths_data()]
+ supported_upgrade_paths=suppoted_upgrade_paths
)
monkeypatch.setattr(api, 'current_actor', curr_actor_mocked)
monkeypatch.setattr(api, 'current_logger', logger_mocked())
diff --git a/repos/system_upgrade/common/actors/scandefinedipupaths/actor.py b/repos/system_upgrade/common/actors/scandefinedipupaths/actor.py
deleted file mode 100644
index a84c85f2..00000000
--- a/repos/system_upgrade/common/actors/scandefinedipupaths/actor.py
+++ /dev/null
@@ -1,31 +0,0 @@
-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
deleted file mode 100644
index 1e39f2c8..00000000
--- a/repos/system_upgrade/common/actors/scandefinedipupaths/libraries/scandefinedipupaths.py
+++ /dev/null
@@ -1,43 +0,0 @@
-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
deleted file mode 100644
index b6107376..00000000
--- a/repos/system_upgrade/common/actors/scandefinedipupaths/tests/files/upgrade_paths.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "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": {
- "default": {
- "8": ["9"]
- }
- }
-}
diff --git a/repos/system_upgrade/common/actors/scandefinedipupaths/tests/test_scandefinedipupaths.py b/repos/system_upgrade/common/actors/scandefinedipupaths/tests/test_scandefinedipupaths.py
deleted file mode 100644
index 9ffc9829..00000000
--- a/repos/system_upgrade/common/actors/scandefinedipupaths/tests/test_scandefinedipupaths.py
+++ /dev/null
@@ -1,97 +0,0 @@
-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
deleted file mode 100644
index 5469f25e..00000000
--- a/repos/system_upgrade/common/models/ipupaths.py
+++ /dev/null
@@ -1,43 +0,0 @@
-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.49.0

View File

@ -0,0 +1,123 @@
From 09ef3dee08656058d9ac4b9c69d6848b2eae6dfb Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Mon, 31 Mar 2025 09:56:58 +0200
Subject: [PATCH 18/37] libs(version): use supported_upgrade_paths
Refactor the config.version library to use actor.configuration to obtain
the list of supported upgrade paths instead of having its own (duplicit)
definitions.
Mark leapp.libraries.common.config.version.SUPPORTED_VERSIONS as
deprecated and update the documentation.
Jira-ref: RHEL-80550
---
.../libraries-and-api/deprecations-list.md | 3 +-
.../libraries/config/tests/test_version.py | 28 +++++++++----------
.../common/libraries/config/version.py | 23 +++++++++------
3 files changed, 31 insertions(+), 23 deletions(-)
diff --git a/docs/source/libraries-and-api/deprecations-list.md b/docs/source/libraries-and-api/deprecations-list.md
index 07cbf1d6..c8489af3 100644
--- a/docs/source/libraries-and-api/deprecations-list.md
+++ b/docs/source/libraries-and-api/deprecations-list.md
@@ -14,7 +14,8 @@ Only the versions in which a deprecation has been made are listed.
## Next release <span style="font-size:0.5em; font-weight:normal">(till TODO date)</span>
-- No new deprecation yet
+- Shared libraries
+ - **`leapp.libraries.common.config.version.SUPPORTED_VERSIONS`** - The `SUPPORTED_VERSIONS` dict has been deprecated as it is problematic with the new design. Use `leapp.libraries.common.config.version.is_supported_version()` or `IPUConfig.supported_upgrade_paths` instead.
## v0.20.0 <span style="font-size:0.5em; font-weight:normal">(till September 2024)</span>
- Models
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 303e4de5..37a91c00 100644
--- a/repos/system_upgrade/common/libraries/config/tests/test_version.py
+++ b/repos/system_upgrade/common/libraries/config/tests/test_version.py
@@ -3,6 +3,7 @@ import pytest
from leapp.libraries.common.config import version
from leapp.libraries.common.testutils import CurrentActorMocked
from leapp.libraries.stdlib import api
+from leapp.models import IPUSourceToPossibleTargets
from leapp.utils.deprecation import suppress_deprecation
@@ -92,21 +93,20 @@ def test_is_rhel_alt(monkeypatch, result, kernel, release_id, src_ver):
assert version.is_rhel_alt() == result
-@pytest.mark.parametrize('result,is_alt,src_ver,saphana', [
- (True, True, '7.6', False),
- (True, False, '7.8', False),
- (False, True, '7.8', False),
- (False, False, '7.6', False),
- (True, True, '7.6', True),
- (True, False, '7.7', True),
- (False, True, '7.7', True),
- (False, False, '7.6', True),
+@pytest.mark.parametrize('result,src_ver,is_saphana', [
+ (True, '7.8', False), # default rhel
+ (False, '7.6', False),
+ (True, '7.7', True), # saphana
+ (False, '7.6', True),
])
-def test_is_supported_version(monkeypatch, result, is_alt, src_ver, saphana):
- monkeypatch.setattr(version, 'is_rhel_alt', lambda: is_alt)
- monkeypatch.setattr(version, 'is_sap_hana_flavour', lambda: saphana)
- monkeypatch.setattr(version, 'SUPPORTED_VERSIONS', {'rhel': ['7.8'], 'rhel-alt': ['7.6'], 'rhel-saphana': ['7.7']})
- monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(src_ver=src_ver))
+def test_is_supported_version(monkeypatch, result, src_ver, is_saphana):
+ if is_saphana:
+ supported_upgrade_paths = [IPUSourceToPossibleTargets(source_version='7.7', target_versions=['8.10'])]
+ else:
+ supported_upgrade_paths = [IPUSourceToPossibleTargets(source_version='7.8', target_versions=['8.10'])]
+
+ actor_mock = CurrentActorMocked(src_ver=src_ver, supported_upgrade_paths=supported_upgrade_paths)
+ monkeypatch.setattr(api, 'current_actor', actor_mock)
assert version.is_supported_version() == result
diff --git a/repos/system_upgrade/common/libraries/config/version.py b/repos/system_upgrade/common/libraries/config/version.py
index febeed36..b8fc550b 100644
--- a/repos/system_upgrade/common/libraries/config/version.py
+++ b/repos/system_upgrade/common/libraries/config/version.py
@@ -126,6 +126,12 @@ class _SupportedVersionsDict(dict):
SUPPORTED_VERSIONS = _SupportedVersionsDict()
+"""
+Deprecated since 2025-03-31.
+
+Use is_supported_version(), or IPUConfig.supported_upgrade_paths to check what source
+versions are supported for the current (release, flavour).
+"""
def _version_to_tuple(version):
@@ -319,13 +325,14 @@ def is_supported_version():
:return: `True` if the current version is supported and `False` otherwise.
:rtype: bool
"""
- release_id, version_id = current_version()
- if is_rhel_alt():
- release_id = 'rhel-alt'
- elif is_sap_hana_flavour():
- release_id = 'rhel-saphana'
+ source_version = get_source_version()
+ supported_upgrade_paths = api.current_actor().configuration.supported_upgrade_paths
- if not matches_release(SUPPORTED_VERSIONS, release_id):
- return False
+ # Check if there are any paths defined from the current source_version. If not,
+ # the upgrade version is unsupported
+ for ipu_source_to_targets in supported_upgrade_paths:
+ # No need to use matches_version - our version list is always a singleton
+ if ipu_source_to_targets.source_version == source_version:
+ return True
- return matches_version(SUPPORTED_VERSIONS[release_id], version_id)
+ return False
--
2.49.0

View File

@ -0,0 +1,322 @@
From e330fef6ef748dd1ae1ca1f4ec2a4142818d1e43 Mon Sep 17 00:00:00 2001
From: Tomas Fratrik <tomasfratrik8@gmail.com>
Date: Mon, 14 Apr 2025 14:40:19 +0200
Subject: [PATCH 19/37] Remove 7to8 CI tests
Removing 7to8 CI tests because the upgrade path from RHEL-7 to RHEL-8 is no longer supported.
Jira: RHELMISC-11004
---
.github/workflows/reuse-copr-build.yml | 4 +-
.github/workflows/tmt-tests.yml | 59 ----------
.github/workflows/unit-tests.yml | 17 ---
.packit.yaml | 152 -------------------------
4 files changed, 2 insertions(+), 230 deletions(-)
diff --git a/.github/workflows/reuse-copr-build.yml b/.github/workflows/reuse-copr-build.yml
index c6702e1a..a772fb64 100644
--- a/.github/workflows/reuse-copr-build.yml
+++ b/.github/workflows/reuse-copr-build.yml
@@ -56,7 +56,7 @@ jobs:
id: copr_build
env:
COPR_CONFIG: "copr_fedora.conf"
- COPR_CHROOT: "epel-7-x86_64,epel-8-x86_64"
+ COPR_CHROOT: "epel-8-x86_64"
COPR_REPO: "@oamg/leapp"
run: |
cat << EOF > $COPR_CONFIG
@@ -122,7 +122,7 @@ jobs:
if: ${{ steps.leapp_pr_regex_match.outputs.match != '' }}
env:
COPR_CONFIG: "copr_fedora.conf"
- COPR_CHROOT: "epel-7-x86_64,epel-8-x86_64"
+ COPR_CHROOT: "epel-8-x86_64"
COPR_REPO: "@oamg/leapp"
run: |
cat << EOF > $COPR_CONFIG
diff --git a/.github/workflows/tmt-tests.yml b/.github/workflows/tmt-tests.yml
index 1fa00e60..c9f76ef7 100644
--- a/.github/workflows/tmt-tests.yml
+++ b/.github/workflows/tmt-tests.yml
@@ -10,65 +10,6 @@ jobs:
uses: ./.github/workflows/reuse-copr-build.yml
secrets: inherit
- call_workflow_tests_79to88_integration:
- needs: call_workflow_copr_build
- uses: oamg/leapp/.github/workflows/reuse-tests-7to8.yml@main
- secrets: inherit
- with:
- copr_artifacts: ${{ needs.call_workflow_copr_build.outputs.artifacts }}
- tmt_plan_regex: "^(?!.*upgrade_plugin)(?!.*tier[2-3].*)(?!.*rhsm)(?!.*c2r)(?!.*sap)(?!.*8to9)(?!.*max_sst)"
- pull_request_status_name: "7.9to8.8"
- variables: 'SOURCE_RELEASE=7.9;TARGET_RELEASE=8.8;LEAPPDATA_BRANCH=upstream'
- if: |
- github.event.issue.pull_request
- && ! startsWith(github.event.comment.body, '/rerun-sst')
- && contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
-
- call_workflow_tests_79to86_integration:
- needs: call_workflow_copr_build
- uses: oamg/leapp/.github/workflows/reuse-tests-7to8.yml@main
- secrets: inherit
- with:
- copr_artifacts: ${{ needs.call_workflow_copr_build.outputs.artifacts }}
- tmt_plan_regex: "^(?!.*max_sst)(.*tier1)"
- variables: 'SOURCE_RELEASE=7.9;TARGET_RELEASE=8.6;LEAPPDATA_BRANCH=upstream'
- pull_request_status_name: "7.9to8.6"
- if: |
- github.event.issue.pull_request
- && ! startsWith(github.event.comment.body, '/rerun-sst')
- && contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
-
- call_workflow_tests_79to88_sst:
- needs: call_workflow_copr_build
- uses: oamg/leapp/.github/workflows/reuse-tests-7to8.yml@main
- secrets: inherit
- with:
- copr_artifacts: ${{ needs.call_workflow_copr_build.outputs.artifacts }}
- tmt_plan_regex: "^(?!.*tier[2-3].*)(.*max_sst.*)"
- pull_request_status_name: "7.9to8.8-sst"
- update_pull_request_status: 'false'
- variables: 'SOURCE_RELEASE=7.9;TARGET_RELEASE=8.8;LEAPPDATA_BRANCH=upstream'
- if: |
- github.event.issue.pull_request
- && startsWith(github.event.comment.body, '/rerun-sst')
- && contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
-
- call_workflow_tests_7to8_aws:
- needs: call_workflow_copr_build
- uses: oamg/leapp/.github/workflows/reuse-tests-7to8.yml@main
- secrets: inherit
- with:
- copr_artifacts: ${{ needs.call_workflow_copr_build.outputs.artifacts }}
- tmt_plan_regex: "^(?!.*upgrade_plugin)(?!.*tier[2-3].*)(?!.*rhsm)(?!.*c2r)(?!.*sap)(?!.*8to9)(.*e2e)"
- compose: "RHEL-7.9-rhui"
- environment_settings: '{"provisioning": {"post_install_script": "#!/bin/sh\nsudo sed -i s/.*ssh-rsa/ssh-rsa/ /root/.ssh/authorized_keys; echo 42; yum-config-manager --enable rhel-7-server-rhui-optional-rpms"}}'
- pull_request_status_name: "7to8-aws-e2e"
- variables: "SOURCE_RELEASE=7.9;TARGET_RELEASE=8.6;RHUI=aws;LEAPPDATA_BRANCH=upstream"
- if: |
- github.event.issue.pull_request
- && ! startsWith(github.event.comment.body, '/rerun-sst')
- && contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
-
call_workflow_tests_86to90_integration:
needs: call_workflow_copr_build
uses: oamg/leapp/.github/workflows/reuse-tests-8to9.yml@main
diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml
index 42b72b8d..37748396 100644
--- a/.github/workflows/unit-tests.yml
+++ b/.github/workflows/unit-tests.yml
@@ -49,23 +49,6 @@ jobs:
python: python3.6
repos: 'el8toel9,common'
container: ubi8-lint
- # 7to8
- - name: Run unit tests for el7toel8 and common repositories on python 3.6
- python: python3.6
- repos: 'el7toel8,common'
- container: ubi8
- - name: Run python linters for el7toel8 and common repositories on python 3.6
- python: python3.6
- repos: 'el7toel8,common'
- container: ubi8-lint
- - name: Run unit tests for el7toel8 and common repositories on python 2.7
- python: python2.7
- repos: 'el7toel8,common'
- container: ubi7
- - name: Run python linters for el7toel8 and common repositories on python 2.7
- python: python2.7
- repos: 'el7toel8,common'
- container: ubi7-lint
steps:
- name: Checkout code
diff --git a/.packit.yaml b/.packit.yaml
index dd17303a..75788a25 100644
--- a/.packit.yaml
+++ b/.packit.yaml
@@ -32,7 +32,6 @@ jobs:
owner: "@oamg"
project: leapp
targets:
- - epel-7-x86_64
- epel-8-x86_64
- epel-9-x86_64
actions:
@@ -53,7 +52,6 @@ jobs:
owner: "@oamg"
project: leapp
targets:
- - epel-7-x86_64
- epel-8-x86_64
- epel-9-x86_64
actions:
@@ -73,7 +71,6 @@ jobs:
owner: "@oamg"
project: leapp
targets:
- - epel-7-x86_64
- epel-8-x86_64
- epel-9-x86_64
actions:
@@ -95,155 +92,6 @@ jobs:
# >7tox path https://gitlab.cee.redhat.com/oamg/leapp-tests/-/blob/main/config.yaml
# Available only to RH Employees.
-# ###################################################################### #
-# ############################### 7 TO 8 ############################### #
-# ###################################################################### #
-
-# ###################################################################### #
-# ### Abstract job definitions to make individual tests/jobs smaller ### #
-# ###################################################################### #
-- &sanity-abstract-7to8
- job: tests
- trigger: ignore
- fmf_url: "https://gitlab.cee.redhat.com/oamg/leapp-tests"
- fmf_ref: "rhel7"
- use_internal_tf: True
- labels:
- - sanity
- targets:
- epel-7-x86_64:
- distros: [RHEL-7.9-ZStream]
- identifier: sanity-abstract-7to8
- tmt_plan: ""
-
-- &sanity-abstract-7to8-aws
- <<: *sanity-abstract-7to8
- labels:
- - sanity
- - aws
- targets:
- epel-7-x86_64:
- distros: [RHEL-7.9-rhui]
- identifier: sanity-abstract-7to8-aws
-
-# On-demand minimal beaker tests
-- &beaker-minimal-7to8-abstract-ondemand
- <<: *sanity-abstract-7to8
- manual_trigger: True
- labels:
- - beaker-minimal
- identifier: beaker-minimal-7to8-abstract-ondemand
-
-# On-demand kernel-rt tests
-- &kernel-rt-abstract-7to8-ondemand
- <<: *beaker-minimal-7to8-abstract-ondemand
- labels:
- - kernel-rt
- identifier: sanity-7to8-kernel-rt-abstract-ondemand
-
-# ###################################################################### #
-# ######################### Individual tests ########################### #
-# ###################################################################### #
-
-# Tests: 7.9 -> 8.10
-- &sanity-79to810
- <<: *sanity-abstract-7to8
- trigger: pull_request
- identifier: sanity-7.9to8.10
- tf_extra_params:
- test:
- tmt:
- plan_filter: 'tag:7to8 & tag:sanity & enabled:true'
- environments:
- - tmt:
- context:
- distro: "rhel-7.9"
- distro_target: "rhel-8.10"
- settings:
- provisioning:
- tags:
- BusinessUnit: sst_upgrades@leapp_upstream_test
- env:
- SOURCE_RELEASE: "7.9"
- TARGET_RELEASE: "8.10"
-
-- &sanity-79to810-aws
- <<: *sanity-abstract-7to8-aws
- trigger: pull_request
- identifier: sanity-7.9to8.10-aws
- tf_extra_params:
- test:
- tmt:
- plan_filter: 'tag:7to8 & tag:upgrade_happy_path & enabled:true'
- environments:
- - tmt:
- context:
- distro: "rhel-7.9"
- distro_target: "rhel-8.10"
- settings:
- provisioning:
- post_install_script: "#!/bin/sh\nsudo sed -i s/.*ssh-rsa/ssh-rsa/ /root/.ssh/authorized_keys"
- tags:
- BusinessUnit: sst_upgrades@leapp_upstream_test
- env:
- SOURCE_RELEASE: "7.9"
- TARGET_RELEASE: "8.10"
- RHUI: "aws"
- LEAPPDATA_BRANCH: "upstream"
- LEAPP_NO_RHSM: "1"
- USE_CUSTOM_REPOS: rhui
-
-- &beaker-minimal-79to810
- <<: *beaker-minimal-7to8-abstract-ondemand
- trigger: pull_request
- labels:
- - beaker-minimal
- - beaker-minimal-7.9to8.10
- - 7.9to8.10
- identifier: sanity-7.9to8.10-beaker-minimal-ondemand
- tf_extra_params:
- test:
- tmt:
- plan_filter: 'tag:7to8 & tag:partitioning & enabled:true'
- environments:
- - tmt:
- context:
- distro: "rhel-7.9"
- distro_target: "rhel-8.10"
- settings:
- provisioning:
- tags:
- BusinessUnit: sst_upgrades@leapp_upstream_test
- env:
- SOURCE_RELEASE: "7.9"
- TARGET_RELEASE: "8.10"
-
-- &kernel-rt-79to810
- <<: *kernel-rt-abstract-7to8-ondemand
- trigger: pull_request
- labels:
- - kernel-rt
- - kernel-rt-7.9to8.10
- - 7.9to8.10
- identifier: sanity-7.9to8.10-kernel-rt-ondemand
- tf_extra_params:
- test:
- tmt:
- plan_filter: 'tag:7to8 & tag:kernel-rt & enabled:true'
- environments:
- - tmt:
- context:
- distro: "rhel-7.9"
- distro_target: "rhel-8.10"
- settings:
- provisioning:
- tags:
- BusinessUnit: sst_upgrades@leapp_upstream_test
- env:
- SOURCE_RELEASE: "7.9"
- TARGET_RELEASE: "8.10"
-
-
# ###################################################################### #
# ############################## 8 TO 9 ################################ #
# ###################################################################### #
--
2.49.0

View File

@ -0,0 +1,45 @@
From 9dd50a2fc3f30d3f5a00998ed9fc96d34129426d Mon Sep 17 00:00:00 2001
From: karolinku <kkula@redhat.com>
Date: Fri, 25 Apr 2025 14:23:20 +0200
Subject: [PATCH 20/37] Fix lint in Makefile for docs
isort is failing when getting empty list of arguments, what takes
place when only doc files was modified in a commit. This fix handles
that issue.
JIRA: RHELMISC-11679
---
Makefile | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/Makefile b/Makefile
index 3e090159..ceb013ab 100644
--- a/Makefile
+++ b/Makefile
@@ -356,16 +356,17 @@ lint:
echo "--- Linting done. ---"; \
fi
- if [[ "`git rev-parse --abbrev-ref HEAD`" != "$(MASTER_BRANCH)" ]] && [[ -n "`git diff $(MASTER_BRANCH) --name-only --diff-filter AMR`" ]]; then \
+ if [[ "`git rev-parse --abbrev-ref HEAD`" != "$(MASTER_BRANCH)" ]]; then \
. $(VENVNAME)/bin/activate; \
- git diff $(MASTER_BRANCH) --name-only --diff-filter AMR | grep -v "^docs/" | xargs isort -c --diff || \
- { \
+ files_to_sort=`git diff main --name-only --diff-filter AMR | grep -v "^docs/"`; \
+ if [ -n "$$files_to_sort" ]; then \
+ echo "$$files_to_sort" | xargs isort -c --diff || { \
echo; \
- echo "------------------------------------------------------------------------------"; \
- echo "Hint: Apply the required changes."; \
+ echo "Hint: Apply the required changes.";\
echo " Execute the following command to apply them automatically: make lint_fix"; \
exit 1; \
- } && echo "--- isort check done. ---"; \
+ } && echo "--- isort check done. ---"; \
+ fi \
fi
lint_fix:
--
2.49.0

View File

@ -0,0 +1,41 @@
From 47f37314e26fe0e899b8fdd2fe280f2f8ebf15b5 Mon Sep 17 00:00:00 2001
From: Tomas Fratrik <tomasfratrik8@gmail.com>
Date: Mon, 28 Apr 2025 14:32:54 +0200
Subject: [PATCH 21/37] Improve report of removed kernel drivers
* Insert target RHEL version in report KCS titles for removed kernel drivers.
Jira: RHEL-49402
---
.../libraries/checkdddd.py | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/repos/system_upgrade/common/actors/checkdetecteddevicesanddrivers/libraries/checkdddd.py b/repos/system_upgrade/common/actors/checkdetecteddevicesanddrivers/libraries/checkdddd.py
index defe3f9a..1f01adde 100644
--- a/repos/system_upgrade/common/actors/checkdetecteddevicesanddrivers/libraries/checkdddd.py
+++ b/repos/system_upgrade/common/actors/checkdetecteddevicesanddrivers/libraries/checkdddd.py
@@ -37,13 +37,17 @@ def create_inhibitors(inhibiting_entries):
),
reporting.ExternalLink(
url='https://access.redhat.com/solutions/6971716',
- title='Leapp preupgrade getting "Inhibitor: Detected loaded kernel drivers which have been '
- 'removed in RHEL 8. Upgrade cannot proceed." '
+ title=('Leapp preupgrade getting "Inhibitor: Detected loaded kernel drivers which have been '
+ 'removed in RHEL {target}. Upgrade cannot proceed."').format(target=get_target_major_version())
),
reporting.ExternalLink(
url='https://access.redhat.com/solutions/5436131',
- title='Leapp upgrade fail with error "Inhibitor: Detected loaded kernel drivers which '
- 'have been removed in RHEL 8. Upgrade cannot proceed."'
+ title=(
+ 'Leapp upgrade fail with error "Inhibitor: Detected loaded kernel drivers which '
+ 'have been removed in RHEL {target}. Upgrade cannot proceed."'
+ ).format(
+ target=get_target_major_version()
+ )
),
reporting.Audience('sysadmin'),
reporting.Groups([reporting.Groups.KERNEL, reporting.Groups.DRIVERS]),
--
2.49.0

View File

@ -0,0 +1,151 @@
From daaf3cea58f4065e9e938c0c76ecd5d302ec7969 Mon Sep 17 00:00:00 2001
From: Tomas Fratrik <tomasfratrik8@gmail.com>
Date: Mon, 28 Apr 2025 14:19:01 +0200
Subject: [PATCH 22/37] Improve report of unsupported network configuration
* Remove KCS from summary since it is present in the related links.
* Generalize KCS title when using Kernel-Assigned NIC Names.
* Show KCS about unsupported network configuration device types only when IPU 8 -> 9.
* Adjust unit tests to reflect this change.
Jira: RHEL-77175
---
.../actors/persistentnetnamesdisable/actor.py | 24 ++++++----
.../tests/test_persistentnetnamesdisable.py | 46 +++++++++++++++++--
2 files changed, 56 insertions(+), 14 deletions(-)
diff --git a/repos/system_upgrade/common/actors/persistentnetnamesdisable/actor.py b/repos/system_upgrade/common/actors/persistentnetnamesdisable/actor.py
index 1f7f1413..1add3588 100644
--- a/repos/system_upgrade/common/actors/persistentnetnamesdisable/actor.py
+++ b/repos/system_upgrade/common/actors/persistentnetnamesdisable/actor.py
@@ -2,6 +2,7 @@ import re
from leapp import reporting
from leapp.actors import Actor
+from leapp.libraries.common.config.version import get_target_major_version
from leapp.models import KernelCmdlineArg, PersistentNetNamesFacts
from leapp.reporting import create_report, Report
from leapp.tags import FactsPhaseTag, IPUWorkflowTag
@@ -39,26 +40,31 @@ class PersistentNetNamesDisable(Actor):
if self.single_eth0(interfaces):
self.disable_persistent_naming()
elif len(interfaces) > 1 and self.ethX_count(interfaces) > 0:
- create_report([
+ report_entries = [
reporting.Title('Unsupported network configuration'),
reporting.Summary(
'Detected multiple physical network interfaces where one or more use kernel naming (e.g. eth0). '
'Upgrade process can not continue because stability of names can not be guaranteed. '
- 'Please read the article at https://access.redhat.com/solutions/4067471 for more information.'
),
reporting.ExternalLink(
- title='How to perform an in-place upgrade to RHEL 8 when using kernel NIC names on RHEL 7',
+ title='How to Perform an In-Place Upgrade when Using Kernel-Assigned NIC Names',
url='https://access.redhat.com/solutions/4067471'
),
- reporting.ExternalLink(
- title='RHEL 8 to RHEL 9: inplace upgrade fails at '
- '"Network configuration for unsupported device types detected"',
- url='https://access.redhat.com/solutions/7009239'
- ),
reporting.Remediation(
hint='Rename all ethX network interfaces following the attached KB solution article.'
),
reporting.Severity(reporting.Severity.HIGH),
reporting.Groups([reporting.Groups.NETWORK]),
reporting.Groups([reporting.Groups.INHIBITOR])
- ])
+ ]
+
+ if get_target_major_version() == '9':
+ report_entries.append(
+ reporting.ExternalLink(
+ title='RHEL 8 to RHEL 9: inplace upgrade fails at '
+ '"Network configuration for unsupported device types detected"',
+ url='https://access.redhat.com/solutions/7009239'
+ )
+ )
+
+ create_report(report_entries)
diff --git a/repos/system_upgrade/common/actors/persistentnetnamesdisable/tests/test_persistentnetnamesdisable.py b/repos/system_upgrade/common/actors/persistentnetnamesdisable/tests/test_persistentnetnamesdisable.py
index 96768da9..95b695c0 100644
--- a/repos/system_upgrade/common/actors/persistentnetnamesdisable/tests/test_persistentnetnamesdisable.py
+++ b/repos/system_upgrade/common/actors/persistentnetnamesdisable/tests/test_persistentnetnamesdisable.py
@@ -1,3 +1,6 @@
+import pytest
+
+from leapp.libraries.common.config import version
from leapp.models import Interface, KernelCmdlineArg, PCIAddress, PersistentNetNamesFacts
from leapp.reporting import Report
from leapp.snactor.fixture import current_actor_context
@@ -14,7 +17,11 @@ def test_actor_single_eth0(current_actor_context):
assert not current_actor_context.consume(Report)
-def test_actor_more_ethX(current_actor_context):
+@pytest.mark.parametrize(
+ 'target_version', ['9', '10']
+)
+def test_actor_more_ethX(monkeypatch, current_actor_context, target_version):
+ monkeypatch.setattr(version, 'get_target_major_version', lambda: target_version)
pci1 = PCIAddress(domain="0000", bus="3e", function="00", device="PCI bridge")
pci2 = PCIAddress(domain="0000", bus="3d", function="00", device="Serial controller")
interface = [Interface(name="eth0", mac="52:54:00:0b:4a:6d", vendor="redhat",
@@ -25,8 +32,20 @@ def test_actor_more_ethX(current_actor_context):
devpath="/devices/hidraw/hidraw0")]
current_actor_context.feed(PersistentNetNamesFacts(interfaces=interface))
current_actor_context.run()
- assert current_actor_context.consume(Report)
- assert is_inhibitor(current_actor_context.consume(Report)[0].report)
+
+ report_fields = current_actor_context.consume(Report)[0].report
+ assert is_inhibitor(report_fields)
+
+ external_links = report_fields.get('detail', {}).get('external', [])
+
+ rhel8to9_present = any(
+ 'RHEL 8 to RHEL 9' in link.get('title', '') for link in external_links
+ )
+
+ if target_version == '9':
+ assert rhel8to9_present
+ else:
+ assert not rhel8to9_present
def test_actor_single_int_not_ethX(current_actor_context):
@@ -39,7 +58,11 @@ def test_actor_single_int_not_ethX(current_actor_context):
assert not current_actor_context.consume(Report)
-def test_actor_ethX_and_not_ethX(current_actor_context):
+@pytest.mark.parametrize(
+ 'target_version', ['9', '10']
+)
+def test_actor_ethX_and_not_ethX(monkeypatch, current_actor_context, target_version):
+ monkeypatch.setattr(version, 'get_target_major_version', lambda: target_version)
pci1 = PCIAddress(domain="0000", bus="3e", function="00", device="PCI bridge")
pci2 = PCIAddress(domain="0000", bus="3d", function="00", device="Serial controller")
interface = [Interface(name="virbr0", mac="52:54:00:0b:4a:6d", vendor="redhat",
@@ -51,4 +74,17 @@ def test_actor_ethX_and_not_ethX(current_actor_context):
current_actor_context.feed(PersistentNetNamesFacts(interfaces=interface))
current_actor_context.run()
assert current_actor_context.consume(Report)
- assert is_inhibitor(current_actor_context.consume(Report)[0].report)
+
+ report_fields = current_actor_context.consume(Report)[0].report
+ assert is_inhibitor(report_fields)
+
+ external_links = report_fields.get('detail', {}).get('external', [])
+
+ rhel8to9_present = any(
+ 'RHEL 8 to RHEL 9' in link.get('title', '') for link in external_links
+ )
+
+ if target_version == '9':
+ assert rhel8to9_present
+ else:
+ assert not rhel8to9_present
--
2.49.0

View File

@ -0,0 +1,35 @@
From d3793ab2546148d3fc9832e5164a2f0a7de80352 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Wed, 30 Apr 2025 13:29:40 +0200
Subject: [PATCH 23/37] DOCS: add missing envar LEAPP_OVL_IMG_FS_EXT4
The LEAPP_OVL_IMG_FS_EXT4 has not been documented and it can be
quite useful on some systems.
---
docs/source/configuring-ipu/envars.md | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/docs/source/configuring-ipu/envars.md b/docs/source/configuring-ipu/envars.md
index 61a50b82..a042ba4a 100644
--- a/docs/source/configuring-ipu/envars.md
+++ b/docs/source/configuring-ipu/envars.md
@@ -47,6 +47,16 @@ Set the path to the target OS ISO image that should be used for the IPU. Its
#### LEAPP_TARGET_PRODUCT_CHANNEL
The alternative to the --channel leapp option. As a parameter accepts a channel acronym. E.g. `eus` or `e4s`. For more info, see the leapp preupgrade --help. In case the beta channel is required, use the `LEAPP_DEVEL_TARGET_PRODUCT_TYPE` envar instead.
+#### LEAPP_OVL_IMG_FS_EXT4
+During the execution of IPUWorkflow the process requires creation of internal
+disk images for the correct virtualisation of the host storage and creation
+of OverlayFS (OVL) layer. During that time these images are formatted with
+XFS filesystem by default. However for some system setups this could be
+problematic and could lead sometimes to issues. For these uncommon problems
+it is possible to specify `LEAPP_OVL_IMG_FS_EXT4=1` when running leapp to
+instruct the use of the EXT4 file system instead.
+
+
### Development variables
```{note}
To use development variables, the LEAPP_UNSUPPORTED variable has to be set.
--
2.49.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,701 @@
From 5fe6b4df9cfde15f527b5ecf52fda4e7fec6dfe5 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Mon, 5 May 2025 13:55:35 +0200
Subject: [PATCH 25/37] Add RHEL 10.1 and 9.7 product certificates
---
.../common/files/prod-certs/10.1/279.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/10.1/362.pem | 36 +++++++++++++++++++
.../common/files/prod-certs/10.1/363.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/10.1/419.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/10.1/433.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/10.1/479.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/10.1/486.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/10.1/72.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/9.7/279.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/9.7/362.pem | 36 +++++++++++++++++++
.../common/files/prod-certs/9.7/363.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/9.7/419.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/9.7/433.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/9.7/479.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/9.7/486.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/9.7/72.pem | 35 ++++++++++++++++++
16 files changed, 562 insertions(+)
create mode 100644 repos/system_upgrade/common/files/prod-certs/10.1/279.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/10.1/362.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/10.1/363.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/10.1/419.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/10.1/433.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/10.1/479.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/10.1/486.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/10.1/72.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.7/279.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.7/362.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.7/363.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.7/419.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.7/433.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.7/479.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.7/486.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.7/72.pem
diff --git a/repos/system_upgrade/common/files/prod-certs/10.1/279.pem b/repos/system_upgrade/common/files/prod-certs/10.1/279.pem
new file mode 100644
index 00000000..958d5716
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/10.1/279.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGKDCCBBCgAwIBAgIJALDxRLt/tU/zMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDEyOTEyNDkwM1oXDTQ1MDEy
+OTEyNDkwM1owRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs3YzNhZTNl
+ZC01M2U1LTQ3MjYtOGM4Ny1kNGIwZjk4MTU5MjNdMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxj9J04z+Ezdyx1U33kFftLv0ntNS1BSeuhoZLDhs18yk
+sepG7hXXtHh2CMFfLZmTjAyL9i1XsxykQpVQdXTGpUF33C2qBQHB5glYs9+d781x
+8p8m8zFxbPcW82TIJXbgW3ErVh8vk5qCbG1cCAAHb+DWMq0EAyy1bl/JgAghYNGB
+RvKJObTdCrdpYh02KUqBLkSPZHvo6DUJFN37MXDpVeQq9VtqRjpKLLwuEfXb0Y7I
+5xEOrR3kYbOaBAWVt3mYZ1t0L/KfY2jVOdU5WFyyB9PhbMdLi1xE801j+GJrwcLa
+xmqvj4UaICRzcPATP86zVM1BBQa+lilkRQes5HyjZzZDiGYudnXhbqmLo/n0cuXo
+QBVVjhzRTMx71Eiiahmiw+U1vGqkHhQNxb13HtN1lcAhUCDrxxeMvrAjYdWpYlpI
+yW3NssPWt1YUHidMBSAJ4KctIf91dyE93aStlxwC/QnyFsZOmcEsBzVCnz9GmWMl
+1/6XzBS1yDUqByklx0TLH+z/sK9A+O2rZAy1mByCYwVxvbOZhnqGxAuToIS+A81v
+5hCjsCiOScVB+cil30YBu0cH85RZ0ILNkHdKdrLLWW4wjphK2nBn2g2i3+ztf+nQ
+ED2pQqZ/rhuW79jcyCZl9kXqe1wOdF0Cwah4N6/3LzIXEEKyEJxNqQwtNc2IVE8C
+AwEAAaOBsTCBrjAJBgNVHRMEAjAAMEMGDCsGAQQBkggJAYIXAQQzDDFSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIFBvd2VyLCBsaXR0bGUgZW5kaWFuMBYGDCsG
+AQQBkggJAYIXAgQGDAQxMC4xMBkGDCsGAQQBkggJAYIXAwQJDAdwcGM2NGxlMCkG
+DCsGAQQBkggJAYIXBAQZDBdyaGVsLTEwLHJoZWwtMTAtcHBjNjRsZTANBgkqhkiG
+9w0BAQsFAAOCAgEAfVg6glBn6Igkl0ynxbwfLLrR7D3HcWhIBpcFFfw9btjx74Zi
+Pi7RcQeV8xR03S7SQO0B+84yTAy48DMtv0jTGZacqovv9iXNqJBuXhfFZgSvYnr/
+cqAXExpQc5PvCzDW0/6JKWkGJsrxS++KtRRwPjZKV/Ie9Xa0P/LnVhraDZUGHRLt
+fo5lbElmpy0GvYnOp/xVMfP/R7Gy/rC3AfrTxrTUY911eguT4ziJftzTVbq0Bpn4
+tEBqPQ9B0NBpgwiQJteLHtwHjm8c46E+bzb5JHRNtHVUX6ukG9FPPpehJyJmgILu
+tNadbee3gpRvNpVTInDZyftIcXHZzh+rirWg8oC9b0kj/z7Cr+OBx5BHAlcFzJNb
+KX49ezONhjWgSlKGTu90fcJk60TvrWfYymXpym0B70uCKZbKXTAwDTtg2gIydFS/
+YZydCgY6h6/s4Vk7NeccIHRz7xSQ/eiVSGk7TM/DbACjp1pl9CVX2BMn5p1GNn3W
+oS0c9DY/pbphdlGVDrcDRmYjuAZ6fNtmy7zDqtUSJnen0A+PrcRIc5ICEoTXUE9l
+RtxUFT2Caja3PWVumVu1kNGzjbNAvFRD9FHQt80ADpSLgEcG0HEaFUdevYN3glKb
+7J1RXTKEhhnBBCI9qfrl4SIz3VvLrxW4AeJ87h/7FPJZFAJrkKQmQPeyadA=
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/10.1/362.pem b/repos/system_upgrade/common/files/prod-certs/10.1/362.pem
new file mode 100644
index 00000000..6382f50a
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/10.1/362.pem
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIGNzCCBB+gAwIBAgIJALDxRLt/tU/gMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDEyOTEyNDg0NFoXDTQ1MDEy
+OTEyNDg0NFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs0MGFlYjVl
+ZC0yZjNiLTRiZWYtOTRjYi00YjgzMDkyZmEzY2NdMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxj9J04z+Ezdyx1U33kFftLv0ntNS1BSeuhoZLDhs18yk
+sepG7hXXtHh2CMFfLZmTjAyL9i1XsxykQpVQdXTGpUF33C2qBQHB5glYs9+d781x
+8p8m8zFxbPcW82TIJXbgW3ErVh8vk5qCbG1cCAAHb+DWMq0EAyy1bl/JgAghYNGB
+RvKJObTdCrdpYh02KUqBLkSPZHvo6DUJFN37MXDpVeQq9VtqRjpKLLwuEfXb0Y7I
+5xEOrR3kYbOaBAWVt3mYZ1t0L/KfY2jVOdU5WFyyB9PhbMdLi1xE801j+GJrwcLa
+xmqvj4UaICRzcPATP86zVM1BBQa+lilkRQes5HyjZzZDiGYudnXhbqmLo/n0cuXo
+QBVVjhzRTMx71Eiiahmiw+U1vGqkHhQNxb13HtN1lcAhUCDrxxeMvrAjYdWpYlpI
+yW3NssPWt1YUHidMBSAJ4KctIf91dyE93aStlxwC/QnyFsZOmcEsBzVCnz9GmWMl
+1/6XzBS1yDUqByklx0TLH+z/sK9A+O2rZAy1mByCYwVxvbOZhnqGxAuToIS+A81v
+5hCjsCiOScVB+cil30YBu0cH85RZ0ILNkHdKdrLLWW4wjphK2nBn2g2i3+ztf+nQ
+ED2pQqZ/rhuW79jcyCZl9kXqe1wOdF0Cwah4N6/3LzIXEEKyEJxNqQwtNc2IVE8C
+AwEAAaOBwDCBvTAJBgNVHRMEAjAAMEgGDCsGAQQBkggJAYJqAQQ4DDZSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIFBvd2VyLCBsaXR0bGUgZW5kaWFuIEJldGEw
+GwYMKwYBBAGSCAkBgmoCBAsMCTEwLjEgQmV0YTAZBgwrBgEEAZIICQGCagMECQwH
+cHBjNjRsZTAuBgwrBgEEAZIICQGCagQEHgwccmhlbC0xMCxyaGVsLTEwLWJldGEt
+cHBjNjRsZTANBgkqhkiG9w0BAQsFAAOCAgEA1SukDSn9NakDXTq8UO5TatAHiSu+
+qWNgEtddX3XUZ1nB8S3n8QDhk4RoQIs2e66w95vOYyNipBO93gqVeJbEK7Krxgbl
+Xx6s08kPuwcdG8FxgqPC8jote7eVEHmrMnlhOyNz9WRYULyz6IlfQ6gQe7SmeSrC
+lsla8bykzN2/7MnDPqjByF0zbdtdoZ9U5JXlqJn2UuTIe+Z65jDqSwBv8bQF+F8g
+EiZtesy4n7sxXpINSFBkh24ohRd0ur8BXCoOLpzS96YkyHvXXdqaJcCoSJ6abqe0
+Q7IFWYfUIU7GCwtSL4M9ODjc8Cr5YUJgnsnlC1qYekOB1pGfROMC/9qEAU2TsOYp
+8yOZN+NmrsmSnaBLHEN9lhwpt+2It5Dm9B/SAW64fil/oVyHUj3qfIDXSzbD+l0q
+LQ6l66epVP/b3UU1R7+JzDDLUDm2bBWFr205L4CKkcpaReK+mXM3eTuMtiHWnLkY
+MQ6jgDAM+5GGGHqq/iJmBWM+Trp5HfyI3XEVWsXDBJ2zEDAAEwByWwhwGFI58SFy
+Zv3x3vpv56b7MW5fALXYFKkHzwjVw9YVXnhJmXO09GN7auPVYsFEPl3QUS/OiXPL
+suQmwYd7aS8Bua3kgAfg204O6OppflhkExzroRvvr7FT/9LftaaBI+HLDnvOdd2n
+y+Nqehto96G/A6A=
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/10.1/363.pem b/repos/system_upgrade/common/files/prod-certs/10.1/363.pem
new file mode 100644
index 00000000..2b7eeb6d
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/10.1/363.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGKTCCBBGgAwIBAgIJALDxRLt/tU/fMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDEyOTEyNDg0NFoXDTQ1MDEy
+OTEyNDg0NFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs4MGRiNGJj
+MC1hZTY1LTRhMjgtODRjNC1hZTgwZWFjZDQ2M2VdMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxj9J04z+Ezdyx1U33kFftLv0ntNS1BSeuhoZLDhs18yk
+sepG7hXXtHh2CMFfLZmTjAyL9i1XsxykQpVQdXTGpUF33C2qBQHB5glYs9+d781x
+8p8m8zFxbPcW82TIJXbgW3ErVh8vk5qCbG1cCAAHb+DWMq0EAyy1bl/JgAghYNGB
+RvKJObTdCrdpYh02KUqBLkSPZHvo6DUJFN37MXDpVeQq9VtqRjpKLLwuEfXb0Y7I
+5xEOrR3kYbOaBAWVt3mYZ1t0L/KfY2jVOdU5WFyyB9PhbMdLi1xE801j+GJrwcLa
+xmqvj4UaICRzcPATP86zVM1BBQa+lilkRQes5HyjZzZDiGYudnXhbqmLo/n0cuXo
+QBVVjhzRTMx71Eiiahmiw+U1vGqkHhQNxb13HtN1lcAhUCDrxxeMvrAjYdWpYlpI
+yW3NssPWt1YUHidMBSAJ4KctIf91dyE93aStlxwC/QnyFsZOmcEsBzVCnz9GmWMl
+1/6XzBS1yDUqByklx0TLH+z/sK9A+O2rZAy1mByCYwVxvbOZhnqGxAuToIS+A81v
+5hCjsCiOScVB+cil30YBu0cH85RZ0ILNkHdKdrLLWW4wjphK2nBn2g2i3+ztf+nQ
+ED2pQqZ/rhuW79jcyCZl9kXqe1wOdF0Cwah4N6/3LzIXEEKyEJxNqQwtNc2IVE8C
+AwEAAaOBsjCBrzAJBgNVHRMEAjAAMDoGDCsGAQQBkggJAYJrAQQqDChSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIEFSTSA2NCBCZXRhMBsGDCsGAQQBkggJAYJr
+AgQLDAkxMC4xIEJldGEwGQYMKwYBBAGSCAkBgmsDBAkMB2FhcmNoNjQwLgYMKwYB
+BAGSCAkBgmsEBB4MHHJoZWwtMTAscmhlbC0xMC1iZXRhLWFhcmNoNjQwDQYJKoZI
+hvcNAQELBQADggIBAJ1siyraC4EY80gYkCaBag7l8BaLUuXcVgk67a4VNsCytxnn
+Pe0RGLoNcfI1p3Y3S2rDXCNQeAkMaJkraAt2TWxJz16pQY2XL2jS4J3wH3cD3MWc
+inEyJOxNRtx7vT2+2dWCKtgyLlg/GCu8q3Eojd97krId3Uz6f2obDcgawkmhvZZc
+QmwLncbhc9knDQX/Dxeep53i3QGgojOfCqRWj/xY/9L3Fq7KcHupMrXx8IktHEZL
+8yvFLx3QoqtYGKckxRC91RqKWG4edk8LYeL2mUSuONwzGpXvqKcfIMyWAhLaVfnG
+AqC7keoSm4RyGA47tL3dIFPuu5IYMa+Kdr4lyNGNmAfSYiPhkjte8YxMz9Y3fGBX
+BTRrWMN5LvvodEz33prFFfHl647sq4j7Qq6GSDBllV5B0nlJZvDIiBLGa/rpnJie
+dD76DhtNdtWr1ghqZTS0dQ+vxI3bZBcqYWxFoV30+3e700Xq2p+C4peY9fWGupVC
+w79WsJHj0aF2GBUtJlhqYo1ReZm4YH6CDv+DHDNEVmtu7bR0klTEpmFznuni6/Kr
++z/9FFnAYzVkECKA5zzQ52EfqclkYscADhlnBqY/knVDaAJAXZD5QIFlcGeXMxiS
+zIhD+K2P9GM4Z4n1CoYZceTwIaCDogRGo/2gO20dB0AZW2tPjvr/RpfI7zpR
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/10.1/419.pem b/repos/system_upgrade/common/files/prod-certs/10.1/419.pem
new file mode 100644
index 00000000..906b58e2
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/10.1/419.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGGjCCBAKgAwIBAgIJALDxRLt/tU/yMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDEyOTEyNDkwM1oXDTQ1MDEy
+OTEyNDkwM1owRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs4ZDMyOWZh
+MS0wYTgyLTRlMTktYmUxMy1mYzFiNWUxNDVhYzhdMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxj9J04z+Ezdyx1U33kFftLv0ntNS1BSeuhoZLDhs18yk
+sepG7hXXtHh2CMFfLZmTjAyL9i1XsxykQpVQdXTGpUF33C2qBQHB5glYs9+d781x
+8p8m8zFxbPcW82TIJXbgW3ErVh8vk5qCbG1cCAAHb+DWMq0EAyy1bl/JgAghYNGB
+RvKJObTdCrdpYh02KUqBLkSPZHvo6DUJFN37MXDpVeQq9VtqRjpKLLwuEfXb0Y7I
+5xEOrR3kYbOaBAWVt3mYZ1t0L/KfY2jVOdU5WFyyB9PhbMdLi1xE801j+GJrwcLa
+xmqvj4UaICRzcPATP86zVM1BBQa+lilkRQes5HyjZzZDiGYudnXhbqmLo/n0cuXo
+QBVVjhzRTMx71Eiiahmiw+U1vGqkHhQNxb13HtN1lcAhUCDrxxeMvrAjYdWpYlpI
+yW3NssPWt1YUHidMBSAJ4KctIf91dyE93aStlxwC/QnyFsZOmcEsBzVCnz9GmWMl
+1/6XzBS1yDUqByklx0TLH+z/sK9A+O2rZAy1mByCYwVxvbOZhnqGxAuToIS+A81v
+5hCjsCiOScVB+cil30YBu0cH85RZ0ILNkHdKdrLLWW4wjphK2nBn2g2i3+ztf+nQ
+ED2pQqZ/rhuW79jcyCZl9kXqe1wOdF0Cwah4N6/3LzIXEEKyEJxNqQwtNc2IVE8C
+AwEAAaOBozCBoDAJBgNVHRMEAjAAMDUGDCsGAQQBkggJAYMjAQQlDCNSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIEFSTSA2NDAWBgwrBgEEAZIICQGDIwIEBgwE
+MTAuMTAZBgwrBgEEAZIICQGDIwMECQwHYWFyY2g2NDApBgwrBgEEAZIICQGDIwQE
+GQwXcmhlbC0xMCxyaGVsLTEwLWFhcmNoNjQwDQYJKoZIhvcNAQELBQADggIBAHgs
+Io5uxwPYpQFtIBiQ/wTzNfokMoBcL2eBt/pnCXMPBmAlscm1l96P92pB9b+uGxXx
+WWUPlwwsn87WABQkIVJJgW2Y723ZqJungj4duhuQB/c8pXqy6bEOIkSFqoiez3n+
+49adg2Fr/uXSj1NBbY+CGFU3QStKLNbDfFQJEEwvFbajTE4jp1e9Db0B60H4nX4n
+Z09Rl7IrBC+AO3d/bIc4Ed2Uk5oTozR+vVx6/JFewAE5aEYdrdqXVj+NHpLBbVpE
+KDlHJ41LdPu7HKXcqw/sqTyYuZJHqi5AZ2eLbBB6+0FRfgZC4B29LFokTlAoDTCM
+C0q7e2NwITdDDULLJq37DZlZiHBdDRrwyBNM5O4P5Ufyy6y5djN/93P/OxNhXMum
+n2J/yAQNvmzONEgz4g8Rfl+EIdNRaXMYdEHzQ4Rn0ba6f68hAilqVUgIdUdiLFG9
+ni0ISWWPQefkMRAWpOZymD0cumQUI2s+2nkzwVzTsmrQPAyFwHpIn+yfbUUDNBUR
+osnW+tTG51K7b2RVTkh6/ecXTGgaxHlltg6FILj/sS7umphD2CEmDSAK0eqLvUaE
+SqjtntlkgwbEGdHSvoMBVdl232yXCvxTX612VauD3e3HGr01Z2/lXqDq/5lZfZe9
+5YO65vQQLn1D8bNvKJ5hhI9m0qc4vYVbvwNqztLh
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/10.1/433.pem b/repos/system_upgrade/common/files/prod-certs/10.1/433.pem
new file mode 100644
index 00000000..b834a5f4
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/10.1/433.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGLDCCBBSgAwIBAgIJALDxRLt/tU/hMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDEyOTEyNDg0NFoXDTQ1MDEy
+OTEyNDg0NFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFsxMWVlMzk5
+MC1lNmJiLTQzMDUtOWNiMi0zYTk1OGQ2OTJlYzBdMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxj9J04z+Ezdyx1U33kFftLv0ntNS1BSeuhoZLDhs18yk
+sepG7hXXtHh2CMFfLZmTjAyL9i1XsxykQpVQdXTGpUF33C2qBQHB5glYs9+d781x
+8p8m8zFxbPcW82TIJXbgW3ErVh8vk5qCbG1cCAAHb+DWMq0EAyy1bl/JgAghYNGB
+RvKJObTdCrdpYh02KUqBLkSPZHvo6DUJFN37MXDpVeQq9VtqRjpKLLwuEfXb0Y7I
+5xEOrR3kYbOaBAWVt3mYZ1t0L/KfY2jVOdU5WFyyB9PhbMdLi1xE801j+GJrwcLa
+xmqvj4UaICRzcPATP86zVM1BBQa+lilkRQes5HyjZzZDiGYudnXhbqmLo/n0cuXo
+QBVVjhzRTMx71Eiiahmiw+U1vGqkHhQNxb13HtN1lcAhUCDrxxeMvrAjYdWpYlpI
+yW3NssPWt1YUHidMBSAJ4KctIf91dyE93aStlxwC/QnyFsZOmcEsBzVCnz9GmWMl
+1/6XzBS1yDUqByklx0TLH+z/sK9A+O2rZAy1mByCYwVxvbOZhnqGxAuToIS+A81v
+5hCjsCiOScVB+cil30YBu0cH85RZ0ILNkHdKdrLLWW4wjphK2nBn2g2i3+ztf+nQ
+ED2pQqZ/rhuW79jcyCZl9kXqe1wOdF0Cwah4N6/3LzIXEEKyEJxNqQwtNc2IVE8C
+AwEAAaOBtTCBsjAJBgNVHRMEAjAAMEEGDCsGAQQBkggJAYMxAQQxDC9SZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIElCTSB6IFN5c3RlbXMgQmV0YTAbBgwrBgEE
+AZIICQGDMQIECwwJMTAuMSBCZXRhMBcGDCsGAQQBkggJAYMxAwQHDAVzMzkweDAs
+BgwrBgEEAZIICQGDMQQEHAwacmhlbC0xMCxyaGVsLTEwLWJldGEtczM5MHgwDQYJ
+KoZIhvcNAQELBQADggIBACwo67Ht6qWmhyumMwWHpdlU7yzLc/s4oGTixAYsNEjf
++wtcCNtoO89crtwd6upsrK0V/qaDRpqugk40QyoGwDKGN7J9GLqrSBDTtMwKv5vY
+gE0GNiK/AUmE65uT6qAHq35OCAsNphGHyvOhDSEnLdAeU0VAMAOxi3Rb2KxmquE9
+mpjledsrBHUTHxUYobHKKEVSRS3JmVTIxcuLEKnIS69k4jq3hnbbd7y9jyadZQWB
+3ASqCnrm+1jKg4U8sYdF1yRdkh9TTU1XS+7z5MZ3tB6Fdzd67SJCkvH2XQGLdx/8
+4AL7Dm09uJrYWBunjs3DRKSIJ7As+l8iE99C4yfgR1rqogQmss57+24uI0UTC3O2
+4q1G+MfPXqF3N4NUuQmuO/M2ATfCXAfM3T6pkdS4g4XhWrpn5Pm5LvLhjU3/3/GM
+I8fANCW84MZmadnPjx77MJphF/mJzvwbkp8sCNUYy5Lbk/vleWOClGG/sgqrUlBj
+k8lI2ngkuIV3+tk0wfIZDOGIt67r3HZ9hP17jhmOR5olSaB36EB1q6OHktEO19uX
+xSRKHqgNMP7KQT/YmxKJb4lz49yQEj8XUiEt+K0r18OmA4QDJrl4jQ37yerlZLQj
+tKniBp5H/p7UN1dO5bKQ5Dp0p4YjXpqp6/K4kpJs6eVZh0Ikp3KcSO5afv604/aF
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/10.1/479.pem b/repos/system_upgrade/common/files/prod-certs/10.1/479.pem
new file mode 100644
index 00000000..23ff46a9
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/10.1/479.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGGDCCBACgAwIBAgIJALDxRLt/tU/1MA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDEyOTEyNDkwM1oXDTQ1MDEy
+OTEyNDkwM1owRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFszMWE2MzI1
+Zi1mOTE3LTQzNjgtOGM2MC05ODYwMDgyNWQzOThdMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxj9J04z+Ezdyx1U33kFftLv0ntNS1BSeuhoZLDhs18yk
+sepG7hXXtHh2CMFfLZmTjAyL9i1XsxykQpVQdXTGpUF33C2qBQHB5glYs9+d781x
+8p8m8zFxbPcW82TIJXbgW3ErVh8vk5qCbG1cCAAHb+DWMq0EAyy1bl/JgAghYNGB
+RvKJObTdCrdpYh02KUqBLkSPZHvo6DUJFN37MXDpVeQq9VtqRjpKLLwuEfXb0Y7I
+5xEOrR3kYbOaBAWVt3mYZ1t0L/KfY2jVOdU5WFyyB9PhbMdLi1xE801j+GJrwcLa
+xmqvj4UaICRzcPATP86zVM1BBQa+lilkRQes5HyjZzZDiGYudnXhbqmLo/n0cuXo
+QBVVjhzRTMx71Eiiahmiw+U1vGqkHhQNxb13HtN1lcAhUCDrxxeMvrAjYdWpYlpI
+yW3NssPWt1YUHidMBSAJ4KctIf91dyE93aStlxwC/QnyFsZOmcEsBzVCnz9GmWMl
+1/6XzBS1yDUqByklx0TLH+z/sK9A+O2rZAy1mByCYwVxvbOZhnqGxAuToIS+A81v
+5hCjsCiOScVB+cil30YBu0cH85RZ0ILNkHdKdrLLWW4wjphK2nBn2g2i3+ztf+nQ
+ED2pQqZ/rhuW79jcyCZl9kXqe1wOdF0Cwah4N6/3LzIXEEKyEJxNqQwtNc2IVE8C
+AwEAAaOBoTCBnjAJBgNVHRMEAjAAMDUGDCsGAQQBkggJAYNfAQQlDCNSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIHg4Nl82NDAWBgwrBgEEAZIICQGDXwIEBgwE
+MTAuMTAYBgwrBgEEAZIICQGDXwMECAwGeDg2XzY0MCgGDCsGAQQBkggJAYNfBAQY
+DBZyaGVsLTEwLHJoZWwtMTAteDg2XzY0MA0GCSqGSIb3DQEBCwUAA4ICAQAEY2Oc
+fkUeiHFmZFf9Pb9nnCZqfRmrYl19aQeM8fVf4EKQVTy0WSadu6COTUngPl3Nsv3L
+nTl5rhvNXqVLN7kILZVbUBkzLeC89VrdwT0i9IoiINFDIOYxi55Ul8d/mS5o2Vla
+j3gy9cEOJBX/gfgTTG72nOp0f9B6CI2DmSjNVdA4ClOCfX0VRP+QhvOasEvKp4xg
+8b9lTi1lhE5E/axIpCtkc9JsPcp6sqLD4He8xSmNyuqOUowmDcYU2P2WSKSFNS8o
+kKL6EPMWk9W8QnirdjzBqNbIZY2qr9Pc9+Lk8kZ7T0JHGxfccaDLlunWOzEPQWtl
+AtTmzLVSKs3kCuxM4kiOd8sbMjIUth+G56bECD+lCYtsK8GdkAy+ACRN/7knirEC
+pv2eOYDnIaaWyI7kTUrN3fiCrSeQ9PydZ4nonL1VjiY5GS+2+LjmD8XGFJiEnWll
+tyvjvio2PjhqwayEOR1dOzsdgDko5fAnfdxA/pPCYB9uyXxE/pjE5sH6m2qIhCSw
+UcDIgpWpHnBPjw2sstnSRIdOkN4lb086vorvHph3YuEMa00SIWR2QAOY3cAYeqn0
+7RHCUVVdHHo5BlQjU4Fzpsxft8lmdzVsvMDI2fuT4at9UEe0ViTPKIBohVIgp5hz
+WQpi9eB/4PJNIWup9hrcVQxNWiid/Zk9IKpSyw==
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/10.1/486.pem b/repos/system_upgrade/common/files/prod-certs/10.1/486.pem
new file mode 100644
index 00000000..c66eae07
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/10.1/486.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGJzCCBA+gAwIBAgIJALDxRLt/tU/iMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDEyOTEyNDg0NFoXDTQ1MDEy
+OTEyNDg0NFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFthYThkMTI0
+NS1kODY4LTQwYzYtODg4MS02OWM3MGIyZGI0NmFdMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxj9J04z+Ezdyx1U33kFftLv0ntNS1BSeuhoZLDhs18yk
+sepG7hXXtHh2CMFfLZmTjAyL9i1XsxykQpVQdXTGpUF33C2qBQHB5glYs9+d781x
+8p8m8zFxbPcW82TIJXbgW3ErVh8vk5qCbG1cCAAHb+DWMq0EAyy1bl/JgAghYNGB
+RvKJObTdCrdpYh02KUqBLkSPZHvo6DUJFN37MXDpVeQq9VtqRjpKLLwuEfXb0Y7I
+5xEOrR3kYbOaBAWVt3mYZ1t0L/KfY2jVOdU5WFyyB9PhbMdLi1xE801j+GJrwcLa
+xmqvj4UaICRzcPATP86zVM1BBQa+lilkRQes5HyjZzZDiGYudnXhbqmLo/n0cuXo
+QBVVjhzRTMx71Eiiahmiw+U1vGqkHhQNxb13HtN1lcAhUCDrxxeMvrAjYdWpYlpI
+yW3NssPWt1YUHidMBSAJ4KctIf91dyE93aStlxwC/QnyFsZOmcEsBzVCnz9GmWMl
+1/6XzBS1yDUqByklx0TLH+z/sK9A+O2rZAy1mByCYwVxvbOZhnqGxAuToIS+A81v
+5hCjsCiOScVB+cil30YBu0cH85RZ0ILNkHdKdrLLWW4wjphK2nBn2g2i3+ztf+nQ
+ED2pQqZ/rhuW79jcyCZl9kXqe1wOdF0Cwah4N6/3LzIXEEKyEJxNqQwtNc2IVE8C
+AwEAAaOBsDCBrTAJBgNVHRMEAjAAMDoGDCsGAQQBkggJAYNmAQQqDChSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIHg4Nl82NCBCZXRhMBsGDCsGAQQBkggJAYNm
+AgQLDAkxMC4xIEJldGEwGAYMKwYBBAGSCAkBg2YDBAgMBng4Nl82NDAtBgwrBgEE
+AZIICQGDZgQEHQwbcmhlbC0xMCxyaGVsLTEwLWJldGEteDg2XzY0MA0GCSqGSIb3
+DQEBCwUAA4ICAQCWsIqn8Ff5r9SSNzKwMgRHaDjg/RXN9Zhau1DKDwpqp4m40+cK
+bdKYcS6WrZ2UGgJ1bQ0xHZf7Fh6FYd8wOH9zs0rtfUYuRQwbUlCmipVhhf5EY2FW
+vMTRj8DW1RdOQv7cEo9w4QWFSFQnsTvhR6DZuS8/WK4Z+8i8TV5KoQy6z4nVPdVu
+NiclCJNkjGZgYMqWA3yfmrhh1kxTCnvRdRro+tbTEkdC9oLKrGCrACucjHhAyuK5
+2xfr0q7rmHvxia2oc/9HjB3HV/xai1b/DiWuOb4mjLj/3SS7Ua07a14TZIlEDUrM
+YEzZBFIha+241FVdF434jFr4mAYSbm6yhNahSsPswV2O3vDMGz5tNOc1caWmQXkT
+UC/EXzfyrmy6fBQN32lacDr0OOD9LdVz28IT90brVIAVkFyRtGLLGwId/aDxoJJe
+M+TLHMGf+LfvP/jiwbpZxa6yfXDp6J0rHofNYLCYkeSa6TH55qYDWbi7DosCjpWj
+NnqN8aiDKf3f0OO0tRo1zcGCEMnfG3UzDjp37CWyVYZ/TUq8/ygJrcIxjXg0K1SH
+v01NOwphvkXlsNvjapGIgZTuo3/nASIjC92WP14MjdWv/nKhRkJ4ZMJtKSc6FgLC
+SXF8MHwPmaIyne4k3+tJ0AlmQenPqBs6GCB5xBd01wxhRTf7qxIF/+yr6A==
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/10.1/72.pem b/repos/system_upgrade/common/files/prod-certs/10.1/72.pem
new file mode 100644
index 00000000..fa452aa5
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/10.1/72.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGGTCCBAGgAwIBAgIJALDxRLt/tU/0MA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDEyOTEyNDkwM1oXDTQ1MDEy
+OTEyNDkwM1owRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFswMjNkYTRj
+Zi0xNTgwLTRkYTYtYWFhMy0yMGE1ZDZkMjE1OWNdMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxj9J04z+Ezdyx1U33kFftLv0ntNS1BSeuhoZLDhs18yk
+sepG7hXXtHh2CMFfLZmTjAyL9i1XsxykQpVQdXTGpUF33C2qBQHB5glYs9+d781x
+8p8m8zFxbPcW82TIJXbgW3ErVh8vk5qCbG1cCAAHb+DWMq0EAyy1bl/JgAghYNGB
+RvKJObTdCrdpYh02KUqBLkSPZHvo6DUJFN37MXDpVeQq9VtqRjpKLLwuEfXb0Y7I
+5xEOrR3kYbOaBAWVt3mYZ1t0L/KfY2jVOdU5WFyyB9PhbMdLi1xE801j+GJrwcLa
+xmqvj4UaICRzcPATP86zVM1BBQa+lilkRQes5HyjZzZDiGYudnXhbqmLo/n0cuXo
+QBVVjhzRTMx71Eiiahmiw+U1vGqkHhQNxb13HtN1lcAhUCDrxxeMvrAjYdWpYlpI
+yW3NssPWt1YUHidMBSAJ4KctIf91dyE93aStlxwC/QnyFsZOmcEsBzVCnz9GmWMl
+1/6XzBS1yDUqByklx0TLH+z/sK9A+O2rZAy1mByCYwVxvbOZhnqGxAuToIS+A81v
+5hCjsCiOScVB+cil30YBu0cH85RZ0ILNkHdKdrLLWW4wjphK2nBn2g2i3+ztf+nQ
+ED2pQqZ/rhuW79jcyCZl9kXqe1wOdF0Cwah4N6/3LzIXEEKyEJxNqQwtNc2IVE8C
+AwEAAaOBojCBnzAJBgNVHRMEAjAAMDsGCysGAQQBkggJAUgBBCwMKlJlZCBIYXQg
+RW50ZXJwcmlzZSBMaW51eCBmb3IgSUJNIHogU3lzdGVtczAVBgsrBgEEAZIICQFI
+AgQGDAQxMC4xMBYGCysGAQQBkggJAUgDBAcMBXMzOTB4MCYGCysGAQQBkggJAUgE
+BBcMFXJoZWwtMTAscmhlbC0xMC1zMzkweDANBgkqhkiG9w0BAQsFAAOCAgEAM0cP
+KmcFfsVzBVVDZVZRLsQcWTnoZ8Hhufc8rNdE/LkoV1xGXIsN9ejsxZyfVhYvF8G9
+YP41uvQbR2jnXMAQyB7UNxf6I73hIu3yoJ4s6EqX53o9YfejIFFh0V802WpX4yJ8
+1UCKmQVNxnQCwH2Ybxess13F9oKjh7Ni1MMBpQc8i1vEXfkA/vroKS50tvO6vQgT
+Xh72DJ2dKjdnnMNHnuSq0sVcpEbmvPLR3PFrHAxTm0jzngN3S4JCcstiiHsKCCrV
+muSxW3ydQlC27C3Rdd/gB/fc5rxl9xh9Piq6a9UHDuqrXb83hMXL+nuvDbt+eERX
+j2Y7NA0BVgQTwW/zERNgIa8j4X7VtRtoeF7X6BF0gdHAsILzOIAIanZXXld6IiKS
+2m6ackoXPUvdUt3jnYTqYyXQmrpvYs13+AhzENdF+AaJGbcxKf4aAbSe5GEbGe9T
+jxoM2+FR+8zOIc8nVcEGaCryPc8kmNEYEVlCqD0DREB+LXeAYtI4MbGeezpQyfEu
+6jgf1njPd2mGihAlNUVePLdF9W96bc1RjOhiVzbjg9lwIWupTu5fPAeoxPNxSvJc
+nijOHvW5tr+ijG32dMSAKVwBSeFAGB+HssPr3hVoebNYniDIlKPIrv/cUkxwQNKL
+rifVE8bFrfYMm83IIR9pNy+wKjArX6S1OIW8A+A=
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.7/279.pem b/repos/system_upgrade/common/files/prod-certs/9.7/279.pem
new file mode 100644
index 00000000..d03c3bb3
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.7/279.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGJTCCBA2gAwIBAgIJALDxRLt/tU/KMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDEyOTEyNDc1NVoXDTQ1MDEy
+OTEyNDc1NVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFtkMjU0NzVk
+Ni1kZTI1LTQ1ZWItYjQwOC1kNzQ2ZDJiYjE2NjddMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxj9J04z+Ezdyx1U33kFftLv0ntNS1BSeuhoZLDhs18yk
+sepG7hXXtHh2CMFfLZmTjAyL9i1XsxykQpVQdXTGpUF33C2qBQHB5glYs9+d781x
+8p8m8zFxbPcW82TIJXbgW3ErVh8vk5qCbG1cCAAHb+DWMq0EAyy1bl/JgAghYNGB
+RvKJObTdCrdpYh02KUqBLkSPZHvo6DUJFN37MXDpVeQq9VtqRjpKLLwuEfXb0Y7I
+5xEOrR3kYbOaBAWVt3mYZ1t0L/KfY2jVOdU5WFyyB9PhbMdLi1xE801j+GJrwcLa
+xmqvj4UaICRzcPATP86zVM1BBQa+lilkRQes5HyjZzZDiGYudnXhbqmLo/n0cuXo
+QBVVjhzRTMx71Eiiahmiw+U1vGqkHhQNxb13HtN1lcAhUCDrxxeMvrAjYdWpYlpI
+yW3NssPWt1YUHidMBSAJ4KctIf91dyE93aStlxwC/QnyFsZOmcEsBzVCnz9GmWMl
+1/6XzBS1yDUqByklx0TLH+z/sK9A+O2rZAy1mByCYwVxvbOZhnqGxAuToIS+A81v
+5hCjsCiOScVB+cil30YBu0cH85RZ0ILNkHdKdrLLWW4wjphK2nBn2g2i3+ztf+nQ
+ED2pQqZ/rhuW79jcyCZl9kXqe1wOdF0Cwah4N6/3LzIXEEKyEJxNqQwtNc2IVE8C
+AwEAAaOBrjCBqzAJBgNVHRMEAjAAMEMGDCsGAQQBkggJAYIXAQQzDDFSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIFBvd2VyLCBsaXR0bGUgZW5kaWFuMBUGDCsG
+AQQBkggJAYIXAgQFDAM5LjcwGQYMKwYBBAGSCAkBghcDBAkMB3BwYzY0bGUwJwYM
+KwYBBAGSCAkBghcEBBcMFXJoZWwtOSxyaGVsLTktcHBjNjRsZTANBgkqhkiG9w0B
+AQsFAAOCAgEAdT5r3gd+2xXBetsU7BFxMZBiHkgkR642GW0U1jvhX0nMIo6CYJav
+i776Be1aRLprzThI5ZpXZtRgyp9aytmKBKw31WdfccI9jHDpn6HMzWBmO7cyQQ+4
+px3Z9kl2N07YXoZrQZpr3/vahoKTyEpsRWK9GcG6oSKeg5//mGXPlWz+cu6Yj6i5
+WRD//ppcERv1Qrzzog8xgAn7J77dcl57WArlflZRL4QJDKPMDl5f/VwrLPaZ+9LB
+YVUVvn6iYebK9yfM/mkaqXmjTFTmIcblcnC7He0lWCnlPvCDr8T3qXM2xJX42/Dk
+PRDY+/E84LrvURx8hbFUgj4YXEPnk/O7nJf3tTHp3l05GAB52gDycQ/AnvhOcwf7
+KHjUnTqvSnMbgtlbg4rhutn3Ag/vuVEwd+gTMT6pF2lE8eA4ILttcCH6wHrv4Rs1
+dyDkRPxVFPoYCJ8NMU/dRdhZoyfOKYVYGXD80ynjWH+lV4O+wVgRj+cMXzs2Y78l
+4WnBcBlTGFk6ZWuFgurZWelhSUXK/hkhxDIX1eMh3HZoUwu8fP6H3q0r2qsCCRhV
+g6yzu4uzd5sgNVaOS99573Hvcga+3tZJZbX49xb2lgVlnbyNzINEQxrPqVXi9CsZ
+r5vbXJg9DCJ1SVRxTSjUDcjkQ1TmAWzOt0QUN8iJYLyRpy/Y+NEPRZk=
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.7/362.pem b/repos/system_upgrade/common/files/prod-certs/9.7/362.pem
new file mode 100644
index 00000000..41c163cf
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.7/362.pem
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIGNDCCBBygAwIBAgIJALDxRLt/tU+0MA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDEyOTEyNDczNFoXDTQ1MDEy
+OTEyNDczNFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFtjYjlhMGM4
+NS05NDliLTRmMTUtYTlhNS03MjNhNmExMzY3NTRdMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxj9J04z+Ezdyx1U33kFftLv0ntNS1BSeuhoZLDhs18yk
+sepG7hXXtHh2CMFfLZmTjAyL9i1XsxykQpVQdXTGpUF33C2qBQHB5glYs9+d781x
+8p8m8zFxbPcW82TIJXbgW3ErVh8vk5qCbG1cCAAHb+DWMq0EAyy1bl/JgAghYNGB
+RvKJObTdCrdpYh02KUqBLkSPZHvo6DUJFN37MXDpVeQq9VtqRjpKLLwuEfXb0Y7I
+5xEOrR3kYbOaBAWVt3mYZ1t0L/KfY2jVOdU5WFyyB9PhbMdLi1xE801j+GJrwcLa
+xmqvj4UaICRzcPATP86zVM1BBQa+lilkRQes5HyjZzZDiGYudnXhbqmLo/n0cuXo
+QBVVjhzRTMx71Eiiahmiw+U1vGqkHhQNxb13HtN1lcAhUCDrxxeMvrAjYdWpYlpI
+yW3NssPWt1YUHidMBSAJ4KctIf91dyE93aStlxwC/QnyFsZOmcEsBzVCnz9GmWMl
+1/6XzBS1yDUqByklx0TLH+z/sK9A+O2rZAy1mByCYwVxvbOZhnqGxAuToIS+A81v
+5hCjsCiOScVB+cil30YBu0cH85RZ0ILNkHdKdrLLWW4wjphK2nBn2g2i3+ztf+nQ
+ED2pQqZ/rhuW79jcyCZl9kXqe1wOdF0Cwah4N6/3LzIXEEKyEJxNqQwtNc2IVE8C
+AwEAAaOBvTCBujAJBgNVHRMEAjAAMEgGDCsGAQQBkggJAYJqAQQ4DDZSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIFBvd2VyLCBsaXR0bGUgZW5kaWFuIEJldGEw
+GgYMKwYBBAGSCAkBgmoCBAoMCDkuNyBCZXRhMBkGDCsGAQQBkggJAYJqAwQJDAdw
+cGM2NGxlMCwGDCsGAQQBkggJAYJqBAQcDBpyaGVsLTkscmhlbC05LWJldGEtcHBj
+NjRsZTANBgkqhkiG9w0BAQsFAAOCAgEARIGB5FE60xrKLHZinX4m6eqq5lAFqvus
+HM3jS0R5qrg1QcoPuQGoZdOI3BlBDZXkuaR/K34e2+dCB+qu7LAOs5FqrUBGxL1V
+gOVeMehWZN5mDAgEtJNE7rIKa6DlPNGqW1WXcnWqCCpduppGDaHKO6jSqlkxJxrQ
+SadszgeVPifp7t1xq4vaFUDEGMZJlYov2uL1WQC2tuLaRJMBQv6OyZvEbC/fxYKX
+xena2M9FccS8yr8xJ7SRN/2v3uaPBxjHDUbbGDzoeXCIVPyF0cVDeO3MblANVkcf
+RNCu2WUkWGM78wBLVdavwp2Cal++J6kSzImuetCoPaJvRpS4mc/nRMOpcz8ly4DF
+4HwNieBT8sJmKlcOXYLyUywvpFdLKQgnSPMEUyAqfhiPsSqy7xQOvgOQ/Cjf5Q6p
+xVhEhvi86Puxh80kpbHM+LNFXDmcgVgnsbdBriO4mW+9hnelsa4J+7vn5q43Hsbg
+z4LlZpS1PqcNRNa8b65FmEWsvjd74vLowL2SWe0xSbyeqvtWZR5KglOHK9ggsGBz
+dKb5vvLTeSXCogtDgl2qkaDSXqYu3Af5/0Zwe57c5MC3k5+0jW91ZjzoTunRgHWo
+cDgpyvABKiglu/xKlVzE3Te/Cr11zV1jBwFxsASuIWmI4VPYAtWCAxtG6XrJKfPi
+iDaGn3oBNKU=
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.7/363.pem b/repos/system_upgrade/common/files/prod-certs/9.7/363.pem
new file mode 100644
index 00000000..eb822e4d
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.7/363.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGJjCCBA6gAwIBAgIJALDxRLt/tU+zMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDEyOTEyNDczNFoXDTQ1MDEy
+OTEyNDczNFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs3NTU2NjYw
+Ny1mNzBiLTRhNjYtYmI3YS1iOWJlYzU1NTAyY2FdMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxj9J04z+Ezdyx1U33kFftLv0ntNS1BSeuhoZLDhs18yk
+sepG7hXXtHh2CMFfLZmTjAyL9i1XsxykQpVQdXTGpUF33C2qBQHB5glYs9+d781x
+8p8m8zFxbPcW82TIJXbgW3ErVh8vk5qCbG1cCAAHb+DWMq0EAyy1bl/JgAghYNGB
+RvKJObTdCrdpYh02KUqBLkSPZHvo6DUJFN37MXDpVeQq9VtqRjpKLLwuEfXb0Y7I
+5xEOrR3kYbOaBAWVt3mYZ1t0L/KfY2jVOdU5WFyyB9PhbMdLi1xE801j+GJrwcLa
+xmqvj4UaICRzcPATP86zVM1BBQa+lilkRQes5HyjZzZDiGYudnXhbqmLo/n0cuXo
+QBVVjhzRTMx71Eiiahmiw+U1vGqkHhQNxb13HtN1lcAhUCDrxxeMvrAjYdWpYlpI
+yW3NssPWt1YUHidMBSAJ4KctIf91dyE93aStlxwC/QnyFsZOmcEsBzVCnz9GmWMl
+1/6XzBS1yDUqByklx0TLH+z/sK9A+O2rZAy1mByCYwVxvbOZhnqGxAuToIS+A81v
+5hCjsCiOScVB+cil30YBu0cH85RZ0ILNkHdKdrLLWW4wjphK2nBn2g2i3+ztf+nQ
+ED2pQqZ/rhuW79jcyCZl9kXqe1wOdF0Cwah4N6/3LzIXEEKyEJxNqQwtNc2IVE8C
+AwEAAaOBrzCBrDAJBgNVHRMEAjAAMDoGDCsGAQQBkggJAYJrAQQqDChSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIEFSTSA2NCBCZXRhMBoGDCsGAQQBkggJAYJr
+AgQKDAg5LjcgQmV0YTAZBgwrBgEEAZIICQGCawMECQwHYWFyY2g2NDAsBgwrBgEE
+AZIICQGCawQEHAwacmhlbC05LHJoZWwtOS1iZXRhLWFhcmNoNjQwDQYJKoZIhvcN
+AQELBQADggIBAJrJftJS2xfoJVxLo76MMFZ6F2RBW+IgyFq45GphNNN8nUUixGTN
+exzgAI1TgqqhKvFpDHk49PlSq2syzOWqUuAn1dnxU8W5pfWZuBOs/NxdhCKgGUxT
+GrkiRi+RUVoUi9+Qx2P/UvNS/URCrOxyB1HC2x7Pl5r3NaQjf3s6JAfIsxPzptZa
+4x/RsRGu2Q41VQgX/ItAzFrPfZh6O94OfwXBP+FwEjSCVA00EGXO+m8BfHE4/eEm
+E1C4uw54BwlW5SIy2VCiv96MD+u0YlTITQEMqa+6fXXhiWi9FMjvsfPbldP9iScc
+6GXf+hbyUrjhilxva0AuxneBkJb3u7maCNPUEpJ9fhm+A3bPtyhDPG+0AwQCW637
+mNrjEGowbGehw4wO+T2+CxdAhR2WPpeLKQgwHxiJgH52OeI0wn7+nkI8I1TK/r6q
+JVwGEXi/I5wY0z8oYF5MeU+oE0pA06t471/bM0zTVnzVSFd0UUnVe+1nKjehPtDf
+1EI8XCbuTK1lyEiYMMx92T39jrXRjt+mkW3OJRzSCTef8wfbyNxaBo6FTyJG5Jvm
+EEaiVpsZs7UEx0CHdCbPJ+gb5SZ7nsmPT2GdJyfhO928dwmJzANYcI1mlDWFjjyx
+DJYI+otDEDl3TFh6LXMjM7fPvnIoTq9vvxCgMohrgFWLiUOdcdZSdH4I
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.7/419.pem b/repos/system_upgrade/common/files/prod-certs/9.7/419.pem
new file mode 100644
index 00000000..43c22d13
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.7/419.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGFzCCA/+gAwIBAgIJALDxRLt/tU/JMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDEyOTEyNDc1NVoXDTQ1MDEy
+OTEyNDc1NVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs2NjU1MzE5
+Zi1kYWE2LTQyZjQtYmVlYS05OGUwNWJkZDJlMjhdMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxj9J04z+Ezdyx1U33kFftLv0ntNS1BSeuhoZLDhs18yk
+sepG7hXXtHh2CMFfLZmTjAyL9i1XsxykQpVQdXTGpUF33C2qBQHB5glYs9+d781x
+8p8m8zFxbPcW82TIJXbgW3ErVh8vk5qCbG1cCAAHb+DWMq0EAyy1bl/JgAghYNGB
+RvKJObTdCrdpYh02KUqBLkSPZHvo6DUJFN37MXDpVeQq9VtqRjpKLLwuEfXb0Y7I
+5xEOrR3kYbOaBAWVt3mYZ1t0L/KfY2jVOdU5WFyyB9PhbMdLi1xE801j+GJrwcLa
+xmqvj4UaICRzcPATP86zVM1BBQa+lilkRQes5HyjZzZDiGYudnXhbqmLo/n0cuXo
+QBVVjhzRTMx71Eiiahmiw+U1vGqkHhQNxb13HtN1lcAhUCDrxxeMvrAjYdWpYlpI
+yW3NssPWt1YUHidMBSAJ4KctIf91dyE93aStlxwC/QnyFsZOmcEsBzVCnz9GmWMl
+1/6XzBS1yDUqByklx0TLH+z/sK9A+O2rZAy1mByCYwVxvbOZhnqGxAuToIS+A81v
+5hCjsCiOScVB+cil30YBu0cH85RZ0ILNkHdKdrLLWW4wjphK2nBn2g2i3+ztf+nQ
+ED2pQqZ/rhuW79jcyCZl9kXqe1wOdF0Cwah4N6/3LzIXEEKyEJxNqQwtNc2IVE8C
+AwEAAaOBoDCBnTAJBgNVHRMEAjAAMDUGDCsGAQQBkggJAYMjAQQlDCNSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIEFSTSA2NDAVBgwrBgEEAZIICQGDIwIEBQwD
+OS43MBkGDCsGAQQBkggJAYMjAwQJDAdhYXJjaDY0MCcGDCsGAQQBkggJAYMjBAQX
+DBVyaGVsLTkscmhlbC05LWFhcmNoNjQwDQYJKoZIhvcNAQELBQADggIBAG1dALly
+8sSax1sy31WsbXTtDkiLyzUMOLCWQtEVo77l8MWse76+LEyvUnSCyYB2V3w6IK5P
+IfRGqGPksWGnPHoRgAVvAIwa0DDH9UQl/se4J3dOSLfnkRFAthMew9eLBFzCltCl
+fZWmBsR84qfOha4m45QMwogysbIxTPBr6JqrpN0qkc87zBkx2SrtjavTf83g7lGE
+0XmRqY8Pyr5SSdHDUmxHSxoDvx1+/Rt2b3d3+nwRrhUgXU+4Ev7P0YyS3T22jZ8g
+GVZ330tXOhhIhFWmB5hI7eAwU8IIkxhH+TEsHHWbF4yaGveDnpgIpyGThGnsK3pB
+M2BTeB0UiY2COFg6Mm4iODJ2GuM2mDPR0ZAhphGV/JSqZE3N9vSm1rO8tZjc8sDv
+xIdHSVQupm5Dbbs6iO31vl+PkQ23WpHtNEVkKhhkUNS5g3rO9P3ULZeFigAWtWuw
++IClKc/8R2ksGegS69H4wXXVh1Ie3sHEyWlkB8pgzQmvS0VCX+EhaIs6P8QCu90Z
+NLscEhCeLT+pBDISXuf58R6W+DOyetwpFBh7Z5glcw8bmCkne5Su06/9+crfULup
+i8/1NtQO28KMvuDdHchtZ6arn0xHSkcwW9NyRBnnjAUjDH0nOvkJVJqzubvNj8uW
+7+Bph5JIcD945pirT4gt1WAEhLUPqdBoFfKw
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.7/433.pem b/repos/system_upgrade/common/files/prod-certs/9.7/433.pem
new file mode 100644
index 00000000..c3309765
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.7/433.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGKTCCBBGgAwIBAgIJALDxRLt/tU+1MA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDEyOTEyNDczNFoXDTQ1MDEy
+OTEyNDczNFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFtmYzhkZWI4
+OS0xZTJjLTRhOWEtOTRlZS01MzBmYWRhNDA0YTddMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxj9J04z+Ezdyx1U33kFftLv0ntNS1BSeuhoZLDhs18yk
+sepG7hXXtHh2CMFfLZmTjAyL9i1XsxykQpVQdXTGpUF33C2qBQHB5glYs9+d781x
+8p8m8zFxbPcW82TIJXbgW3ErVh8vk5qCbG1cCAAHb+DWMq0EAyy1bl/JgAghYNGB
+RvKJObTdCrdpYh02KUqBLkSPZHvo6DUJFN37MXDpVeQq9VtqRjpKLLwuEfXb0Y7I
+5xEOrR3kYbOaBAWVt3mYZ1t0L/KfY2jVOdU5WFyyB9PhbMdLi1xE801j+GJrwcLa
+xmqvj4UaICRzcPATP86zVM1BBQa+lilkRQes5HyjZzZDiGYudnXhbqmLo/n0cuXo
+QBVVjhzRTMx71Eiiahmiw+U1vGqkHhQNxb13HtN1lcAhUCDrxxeMvrAjYdWpYlpI
+yW3NssPWt1YUHidMBSAJ4KctIf91dyE93aStlxwC/QnyFsZOmcEsBzVCnz9GmWMl
+1/6XzBS1yDUqByklx0TLH+z/sK9A+O2rZAy1mByCYwVxvbOZhnqGxAuToIS+A81v
+5hCjsCiOScVB+cil30YBu0cH85RZ0ILNkHdKdrLLWW4wjphK2nBn2g2i3+ztf+nQ
+ED2pQqZ/rhuW79jcyCZl9kXqe1wOdF0Cwah4N6/3LzIXEEKyEJxNqQwtNc2IVE8C
+AwEAAaOBsjCBrzAJBgNVHRMEAjAAMEEGDCsGAQQBkggJAYMxAQQxDC9SZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIElCTSB6IFN5c3RlbXMgQmV0YTAaBgwrBgEE
+AZIICQGDMQIECgwIOS43IEJldGEwFwYMKwYBBAGSCAkBgzEDBAcMBXMzOTB4MCoG
+DCsGAQQBkggJAYMxBAQaDBhyaGVsLTkscmhlbC05LWJldGEtczM5MHgwDQYJKoZI
+hvcNAQELBQADggIBALijiB6VwIQ1IscN4cQJATyy4IP2ZqPq4Uu2v2c+bxlmFSIK
+7paz9pWmXYmOSmBQgLYkZ1hkAXQdlj7ECmp5Q/rWscu8yw0obwFk1ned/4PnHf+/
+gn3osXUqixnj6RiT2SWlBtTnTqomiwpIeKc/JN0zNcsWagNx/B2Uw+kxfGDW4jF/
+L9rw9meOiQQwdzxbQJbiaCQQq1xE0Kx1yDoDDV/7Zg3eDfwzAUUwj1aE6xt9rms2
+ZhiP/ATlKYbePgIdqaO2sKLoRBugaaUEUSXSyZA6Q+8B7cO66rTtqsGqf83RjIOi
+i5nFTYZwALbUtNFvKN2nhP6ovBPYCX4rTHQ18WqoIzJLEGdO66hchPUP7LnwUJ0i
+vHgLrmiVwzh/LjtrXFt6+MMsvqfrxfre+U5OhjMwtyajjwvw7uJJ9tZjkXkDJs2J
+cZZCSKbj9T/bU7Rnak0eit2Fw75o3eLXaBOeBGUJgCVLlehSaema997V2LeAXtfU
+AcGXvS44YawXXbJHPawW5nXHtHVQnR0M0ksJObvji4DXZndp/TIl0paF5TRPwk7k
+XdNzVDx+2MDTo+hrs8CisMhdV+vIHtdRkXLpmgPlsHCrhBcqYiW37h37tYK9EuZP
+zViezq0rOn/mroAjemIfo1ZdjTDdQn+xQ/W0MCYk5QKf092PKjplsAYoF87H
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.7/479.pem b/repos/system_upgrade/common/files/prod-certs/9.7/479.pem
new file mode 100644
index 00000000..e38d2e54
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.7/479.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGFTCCA/2gAwIBAgIJALDxRLt/tU/MMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDEyOTEyNDc1NVoXDTQ1MDEy
+OTEyNDc1NVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFsxMmVmNTE1
+ZC03OWJhLTRkZjAtYmExMC01ZjE4OGJkYWQ5NGFdMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxj9J04z+Ezdyx1U33kFftLv0ntNS1BSeuhoZLDhs18yk
+sepG7hXXtHh2CMFfLZmTjAyL9i1XsxykQpVQdXTGpUF33C2qBQHB5glYs9+d781x
+8p8m8zFxbPcW82TIJXbgW3ErVh8vk5qCbG1cCAAHb+DWMq0EAyy1bl/JgAghYNGB
+RvKJObTdCrdpYh02KUqBLkSPZHvo6DUJFN37MXDpVeQq9VtqRjpKLLwuEfXb0Y7I
+5xEOrR3kYbOaBAWVt3mYZ1t0L/KfY2jVOdU5WFyyB9PhbMdLi1xE801j+GJrwcLa
+xmqvj4UaICRzcPATP86zVM1BBQa+lilkRQes5HyjZzZDiGYudnXhbqmLo/n0cuXo
+QBVVjhzRTMx71Eiiahmiw+U1vGqkHhQNxb13HtN1lcAhUCDrxxeMvrAjYdWpYlpI
+yW3NssPWt1YUHidMBSAJ4KctIf91dyE93aStlxwC/QnyFsZOmcEsBzVCnz9GmWMl
+1/6XzBS1yDUqByklx0TLH+z/sK9A+O2rZAy1mByCYwVxvbOZhnqGxAuToIS+A81v
+5hCjsCiOScVB+cil30YBu0cH85RZ0ILNkHdKdrLLWW4wjphK2nBn2g2i3+ztf+nQ
+ED2pQqZ/rhuW79jcyCZl9kXqe1wOdF0Cwah4N6/3LzIXEEKyEJxNqQwtNc2IVE8C
+AwEAAaOBnjCBmzAJBgNVHRMEAjAAMDUGDCsGAQQBkggJAYNfAQQlDCNSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIHg4Nl82NDAVBgwrBgEEAZIICQGDXwIEBQwD
+OS43MBgGDCsGAQQBkggJAYNfAwQIDAZ4ODZfNjQwJgYMKwYBBAGSCAkBg18EBBYM
+FHJoZWwtOSxyaGVsLTkteDg2XzY0MA0GCSqGSIb3DQEBCwUAA4ICAQDXiXDrVOMw
+eIApNOeZcaveYY6XSkeWv5Kb9/yZShZ00gp3thOawaGWz6/1lwV7TOlp6XLe4OiB
+NOWpeA6YNfOjQjIkrjzXIzXc/PhahJEddXq7OaGnHYkL8+vbZQurIHxEZVGnloJi
+IbvHWgjXkx0CJ4dX5IEpbBTJYVT+XvO4xgTayipG7c38XvIQif91xwoUBjznxhSh
+6e0deGAE/+ho5ouOgDCssD+jz2f7ekCOR3ehe5+9U3u/3cfQ/QnkW7LGRAvr7Vcz
+RJx1N49AnsJ+I5FdUxIEMgw0xpXA9WyKRUzImgiMboW+Qw6DaQPIyF8eXj6AKFjs
+dFHvi24891HjF7vNBrwLS9jMdrwoNo7+MBGN3M4Q8E6q0K+eRccpYEIt5tLqTBiU
+LrP/RPfY7wZaiHrXNFtuHFdBMdgG9SXMAVjThBsSB22LIYeIHbtvXoF5NRF7F2x8
+f1BuGRkTpWERDeO0iQCm1feSzhnfpmZ4uqrGKINr98SqHaRv7NyWcEAq8BZ8iMsq
+iSmpwRnpK3Y3Z7JZaa5qOyhANvdJjhiV42QNZ9B3WESB5Y22uf643RqcquCSnKTd
+RmXymDyyO7NNBUWdBceTdomAOEviDl0FNv5nhGs++eEJHMfKL2rFXYvRyqSwVkIm
+Y6MmDGFEYYvHybEKh25m3wrwoZai3LGX4g==
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.7/486.pem b/repos/system_upgrade/common/files/prod-certs/9.7/486.pem
new file mode 100644
index 00000000..a9c3a580
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.7/486.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGJDCCBAygAwIBAgIJALDxRLt/tU+2MA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDEyOTEyNDczNFoXDTQ1MDEy
+OTEyNDczNFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFtkMGEzYzRj
+Zi01ZDZjLTQ5OWMtYTQ5Zi01OTFhNzg3ZTI2MWVdMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxj9J04z+Ezdyx1U33kFftLv0ntNS1BSeuhoZLDhs18yk
+sepG7hXXtHh2CMFfLZmTjAyL9i1XsxykQpVQdXTGpUF33C2qBQHB5glYs9+d781x
+8p8m8zFxbPcW82TIJXbgW3ErVh8vk5qCbG1cCAAHb+DWMq0EAyy1bl/JgAghYNGB
+RvKJObTdCrdpYh02KUqBLkSPZHvo6DUJFN37MXDpVeQq9VtqRjpKLLwuEfXb0Y7I
+5xEOrR3kYbOaBAWVt3mYZ1t0L/KfY2jVOdU5WFyyB9PhbMdLi1xE801j+GJrwcLa
+xmqvj4UaICRzcPATP86zVM1BBQa+lilkRQes5HyjZzZDiGYudnXhbqmLo/n0cuXo
+QBVVjhzRTMx71Eiiahmiw+U1vGqkHhQNxb13HtN1lcAhUCDrxxeMvrAjYdWpYlpI
+yW3NssPWt1YUHidMBSAJ4KctIf91dyE93aStlxwC/QnyFsZOmcEsBzVCnz9GmWMl
+1/6XzBS1yDUqByklx0TLH+z/sK9A+O2rZAy1mByCYwVxvbOZhnqGxAuToIS+A81v
+5hCjsCiOScVB+cil30YBu0cH85RZ0ILNkHdKdrLLWW4wjphK2nBn2g2i3+ztf+nQ
+ED2pQqZ/rhuW79jcyCZl9kXqe1wOdF0Cwah4N6/3LzIXEEKyEJxNqQwtNc2IVE8C
+AwEAAaOBrTCBqjAJBgNVHRMEAjAAMDoGDCsGAQQBkggJAYNmAQQqDChSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIHg4Nl82NCBCZXRhMBoGDCsGAQQBkggJAYNm
+AgQKDAg5LjcgQmV0YTAYBgwrBgEEAZIICQGDZgMECAwGeDg2XzY0MCsGDCsGAQQB
+kggJAYNmBAQbDBlyaGVsLTkscmhlbC05LWJldGEteDg2XzY0MA0GCSqGSIb3DQEB
+CwUAA4ICAQBTdLKi7NjqPmP+Sy9Bd0xQRQDNS0Tpvs4OR11rYuBRvQl04maKij4X
+OiYWp0/PeQdkT2GMRcU4Yvs3oFtnj9jIAUmDAxT4wCrPUGgxRiwve5RJSRpXwaYt
+eCXJVa0TkJ9CPy1h1am5r8/tD+5amftuy5ActB5R1yuiUhtao+ii12BscFBa0GxL
+xBYD9Kp0+/bgXWY5vLQfcAdRmCGWnWD7DiH6+63o100RdMM7NKiErzC88GEtzbJJ
+hEkBB+BkxhKP+LTiJOXQWwstd6u7E0yk9t5vyCuZmWVUdF1ZEP60+GrY7j4wB1uX
+hQ62x2aXnTalx2mFiRJWt3enF9Si2fH+2UOwZm9iRLeblhf+C7N6bpxO/mXkPWEq
+cInjmpRzJh8w7nqZU7HFdt0v71ZHDr+Ppu61gStbebJyUNU4R93jqXqatEfzmhTB
+beuLeTwf5M0gYt19PHFE5ls8qsjCNbppxNTo4FmpTi8XvSSYoe/FjzoChTZWD8La
+w5MQrKxqlScRkI2yWMoNJNfS/0mTE7e7DoEnwbbDWQVdb6Kx7bi5HVMW+PLPsX+U
+aeDYf2i6Vlqhr8mtLcV+9HUdDP+a13OOKjIqNRMGnq4Ks+h5XbFpUa10ZTdtqbQJ
+Xj72H08QzoBwcZfFwWDODjU5co0X7QAhQ6D6b9b1OrGtt1lXurS53w==
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.7/72.pem b/repos/system_upgrade/common/files/prod-certs/9.7/72.pem
new file mode 100644
index 00000000..4c6e257c
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.7/72.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGFjCCA/6gAwIBAgIJALDxRLt/tU/LMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDEyOTEyNDc1NVoXDTQ1MDEy
+OTEyNDc1NVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFtlOWQyNzc3
+Mi1hMmFlLTQ1YTUtYjYxMS1jZDViZmY3Y2Y4NTNdMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxj9J04z+Ezdyx1U33kFftLv0ntNS1BSeuhoZLDhs18yk
+sepG7hXXtHh2CMFfLZmTjAyL9i1XsxykQpVQdXTGpUF33C2qBQHB5glYs9+d781x
+8p8m8zFxbPcW82TIJXbgW3ErVh8vk5qCbG1cCAAHb+DWMq0EAyy1bl/JgAghYNGB
+RvKJObTdCrdpYh02KUqBLkSPZHvo6DUJFN37MXDpVeQq9VtqRjpKLLwuEfXb0Y7I
+5xEOrR3kYbOaBAWVt3mYZ1t0L/KfY2jVOdU5WFyyB9PhbMdLi1xE801j+GJrwcLa
+xmqvj4UaICRzcPATP86zVM1BBQa+lilkRQes5HyjZzZDiGYudnXhbqmLo/n0cuXo
+QBVVjhzRTMx71Eiiahmiw+U1vGqkHhQNxb13HtN1lcAhUCDrxxeMvrAjYdWpYlpI
+yW3NssPWt1YUHidMBSAJ4KctIf91dyE93aStlxwC/QnyFsZOmcEsBzVCnz9GmWMl
+1/6XzBS1yDUqByklx0TLH+z/sK9A+O2rZAy1mByCYwVxvbOZhnqGxAuToIS+A81v
+5hCjsCiOScVB+cil30YBu0cH85RZ0ILNkHdKdrLLWW4wjphK2nBn2g2i3+ztf+nQ
+ED2pQqZ/rhuW79jcyCZl9kXqe1wOdF0Cwah4N6/3LzIXEEKyEJxNqQwtNc2IVE8C
+AwEAAaOBnzCBnDAJBgNVHRMEAjAAMDsGCysGAQQBkggJAUgBBCwMKlJlZCBIYXQg
+RW50ZXJwcmlzZSBMaW51eCBmb3IgSUJNIHogU3lzdGVtczAUBgsrBgEEAZIICQFI
+AgQFDAM5LjcwFgYLKwYBBAGSCAkBSAMEBwwFczM5MHgwJAYLKwYBBAGSCAkBSAQE
+FQwTcmhlbC05LHJoZWwtOS1zMzkweDANBgkqhkiG9w0BAQsFAAOCAgEAdVhrTT0k
+0sBZOpLSW3fWCbIdJ0lChyYtPCii6O4vj5hE1oCV0tHmCGcfEp4j49GXwB6zs3F7
+cZsJO2aGrMEZkiGPMTPGW0VV+QKJIq7wo23ogWw/fxF3K3QbFTDNbfdv/E8MRkcN
+P9bLgTGqcs9VpNKp48+TovpxtjYeF9/XQi+h5wll5gqEfFnq8VaKi6P9eZvbGuue
+DhdItkN+RdHMj8AQpMAezKyOb3QURCBUJMtbvZgJk6tRCHnhF3NSig/h9lbrVqmu
+Wd7b/+uw/ElzXsLr6ekHuVH5oI9A9F+4SEFBKjCVvwEkd+FK+P2iudF6YR3Ods6t
+uXMBcI9e9bXdzzn3XLKHcpgeDURkPgD8xW/ICut1pFeqO/YnR8xodJ7X+8h4JJpn
+yNOFlaqEV0t9BTRGX7vfCSFZ8k07RQLmTvRFUC/OniL50hfUw+L2fedpTD2JtTRN
+aeMBN2kiAzKn7K28Ejv6BJcDnohXDMWNfmL85i5jvQ/BMxu7pvFiAuPsGeCZ1Yj5
+1s3kQxKzQ/nCE/ZBDLG+B7hlRGNYPoYvfxcNjEaKbYny9jkvb8JqPgRBmowsLcxC
+jukhm6gp+R/kkp0nQjnYsoan49ai/YTU4pY0uyDAAfM9h6owwKkO/1PWTiXCqVJK
+Rm6ezgUGOYAUA/i4p+LLyIArOUqHwRxJ2S4=
+-----END CERTIFICATE-----
--
2.49.0

View File

@ -0,0 +1,178 @@
From 9c621a91199c093f603ef30ba3daf59010c20e47 Mon Sep 17 00:00:00 2001
From: karolinku <kkula@redhat.com>
Date: Thu, 10 Apr 2025 09:14:51 +0200
Subject: [PATCH 26/37] Add handling of shorten PCI ID and lowercases
HW data file is inconsistent and sometimes contains both upper/lower
cases so this patch is unifying it. Also PCI ID can be passed as full
ID: Vendor:Device:SVendor:SDevice, but also in shorten version:
Vendor:Device. This patch introduce handling of both cases.
The data comming from DDDD file was sanitised.
JIRA: RHEL-72544
---
.../deviceanddriverdeprecationdataload.py | 9 +++
.../libraries/pcidevicesscanner.py | 19 ++++--
.../tests/test_pcidevicesscanner.py | 64 +++++++++++++++++--
3 files changed, 81 insertions(+), 11 deletions(-)
diff --git a/repos/system_upgrade/common/actors/loaddevicedriverdeprecationdata/libraries/deviceanddriverdeprecationdataload.py b/repos/system_upgrade/common/actors/loaddevicedriverdeprecationdata/libraries/deviceanddriverdeprecationdataload.py
index b12e77c9..acea583d 100644
--- a/repos/system_upgrade/common/actors/loaddevicedriverdeprecationdata/libraries/deviceanddriverdeprecationdataload.py
+++ b/repos/system_upgrade/common/actors/loaddevicedriverdeprecationdata/libraries/deviceanddriverdeprecationdataload.py
@@ -25,6 +25,15 @@ def process():
docs_url='',
docs_title='')
+ # Unify all device ids to lowercase
+ try:
+ for entry in deprecation_data['data']:
+ if "device_id" in entry.keys():
+ entry["device_id"] = entry.get("device_id").lower()
+ except (KeyError, AttributeError, TypeError):
+ # this may happen if receiving invalid data
+ pass
+
try:
api.produce(
DeviceDriverDeprecationData(
diff --git a/repos/system_upgrade/common/actors/pcidevicesscanner/libraries/pcidevicesscanner.py b/repos/system_upgrade/common/actors/pcidevicesscanner/libraries/pcidevicesscanner.py
index eb063abb..285a8a21 100644
--- a/repos/system_upgrade/common/actors/pcidevicesscanner/libraries/pcidevicesscanner.py
+++ b/repos/system_upgrade/common/actors/pcidevicesscanner/libraries/pcidevicesscanner.py
@@ -60,7 +60,7 @@ def parse_pci_device(textual_block, numeric_block):
driver=device['Driver'],
modules=device['Module'],
numa_node=device['NUMANode'],
- pci_id=":".join(PCI_ID_REG.findall(numeric_block))
+ pci_id=(":".join(PCI_ID_REG.findall(numeric_block)).lower())
)
@@ -78,14 +78,19 @@ def parse_pci_devices(pci_textual, pci_numeric):
def produce_detected_devices(devices):
prefix_re = re.compile('0x')
entry_lookup = {
- prefix_re.sub('', entry.device_id): entry
+ prefix_re.sub('', entry.device_id.lower()): entry
for message in api.consume(DeviceDriverDeprecationData) for entry in message.entries
}
- api.produce(*[
- DetectedDeviceOrDriver(**entry_lookup[device.pci_id].dump())
- for device in devices
- if device.pci_id in entry_lookup
- ])
+
+ device_list = []
+ for device in devices:
+ shorten_pci_id = ":".join(device.pci_id.split(':')[:-2])
+ if device.pci_id in entry_lookup:
+ device_list.append(DetectedDeviceOrDriver(**entry_lookup[device.pci_id].dump()))
+ elif shorten_pci_id in entry_lookup:
+ device_list.append(DetectedDeviceOrDriver(**entry_lookup[shorten_pci_id].dump()))
+
+ api.produce(*device_list)
def produce_detected_drivers(devices):
diff --git a/repos/system_upgrade/common/actors/pcidevicesscanner/tests/test_pcidevicesscanner.py b/repos/system_upgrade/common/actors/pcidevicesscanner/tests/test_pcidevicesscanner.py
index 4bd545ba..2bfde232 100644
--- a/repos/system_upgrade/common/actors/pcidevicesscanner/tests/test_pcidevicesscanner.py
+++ b/repos/system_upgrade/common/actors/pcidevicesscanner/tests/test_pcidevicesscanner.py
@@ -2,8 +2,16 @@ import os
import pytest
-from leapp.libraries.actor.pcidevicesscanner import parse_pci_devices, produce_pci_devices
-from leapp.models import PCIDevice, PCIDevices
+from leapp.libraries.actor.pcidevicesscanner import parse_pci_devices, produce_detected_devices, produce_pci_devices
+from leapp.libraries.common.testutils import CurrentActorMocked, produce_mocked
+from leapp.libraries.stdlib import api
+from leapp.models import (
+ DetectedDeviceOrDriver,
+ DeviceDriverDeprecationData,
+ DeviceDriverDeprecationEntry,
+ PCIDevice,
+ PCIDevices
+)
def test_parse_pci_devices():
@@ -37,9 +45,9 @@ Module: ata_generic
'''
devices_numeric = '''Slot: 00:00.0
Class: Host bridge
-Vendor: 15b45
+Vendor: 15B45
Device: 0724
-SVendor: 15b46
+SVendor: 15B46
SDevice: 0725
PhySlot: 3
Rev: 02
@@ -76,6 +84,7 @@ Module: ata_generic
assert dev.progif == '80'
assert dev.driver == 'ata_piix'
assert dev.pci_id == '15b43:0722'
+ assert dev.pci_id.islower() is True
assert len(dev.modules) == 3
assert 'ata_piix' in dev.modules
assert 'pata_acpi' in dev.modules
@@ -206,6 +215,53 @@ def test_produce_no_devices():
assert not output[0].devices
+def test_shorten_id(monkeypatch):
+
+ input_data = [PCIDevice(
+ slot='b765:00:02.0',
+ dev_cls='Ethernet controller',
+ vendor='Mellanox Technologies',
+ name='MT27500/MT27520 Family [ConnectX-3/ConnectX-3 Pro Virtual Function]',
+ subsystem_vendor='Mellanox Technologies',
+ subsystem_name='Device 61b0',
+ physical_slot='2',
+ rev='',
+ progif='',
+ driver='mlx4_core',
+ modules=['mlx4_core'],
+ numa_node='0',
+ pci_id='15b3:1004:15b3:61b0'
+ )]
+
+ messages = [DeviceDriverDeprecationData(entries=[DeviceDriverDeprecationEntry(
+ available_in_rhel=[7, 8, 9],
+ deprecation_announced="",
+ device_id="0x15B3:0x1004",
+ device_name="Mellanox Technologies: MT27500 Family [ConnectX-3 Virtual Function]",
+ device_type="pci",
+ driver_name="mlx4_core",
+ maintained_in_rhel=[7, 8]
+ )])]
+
+ expected_output = DetectedDeviceOrDriver(
+ available_in_rhel=[7, 8, 9],
+ deprecation_announced="",
+ device_id="0x15B3:0x1004",
+ device_name="Mellanox Technologies: MT27500 Family [ConnectX-3 Virtual Function]",
+ device_type="pci",
+ driver_name="mlx4_core",
+ maintained_in_rhel=[7, 8]
+ )
+
+ current_actor = CurrentActorMocked(msgs=messages, src_ver='8.10', dst_ver='9.6')
+ monkeypatch.setattr(api, 'current_actor', current_actor)
+ monkeypatch.setattr(api, 'produce', produce_mocked())
+
+ produce_detected_devices(input_data)
+ assert api.produce.model_instances
+ assert expected_output == api.produce.model_instances[0]
+
+
# TODO(pstodulk): update the test - drop current_actor_context and use monkeypatch
@pytest.mark.skipif(not os.path.exists('/usr/sbin/lspci'), reason='lspci not installed on the system')
def test_actor_execution(current_actor_context):
--
2.49.0

View File

@ -0,0 +1,125 @@
From d7d37caae69e27caec73d35236bedb6e1e70bcd4 Mon Sep 17 00:00:00 2001
From: karolinku <kkula@redhat.com>
Date: Wed, 7 May 2025 13:35:37 +0200
Subject: [PATCH 27/37] Prevent device list from containing incorrent content
Some PCI devices got from lspci output do not have to neccessarily
provide SVendor and SDevice fields. PCI ID of such devices is
composed in the pci_device_scanner actor just from:
Vendor:Device
instead of the full id:
Vendor:Device:SVendor:SDevice
The recent change comparing such devices with bundled DDDD
data drops last two fragments from the composed PCI ID,
which led to the situation when the `shortened_pci_id`
resulted in an empty string and it has been incorrectly
matched with one of (consider random) drivers and possibly
inhibited the in-place upgrade.
So let's ensure that we do not match any PCI device with
any entry from DDDD undefined PCI ID.
JIRA: RHEL-72544
---
.../libraries/pcidevicesscanner.py | 1 +
.../tests/test_pcidevicesscanner.py | 71 +++++++++++++++++++
2 files changed, 72 insertions(+)
diff --git a/repos/system_upgrade/common/actors/pcidevicesscanner/libraries/pcidevicesscanner.py b/repos/system_upgrade/common/actors/pcidevicesscanner/libraries/pcidevicesscanner.py
index 285a8a21..36e4f7e0 100644
--- a/repos/system_upgrade/common/actors/pcidevicesscanner/libraries/pcidevicesscanner.py
+++ b/repos/system_upgrade/common/actors/pcidevicesscanner/libraries/pcidevicesscanner.py
@@ -80,6 +80,7 @@ def produce_detected_devices(devices):
entry_lookup = {
prefix_re.sub('', entry.device_id.lower()): entry
for message in api.consume(DeviceDriverDeprecationData) for entry in message.entries
+ if entry.device_id
}
device_list = []
diff --git a/repos/system_upgrade/common/actors/pcidevicesscanner/tests/test_pcidevicesscanner.py b/repos/system_upgrade/common/actors/pcidevicesscanner/tests/test_pcidevicesscanner.py
index 2bfde232..e8e4bb99 100644
--- a/repos/system_upgrade/common/actors/pcidevicesscanner/tests/test_pcidevicesscanner.py
+++ b/repos/system_upgrade/common/actors/pcidevicesscanner/tests/test_pcidevicesscanner.py
@@ -262,6 +262,77 @@ def test_shorten_id(monkeypatch):
assert expected_output == api.produce.model_instances[0]
+def test_cut_pci_id(monkeypatch):
+
+ input_data = [
+ PCIDevice(
+ slot='00:03.0',
+ dev_cls='Ethernet controller',
+ vendor='Intel Corporation',
+ name='82599 Ethernet Controller Virtual Function',
+ subsystem_vendor='',
+ subsystem_name='',
+ physical_slot='3',
+ rev='01',
+ progif='',
+ driver='ixgbevf',
+ modules=['ixgbevf'],
+ numa_node='',
+ pci_id='8086:10ed'
+ ),
+ PCIDevice(
+ slot='b765:00:02.0',
+ dev_cls='Ethernet controller',
+ vendor='Mellanox Technologies',
+ name='MT27500/MT27520 Family [ConnectX-3/ConnectX-3 Pro Virtual Function]',
+ subsystem_vendor='Mellanox Technologies',
+ subsystem_name='Device 61b0',
+ physical_slot='2',
+ rev='',
+ progif='',
+ driver='mlx4_core',
+ modules=['mlx4_core'],
+ numa_node='0',
+ pci_id='15b3:1004:15b3:61b0'
+ )]
+
+ messages = [DeviceDriverDeprecationData(entries=[DeviceDriverDeprecationEntry(
+ available_in_rhel=[7],
+ deprecation_announced='',
+ device_id='',
+ device_name='',
+ device_type='pci',
+ driver_name='wil6210',
+ maintained_in_rhel=[]
+ ),
+ DeviceDriverDeprecationEntry(
+ available_in_rhel=[7, 8, 9],
+ deprecation_announced="",
+ device_id="0x15B3:0x1004",
+ device_name="Mellanox Technologies: MT27500 Family [ConnectX-3 Virtual Function]",
+ device_type="pci",
+ driver_name="mlx4_core",
+ maintained_in_rhel=[7, 8])]
+ )]
+
+ expected_output = DetectedDeviceOrDriver(
+ available_in_rhel=[7, 8, 9],
+ deprecation_announced="",
+ device_id="0x15B3:0x1004",
+ device_name="Mellanox Technologies: MT27500 Family [ConnectX-3 Virtual Function]",
+ device_type="pci",
+ driver_name="mlx4_core",
+ maintained_in_rhel=[7, 8]
+ )
+ current_actor = CurrentActorMocked(msgs=messages, src_ver='8.10', dst_ver='9.6')
+ monkeypatch.setattr(api, 'current_actor', current_actor)
+ monkeypatch.setattr(api, 'produce', produce_mocked())
+
+ produce_detected_devices(input_data)
+ assert api.produce.model_instances
+ assert expected_output == api.produce.model_instances[0]
+
+
# TODO(pstodulk): update the test - drop current_actor_context and use monkeypatch
@pytest.mark.skipif(not os.path.exists('/usr/sbin/lspci'), reason='lspci not installed on the system')
def test_actor_execution(current_actor_context):
--
2.49.0

View File

@ -0,0 +1,206 @@
From 097981dd9505d1609b91fbed4e6d28e960161926 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Mon, 14 Apr 2025 13:02:40 +0200
Subject: [PATCH 28/37] feat(command_utils): allow missing minor/major version
for CentOS
CentOS versioning consists only of the major version number. Therefore,
in case we are running on CentOS, we do not want to enforce version to
have the format MAJOR.MINOR. Rather, we want to check that the version
is of the form MAJOR. This patch introduces the necessary
infrastructure, allowing easy extensibility of version format checking
for also other distributions. In case we do not know what version
format should a distro use, we default to MINOR.MAJOR.
Jira-ref: RHEL-80334
---
commands/command_utils.py | 92 ++++++++++++++++++++++++++++++---------
commands/upgrade/util.py | 4 +-
2 files changed, 74 insertions(+), 22 deletions(-)
diff --git a/commands/command_utils.py b/commands/command_utils.py
index a13ca59b..155bacad 100644
--- a/commands/command_utils.py
+++ b/commands/command_utils.py
@@ -3,6 +3,8 @@ import json
import os
import re
import resource
+from collections import namedtuple
+from enum import Enum
from leapp.actors import config as actor_config
from leapp.exceptions import CommandError
@@ -16,26 +18,52 @@ LEAPP_UPGRADE_FLAVOUR_DEFAULT = 'default'
LEAPP_UPGRADE_FLAVOUR_SAP_HANA = 'saphana'
LEAPP_UPGRADE_PATHS = 'upgrade_paths.json'
-VERSION_REGEX = re.compile(r"^([1-9]\d*)\.(\d+)$")
+_VersionFormat = namedtuple('VersionFormat', ('human_readable', 'regex'))
-def check_version(version):
+
+class VersionFormats(Enum):
+ MAJOR_ONLY = _VersionFormat('MAJOR_VER', re.compile(r'^[1-9]\d*$'))
+ MAJOR_MINOR = _VersionFormat('MAJOR_VER.MINOR_VER', re.compile(r"^([1-9]\d*)\.(\d+)$"))
+
+
+class _VersionKind(str, Enum):
+ """ Enum encoding information whether the given OS version is source or target. """
+ SOURCE = 'source'
+ TARGET = 'target'
+
+
+class DistroIDs(str, Enum):
+ RHEL = 'rhel'
+ CENTOS = 'centos'
+
+
+_DISTRO_VERSION_FORMATS = {
+ DistroIDs.RHEL: VersionFormats.MAJOR_MINOR,
+ DistroIDs.CENTOS: VersionFormats.MAJOR_ONLY,
+}
+"""
+Maps distro ID to the expected OS version format.
+
+If a distro is not listed in the dictionary, then VersionFormats.MAJOR_MINOR
+is used as a default.
+"""
+
+
+def assert_version_format(version_str, desired_format, version_kind):
"""
- Versioning schema: MAJOR.MINOR
- In case version contains an invalid version string, an CommandError will be raised.
+ Check whether a given version_str has the given desired format.
+
+ In case the version does not conform to the desired_format, an CommandError will be raised.
:raises: CommandError
- :return: release tuple
"""
- if not re.match(VERSION_REGEX, version):
- raise CommandError(
- "Unexpected format of target version: {}. "
- "The required format is 'X.Y' (major and minor version).".format(version)
- )
- return version.split('.')
+ if not re.match(desired_format.regex, version_str):
+ error_str = 'Unexpected format of target version: {0}. The required format is \'{1}\'.'
+ raise CommandError(error_str.format(version_str, desired_format.human_readable))
-def get_major_version(version):
+def get_major_version_from_a_valid_version(version):
"""
Return the major version from the given version string.
@@ -45,7 +73,7 @@ def get_major_version(version):
:rtype: str
:returns: The major version from the given version string.
"""
- return str(check_version(version)[0])
+ return version.split('.')[0]
def detect_sap_hana():
@@ -71,7 +99,7 @@ def get_upgrade_flavour():
return LEAPP_UPGRADE_FLAVOUR_DEFAULT
-def _retrieve_os_release_contents(_os_release_path='/etc/os-release'):
+def _retrieve_os_release_contents(_os_release_path='/etc/os-release', strip_double_quotes=True):
"""
Retrieve the contents of /etc/os-release
@@ -79,7 +107,20 @@ def _retrieve_os_release_contents(_os_release_path='/etc/os-release'):
"""
with open(_os_release_path) as os_release_handle:
lines = os_release_handle.readlines()
- return dict(line.strip().split('=', 1) for line in lines if '=' in line)
+
+ os_release_contents = {}
+ for line in lines:
+ if '=' not in line:
+ continue
+
+ key, value = line.strip().split('=', 1)
+
+ if strip_double_quotes:
+ value = value.strip('"')
+
+ os_release_contents[key] = value
+
+ return os_release_contents
def get_os_release_version_id(filepath):
@@ -88,7 +129,7 @@ def get_os_release_version_id(filepath):
:return: `str` version_id
"""
- return _retrieve_os_release_contents(_os_release_path=filepath).get('VERSION_ID', '').strip('"')
+ return _retrieve_os_release_contents(_os_release_path=filepath).get('VERSION_ID', '')
def get_upgrade_paths_config():
@@ -117,15 +158,20 @@ def get_supported_target_versions(flavour=get_upgrade_flavour()):
"""
os_release_contents = _retrieve_os_release_contents()
- current_version_id = os_release_contents.get('VERSION_ID', '').strip('"')
- distro_id = os_release_contents.get('ID', '').strip('"')
+ current_version_id = os_release_contents.get('VERSION_ID', '')
+ distro_id = os_release_contents.get('ID', '')
+
+ # We want to guarantee our actors that if they see 'centos'/'rhel'/...
+ # then they will always see expected version format
+ expected_version_format = _DISTRO_VERSION_FORMATS.get(distro_id, VersionFormats.MAJOR_MINOR).value
+ assert_version_format(current_version_id, expected_version_format, _VersionKind.SOURCE)
target_versions = get_target_versions_from_config(current_version_id, distro_id, flavour)
if not target_versions:
# If we cannot find a particular major.minor version in the map,
# we fallback to pick a target version just based on a major version.
# This can happen for example when testing not yet released versions
- major_version = get_major_version(current_version_id)
+ major_version = get_major_version_from_a_valid_version(current_version_id)
target_versions = get_target_versions_from_config(major_version, distro_id, flavour)
return target_versions
@@ -145,9 +191,15 @@ def vet_upgrade_path(args):
"""
flavor = get_upgrade_flavour()
env_version_override = os.getenv('LEAPP_DEVEL_TARGET_RELEASE')
+
if env_version_override:
- check_version(env_version_override)
+ os_release_contents = _retrieve_os_release_contents()
+ distro_id = os_release_contents.get('ID', '')
+ expected_version_format = _DISTRO_VERSION_FORMATS.get(distro_id, VersionFormats.MAJOR_MINOR).value
+ assert_version_format(env_version_override, expected_version_format, _VersionKind.TARGET)
+
return (env_version_override, flavor)
+
target_release = args.target or get_target_version(flavor)
return (target_release, flavor)
diff --git a/commands/upgrade/util.py b/commands/upgrade/util.py
index 6cdfa6d8..b54b0b34 100644
--- a/commands/upgrade/util.py
+++ b/commands/upgrade/util.py
@@ -260,8 +260,8 @@ def prepare_configuration(args):
current_version = command_utils.get_os_release_version_id('/etc/os-release')
os.environ['LEAPP_IPU_IN_PROGRESS'] = '{source}to{target}'.format(
- source=command_utils.get_major_version(current_version),
- target=command_utils.get_major_version(target_version)
+ source=command_utils.get_major_version_from_a_valid_version(current_version),
+ target=command_utils.get_major_version_from_a_valid_version(target_version)
)
configuration = {
--
2.49.0

View File

@ -0,0 +1,62 @@
From d450430eb06a9649ea924fa8b0ba4f123197dd27 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Mon, 21 Apr 2025 20:15:34 +0200
Subject: [PATCH 29/37] refactor(versions/config): rename _simple_versions
Rename the function _simple_versions to _are_comparison_operators_used
with **negated semantics**. The new name should make it clear what is
being checked in the version list.
---
.../common/libraries/config/tests/test_version.py | 6 +++---
repos/system_upgrade/common/libraries/config/version.py | 7 ++++---
2 files changed, 7 insertions(+), 6 deletions(-)
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 37a91c00..3cb6479c 100644
--- a/repos/system_upgrade/common/libraries/config/tests/test_version.py
+++ b/repos/system_upgrade/common/libraries/config/tests/test_version.py
@@ -17,9 +17,9 @@ def test_validate_versions():
assert version._validate_versions(['7.6', 'z.z'])
-def test_simple_versions():
- assert version._simple_versions(['7.6', '7.7'])
- assert not version._simple_versions(['7.6', '< 7.7'])
+def test_comparison_operator_detection():
+ assert not version._are_comparison_operators_used(['7.6', '7.7'])
+ assert version._are_comparison_operators_used(['7.6', '< 7.7'])
def test_cmp_versions():
diff --git a/repos/system_upgrade/common/libraries/config/version.py b/repos/system_upgrade/common/libraries/config/version.py
index b8fc550b..24bb7729 100644
--- a/repos/system_upgrade/common/libraries/config/version.py
+++ b/repos/system_upgrade/common/libraries/config/version.py
@@ -149,9 +149,9 @@ def _validate_versions(versions):
"but provided was '{}'".format(versions))
-def _simple_versions(versions):
+def _are_comparison_operators_used(versions):
"""Return ``True`` if provided versions are list of strings without comparison operators."""
- return all(len(v.split()) == 1 for v in versions)
+ return not all(len(v.split()) == 1 for v in versions)
def _cmp_versions(versions):
@@ -190,10 +190,11 @@ def matches_version(match_list, detected):
"but provided was {}: '{}'".format(type(detected), detected))
_validate_versions([detected])
- if _simple_versions(match_list):
+ if not _are_comparison_operators_used(match_list):
# match_list = ['7.6', '7.7', '7.8', '7.9']
_validate_versions(match_list)
return detected in match_list
+
if _cmp_versions(match_list):
detected = _version_to_tuple(detected)
# match_list = ['>= 7.6', '< 7.10']
--
2.49.0

View File

@ -0,0 +1,40 @@
From 70557869df83660a1a0c31808cf9c97a2704aa9a Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Mon, 21 Apr 2025 20:40:11 +0200
Subject: [PATCH 30/37] fix(lib/version): broken _validate_version on RHEL 10
The validate version used to split a given version on `.` and then
check that every fragment is a digit, which is false for RHEL 10
since `10` is not a digit.
---
repos/system_upgrade/common/libraries/config/version.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/repos/system_upgrade/common/libraries/config/version.py b/repos/system_upgrade/common/libraries/config/version.py
index 24bb7729..2e837a61 100644
--- a/repos/system_upgrade/common/libraries/config/version.py
+++ b/repos/system_upgrade/common/libraries/config/version.py
@@ -1,4 +1,5 @@
import operator
+import re
import six
@@ -141,10 +142,10 @@ def _version_to_tuple(version):
def _validate_versions(versions):
- """Raise ``TypeError`` if provided versions are not strings in the form ``<integer>.<integer>``."""
- for ver in versions:
- split = ver.split('.')
- if not len(split) == 2 or not all(x.isdigit() for x in split):
+ """Raise ``ValueError`` if provided versions are not strings in the form ``<integer>.<integer>``."""
+ version_format_regex = re.compile(r'^([1-9]\d*)\.(\d+)$')
+ for version in versions:
+ if not re.match(version_format_regex, version):
raise ValueError("Versions have to be in the form of '<integer>.<integer>' "
"but provided was '{}'".format(versions))
--
2.49.0

View File

@ -0,0 +1,37 @@
From a633641884f50fc917668cf1c8bd80d6c88297c7 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Fri, 2 May 2025 16:29:10 +0200
Subject: [PATCH 31/37] upgrade_paths: add information about centos virtual
versions
Add additional field to upgrade paths for CentOS that maps CentOS
versions consisting only of a major version number to corresponding
RHEL versions of the form MAJOR.MINOR ("virtual version"). This
information is inteded to be used by leapp to in version checks
to obtain a MAJOR.MINOR version so that code written for RHEL can work
as expected also on CentOS.
Jira-ref: RHEL-80334
---
repos/system_upgrade/common/files/upgrade_paths.json | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/repos/system_upgrade/common/files/upgrade_paths.json b/repos/system_upgrade/common/files/upgrade_paths.json
index 7ace7943..279e6eaa 100644
--- a/repos/system_upgrade/common/files/upgrade_paths.json
+++ b/repos/system_upgrade/common/files/upgrade_paths.json
@@ -21,6 +21,11 @@
"default": {
"8": ["9"],
"9": ["10"]
+ },
+ "_virtual_versions": {
+ "8": "8.10",
+ "9": "9.6",
+ "10": "10.0"
}
}
}
--
2.49.0

View File

@ -0,0 +1,334 @@
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

View File

@ -0,0 +1,101 @@
From 9a48ac590bf9594ea7e9eefdaa668af5f7c75976 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Fri, 2 May 2025 17:12:55 +0200
Subject: [PATCH 33/37] libs(common, version): autocorrect centos versions into
MAJOR.MINOR
When executing version.matches_version on CentOS, autocorrect versions
of the form MAJOR into MAJOR.MINOR using virtual versions available in
IPU configuration. Autocorrection is implemented only if a used version
matches source/target version. For example, if match_list contains '8'
on a CentOS 8 system, the version will be autocorrected to '8.10'.
However, if a version that does not match the source/target version is
present, it will be left untouched.
Jira-ref: RHEL-80334
---
.../libraries/config/tests/test_version.py | 15 ++++++++
.../common/libraries/config/version.py | 34 +++++++++++++++++++
2 files changed, 49 insertions(+)
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 a8a1023e..420571c0 100644
--- a/repos/system_upgrade/common/libraries/config/tests/test_version.py
+++ b/repos/system_upgrade/common/libraries/config/tests/test_version.py
@@ -61,6 +61,21 @@ def test_matches_version_pass(monkeypatch):
assert version.matches_version(['> 7.6', '< 7.10'], '7.7')
+def test_matches_version_centos_autocorrect(monkeypatch):
+ actor_mock = CurrentActorMocked(release_id='centos',
+ src_ver='8', dst_ver='9',
+ virtual_source_version='8.10', virtual_target_version='9.5')
+ monkeypatch.setattr(api, 'current_actor', actor_mock)
+
+ assert version.matches_version(['8'], '8.10')
+ assert version.matches_version(['9'], '9.5')
+ assert not version.matches_version(['8'], '9.5')
+
+ assert version.matches_version(['> 8', '<= 9'], '9.5')
+
+ assert version.matches_version(['> 8.10', '<= 9.7'], '9')
+
+
@pytest.mark.parametrize('result,version_list', [
(True, ['7.6', '7.7']),
(True, ['7.6']),
diff --git a/repos/system_upgrade/common/libraries/config/version.py b/repos/system_upgrade/common/libraries/config/version.py
index 2e837a61..4b6e616c 100644
--- a/repos/system_upgrade/common/libraries/config/version.py
+++ b/repos/system_upgrade/common/libraries/config/version.py
@@ -164,6 +164,15 @@ def _cmp_versions(versions):
return all(s[0] in OP_MAP for s in split)
+def _autocorrect_centos_version(version_to_correct):
+ version_cfg = api.current_actor().configuration.version
+ if version_to_correct == version_cfg.source:
+ version_to_correct = version_cfg.virtual_source_version
+ elif version_to_correct == version_cfg.target:
+ version_to_correct = version_cfg.virtual_target_version
+ return version_to_correct
+
+
def matches_version(match_list, detected):
"""
Check if the `detected` version meets the criteria specified in `match_list`.
@@ -189,6 +198,31 @@ def matches_version(match_list, detected):
if not isinstance(detected, six.string_types):
raise TypeError("Detected version has to be a string "
"but provided was {}: '{}'".format(type(detected), detected))
+
+ # If we are on CentOS, and we are provided with a version of the form MAJOR, try to correct
+ # the version into MAJOR.MINOR using virtual versions
+ if api.current_actor().configuration.os_release.release_id == 'centos':
+ new_detected = _autocorrect_centos_version(detected)
+ # We might have a matchlist ['> 8', '<= 9'] that, e.g., results from blindly using source/target versions
+ # to make a matchlist. Our `detected` version might be some fixed string, e.g., `9.1`. So we need to
+ # also autocorrect the matchlist. Due to how autocorrection works, no changes are done to matchlist
+ # parts that contain full versions.
+ new_matchlist = []
+ for predicate in match_list:
+ if ' ' in predicate:
+ op, version = predicate.split(' ', 1)
+ version = _autocorrect_centos_version(version)
+ new_matchlist.append('{} {}'.format(op, version))
+ else:
+ version = _autocorrect_centos_version(predicate)
+ new_matchlist.append(version)
+
+ msg = 'Performed autocorrection from matches_version(%s, %s) to matches_version(%s, %s)'
+ api.current_logger().debug(msg, match_list, detected, new_matchlist, new_detected)
+
+ match_list = new_matchlist
+ detected = new_detected
+
_validate_versions([detected])
if not _are_comparison_operators_used(match_list):
--
2.49.0

View File

@ -0,0 +1,127 @@
From c82153f14d9391c72d914c80d764de0d7ef7ff1e Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Wed, 7 May 2025 22:23:21 +0200
Subject: [PATCH 34/37] Introduce distro-based rpm-gpg trusted directory
The original trusted rpm-gpg directories under
files/rpm-gpg/
is not flexible when considering other distributions as well.
The new path pattern will be:
files/distro/<DISTRO>/rpm-gpg/
Removing files/rpm-gpg directory with the included RHEL GPG keys
in favor of the new distro based directory.
jira: RHEL-80335
Signed-off-by: Petr Stodulka <pstodulk@redhat.com>
---
.../rpm-gpg/10/RPM-GPG-KEY-redhat-release | 0
.../rpm-gpg/10beta/RPM-GPG-KEY-redhat-release | 0
.../rpm-gpg/8/RPM-GPG-KEY-redhat-release | 0
.../rpm-gpg/8beta/RPM-GPG-KEY-redhat-beta | 0
.../rpm-gpg/9/RPM-GPG-KEY-redhat-release | 0
.../rpm-gpg/9beta/RPM-GPG-KEY-redhat-beta | 0
repos/system_upgrade/common/libraries/gpg.py | 8 ++++++-
.../common/libraries/tests/test_gpg.py | 21 +++++++++++--------
8 files changed, 19 insertions(+), 10 deletions(-)
rename repos/system_upgrade/common/files/{ => distro/rhel}/rpm-gpg/10/RPM-GPG-KEY-redhat-release (100%)
rename repos/system_upgrade/common/files/{ => distro/rhel}/rpm-gpg/10beta/RPM-GPG-KEY-redhat-release (100%)
rename repos/system_upgrade/common/files/{ => distro/rhel}/rpm-gpg/8/RPM-GPG-KEY-redhat-release (100%)
rename repos/system_upgrade/common/files/{ => distro/rhel}/rpm-gpg/8beta/RPM-GPG-KEY-redhat-beta (100%)
rename repos/system_upgrade/common/files/{ => distro/rhel}/rpm-gpg/9/RPM-GPG-KEY-redhat-release (100%)
rename repos/system_upgrade/common/files/{ => distro/rhel}/rpm-gpg/9beta/RPM-GPG-KEY-redhat-beta (100%)
diff --git a/repos/system_upgrade/common/files/rpm-gpg/10/RPM-GPG-KEY-redhat-release b/repos/system_upgrade/common/files/distro/rhel/rpm-gpg/10/RPM-GPG-KEY-redhat-release
similarity index 100%
rename from repos/system_upgrade/common/files/rpm-gpg/10/RPM-GPG-KEY-redhat-release
rename to repos/system_upgrade/common/files/distro/rhel/rpm-gpg/10/RPM-GPG-KEY-redhat-release
diff --git a/repos/system_upgrade/common/files/rpm-gpg/10beta/RPM-GPG-KEY-redhat-release b/repos/system_upgrade/common/files/distro/rhel/rpm-gpg/10beta/RPM-GPG-KEY-redhat-release
similarity index 100%
rename from repos/system_upgrade/common/files/rpm-gpg/10beta/RPM-GPG-KEY-redhat-release
rename to repos/system_upgrade/common/files/distro/rhel/rpm-gpg/10beta/RPM-GPG-KEY-redhat-release
diff --git a/repos/system_upgrade/common/files/rpm-gpg/8/RPM-GPG-KEY-redhat-release b/repos/system_upgrade/common/files/distro/rhel/rpm-gpg/8/RPM-GPG-KEY-redhat-release
similarity index 100%
rename from repos/system_upgrade/common/files/rpm-gpg/8/RPM-GPG-KEY-redhat-release
rename to repos/system_upgrade/common/files/distro/rhel/rpm-gpg/8/RPM-GPG-KEY-redhat-release
diff --git a/repos/system_upgrade/common/files/rpm-gpg/8beta/RPM-GPG-KEY-redhat-beta b/repos/system_upgrade/common/files/distro/rhel/rpm-gpg/8beta/RPM-GPG-KEY-redhat-beta
similarity index 100%
rename from repos/system_upgrade/common/files/rpm-gpg/8beta/RPM-GPG-KEY-redhat-beta
rename to repos/system_upgrade/common/files/distro/rhel/rpm-gpg/8beta/RPM-GPG-KEY-redhat-beta
diff --git a/repos/system_upgrade/common/files/rpm-gpg/9/RPM-GPG-KEY-redhat-release b/repos/system_upgrade/common/files/distro/rhel/rpm-gpg/9/RPM-GPG-KEY-redhat-release
similarity index 100%
rename from repos/system_upgrade/common/files/rpm-gpg/9/RPM-GPG-KEY-redhat-release
rename to repos/system_upgrade/common/files/distro/rhel/rpm-gpg/9/RPM-GPG-KEY-redhat-release
diff --git a/repos/system_upgrade/common/files/rpm-gpg/9beta/RPM-GPG-KEY-redhat-beta b/repos/system_upgrade/common/files/distro/rhel/rpm-gpg/9beta/RPM-GPG-KEY-redhat-beta
similarity index 100%
rename from repos/system_upgrade/common/files/rpm-gpg/9beta/RPM-GPG-KEY-redhat-beta
rename to repos/system_upgrade/common/files/distro/rhel/rpm-gpg/9beta/RPM-GPG-KEY-redhat-beta
diff --git a/repos/system_upgrade/common/libraries/gpg.py b/repos/system_upgrade/common/libraries/gpg.py
index a8071329..c9c3f1fc 100644
--- a/repos/system_upgrade/common/libraries/gpg.py
+++ b/repos/system_upgrade/common/libraries/gpg.py
@@ -121,7 +121,13 @@ def get_path_to_gpg_certs():
# only beta is special in regards to the GPG signing keys
if target_product_type == 'beta':
certs_dir = '{}beta'.format(target_major_version)
- return os.path.join(api.get_common_folder_path(GPG_CERTS_FOLDER), certs_dir)
+ distro = api.current_actor().configuration.os_release.release_id
+ return os.path.join(
+ api.get_common_folder_path('distro'),
+ distro,
+ GPG_CERTS_FOLDER,
+ certs_dir
+ )
def is_nogpgcheck_set():
diff --git a/repos/system_upgrade/common/libraries/tests/test_gpg.py b/repos/system_upgrade/common/libraries/tests/test_gpg.py
index 7cf37fa2..82b51abb 100644
--- a/repos/system_upgrade/common/libraries/tests/test_gpg.py
+++ b/repos/system_upgrade/common/libraries/tests/test_gpg.py
@@ -11,14 +11,16 @@ from leapp.libraries.stdlib import api
from leapp.models import GpgKey, InstalledRPM, RPM
-@pytest.mark.parametrize('target, product_type, exp', [
- ('8.6', 'beta', '../../files/rpm-gpg/8beta'),
- ('8.8', 'htb', '../../files/rpm-gpg/8'),
- ('9.0', 'beta', '../../files/rpm-gpg/9beta'),
- ('9.2', 'ga', '../../files/rpm-gpg/9'),
+@pytest.mark.parametrize('target, product_type, distro, exp', [
+ ('8.6', 'beta', 'rhel', '../../files/distro/rhel/rpm-gpg/8beta'),
+ ('8.8', 'htb', 'rhel', '../../files/distro/rhel/rpm-gpg/8'),
+ ('9.0', 'beta', 'rhel', '../../files/distro/rhel/rpm-gpg/9beta'),
+ ('9.2', 'ga', 'rhel', '../../files/distro/rhel/rpm-gpg/9'),
+ ('10.0', 'ga', 'rhel', '../../files/distro/rhel/rpm-gpg/10'),
+ ('10', 'ga', 'centos', '../../files/distro/centos/rpm-gpg/10'),
])
-def test_get_path_to_gpg_certs(monkeypatch, target, product_type, exp):
- current_actor = CurrentActorMocked(dst_ver=target,
+def test_get_path_to_gpg_certs(monkeypatch, target, product_type, distro, exp):
+ current_actor = CurrentActorMocked(dst_ver=target, release_id=distro,
envars={'LEAPP_DEVEL_TARGET_PRODUCT_TYPE': product_type})
monkeypatch.setattr(api, 'current_actor', current_actor)
@@ -33,7 +35,7 @@ def is_rhel7():
@pytest.mark.skipif(distro.id() not in ("rhel", "centos"), reason="Requires RHEL or CentOS for valid results.")
def test_gpg_show_keys(loaded_leapp_repository, monkeypatch):
src = '7.9' if is_rhel7() else '8.6'
- current_actor = CurrentActorMocked(src_ver=src)
+ current_actor = CurrentActorMocked(src_ver=src, release_id='rhel')
monkeypatch.setattr(api, 'current_actor', current_actor)
# python2 compatibility :/
@@ -78,7 +80,8 @@ def test_gpg_show_keys(loaded_leapp_repository, monkeypatch):
# with some test data now -- rhel9 release key
# rhel9_key_path = os.path.join(api.get_common_folder_path('rpm-gpg'), '9')
cur_dir = os.path.dirname(os.path.abspath(__file__))
- rhel9_key_path = os.path.join(cur_dir, '..', '..', 'files', 'rpm-gpg', '9',
+ rhel9_key_path = os.path.join(cur_dir, '..', '..', 'files',
+ 'distro', 'rhel', 'rpm-gpg', '9',
'RPM-GPG-KEY-redhat-release')
res = gpg._gpg_show_keys(rhel9_key_path)
finally:
--
2.49.0

View File

@ -0,0 +1,227 @@
From cacee2edb7d93fa4418e9795ab3462a707868937 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Wed, 7 May 2025 22:31:35 +0200
Subject: [PATCH 35/37] Add official Centos Stream 9 and 10 RPM GPG keys
These keys are obtained from centos-gpg-keys packages on 7th May
jira: RHEL-80335
Signed-off-by: Petr Stodulka <pstodulk@redhat.com>
---
.../10/RPM-GPG-KEY-CentOS-SIG-Extras-SHA512 | 37 +++++++++++++++++++
.../10/RPM-GPG-KEY-centosofficial-SHA256 | 30 +++++++++++++++
.../rpm-gpg/9/RPM-GPG-KEY-CentOS-SIG-Extras | 37 +++++++++++++++++++
.../9/RPM-GPG-KEY-CentOS-SIG-Extras-SHA512 | 37 +++++++++++++++++++
.../rpm-gpg/9/RPM-GPG-KEY-centosofficial | 30 +++++++++++++++
5 files changed, 171 insertions(+)
create mode 100644 repos/system_upgrade/common/files/distro/centos/rpm-gpg/10/RPM-GPG-KEY-CentOS-SIG-Extras-SHA512
create mode 100644 repos/system_upgrade/common/files/distro/centos/rpm-gpg/10/RPM-GPG-KEY-centosofficial-SHA256
create mode 100644 repos/system_upgrade/common/files/distro/centos/rpm-gpg/9/RPM-GPG-KEY-CentOS-SIG-Extras
create mode 100644 repos/system_upgrade/common/files/distro/centos/rpm-gpg/9/RPM-GPG-KEY-CentOS-SIG-Extras-SHA512
create mode 100644 repos/system_upgrade/common/files/distro/centos/rpm-gpg/9/RPM-GPG-KEY-centosofficial
diff --git a/repos/system_upgrade/common/files/distro/centos/rpm-gpg/10/RPM-GPG-KEY-CentOS-SIG-Extras-SHA512 b/repos/system_upgrade/common/files/distro/centos/rpm-gpg/10/RPM-GPG-KEY-CentOS-SIG-Extras-SHA512
new file mode 100644
index 00000000..e15f9a82
--- /dev/null
+++ b/repos/system_upgrade/common/files/distro/centos/rpm-gpg/10/RPM-GPG-KEY-CentOS-SIG-Extras-SHA512
@@ -0,0 +1,37 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2.0.22 (GNU/Linux)
+
+mQENBGG65jsBCADef7Fspss6f2PKrlrxufWlBaQI+kcdSDbY7o/dyyjpT7dcX8t8
+Ou73irjiShK3q0pdrh1Wy/mXc7RIJwAbCt9OVgyx4PV6AW5LfU7P7xyEAbTgLhz9
+lLPjBGhBvfRpW+7naPqkTcIKxpVR8Khq6fsvThGCNzNkGa46F1srE3mf1zC9wdVR
+VtXO7gHEZ2LrNcl195jZkBQOLcXANcSOFh5eRfhumULmk4XgCGmZQT5UNFofqOmn
+aWQGBq3XaU7RWjl7RH+IS2EW0rAtz9Le+cH+j0aFhzo7jBMOxGYG62rUaHdxssjV
+S1CrfpYT6NeG5i/1hiP4hO9suezJw4yuXNZ3ABEBAAG0VkNlbnRPUyBFeHRyYXMg
+U0lHIChodHRwczovL3dpa2kuY2VudG9zLm9yZy9TcGVjaWFsSW50ZXJlc3RHcm91
+cCkgPHNlY3VyaXR5QGNlbnRvcy5vcmc+iQE5BBMBCgAjAhsvBwsJCAcDAgEGFQgC
+CQoLBBYCAwECHgECF4AFAmIePKwACgkQH/aiFx2ZdmgUpAgAt1Y139EUQOLd013m
+jZx3shUVHRWCU0SaWLuXLupdxqhe/Iygen48aiDWfAtWr9neAJKKZFboDXXPyxDy
+9529aDgJnjwGRSFAcmvsuMaEMse6PZepTFtwhg2A/N0sDLVJSWagbQmTHdpkgEwn
+rrwO/TEaqjJ2+vZG67IIvw2rgtF3sQC28I1z7c1cPH5/NNf7dOZ29vtn44juMFFs
+o2Kd2FjZ0WP4wRmFF646nS5S1WHGS32K0xvDJMXO3MBXhaATVg+5i5ICA6fx6F3Y
+FFLJrXjx/LBtsY3EbJ0OddeZQtaAHFM1Xm6e0UHpnfjG9EGl9QrC5qzLSng0YMrG
+emhIy7kBDQRhuuY7AQgAs+enJDbwE/Iln3BnxodDQ3/1t9ULlMLJLiV+FgS7yREZ
+QvhVQxFWaJqbiPV6EJVxEP5lUHND2DAE2ZTr60y0rI3ZAY52go+QYHXb+M5HC12H
+HbhIDTWaETNo5heq/qyVSRT1u0g/yKCxQdyqnVsL86bro0wgrpj7XuApQifFhy16
+AkDjhcB0C0dXkfvEnHJylWiHpp7upfSgOcGwQ+yRHOZWJnyF+OMrFfNiwD74/zEN
+4RoNFgpqJZ81TF0qCdllTYGAXXUdYsJlg64dH0u84naTOFIuInywCmNyPmC8e8/0
+g56hCV2L7bRJGjBCa6VH+TgvVGnkFsoMM9ijhuTIIQARAQABiQI+BBgBCgAJAhsu
+BQJiHjnNASnAXSAEGQECAAYFAmG65jsACgkQi1yBEfyl0P9m/QgAh2KmBA4h/slx
+aZeWLb2cV53B1jVElsrEAE/a8yKhhcNeNOQsEWwT2/i6mdWchnIQzojKs3ypoRUY
+xsICIb4b4AFzc//aYhaOWThNRHh0UwaueNu0YBqVF3URUlf/Hw1Wv16v4QwkNhHQ
++EohCRltR2PBjAHRHXDImy9OxV/uTnZjTXegj2Jl3ueQ5nF4pleqUctt/V9JjqzO
+YcQZW78s1jyBRzefbPxQHKKp4na6etTmIvgVDjkMChRZPRjZYEVZNi8kJM0aaK4q
+ugGoL6cWBR6RYka+/eEFMd3kSrng9ahbNX0F4ztdZ2alPrrE6BvJ7n/Mt6tZKgL7
+x9V0GpbstAkQH/aiFx2ZdmgN/gf+PEUa1LT98RS28fyNPaXYGx5vLWYxUtAdeN9a
+TfugGHCVhVsowbIEnuFUHE1JmTJ1hDaFYXqkgG9zDo81JVz/yCHpNIQO0YF2h+qX
+BXiKP7PQ+iT/PjQHidlYUuz73hjDwRl3AhLafcwVHeD3cCgo/ZP/Vi9Y9iBFVZDl
+jGHxAIe0PWbEAUuqNJOgrlVmmCtSqVkN1Neihx1zjpw3rqfUQzwvhvcsOfkKfnBs
+Boc66IZ0J5pmSzgJnSbLrr2dv1/jYHaolA24vkMqMxKzJbz+GeQ/SqBZ5/rA37VL
+x90Tu9UVSfbyEbwS9Zj1sVmc3mdm1kn6dmTlOfTDIqehfHBlnQ==
+=jx2B
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/repos/system_upgrade/common/files/distro/centos/rpm-gpg/10/RPM-GPG-KEY-centosofficial-SHA256 b/repos/system_upgrade/common/files/distro/centos/rpm-gpg/10/RPM-GPG-KEY-centosofficial-SHA256
new file mode 100644
index 00000000..ceee67dd
--- /dev/null
+++ b/repos/system_upgrade/common/files/distro/centos/rpm-gpg/10/RPM-GPG-KEY-centosofficial-SHA256
@@ -0,0 +1,30 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2.0.22 (GNU/Linux)
+
+mQINBFzMWxkBEADHrskpBgN9OphmhRkc7P/YrsAGSvvl7kfu+e9KAaU6f5MeAVyn
+rIoM43syyGkgFyWgjZM8/rur7EMPY2yt+2q/1ZfLVCRn9856JqTIq0XRpDUe4nKQ
+8BlA7wDVZoSDxUZkSuTIyExbDf0cpw89Tcf62Mxmi8jh74vRlPy1PgjWL5494b3X
+5fxDidH4bqPZyxTBqPrUFuo+EfUVEqiGF94Ppq6ZUvrBGOVo1V1+Ifm9CGEK597c
+aevcGc1RFlgxIgN84UpuDjPR9/zSndwJ7XsXYvZ6HXcKGagRKsfYDWGPkA5cOL/e
+f+yObOnC43yPUvpggQ4KaNJ6+SMTZOKikM8yciyBwLqwrjo8FlJgkv8Vfag/2UR7
+JINbyqHHoLUhQ2m6HXSwK4YjtwidF9EUkaBZWrrskYR3IRZLXlWqeOi/+ezYOW0m
+vufrkcvsh+TKlVVnuwmEPjJ8mwUSpsLdfPJo1DHsd8FS03SCKPaXFdD7ePfEjiYk
+nHpQaKE01aWVSLUiygn7F7rYemGqV9Vt7tBw5pz0vqSC72a5E3zFzIIuHx6aANry
+Gat3aqU3qtBXOrA/dPkX9cWE+UR5wo/A2UdKJZLlGhM2WRJ3ltmGT48V9CeS6N9Y
+m4CKdzvg7EWjlTlFrd/8WJ2KoqOE9leDPeXRPncubJfJ6LLIHyG09h9kKQARAQAB
+tDpDZW50T1MgKENlbnRPUyBPZmZpY2lhbCBTaWduaW5nIEtleSkgPHNlY3VyaXR5
+QGNlbnRvcy5vcmc+iQI3BBMBCAAhAhsDBgsJCAcDAgYVCAIJCgsDFgIBAh4BAheA
+BQJczFsaAAoJEAW1VbOEg8ZdvOgQAMFTGIQokADy5+CynFKjfO7R0VVpJxmYGVr1
+TjnKaHmjxnJaYqoha9ukGgmLu0r+lJ42Kk6nREk1vlxfRAfiWd00Zkm+K3IMq1/D
+E0heC2vX8qqjsLJs3jzq0hgNvo9X0uHDaA4J1BHsD8sE5in/f4SivjbngvFovRGU
+1XLNCgoqpFNcROP18LqKUw8WtqgWdnYBa5i6D5qx+WMRX0NHNwcCMy1lz+sTFxIU
+9mW6cLsMaacPGD8pUXIVli8P9Vlv3jBk1wFIqRgQPW01ph/3bM7pf9hyM9FAfU4X
+AFcyb1oYI4/82EkICUe6jeuZrz67dPeLVAlYrGW4hp/825g0fqJHxPDp25GS4rAa
+4RqyibLzNjSGdXYeLj2NcB/8OqaP+T1hv3JDaqe70QoYa/GIC4rh15NyXVbUP+LG
+V4vUiL7mb9ynzvF5zYHJbcg4R7dOsiZHrMFwy7FZesQaVrXeJlxRcEj65rpm1ZtZ
+mwAE1k2LsRkvLyr9hpZkXnMeOKYIPwpdmBjXNVNVbq7097OxZOYPPos+iZKMWfl4
+UQnMsCVxonZtamdI4qEc3jMkSZPJKgOplGOms5jdY+EdSvsFWEQ0Snd3dChfU7DV
+o4Rbcy5klwHrvuZIOLaovhyxuRPhP6gV9+gzpTK/7vrvDlFbbZE6s212mDZ13RWB
+mTfAxz4h
+=agO/
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/repos/system_upgrade/common/files/distro/centos/rpm-gpg/9/RPM-GPG-KEY-CentOS-SIG-Extras b/repos/system_upgrade/common/files/distro/centos/rpm-gpg/9/RPM-GPG-KEY-CentOS-SIG-Extras
new file mode 100644
index 00000000..5ea1515a
--- /dev/null
+++ b/repos/system_upgrade/common/files/distro/centos/rpm-gpg/9/RPM-GPG-KEY-CentOS-SIG-Extras
@@ -0,0 +1,37 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2.0.22 (GNU/Linux)
+
+mQENBGG65jsBCADef7Fspss6f2PKrlrxufWlBaQI+kcdSDbY7o/dyyjpT7dcX8t8
+Ou73irjiShK3q0pdrh1Wy/mXc7RIJwAbCt9OVgyx4PV6AW5LfU7P7xyEAbTgLhz9
+lLPjBGhBvfRpW+7naPqkTcIKxpVR8Khq6fsvThGCNzNkGa46F1srE3mf1zC9wdVR
+VtXO7gHEZ2LrNcl195jZkBQOLcXANcSOFh5eRfhumULmk4XgCGmZQT5UNFofqOmn
+aWQGBq3XaU7RWjl7RH+IS2EW0rAtz9Le+cH+j0aFhzo7jBMOxGYG62rUaHdxssjV
+S1CrfpYT6NeG5i/1hiP4hO9suezJw4yuXNZ3ABEBAAG0VkNlbnRPUyBFeHRyYXMg
+U0lHIChodHRwczovL3dpa2kuY2VudG9zLm9yZy9TcGVjaWFsSW50ZXJlc3RHcm91
+cCkgPHNlY3VyaXR5QGNlbnRvcy5vcmc+iQE5BBMBAgAjBQJhuuY7AhsvBwsJCAcD
+AgEGFQgCCQoLBBYCAwECHgECF4AACgkQH/aiFx2ZdmjUtwf9GX3exQy6bC/A7miq
+I0yfoBR+jvZQKy7+U8vexbr0cgkYDTJ2zN3y+JL1391Y9CS0oDNqYLIv1BwHXAmX
+EarpQV/YyEocnYXwcVLugKCnbIN92vMTiyb/NESx1vHbduK+B8wWo3bp3sPK+Ha/
+zXrHXWSEgUeCBY/b7Tbl3GW8NX9Pr+yY0zHcvTfLByVH0KpNNLsyOsrCdk4MSKMl
+IBZWDaUYVAbyHXB92wZlQOKp+HqRxNhceGHTzeXBymK1LadntlCYTaqsg3ErRq8p
+ZwkpeyAi/avjIPYc53QE3dKGw2cUjZxkMOe6BoMbeLlO3+INdJBc/gcW4xUsQ28Y
+QtY8jLkBDQRhuuY7AQgAs+enJDbwE/Iln3BnxodDQ3/1t9ULlMLJLiV+FgS7yREZ
+QvhVQxFWaJqbiPV6EJVxEP5lUHND2DAE2ZTr60y0rI3ZAY52go+QYHXb+M5HC12H
+HbhIDTWaETNo5heq/qyVSRT1u0g/yKCxQdyqnVsL86bro0wgrpj7XuApQifFhy16
+AkDjhcB0C0dXkfvEnHJylWiHpp7upfSgOcGwQ+yRHOZWJnyF+OMrFfNiwD74/zEN
+4RoNFgpqJZ81TF0qCdllTYGAXXUdYsJlg64dH0u84naTOFIuInywCmNyPmC8e8/0
+g56hCV2L7bRJGjBCa6VH+TgvVGnkFsoMM9ijhuTIIQARAQABiQI+BBgBAgAJBQJh
+uuY7AhsuASkJEB/2ohcdmXZowF0gBBkBAgAGBQJhuuY7AAoJEItcgRH8pdD/Zv0I
+AIdipgQOIf7JcWmXli29nFedwdY1RJbKxABP2vMioYXDXjTkLBFsE9v4upnVnIZy
+EM6IyrN8qaEVGMbCAiG+G+ABc3P/2mIWjlk4TUR4dFMGrnjbtGAalRd1EVJX/x8N
+Vr9er+EMJDYR0PhKIQkZbUdjwYwB0R1wyJsvTsVf7k52Y013oI9iZd7nkOZxeKZX
+qlHLbf1fSY6szmHEGVu/LNY8gUc3n2z8UByiqeJ2unrU5iL4FQ45DAoUWT0Y2WBF
+WTYvJCTNGmiuKroBqC+nFgUekWJGvv3hBTHd5Eq54PWoWzV9BeM7XWdmpT66xOgb
+ye5/zLerWSoC+8fVdBqW7LSEqggAzRaID+mLFPTe2LbQkaBkmIpqeoDOy700Xy6K
+VW05GndH0E0t86DbQClFyzucYLzX2dXyV2DWjoWDIevQnS51zzsd+lWyuKPICKte
++K+yk5QEiwgaDf5oPmI8WL2zIAfiwVHlU0epMLU1pZLAQYotsQ6m5qPPMVXcfIqF
+3UJwZEnZRccfOKq1hHSS2/Ns4ihAfkrfes1IFLSzbyvinXQUqFVrY8oZCKhNPSRd
+IXXPIx0KvnlI9e0EittvsrQxebAa2MwLXOVYL8WVvOLY7oNTrOxe45jOdzMz2+rK
+dodVWwuBwNKuwSE6b5A0dwUj8ZEo/5L4noufZF6aGOLdbVcoUg==
+=RGYd
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/repos/system_upgrade/common/files/distro/centos/rpm-gpg/9/RPM-GPG-KEY-CentOS-SIG-Extras-SHA512 b/repos/system_upgrade/common/files/distro/centos/rpm-gpg/9/RPM-GPG-KEY-CentOS-SIG-Extras-SHA512
new file mode 100644
index 00000000..e15f9a82
--- /dev/null
+++ b/repos/system_upgrade/common/files/distro/centos/rpm-gpg/9/RPM-GPG-KEY-CentOS-SIG-Extras-SHA512
@@ -0,0 +1,37 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2.0.22 (GNU/Linux)
+
+mQENBGG65jsBCADef7Fspss6f2PKrlrxufWlBaQI+kcdSDbY7o/dyyjpT7dcX8t8
+Ou73irjiShK3q0pdrh1Wy/mXc7RIJwAbCt9OVgyx4PV6AW5LfU7P7xyEAbTgLhz9
+lLPjBGhBvfRpW+7naPqkTcIKxpVR8Khq6fsvThGCNzNkGa46F1srE3mf1zC9wdVR
+VtXO7gHEZ2LrNcl195jZkBQOLcXANcSOFh5eRfhumULmk4XgCGmZQT5UNFofqOmn
+aWQGBq3XaU7RWjl7RH+IS2EW0rAtz9Le+cH+j0aFhzo7jBMOxGYG62rUaHdxssjV
+S1CrfpYT6NeG5i/1hiP4hO9suezJw4yuXNZ3ABEBAAG0VkNlbnRPUyBFeHRyYXMg
+U0lHIChodHRwczovL3dpa2kuY2VudG9zLm9yZy9TcGVjaWFsSW50ZXJlc3RHcm91
+cCkgPHNlY3VyaXR5QGNlbnRvcy5vcmc+iQE5BBMBCgAjAhsvBwsJCAcDAgEGFQgC
+CQoLBBYCAwECHgECF4AFAmIePKwACgkQH/aiFx2ZdmgUpAgAt1Y139EUQOLd013m
+jZx3shUVHRWCU0SaWLuXLupdxqhe/Iygen48aiDWfAtWr9neAJKKZFboDXXPyxDy
+9529aDgJnjwGRSFAcmvsuMaEMse6PZepTFtwhg2A/N0sDLVJSWagbQmTHdpkgEwn
+rrwO/TEaqjJ2+vZG67IIvw2rgtF3sQC28I1z7c1cPH5/NNf7dOZ29vtn44juMFFs
+o2Kd2FjZ0WP4wRmFF646nS5S1WHGS32K0xvDJMXO3MBXhaATVg+5i5ICA6fx6F3Y
+FFLJrXjx/LBtsY3EbJ0OddeZQtaAHFM1Xm6e0UHpnfjG9EGl9QrC5qzLSng0YMrG
+emhIy7kBDQRhuuY7AQgAs+enJDbwE/Iln3BnxodDQ3/1t9ULlMLJLiV+FgS7yREZ
+QvhVQxFWaJqbiPV6EJVxEP5lUHND2DAE2ZTr60y0rI3ZAY52go+QYHXb+M5HC12H
+HbhIDTWaETNo5heq/qyVSRT1u0g/yKCxQdyqnVsL86bro0wgrpj7XuApQifFhy16
+AkDjhcB0C0dXkfvEnHJylWiHpp7upfSgOcGwQ+yRHOZWJnyF+OMrFfNiwD74/zEN
+4RoNFgpqJZ81TF0qCdllTYGAXXUdYsJlg64dH0u84naTOFIuInywCmNyPmC8e8/0
+g56hCV2L7bRJGjBCa6VH+TgvVGnkFsoMM9ijhuTIIQARAQABiQI+BBgBCgAJAhsu
+BQJiHjnNASnAXSAEGQECAAYFAmG65jsACgkQi1yBEfyl0P9m/QgAh2KmBA4h/slx
+aZeWLb2cV53B1jVElsrEAE/a8yKhhcNeNOQsEWwT2/i6mdWchnIQzojKs3ypoRUY
+xsICIb4b4AFzc//aYhaOWThNRHh0UwaueNu0YBqVF3URUlf/Hw1Wv16v4QwkNhHQ
++EohCRltR2PBjAHRHXDImy9OxV/uTnZjTXegj2Jl3ueQ5nF4pleqUctt/V9JjqzO
+YcQZW78s1jyBRzefbPxQHKKp4na6etTmIvgVDjkMChRZPRjZYEVZNi8kJM0aaK4q
+ugGoL6cWBR6RYka+/eEFMd3kSrng9ahbNX0F4ztdZ2alPrrE6BvJ7n/Mt6tZKgL7
+x9V0GpbstAkQH/aiFx2ZdmgN/gf+PEUa1LT98RS28fyNPaXYGx5vLWYxUtAdeN9a
+TfugGHCVhVsowbIEnuFUHE1JmTJ1hDaFYXqkgG9zDo81JVz/yCHpNIQO0YF2h+qX
+BXiKP7PQ+iT/PjQHidlYUuz73hjDwRl3AhLafcwVHeD3cCgo/ZP/Vi9Y9iBFVZDl
+jGHxAIe0PWbEAUuqNJOgrlVmmCtSqVkN1Neihx1zjpw3rqfUQzwvhvcsOfkKfnBs
+Boc66IZ0J5pmSzgJnSbLrr2dv1/jYHaolA24vkMqMxKzJbz+GeQ/SqBZ5/rA37VL
+x90Tu9UVSfbyEbwS9Zj1sVmc3mdm1kn6dmTlOfTDIqehfHBlnQ==
+=jx2B
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/repos/system_upgrade/common/files/distro/centos/rpm-gpg/9/RPM-GPG-KEY-centosofficial b/repos/system_upgrade/common/files/distro/centos/rpm-gpg/9/RPM-GPG-KEY-centosofficial
new file mode 100644
index 00000000..30235a86
--- /dev/null
+++ b/repos/system_upgrade/common/files/distro/centos/rpm-gpg/9/RPM-GPG-KEY-centosofficial
@@ -0,0 +1,30 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2.0.22 (GNU/Linux)
+
+mQINBFzMWxkBEADHrskpBgN9OphmhRkc7P/YrsAGSvvl7kfu+e9KAaU6f5MeAVyn
+rIoM43syyGkgFyWgjZM8/rur7EMPY2yt+2q/1ZfLVCRn9856JqTIq0XRpDUe4nKQ
+8BlA7wDVZoSDxUZkSuTIyExbDf0cpw89Tcf62Mxmi8jh74vRlPy1PgjWL5494b3X
+5fxDidH4bqPZyxTBqPrUFuo+EfUVEqiGF94Ppq6ZUvrBGOVo1V1+Ifm9CGEK597c
+aevcGc1RFlgxIgN84UpuDjPR9/zSndwJ7XsXYvZ6HXcKGagRKsfYDWGPkA5cOL/e
+f+yObOnC43yPUvpggQ4KaNJ6+SMTZOKikM8yciyBwLqwrjo8FlJgkv8Vfag/2UR7
+JINbyqHHoLUhQ2m6HXSwK4YjtwidF9EUkaBZWrrskYR3IRZLXlWqeOi/+ezYOW0m
+vufrkcvsh+TKlVVnuwmEPjJ8mwUSpsLdfPJo1DHsd8FS03SCKPaXFdD7ePfEjiYk
+nHpQaKE01aWVSLUiygn7F7rYemGqV9Vt7tBw5pz0vqSC72a5E3zFzIIuHx6aANry
+Gat3aqU3qtBXOrA/dPkX9cWE+UR5wo/A2UdKJZLlGhM2WRJ3ltmGT48V9CeS6N9Y
+m4CKdzvg7EWjlTlFrd/8WJ2KoqOE9leDPeXRPncubJfJ6LLIHyG09h9kKQARAQAB
+tDpDZW50T1MgKENlbnRPUyBPZmZpY2lhbCBTaWduaW5nIEtleSkgPHNlY3VyaXR5
+QGNlbnRvcy5vcmc+iQI3BBMBAgAhBQJczFsZAhsDBgsJCAcDAgYVCAIJCgsDFgIB
+Ah4BAheAAAoJEAW1VbOEg8ZdjOsP/2ygSxH9jqffOU9SKyJDlraL2gIutqZ3B8pl
+Gy/Qnb9QD1EJVb4ZxOEhcY2W9VJfIpnf3yBuAto7zvKe/G1nxH4Bt6WTJQCkUjcs
+N3qPWsx1VslsAEz7bXGiHym6Ay4xF28bQ9XYIokIQXd0T2rD3/lNGxNtORZ2bKjD
+vOzYzvh2idUIY1DgGWJ11gtHFIA9CvHcW+SMPEhkcKZJAO51ayFBqTSSpiorVwTq
+a0cB+cgmCQOI4/MY+kIvzoexfG7xhkUqe0wxmph9RQQxlTbNQDCdaxSgwbF2T+gw
+byaDvkS4xtR6Soj7BKjKAmcnf5fn4C5Or0KLUqMzBtDMbfQQihn62iZJN6ZZ/4dg
+q4HTqyVpyuzMXsFpJ9L/FqH2DJ4exGGpBv00ba/Zauy7GsqOc5PnNBsYaHCply0X
+407DRx51t9YwYI/ttValuehq9+gRJpOTTKp6AjZn/a5Yt3h6jDgpNfM/EyLFIY9z
+V6CXqQQ/8JRvaik/JsGCf+eeLZOw4koIjZGEAg04iuyNTjhx0e/QHEVcYAqNLhXG
+rCTTbCn3NSUO9qxEXC+K/1m1kaXoCGA0UWlVGZ1JSifbbMx0yxq/brpEZPUYm+32
+o8XfbocBWljFUJ+6aljTvZ3LQLKTSPW7TFO+GXycAOmCGhlXh2tlc6iTc41PACqy
+yy+mHmSv
+=kkH7
+-----END PGP PUBLIC KEY BLOCK-----
--
2.49.0

View File

@ -0,0 +1,53 @@
From fe6d00b01d667a23964fe273a15ee9e457f85bf7 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Wed, 7 May 2025 21:13:04 +0200
Subject: [PATCH 36/37] Deprecate is_rhel_alt from share libraries
The function has no value anymore as RHEL-ALT 7 is EOL for years
and RHEL 7 is not longer maintained in this project neither.
I have considered the direct removal as this function is really
old (it's not even used anywhere in the project anymore).
But as it is just one small function without additional impact
and another rhel-alt artifacts became deprecated this month,
I consider it better to fulfill our promise and add it on the
deprecation list for 6months instead.
Signed-off-by: Petr Stodulka <pstodulk@redhat.com>
---
docs/source/libraries-and-api/deprecations-list.md | 2 ++
repos/system_upgrade/common/libraries/config/version.py | 5 +++++
2 files changed, 7 insertions(+)
diff --git a/docs/source/libraries-and-api/deprecations-list.md b/docs/source/libraries-and-api/deprecations-list.md
index c8489af3..b3abfc5d 100644
--- a/docs/source/libraries-and-api/deprecations-list.md
+++ b/docs/source/libraries-and-api/deprecations-list.md
@@ -16,6 +16,8 @@ Only the versions in which a deprecation has been made are listed.
- Shared libraries
- **`leapp.libraries.common.config.version.SUPPORTED_VERSIONS`** - The `SUPPORTED_VERSIONS` dict has been deprecated as it is problematic with the new design. Use `leapp.libraries.common.config.version.is_supported_version()` or `IPUConfig.supported_upgrade_paths` instead.
+ - **`leapp.libraries.common.config.version.is_rhel_alt()`** - The function can return only `False` nowadays as RHEL-ALT 7 is EOL for years and future version of leapp-repository will not support RHEL 7 anymore.
+
## v0.20.0 <span style="font-size:0.5em; font-weight:normal">(till September 2024)</span>
- Models
diff --git a/repos/system_upgrade/common/libraries/config/version.py b/repos/system_upgrade/common/libraries/config/version.py
index 4b6e616c..7f29c9cd 100644
--- a/repos/system_upgrade/common/libraries/config/version.py
+++ b/repos/system_upgrade/common/libraries/config/version.py
@@ -314,6 +314,11 @@ def is_sap_hana_flavour():
return api.current_actor().configuration.flavour == 'saphana'
+@deprecated(since='2025-05-31', message=(
+ 'RHEL-ALT reached EOL years ago and it is connected just to RHEL 7 systems.'
+ 'As such the function is useless nowadays and will return always False.'
+ 'The function is going to be removed in the next leapp-repository release.'
+))
def is_rhel_alt():
"""
Check if the current system is RHEL-ALT or not (only for RHEL 7)
--
2.49.0

File diff suppressed because it is too large Load Diff

View File

@ -53,7 +53,7 @@ py2_byte_compile "%1" "%2"}
Epoch: 1
Name: leapp-repository
Version: 0.22.0
Release: 1%{?dist}.elevate.1
Release: 3%{?dist}
Summary: Repositories for leapp
License: ASL 2.0
@ -66,7 +66,44 @@ BuildArch: noarch
### PATCHES HERE
# Patch0001: filename.patch
Patch0100: leapp-repository-0.22.0-elevate.patch
Patch0001: 0001-Use-leapp.libraries.common.rpms.get_leapp_packages-w.patch
Patch0002: 0002-fix-spell-AllowZoneDrifting-correctly.patch
Patch0003: 0003-cli-upgrade-allow-users-to-enable-entire-experimenta.patch
Patch0004: 0004-feat-livemode-exclude-DNF-cache-from-the-created-squ.patch
Patch0005: 0005-livemode-cfg-add-declaration-of-livemode-config-fiel.patch
Patch0006: 0006-livemode-cfg-use-framework-s-configurability-instead.patch
Patch0007: 0007-fix-livemode-do-not-stop-if-dbus-already-appears-to-.patch
Patch0008: 0008-feat-livemode-remove-the-use-of-LEAPP_DEVEL_ENABLE_L.patch
Patch0009: 0009-spec-require-leapp-framework-6.1-for-default-CLI-val.patch
Patch0010: 0010-docs-configuring-ipu-add-experimental-features-secti.patch
Patch0011: 0011-docs-livemode-add-LiveMode-documentation.patch
Patch0012: 0012-DOC-rename-configuring-ipu.md-to-envars.md.patch
Patch0013: 0013-fix-userspacegen-add-exeception-handling-to-swapping.patch
Patch0014: 0014-selinux-do-not-run-semodule-when-no-modules-are-sele.patch
Patch0015: 0015-feat-ipuconfig-provide-info-about-supported-upgrade-.patch
Patch0016: 0016-feat-upgrade_paths-include-information-about-distro-.patch
Patch0017: 0017-cleanup-ipupaths-remove-IPUPaths-message.patch
Patch0018: 0018-libs-version-use-supported_upgrade_paths.patch
Patch0019: 0019-Remove-7to8-CI-tests.patch
Patch0020: 0020-Fix-lint-in-Makefile-for-docs.patch
Patch0021: 0021-Improve-report-of-removed-kernel-drivers.patch
Patch0022: 0022-Improve-report-of-unsupported-network-configuration.patch
Patch0023: 0023-DOCS-add-missing-envar-LEAPP_OVL_IMG_FS_EXT4.patch
Patch0024: 0024-data-update-data-files-stream-3.3-1358.patch
Patch0025: 0025-Add-RHEL-10.1-and-9.7-product-certificates.patch
Patch0026: 0026-Add-handling-of-shorten-PCI-ID-and-lowercases.patch
Patch0027: 0027-Prevent-device-list-from-containing-incorrent-conten.patch
Patch0028: 0028-feat-command_utils-allow-missing-minor-major-version.patch
Patch0029: 0029-refactor-versions-config-rename-_simple_versions.patch
Patch0030: 0030-fix-lib-version-broken-_validate_version-on-RHEL-10.patch
Patch0031: 0031-upgrade_paths-add-information-about-centos-virtual-v.patch
Patch0032: 0032-models-ipuconfig-extend-Version-class-to-contain-vir.patch
Patch0033: 0033-libs-common-version-autocorrect-centos-versions-into.patch
Patch0034: 0034-Introduce-distro-based-rpm-gpg-trusted-directory.patch
Patch0035: 0035-Add-official-Centos-Stream-9-and-10-RPM-GPG-keys.patch
Patch0036: 0036-Deprecate-is_rhel_alt-from-share-libraries.patch
Patch0037: 0037-data-update-data-files-stream-3.3-1380.patch
%description
@ -122,7 +159,7 @@ Requires: leapp-repository-dependencies = %{leapp_repo_deps}
# IMPORTANT: this is capability provided by the leapp framework rpm.
# Check that 'version' instead of the real framework rpm version.
Requires: leapp-framework >= 6.0
Requires: leapp-framework >= 6.1
# Since we provide sub-commands for the leapp utility, we expect the leapp
# tool to be installed as well.
@ -234,8 +271,44 @@ Requires: libdb-utils
%setup -q -n %{name}-%{version} -D -T -a 1
# APPLY PATCHES HERE
# %%patch0001 -p1
%%patch0100 -p1
# %%patch -P 0001 -p1
%patch -P 0001 -p1
%patch -P 0002 -p1
%patch -P 0003 -p1
%patch -P 0004 -p1
%patch -P 0005 -p1
%patch -P 0006 -p1
%patch -P 0007 -p1
%patch -P 0008 -p1
%patch -P 0009 -p1
%patch -P 0010 -p1
%patch -P 0011 -p1
%patch -P 0012 -p1
%patch -P 0013 -p1
%patch -P 0014 -p1
%patch -P 0015 -p1
%patch -P 0016 -p1
%patch -P 0017 -p1
%patch -P 0018 -p1
%patch -P 0019 -p1
%patch -P 0020 -p1
%patch -P 0021 -p1
%patch -P 0022 -p1
%patch -P 0023 -p1
%patch -P 0024 -p1
%patch -P 0025 -p1
%patch -P 0026 -p1
%patch -P 0027 -p1
%patch -P 0028 -p1
%patch -P 0029 -p1
%patch -P 0030 -p1
%patch -P 0031 -p1
%patch -P 0032 -p1
%patch -P 0033 -p1
%patch -P 0034 -p1
%patch -P 0035 -p1
%patch -P 0036 -p1
%patch -P 0037 -p1
%build
@ -320,6 +393,22 @@ done;
# no files here
%changelog
* Wed May 14 2025 Petr Stodulka <pstodulk@redhat.com> - 0.22.0-3
- Rebuild
* Tue May 13 2025 Petr Stodulka <pstodulk@redhat.com> - 0.22.0-2
- Require leapp-framework >= 6.1
- Simplified use of the LiveMode experimental feature with additional enhancements
- Fix the check of deprecated PCI devices and drivers
- Add RHEL 9.7 product certificates
- Gracefully handle CentOS OS versioning style
- Introduced the --enable-experimental-feature to simplify use of experimental features
- Manage RPM GPG keys during the upgrade respecting used linux distributions
- Minor fixes in reports
- Prevent a crach during post-upgrade phases when no custom SELinux modules needs to be migrated
- Update leapp upgrade data files
- Resolves: RHEL-53801, RHEL-77945, RHEL-84978
* Thu Feb 27 2025 Yuriy Kohut <ykohut@almalinux.org> - 0.22.0-1.elevate.1
- ELevate vendors support for upstream 0.22.0-1 version
- Update ELevate patch: