import leapp-repository-0.17.0-5.el8

This commit is contained in:
CentOS Sources 2022-12-13 06:13:56 +00:00 committed by root
parent 1e87a1c8da
commit 97becf6994
37 changed files with 10670 additions and 51 deletions

2
.gitignore vendored
View File

@ -1,2 +1,2 @@
SOURCES/deps-pkgs-7.tar.gz
SOURCES/deps-pkgs-8.tar.gz
SOURCES/leapp-repository-0.17.0.tar.gz

View File

@ -1,2 +1,2 @@
4886551d9ee2259cdfbd8d64a02d0ab9a381ba3d SOURCES/deps-pkgs-7.tar.gz
4f7f6009adfe92d390e09beab710805fb0077c25 SOURCES/deps-pkgs-8.tar.gz
cbb3e6025c6567507d3bc317731b4c2f0a0eb872 SOURCES/leapp-repository-0.17.0.tar.gz

View File

@ -0,0 +1,131 @@
From c5451ffb9a5c964552afd9d419855ea23b764ad7 Mon Sep 17 00:00:00 2001
From: Inessa Vasilevskaya <ivasilev@redhat.com>
Date: Wed, 24 Aug 2022 12:17:44 +0200
Subject: [PATCH 05/32] Disable isort check for deprecated imports
Although isort works fine most of the time, the way it handles
multiline imports with inline comments is not acceptable
to everyone in the team.
So before we implement some solution we are 146% happy about
it was decided to leave those imports just as they have been for
ages. This patch mutes isort import check for deprecated imports.
---
.../common/actors/commonleappdracutmodules/actor.py | 7 ++++---
.../actors/commonleappdracutmodules/libraries/modscan.py | 5 +++--
.../tests/test_modscan_commonleappdracutmodules.py | 5 +++--
.../tests/test_targetinitramfsgenerator.py | 5 +++--
.../tests/unit_test_upgradeinitramfsgenerator.py | 5 +++--
5 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/repos/system_upgrade/common/actors/commonleappdracutmodules/actor.py b/repos/system_upgrade/common/actors/commonleappdracutmodules/actor.py
index 950b6e88..aae42bbb 100644
--- a/repos/system_upgrade/common/actors/commonleappdracutmodules/actor.py
+++ b/repos/system_upgrade/common/actors/commonleappdracutmodules/actor.py
@@ -1,13 +1,14 @@
from leapp.actors import Actor
from leapp.libraries.actor import modscan
-from leapp.models import (
+from leapp.tags import FactsPhaseTag, IPUWorkflowTag
+from leapp.utils.deprecation import suppress_deprecation
+
+from leapp.models import ( # isort:skip
RequiredUpgradeInitramPackages, # deprecated
UpgradeDracutModule, # deprecated
TargetUserSpaceUpgradeTasks,
UpgradeInitramfsTasks
)
-from leapp.tags import FactsPhaseTag, IPUWorkflowTag
-from leapp.utils.deprecation import suppress_deprecation
@suppress_deprecation(RequiredUpgradeInitramPackages, UpgradeDracutModule)
diff --git a/repos/system_upgrade/common/actors/commonleappdracutmodules/libraries/modscan.py b/repos/system_upgrade/common/actors/commonleappdracutmodules/libraries/modscan.py
index a089c4c1..275b2c63 100644
--- a/repos/system_upgrade/common/actors/commonleappdracutmodules/libraries/modscan.py
+++ b/repos/system_upgrade/common/actors/commonleappdracutmodules/libraries/modscan.py
@@ -3,14 +3,15 @@ import re
from leapp.libraries.common.config import architecture, version
from leapp.libraries.stdlib import api
-from leapp.models import (
+from leapp.utils.deprecation import suppress_deprecation
+
+from leapp.models import ( # isort:skip
RequiredUpgradeInitramPackages, # deprecated
UpgradeDracutModule, # deprecated
DracutModule,
TargetUserSpaceUpgradeTasks,
UpgradeInitramfsTasks
)
-from leapp.utils.deprecation import suppress_deprecation
_REQUIRED_PACKAGES = [
'binutils',
diff --git a/repos/system_upgrade/common/actors/commonleappdracutmodules/tests/test_modscan_commonleappdracutmodules.py b/repos/system_upgrade/common/actors/commonleappdracutmodules/tests/test_modscan_commonleappdracutmodules.py
index 307e927c..9c52b51f 100644
--- a/repos/system_upgrade/common/actors/commonleappdracutmodules/tests/test_modscan_commonleappdracutmodules.py
+++ b/repos/system_upgrade/common/actors/commonleappdracutmodules/tests/test_modscan_commonleappdracutmodules.py
@@ -8,13 +8,14 @@ from leapp.libraries.actor import modscan
from leapp.libraries.common.config import architecture
from leapp.libraries.common.testutils import CurrentActorMocked
from leapp.libraries.stdlib import api
-from leapp.models import (
+from leapp.utils.deprecation import suppress_deprecation
+
+from leapp.models import ( # isort:skip
RequiredUpgradeInitramPackages, # deprecated
UpgradeDracutModule, # deprecated
TargetUserSpaceUpgradeTasks,
UpgradeInitramfsTasks
)
-from leapp.utils.deprecation import suppress_deprecation
def _files_get_folder_path(name):
diff --git a/repos/system_upgrade/common/actors/initramfs/targetinitramfsgenerator/tests/test_targetinitramfsgenerator.py b/repos/system_upgrade/common/actors/initramfs/targetinitramfsgenerator/tests/test_targetinitramfsgenerator.py
index 98fe92c6..f5930b9b 100644
--- a/repos/system_upgrade/common/actors/initramfs/targetinitramfsgenerator/tests/test_targetinitramfsgenerator.py
+++ b/repos/system_upgrade/common/actors/initramfs/targetinitramfsgenerator/tests/test_targetinitramfsgenerator.py
@@ -4,13 +4,14 @@ from leapp.exceptions import StopActorExecutionError
from leapp.libraries.actor import targetinitramfsgenerator
from leapp.libraries.common.testutils import CurrentActorMocked, logger_mocked
from leapp.libraries.stdlib import api, CalledProcessError
-from leapp.models import (
+from leapp.utils.deprecation import suppress_deprecation
+
+from leapp.models import ( # isort:skip
InitrdIncludes, # deprecated
DracutModule,
InstalledTargetKernelVersion,
TargetInitramfsTasks
)
-from leapp.utils.deprecation import suppress_deprecation
FILES = ['/file1', '/file2', '/dir/ect/ory/file3', '/file4', '/file5']
MODULES = [
diff --git a/repos/system_upgrade/common/actors/initramfs/upgradeinitramfsgenerator/tests/unit_test_upgradeinitramfsgenerator.py b/repos/system_upgrade/common/actors/initramfs/upgradeinitramfsgenerator/tests/unit_test_upgradeinitramfsgenerator.py
index b54aaa1f..2b401e52 100644
--- a/repos/system_upgrade/common/actors/initramfs/upgradeinitramfsgenerator/tests/unit_test_upgradeinitramfsgenerator.py
+++ b/repos/system_upgrade/common/actors/initramfs/upgradeinitramfsgenerator/tests/unit_test_upgradeinitramfsgenerator.py
@@ -7,7 +7,9 @@ from leapp.exceptions import StopActorExecutionError
from leapp.libraries.actor import upgradeinitramfsgenerator
from leapp.libraries.common.config import architecture
from leapp.libraries.common.testutils import CurrentActorMocked, logger_mocked, produce_mocked
-from leapp.models import (
+from leapp.utils.deprecation import suppress_deprecation
+
+from leapp.models import ( # isort:skip
RequiredUpgradeInitramPackages, # deprecated
UpgradeDracutModule, # deprecated
BootContent,
@@ -16,7 +18,6 @@ from leapp.models import (
TargetUserSpaceUpgradeTasks,
UpgradeInitramfsTasks,
)
-from leapp.utils.deprecation import suppress_deprecation
CUR_DIR = os.path.dirname(os.path.abspath(__file__))
PKGS = ['pkg{}'.format(c) for c in 'ABCDEFGHIJ']
--
2.38.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,39 @@
From 25adde3fe09d200a3f8bc42af1ebcf07b179fb85 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Thu, 1 Sep 2022 11:19:18 +0200
Subject: [PATCH 07/32] Mini updateds in the spec files
To synchronize better with the downstream specfile, making lives
of people again a little bit easier.
---
packaging/leapp-repository.spec | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/packaging/leapp-repository.spec b/packaging/leapp-repository.spec
index c59f8acd..89750927 100644
--- a/packaging/leapp-repository.spec
+++ b/packaging/leapp-repository.spec
@@ -53,6 +53,10 @@ Source1: deps-pkgs.tar.gz
# NOTE: Our packages must be noarch. Do no drop this in any way.
BuildArch: noarch
+### PATCHES HERE
+# Patch0001: filename.patch
+
+
%description
%{summary}
@@ -182,6 +186,9 @@ Requires: dracut
%setup -n %{name}-%{version}
%setup -q -n %{name}-%{version} -D -T -a 1
+# APPLY PATCHES HERE
+# %%patch0001 -p1
+
%build
%if 0%{?rhel} == 7
--
2.38.1

View File

@ -1,8 +1,8 @@
From 505963d51e3989a7d907861dd870133c670ccb78 Mon Sep 17 00:00:00 2001
From 921a3f5ae0fa75ef04eb56857b5f07275e39c112 Mon Sep 17 00:00:00 2001
From: Joe Shimkus <joe@shimkus.com>
Date: Wed, 24 Aug 2022 13:30:19 -0400
Subject: [PATCH] CheckVDO: Ask user only faiulres and undetermined devices (+
report update)
Subject: [PATCH 08/32] CheckVDO: Ask user only faiulres and undetermined
devices (+ report update)
The previous solution made possible to skip the VDO check answering
the user question (confirming no vdo devices are present) if the
@ -43,24 +43,15 @@ to other "unstable" block devices.
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2096159
Jira: OAMG-7025
---
.../el8toel9/actors/checkvdo/actor.py | 96 +++++++----
.../el8toel9/actors/checkvdo/actor.py | 94 +++++++----
.../actors/checkvdo/libraries/checkvdo.py | 155 ++++++++++--------
.../checkvdo/tests/unit_test_checkvdo.py | 44 +++--
3 files changed, 184 insertions(+), 111 deletions(-)
3 files changed, 183 insertions(+), 110 deletions(-)
diff --git a/repos/system_upgrade/el8toel9/actors/checkvdo/actor.py b/repos/system_upgrade/el8toel9/actors/checkvdo/actor.py
index c28b3a9..d43bac0 100644
index 4158253a..d43bac0b 100644
--- a/repos/system_upgrade/el8toel9/actors/checkvdo/actor.py
+++ b/repos/system_upgrade/el8toel9/actors/checkvdo/actor.py
@@ -12,7 +12,7 @@ class CheckVdo(Actor):
`Background`
============
- In RHEL 9.0 the indepdent VDO management software, `vdo manager`, is
+ In RHEL 9.0 the independent VDO management software, `vdo manager`, is
superseded by LVM management. Existing VDOs must be converted to LVM-based
management *before* upgrading to RHEL 9.0.
@@ -32,12 +32,24 @@ class CheckVdo(Actor):
If the VdoConversionInfo model indicates unexpected errors occurred during
scanning CheckVdo will produce appropriate inhibitory reports.
@ -175,7 +166,7 @@ index c28b3a9..d43bac0 100644
def process(self):
for conversion_info in self.consume(VdoConversionInfo):
diff --git a/repos/system_upgrade/el8toel9/actors/checkvdo/libraries/checkvdo.py b/repos/system_upgrade/el8toel9/actors/checkvdo/libraries/checkvdo.py
index 9ba5c70..3b161c9 100644
index 135a279d..3b161c9b 100644
--- a/repos/system_upgrade/el8toel9/actors/checkvdo/libraries/checkvdo.py
+++ b/repos/system_upgrade/el8toel9/actors/checkvdo/libraries/checkvdo.py
@@ -1,10 +1,35 @@
@ -244,7 +235,7 @@ index 9ba5c70..3b161c9 100644
- 'device format level; however, the expected LVM management '
- 'portion of the conversion did not take place. This '
- 'indicates that an exceptional condition (for example, a '
- 'system crash) likely occured during the conversion '
- 'system crash) likely occurred during the conversion '
- 'process. The LVM portion of the conversion must be '
- 'performed in order for upgrade to proceed.'))
+ summary = (
@ -397,7 +388,7 @@ index 9ba5c70..3b161c9 100644
+ if detected_under_dev or detected_failed_check:
+ _report_skip_check()
diff --git a/repos/system_upgrade/el8toel9/actors/checkvdo/tests/unit_test_checkvdo.py b/repos/system_upgrade/el8toel9/actors/checkvdo/tests/unit_test_checkvdo.py
index e0ac39d..865e036 100644
index e0ac39d0..865e036f 100644
--- a/repos/system_upgrade/el8toel9/actors/checkvdo/tests/unit_test_checkvdo.py
+++ b/repos/system_upgrade/el8toel9/actors/checkvdo/tests/unit_test_checkvdo.py
@@ -13,14 +13,16 @@ from leapp.models import (
@ -558,5 +549,5 @@ index e0ac39d..865e036 100644
- 'User has opted to inhibit upgrade')
+ 'User has asserted all VDO devices on the system have been successfully converted')
--
2.37.2
2.38.1

View File

@ -0,0 +1,383 @@
From d2d7999744e97776eda664592ac0cc7ec5747b99 Mon Sep 17 00:00:00 2001
From: Matej Matuska <mmatuska@redhat.com>
Date: Thu, 8 Sep 2022 16:27:10 +0200
Subject: [PATCH 09/32] Add actors for checking and setting systemd services
states
Introduces a new `set_systemd_services_state` actor, which
enables/disables systemd services according to received
`SystemdServicesTasks` messages and a `check_systemd_services_tasks`
actor which checks tasks in the `TargetTransactionCheckPhase` and
inhibits upgrade if there are conflicts.
Actors are in a new directory `systemd`.
---
.../systemd/checksystemdservicetasks/actor.py | 30 +++++++
.../libraries/checksystemdservicetasks.py | 36 ++++++++
.../tests/test_checksystemdservicestasks.py | 88 +++++++++++++++++++
.../systemd/setsystemdservicesstates/actor.py | 18 ++++
.../libraries/setsystemdservicesstate.py | 31 +++++++
.../tests/test_setsystemdservicesstate.py | 83 +++++++++++++++++
.../common/models/systemdservices.py | 22 +++++
7 files changed, 308 insertions(+)
create mode 100644 repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/actor.py
create mode 100644 repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/libraries/checksystemdservicetasks.py
create mode 100644 repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/tests/test_checksystemdservicestasks.py
create mode 100644 repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/actor.py
create mode 100644 repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/libraries/setsystemdservicesstate.py
create mode 100644 repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/tests/test_setsystemdservicesstate.py
create mode 100644 repos/system_upgrade/common/models/systemdservices.py
diff --git a/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/actor.py b/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/actor.py
new file mode 100644
index 00000000..2df995ee
--- /dev/null
+++ b/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/actor.py
@@ -0,0 +1,30 @@
+from leapp.actors import Actor
+from leapp.libraries.actor import checksystemdservicetasks
+from leapp.models import SystemdServicesTasks
+from leapp.reporting import Report
+from leapp.tags import IPUWorkflowTag, TargetTransactionChecksPhaseTag
+
+
+class CheckSystemdServicesTasks(Actor):
+ """
+ Inhibits upgrade if SystemdServicesTasks tasks are in conflict
+
+ There is possibility, that SystemdServicesTasks messages with conflicting
+ requested service states could be produced. For example a service is
+ requested to be both enabled and disabled. This actor inhibits upgrade in
+ such cases.
+
+ Note: We expect that SystemdServicesTasks could be produced even after the
+ TargetTransactionChecksPhase (e.g. during the ApplicationPhase). The
+ purpose of this actor is to report collisions in case we can already detect
+ them. In case of conflicts caused by produced messages later we just log
+ the collisions and the services will end up disabled.
+ """
+
+ name = 'check_systemd_services_tasks'
+ consumes = (SystemdServicesTasks,)
+ produces = (Report,)
+ tags = (TargetTransactionChecksPhaseTag, IPUWorkflowTag)
+
+ def process(self):
+ checksystemdservicetasks.check_conflicts()
diff --git a/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/libraries/checksystemdservicetasks.py b/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/libraries/checksystemdservicetasks.py
new file mode 100644
index 00000000..75833e4f
--- /dev/null
+++ b/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/libraries/checksystemdservicetasks.py
@@ -0,0 +1,36 @@
+from leapp import reporting
+from leapp.libraries.stdlib import api
+from leapp.models import SystemdServicesTasks
+
+FMT_LIST_SEPARATOR = '\n - '
+
+
+def _printable_conflicts(conflicts):
+ return FMT_LIST_SEPARATOR + FMT_LIST_SEPARATOR.join(sorted(conflicts))
+
+
+def _inhibit_upgrade_with_conflicts(conflicts):
+ summary = (
+ 'The requested states for systemd services on the target system are in conflict.'
+ ' The following systemd services were requested to be both enabled and disabled on the target system: {}'
+ )
+ report = [
+ reporting.Title('Conflicting requirements of systemd service states'),
+ reporting.Summary(summary.format(_printable_conflicts(conflicts))),
+ reporting.Severity(reporting.Severity.HIGH),
+ reporting.Groups([reporting.Groups.SANITY]),
+ reporting.Groups([reporting.Groups.INHIBITOR]),
+ ]
+ reporting.create_report(report)
+
+
+def check_conflicts():
+ services_to_enable = set()
+ services_to_disable = set()
+ for task in api.consume(SystemdServicesTasks):
+ services_to_enable.update(task.to_enable)
+ services_to_disable.update(task.to_disable)
+
+ conflicts = services_to_enable.intersection(services_to_disable)
+ if conflicts:
+ _inhibit_upgrade_with_conflicts(conflicts)
diff --git a/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/tests/test_checksystemdservicestasks.py b/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/tests/test_checksystemdservicestasks.py
new file mode 100644
index 00000000..36ded92f
--- /dev/null
+++ b/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/tests/test_checksystemdservicestasks.py
@@ -0,0 +1,88 @@
+import pytest
+
+from leapp import reporting
+from leapp.libraries.actor import checksystemdservicetasks
+from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked
+from leapp.libraries.stdlib import api
+from leapp.models import SystemdServicesTasks
+
+
+@pytest.mark.parametrize(
+ ('tasks', 'should_inhibit'),
+ [
+ (
+ [SystemdServicesTasks(to_enable=['hello.service'], to_disable=['hello.service'])],
+ True
+ ),
+ (
+ [SystemdServicesTasks(to_enable=['hello.service', 'world.service'],
+ to_disable=['hello.service'])],
+ True
+ ),
+ (
+ [
+ SystemdServicesTasks(to_enable=['hello.service']),
+ SystemdServicesTasks(to_disable=['hello.service'])
+ ],
+ True
+ ),
+ (
+ [SystemdServicesTasks(to_enable=['hello.service'], to_disable=['world.service'])],
+ False
+ ),
+ (
+ [
+ SystemdServicesTasks(to_enable=['hello.service']),
+ SystemdServicesTasks(to_disable=['world.service'])
+ ],
+ False
+ ),
+ (
+ [
+ SystemdServicesTasks(to_enable=['hello.service', 'world.service']),
+ SystemdServicesTasks(to_disable=['world.service', 'httpd.service'])
+ ],
+ True
+ ),
+ ]
+)
+def test_conflicts_detected(monkeypatch, tasks, should_inhibit):
+
+ created_reports = create_report_mocked()
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(msgs=tasks))
+ monkeypatch.setattr(reporting, 'create_report', created_reports)
+
+ checksystemdservicetasks.check_conflicts()
+
+ assert bool(created_reports.called) == should_inhibit
+
+
+@pytest.mark.parametrize(
+ ('tasks', 'expected_reported'),
+ [
+ (
+ [SystemdServicesTasks(to_enable=['world.service', 'httpd.service', 'hello.service'],
+ to_disable=['hello.service', 'world.service', 'test.service'])],
+ ['world.service', 'hello.service']
+ ),
+ (
+ [
+ SystemdServicesTasks(to_enable=['hello.service', 'httpd.service'],
+ to_disable=['world.service']),
+ SystemdServicesTasks(to_enable=['world.service', 'httpd.service'],
+ to_disable=['hello.service', 'test.service'])
+ ],
+ ['world.service', 'hello.service']
+ ),
+ ]
+)
+def test_coflict_reported(monkeypatch, tasks, expected_reported):
+
+ created_reports = create_report_mocked()
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(msgs=tasks))
+ monkeypatch.setattr(reporting, 'create_report', created_reports)
+
+ checksystemdservicetasks.check_conflicts()
+
+ report_summary = reporting.create_report.report_fields['summary']
+ assert all(service in report_summary for service in expected_reported)
diff --git a/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/actor.py b/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/actor.py
new file mode 100644
index 00000000..1709091e
--- /dev/null
+++ b/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/actor.py
@@ -0,0 +1,18 @@
+from leapp.actors import Actor
+from leapp.libraries.actor import setsystemdservicesstate
+from leapp.models import SystemdServicesTasks
+from leapp.tags import FinalizationPhaseTag, IPUWorkflowTag
+
+
+class SetSystemdServicesState(Actor):
+ """
+ According to input messages sets systemd services states on the target system
+ """
+
+ name = 'set_systemd_services_state'
+ consumes = (SystemdServicesTasks,)
+ produces = ()
+ tags = (FinalizationPhaseTag, IPUWorkflowTag)
+
+ def process(self):
+ setsystemdservicesstate.process()
diff --git a/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/libraries/setsystemdservicesstate.py b/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/libraries/setsystemdservicesstate.py
new file mode 100644
index 00000000..01272438
--- /dev/null
+++ b/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/libraries/setsystemdservicesstate.py
@@ -0,0 +1,31 @@
+from leapp.libraries.stdlib import api, CalledProcessError, run
+from leapp.models import SystemdServicesTasks
+
+
+def _try_set_service_state(command, service):
+ try:
+ # it is possible to call this on multiple units at once,
+ # but failing to enable one service would cause others to not enable as well
+ run(['systemctl', command, service])
+ except CalledProcessError as err:
+ api.current_logger().error('Failed to {} systemd unit "{}". Message: {}'.format(command, service, str(err)))
+ # TODO(mmatuska) produce post-upgrade report
+
+
+def process():
+ services_to_enable = set()
+ services_to_disable = set()
+ for task in api.consume(SystemdServicesTasks):
+ services_to_enable.update(task.to_enable)
+ services_to_disable.update(task.to_disable)
+
+ intersection = services_to_enable.intersection(services_to_disable)
+ for service in intersection:
+ msg = 'Attempted to both enable and disable systemd service "{}", service will be disabled.'.format(service)
+ api.current_logger().error(msg)
+
+ for service in services_to_enable:
+ _try_set_service_state('enable', service)
+
+ for service in services_to_disable:
+ _try_set_service_state('disable', service)
diff --git a/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/tests/test_setsystemdservicesstate.py b/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/tests/test_setsystemdservicesstate.py
new file mode 100644
index 00000000..dd153329
--- /dev/null
+++ b/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/tests/test_setsystemdservicesstate.py
@@ -0,0 +1,83 @@
+import pytest
+
+from leapp.libraries import stdlib
+from leapp.libraries.actor import setsystemdservicesstate
+from leapp.libraries.common.testutils import CurrentActorMocked, logger_mocked
+from leapp.libraries.stdlib import api, CalledProcessError
+from leapp.models import SystemdServicesTasks
+
+
+class MockedRun(object):
+ def __init__(self):
+ self.commands = []
+
+ def __call__(self, cmd, *args, **kwargs):
+ self.commands.append(cmd)
+ return {}
+
+
+@pytest.mark.parametrize(
+ ('msgs', 'expected_calls'),
+ [
+ (
+ [SystemdServicesTasks(to_enable=['hello.service'],
+ to_disable=['getty.service'])],
+ [['systemctl', 'enable', 'hello.service'], ['systemctl', 'disable', 'getty.service']]
+ ),
+ (
+ [SystemdServicesTasks(to_disable=['getty.service'])],
+ [['systemctl', 'disable', 'getty.service']]
+ ),
+ (
+ [SystemdServicesTasks(to_enable=['hello.service'])],
+ [['systemctl', 'enable', 'hello.service']]
+ ),
+ (
+ [SystemdServicesTasks()],
+ []
+ ),
+ ]
+)
+def test_process(monkeypatch, msgs, expected_calls):
+ mocked_run = MockedRun()
+ monkeypatch.setattr(setsystemdservicesstate, 'run', mocked_run)
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(msgs=msgs))
+
+ setsystemdservicesstate.process()
+
+ assert mocked_run.commands == expected_calls
+
+
+def test_process_invalid(monkeypatch):
+
+ def mocked_run(cmd, *args, **kwargs):
+ if cmd == ['systemctl', 'enable', 'invalid.service']:
+ message = 'Command {0} failed with exit code {1}.'.format(str(cmd), 1)
+ raise CalledProcessError(message, cmd, 1)
+
+ msgs = [SystemdServicesTasks(to_enable=['invalid.service'])]
+
+ monkeypatch.setattr(setsystemdservicesstate, 'run', mocked_run)
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(msgs=msgs))
+ monkeypatch.setattr(api, 'current_logger', logger_mocked())
+
+ setsystemdservicesstate.process()
+
+ expect_msg = ("Failed to enable systemd unit \"invalid.service\". Message:"
+ " Command ['systemctl', 'enable', 'invalid.service'] failed with exit code 1.")
+ assert expect_msg in api.current_logger.errmsg
+
+
+def test_enable_disable_conflict_logged(monkeypatch):
+ msgs = [SystemdServicesTasks(to_enable=['hello.service'],
+ to_disable=['hello.service'])]
+ mocked_run = MockedRun()
+ monkeypatch.setattr(setsystemdservicesstate, 'run', mocked_run)
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(msgs=msgs))
+ monkeypatch.setattr(api, 'current_logger', logger_mocked())
+
+ setsystemdservicesstate.process()
+
+ expect_msg = ('Attempted to both enable and disable systemd service "hello.service",'
+ ' service will be disabled.')
+ assert expect_msg in api.current_logger.errmsg
diff --git a/repos/system_upgrade/common/models/systemdservices.py b/repos/system_upgrade/common/models/systemdservices.py
new file mode 100644
index 00000000..6c7d4a1d
--- /dev/null
+++ b/repos/system_upgrade/common/models/systemdservices.py
@@ -0,0 +1,22 @@
+from leapp.models import fields, Model
+from leapp.topics import SystemInfoTopic
+
+
+class SystemdServicesTasks(Model):
+ topic = SystemInfoTopic
+
+ to_enable = fields.List(fields.String(), default=[])
+ """
+ List of systemd services to enable on the target system
+
+ Masked services will not be enabled. Attempting to enable a masked service
+ will be evaluated by systemctl as usually. The error will be logged and the
+ upgrade process will continue.
+ """
+ to_disable = fields.List(fields.String(), default=[])
+ """
+ List of systemd services to disable on the target system
+ """
+
+ # Note: possible extension in case of requirement (currently not implemented):
+ # to_unmask = fields.List(fields.String(), default=[])
--
2.38.1

View File

@ -0,0 +1,92 @@
From 004e7f3515cc2daa1a7ca72f7c8f5becb945ff17 Mon Sep 17 00:00:00 2001
From: Miroslav Lichvar <mlichvar@redhat.com>
Date: Mon, 19 Sep 2022 15:16:46 +0200
Subject: [PATCH 10/32] migratentp: Replace reports with log messages
Reports are supposed to contain different information.
---
.../actors/migratentp/libraries/migratentp.py | 27 ++++---------------
.../migratentp/tests/unit_test_migratentp.py | 10 -------
2 files changed, 5 insertions(+), 32 deletions(-)
diff --git a/repos/system_upgrade/el7toel8/actors/migratentp/libraries/migratentp.py b/repos/system_upgrade/el7toel8/actors/migratentp/libraries/migratentp.py
index deeaaccd..a0ad634b 100644
--- a/repos/system_upgrade/el7toel8/actors/migratentp/libraries/migratentp.py
+++ b/repos/system_upgrade/el7toel8/actors/migratentp/libraries/migratentp.py
@@ -2,11 +2,8 @@ import base64
import io
import tarfile
-from leapp import reporting
from leapp.exceptions import StopActorExecutionError
-from leapp.libraries.stdlib import CalledProcessError, run
-
-COMMON_REPORT_TAGS = [reporting.Groups.SERVICES, reporting.Groups.TIME_MANAGEMENT]
+from leapp.libraries.stdlib import api, CalledProcessError, run
def extract_tgz64(s):
@@ -82,21 +79,7 @@ def migrate_ntp(migrate_services, config_tgz64):
ignored_lines = ntp2chrony('/', ntp_conf, step_tickers)
- config_resources = [reporting.RelatedResource('file', mc) for mc in migrate_configs + [ntp_conf]]
- package_resources = [reporting.RelatedResource('package', p) for p in ['ntpd', 'chrony']]
-
- if not ignored_lines:
- reporting.create_report([
- reporting.Title('{} configuration migrated to chrony'.format(' and '.join(migrate_configs))),
- reporting.Summary('ntp2chrony executed successfully'),
- reporting.Severity(reporting.Severity.INFO),
- reporting.Groups(COMMON_REPORT_TAGS)
- ] + config_resources + package_resources)
-
- else:
- reporting.create_report([
- reporting.Title('{} configuration partially migrated to chrony'.format(' and '.join(migrate_configs))),
- reporting.Summary('Some lines in /etc/ntp.conf were ignored in migration (check /etc/chrony.conf)'),
- reporting.Severity(reporting.Severity.MEDIUM),
- reporting.Groups(COMMON_REPORT_TAGS)
- ] + config_resources + package_resources)
+ api.current_logger().info('Configuration files migrated to chrony: {}'.format(' '.join(migrate_configs)))
+ if ignored_lines:
+ api.current_logger().warning('Some lines in /etc/ntp.conf were ignored in migration'
+ ' (check /etc/chrony.conf)')
diff --git a/repos/system_upgrade/el7toel8/actors/migratentp/tests/unit_test_migratentp.py b/repos/system_upgrade/el7toel8/actors/migratentp/tests/unit_test_migratentp.py
index 6ce4bb5b..fafff5e7 100644
--- a/repos/system_upgrade/el7toel8/actors/migratentp/tests/unit_test_migratentp.py
+++ b/repos/system_upgrade/el7toel8/actors/migratentp/tests/unit_test_migratentp.py
@@ -55,7 +55,6 @@ def test_migration(monkeypatch):
(['ntp-wait'], ['chrony-wait'], 0),
(['ntpd', 'ntpdate', 'ntp-wait'], ['chronyd', 'chronyd', 'chrony-wait'], 1),
]:
- monkeypatch.setattr(reporting, 'create_report', create_report_mocked())
monkeypatch.setattr(migratentp, 'extract_tgz64', extract_tgz64_mocked())
monkeypatch.setattr(migratentp, 'enable_service', enable_service_mocked())
monkeypatch.setattr(migratentp, 'write_file', write_file_mocked())
@@ -64,14 +63,6 @@ def test_migration(monkeypatch):
migratentp.migrate_ntp(ntp_services, 'abcdef')
if ntp_services:
- assert reporting.create_report.called == 1
- if ignored_lines > 0:
- assert 'configuration partially migrated to chrony' in \
- reporting.create_report.report_fields['title']
- else:
- assert 'configuration migrated to chrony' in \
- reporting.create_report.report_fields['title']
-
assert migratentp.extract_tgz64.called == 1
assert migratentp.extract_tgz64.s == 'abcdef'
assert migratentp.enable_service.called == len(chrony_services)
@@ -86,7 +77,6 @@ def test_migration(monkeypatch):
'/etc/ntp.conf' if 'ntpd' in ntp_services else '/etc/ntp.conf.nosources',
'/etc/ntp/step-tickers' if 'ntpdate' in ntp_services else '')
else:
- assert reporting.create_report.called == 0
assert migratentp.extract_tgz64.called == 0
assert migratentp.enable_service.called == 0
assert migratentp.write_file.called == 0
--
2.38.1

View File

@ -0,0 +1,28 @@
From 83dbc935d1ac32cbfeca7ba52da6bb4bbb965879 Mon Sep 17 00:00:00 2001
From: Miroslav Lichvar <mlichvar@redhat.com>
Date: Mon, 19 Sep 2022 15:35:43 +0200
Subject: [PATCH 11/32] migratentp: Catch more specific exception from
ntp2chrony
Catch OSError instead of Exception from ntp2chrony to avoid pylint
errors.
---
.../el7toel8/actors/migratentp/libraries/migratentp.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/repos/system_upgrade/el7toel8/actors/migratentp/libraries/migratentp.py b/repos/system_upgrade/el7toel8/actors/migratentp/libraries/migratentp.py
index a0ad634b..1bc59448 100644
--- a/repos/system_upgrade/el7toel8/actors/migratentp/libraries/migratentp.py
+++ b/repos/system_upgrade/el7toel8/actors/migratentp/libraries/migratentp.py
@@ -33,7 +33,7 @@ def ntp2chrony(root, ntp_conf, step_tickers):
ntp_configuration = ntp2chrony.NtpConfiguration(root, ntp_conf, step_tickers)
ntp_configuration.write_chrony_configuration('/etc/chrony.conf', '/etc/chrony.keys',
False, True)
- except Exception as e:
+ except OSError as e:
raise StopActorExecutionError('ntp2chrony failed: {}'.format(e))
# Return ignored lines from ntp.conf, except 'disable monitor' from
--
2.38.1

View File

@ -0,0 +1,92 @@
From 02dca0a6b721c89d125c521c7da5e85b89d136f7 Mon Sep 17 00:00:00 2001
From: Miroslav Lichvar <mlichvar@redhat.com>
Date: Wed, 14 Sep 2022 14:55:10 +0200
Subject: [PATCH 12/32] migratentp: Don't raise StopActorExecutionError
When a service cannot be enabled (e.g. due to masking) or when
ntp2chrony fails, log an error message instead of failing the migration.
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2089514
---
.../actors/migratentp/libraries/migratentp.py | 22 ++++++++++---------
.../migratentp/tests/unit_test_migratentp.py | 2 +-
2 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/repos/system_upgrade/el7toel8/actors/migratentp/libraries/migratentp.py b/repos/system_upgrade/el7toel8/actors/migratentp/libraries/migratentp.py
index 1bc59448..306ce09e 100644
--- a/repos/system_upgrade/el7toel8/actors/migratentp/libraries/migratentp.py
+++ b/repos/system_upgrade/el7toel8/actors/migratentp/libraries/migratentp.py
@@ -2,7 +2,6 @@ import base64
import io
import tarfile
-from leapp.exceptions import StopActorExecutionError
from leapp.libraries.stdlib import api, CalledProcessError, run
@@ -17,7 +16,7 @@ def enable_service(name):
try:
run(['systemctl', 'enable', '{}.service'.format(name)])
except CalledProcessError:
- raise StopActorExecutionError('Could not enable {} service'.format(name))
+ api.current_logger().error('Could not enable {} service'.format(name))
def write_file(name, content):
@@ -34,11 +33,12 @@ def ntp2chrony(root, ntp_conf, step_tickers):
ntp_configuration.write_chrony_configuration('/etc/chrony.conf', '/etc/chrony.keys',
False, True)
except OSError as e:
- raise StopActorExecutionError('ntp2chrony failed: {}'.format(e))
+ api.current_logger().error('ntp2chrony failed: {}'.format(e))
+ return False, set()
# Return ignored lines from ntp.conf, except 'disable monitor' from
# the default ntp.conf
- return set(ntp_configuration.ignored_lines) - set(['disable monitor'])
+ return True, set(ntp_configuration.ignored_lines) - set(['disable monitor'])
def migrate_ntp(migrate_services, config_tgz64):
@@ -61,7 +61,8 @@ def migrate_ntp(migrate_services, config_tgz64):
migrate_configs = []
for service in migrate_services:
if service not in service_map:
- raise StopActorExecutionError('Unknown service {}'.format(service))
+ api.current_logger().error('Unknown service {}'.format(service))
+ continue
enable_service(service_map[service][0])
if service_map[service][1]:
migrate_configs.append(service)
@@ -77,9 +78,10 @@ def migrate_ntp(migrate_services, config_tgz64):
step_tickers = '/etc/ntp/step-tickers' if 'ntpdate' in migrate_configs else ''
- ignored_lines = ntp2chrony('/', ntp_conf, step_tickers)
+ conf_migrated, ignored_lines = ntp2chrony('/', ntp_conf, step_tickers)
- api.current_logger().info('Configuration files migrated to chrony: {}'.format(' '.join(migrate_configs)))
- if ignored_lines:
- api.current_logger().warning('Some lines in /etc/ntp.conf were ignored in migration'
- ' (check /etc/chrony.conf)')
+ if conf_migrated:
+ api.current_logger().info('Configuration files migrated to chrony: {}'.format(' '.join(migrate_configs)))
+ if ignored_lines:
+ api.current_logger().warning('Some lines in /etc/ntp.conf were ignored in migration'
+ ' (check /etc/chrony.conf)')
diff --git a/repos/system_upgrade/el7toel8/actors/migratentp/tests/unit_test_migratentp.py b/repos/system_upgrade/el7toel8/actors/migratentp/tests/unit_test_migratentp.py
index fafff5e7..5350029c 100644
--- a/repos/system_upgrade/el7toel8/actors/migratentp/tests/unit_test_migratentp.py
+++ b/repos/system_upgrade/el7toel8/actors/migratentp/tests/unit_test_migratentp.py
@@ -44,7 +44,7 @@ class ntp2chrony_mocked(object):
def __call__(self, *args):
self.called += 1
self.args = args
- return self.ignored_lines * ['a line']
+ return True, self.ignored_lines * ['a line']
def test_migration(monkeypatch):
--
2.38.1

View File

@ -0,0 +1,32 @@
From 7d915f9ce861f999d6fc559e7a466a32c7e4aec9 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Fri, 9 Sep 2022 16:44:27 +0200
Subject: [PATCH 13/32] Make shellcheck happy again
Fixing:
```
85sys-upgrade-redhat/do-upgrade.sh:236:37: warning[SC2166]: Prefer [ p ] && [ q ] as [ p -a q ] is not well defined.
```
It's not a real issue as we do not care about the order of the
evaluation, but making shellcheck happy.
---
.../files/dracut/85sys-upgrade-redhat/do-upgrade.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh b/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh
index 1f39a6b2..ff491316 100755
--- a/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh
+++ b/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh
@@ -233,7 +233,7 @@ do_upgrade() {
# on aarch64 systems during el8 to el9 upgrades the swap is broken due to change in page size (64K to 4k)
# adjust the page size before booting into the new system, as it is possible the swap is necessary for to boot
# `arch` command is not available in the dracut shell, using uname -m instead
- [ "$(uname -m)" = "aarch64" -a "$RHEL_OS_MAJOR_RELEASE" = "9" ] && {
+ [ "$(uname -m)" = "aarch64" ] && [ "$RHEL_OS_MAJOR_RELEASE" = "9" ] && {
cp -aS ".leapp_bp" $NEWROOT/etc/fstab /etc/fstab
# swapon internally uses mkswap and both swapon and mkswap aren't available in dracut shell
# as a workaround we can use the one from $NEWROOT in $NEWROOT/usr/sbin
--
2.38.1

View File

@ -0,0 +1,231 @@
From c109704cb2139dbdba371b83e2f55aad8fb1f9ed Mon Sep 17 00:00:00 2001
From: Eric Garver <egarver@redhat.com>
Date: Wed, 31 Aug 2022 14:24:42 -0400
Subject: [PATCH 14/32] actor: firewalld: support 0.8.z
Prior to this change the actor only supported firewalld-0.9.z and later.
Relevant differences between 0.9.z and 0.8.z:
- Policies don't exist (new in 0.9.0)
- Zones use a tuple based API
Fixes: rhbz2101909
---
...private_firewalldcollectusedobjectnames.py | 31 +++++-
...it_test_firewalldcollectusedobjectnames.py | 105 +++++++++++++++++-
2 files changed, 129 insertions(+), 7 deletions(-)
diff --git a/repos/system_upgrade/el8toel9/actors/firewalldcollectusedobjectnames/libraries/private_firewalldcollectusedobjectnames.py b/repos/system_upgrade/el8toel9/actors/firewalldcollectusedobjectnames/libraries/private_firewalldcollectusedobjectnames.py
index 93e4c6a2..d93b980b 100644
--- a/repos/system_upgrade/el8toel9/actors/firewalldcollectusedobjectnames/libraries/private_firewalldcollectusedobjectnames.py
+++ b/repos/system_upgrade/el8toel9/actors/firewalldcollectusedobjectnames/libraries/private_firewalldcollectusedobjectnames.py
@@ -14,6 +14,13 @@ def is_zone_in_use(conf):
return False
+def is_zone_in_use_tuple(conf):
+ conf_dict = {'interfaces': conf[10],
+ 'sources': conf[11]}
+
+ return is_zone_in_use(conf_dict)
+
+
def is_policy_in_use(conf, used_zones):
# A policy is in use if both ingress_zones and egress_zones contain at
# least one of following: an active zone, 'ANY', 'HOST'.
@@ -49,6 +56,18 @@ def get_used_services(conf, isZone):
return used_services
+def get_used_services_tuple(conf, isZone):
+ if not isZone:
+ return set()
+
+ conf_dict = {'services': conf[5],
+ 'interfaces': conf[10],
+ 'sources': conf[11],
+ 'rules_str': conf[12]}
+
+ return get_used_services(conf_dict, isZone)
+
+
def read_config():
try:
fw = Firewall(offline=True)
@@ -65,12 +84,12 @@ def read_config():
used_zones = set([fw.get_default_zone()])
for zone in fw.config.get_zones():
obj = fw.config.get_zone(zone)
- conf = fw.config.get_zone_config_dict(obj)
- if is_zone_in_use(conf):
+ conf = fw.config.get_zone_config(obj)
+ if is_zone_in_use_tuple(conf):
used_zones.add(zone)
used_policies = []
- for policy in fw.config.get_policy_objects():
+ for policy in fw.config.get_policy_objects() if hasattr(fw.config, "get_policy_objects") else []:
obj = fw.config.get_policy_object(policy)
conf = fw.config.get_policy_object_config_dict(obj)
if is_policy_in_use(conf, used_zones):
@@ -79,9 +98,9 @@ def read_config():
used_services = set()
for zone in fw.config.get_zones():
obj = fw.config.get_zone(zone)
- conf = fw.config.get_zone_config_dict(obj)
- used_services.update(get_used_services(conf, True))
- for policy in fw.config.get_policy_objects():
+ conf = fw.config.get_zone_config(obj)
+ used_services.update(get_used_services_tuple(conf, True))
+ for policy in fw.config.get_policy_objects() if hasattr(fw.config, "get_policy_objects") else []:
obj = fw.config.get_policy_object(policy)
conf = fw.config.get_policy_object_config_dict(obj)
used_services.update(get_used_services(conf, False))
diff --git a/repos/system_upgrade/el8toel9/actors/firewalldcollectusedobjectnames/tests/unit_test_firewalldcollectusedobjectnames.py b/repos/system_upgrade/el8toel9/actors/firewalldcollectusedobjectnames/tests/unit_test_firewalldcollectusedobjectnames.py
index 6e1511eb..9d2cfb47 100644
--- a/repos/system_upgrade/el8toel9/actors/firewalldcollectusedobjectnames/tests/unit_test_firewalldcollectusedobjectnames.py
+++ b/repos/system_upgrade/el8toel9/actors/firewalldcollectusedobjectnames/tests/unit_test_firewalldcollectusedobjectnames.py
@@ -1,7 +1,9 @@
from leapp.libraries.actor.private_firewalldcollectusedobjectnames import (
get_used_services,
+ get_used_services_tuple,
is_policy_in_use,
- is_zone_in_use
+ is_zone_in_use,
+ is_zone_in_use_tuple
)
@@ -20,6 +22,35 @@ def test_is_zone_in_use():
assert is_zone_in_use(conf)
+def test_is_zone_in_use_tuple():
+ conf = (None, None, None, None, None,
+ ['tftp-client'], # conf[5], services
+ None, None, None, None,
+ ['dummy0'], # conf[10], interfaces
+ [], # conf[11], sources
+ [], # conf[12], rules_str
+ None, None, None)
+ assert is_zone_in_use_tuple(conf)
+
+ conf = (None, None, None, None, None,
+ ['tftp-client'], # conf[5], services
+ None, None, None, None,
+ [], # conf[10], interfaces
+ ['10.1.2.0/24'], # conf[11], sources
+ [], # conf[12], rules_str
+ None, None, None)
+ assert is_zone_in_use_tuple(conf)
+
+ conf = (None, None, None, None, None,
+ ['tftp-client'], # conf[5], services
+ None, None, None, None,
+ ['dummy0'], # conf[10], interfaces
+ ['fd00::/8'], # conf[11], sources
+ [], # conf[12], rules_str
+ None, None, None)
+ assert is_zone_in_use_tuple(conf)
+
+
def test_is_zone_in_use_negative():
conf = {'interfaces': [],
'services': ['tftp-client']}
@@ -33,6 +64,17 @@ def test_is_zone_in_use_negative():
assert not is_zone_in_use(conf)
+def test_is_zone_in_use_tuple_negative():
+ conf = (None, None, None, None, None,
+ ['tftp-client'], # conf[5], services
+ None, None, None, None,
+ [], # conf[10], interfaces
+ [], # conf[11], sources
+ [], # conf[12], rules_str
+ None, None, None)
+ assert not is_zone_in_use_tuple(conf)
+
+
def test_is_policy_in_use():
conf = {'ingress_zones': ['HOST'],
'egress_zones': ['public'],
@@ -88,6 +130,35 @@ def test_get_used_services_zone():
assert 'tftp-client' in get_used_services(conf, True)
+def test_get_used_services_tuple_zone():
+ conf = (None, None, None, None, None,
+ ['tftp-client'], # conf[5], services
+ None, None, None, None,
+ ['dummy0'], # conf[10], interfaces
+ [], # conf[11], sources
+ [], # conf[12], rules_str
+ None, None, None)
+ assert 'tftp-client' in get_used_services_tuple(conf, True)
+
+ conf = (None, None, None, None, None,
+ [], # conf[5], services
+ None, None, None, None,
+ [], # conf[10], interfaces
+ ['10.1.2.0/24'], # conf[11], sources
+ ['rule family="ipv4" source address="10.1.1.0/24" service name="tftp-client" reject'],
+ None, None, None)
+ assert 'tftp-client' in get_used_services_tuple(conf, True)
+
+ conf = (None, None, None, None, None,
+ [], # conf[5], services
+ None, None, None, None,
+ ['dummy0'], # conf[10], interfaces
+ ['fd00::/8'], # conf[11], sources
+ ['rule service name="ssh" accept', 'rule service name="tftp-client" accept'], # conf[12], rules_str
+ None, None, None)
+ assert 'tftp-client' in get_used_services_tuple(conf, True)
+
+
def test_get_used_services_zone_negative():
conf = {'interfaces': ['dummy0'],
'services': ['https']}
@@ -105,6 +176,38 @@ def test_get_used_services_zone_negative():
assert 'tftp-client' not in get_used_services(conf, True)
+def test_get_used_services_tuple_zone_negative():
+ conf = (None, None, None, None, None,
+ ['https'], # conf[5], services
+ None, None, None, None,
+ ['dummy0'], # conf[10], interfaces
+ [], # conf[11], sources
+ [], # conf[12], rules_str
+ None, None, None)
+ assert 'tftp-client' not in get_used_services_tuple(conf, True)
+
+ conf = {'sources': ['10.1.2.0/24'],
+ 'rules_str': ['rule family="ipv4" source address="10.1.1.0/24" service name="ssh" reject'],
+ 'services': ['https']}
+ conf = (None, None, None, None, None,
+ ['https'], # conf[5], services
+ None, None, None, None,
+ [], # conf[10], interfaces
+ ['10.1.2.0/24'], # conf[11], sources
+ ['rule family="ipv4" source address="10.1.1.0/24" service name="ssh" reject'], # conf[12], rules_str
+ None, None, None)
+ assert 'tftp-client' not in get_used_services_tuple(conf, True)
+
+ conf = (None, None, None, None, None,
+ [], # conf[5], services
+ None, None, None, None,
+ ['dummy0'], # conf[10], interfaces
+ ['fd00::/8'], # conf[11], sources
+ ['rule service name="ssh" accept', 'rule service name="http" accept'], # conf[12], rules_str
+ None, None, None)
+ assert 'tftp-client' not in get_used_services_tuple(conf, True)
+
+
def test_get_used_services_policy():
conf = {'services': ['tftp-client']}
assert 'tftp-client' in get_used_services(conf, False)
--
2.38.1

View File

@ -0,0 +1,257 @@
From 876e93f233c41aa6c1742ed874ac167f0ddc4dbb Mon Sep 17 00:00:00 2001
From: PeterMocary <petermocary@gmail.com>
Date: Fri, 24 Jun 2022 15:23:30 +0200
Subject: [PATCH 15/32] Scanpkgmanager: detect proxy configuration
This new information enables targetuserspacecreator actor to inform user why the package installation might have failed
---
.../libraries/scanpkgmanager.py | 53 ++++++++++++++++++-
.../tests/test_scanpkgmanager.py | 49 +++++++++++++++++
.../actors/targetuserspacecreator/actor.py | 4 ++
.../libraries/userspacegen.py | 24 +++++++--
.../common/models/packagemanagerinfo.py | 5 ++
.../common/models/repositoriesfacts.py | 1 +
6 files changed, 131 insertions(+), 5 deletions(-)
diff --git a/repos/system_upgrade/common/actors/scanpkgmanager/libraries/scanpkgmanager.py b/repos/system_upgrade/common/actors/scanpkgmanager/libraries/scanpkgmanager.py
index 6f6a79d2..7c97fb1a 100644
--- a/repos/system_upgrade/common/actors/scanpkgmanager/libraries/scanpkgmanager.py
+++ b/repos/system_upgrade/common/actors/scanpkgmanager/libraries/scanpkgmanager.py
@@ -1,9 +1,13 @@
import os
+import re
from leapp.libraries.common.config.version import get_source_major_version
from leapp.libraries.stdlib import api
from leapp.models import PkgManagerInfo
+YUM_CONFIG_PATH = '/etc/yum.conf'
+DNF_CONFIG_PATH = '/etc/dnf/dnf.conf'
+
def _get_releasever_path():
default_manager = 'yum' if get_source_major_version() == '7' else 'dnf'
@@ -28,5 +32,52 @@ def get_etc_releasever():
return releasever
+def _get_config_contents(config_path):
+ if os.path.isfile(config_path):
+ with open(config_path, 'r') as config:
+ return config.read()
+ return ''
+
+
+def _get_proxy_if_set(manager_config_path):
+ """
+ Get proxy address from specified package manager config.
+
+ :param manager_config_path: path to a package manager config
+ :returns: proxy address or None when not set
+ :rtype: String
+ """
+
+ config = _get_config_contents(manager_config_path)
+
+ for line in config.split('\n'):
+ if re.match('^proxy[ \t]*=', line):
+ proxy_address = line.split('=', 1)[1]
+ return proxy_address.strip()
+
+ return None
+
+
+def get_configured_proxies():
+ """
+ Get a list of proxies used in dnf and yum configuration files.
+
+ :returns: sorted list of unique proxies
+ :rtype: List
+ """
+
+ configured_proxies = set()
+ for config_path in (DNF_CONFIG_PATH, YUM_CONFIG_PATH):
+ proxy = _get_proxy_if_set(config_path)
+ if proxy:
+ configured_proxies.add(proxy)
+
+ return sorted(configured_proxies)
+
+
def process():
- api.produce(PkgManagerInfo(etc_releasever=get_etc_releasever()))
+ pkg_manager_info = PkgManagerInfo()
+ pkg_manager_info.etc_releasever = get_etc_releasever()
+ pkg_manager_info.configured_proxies = get_configured_proxies()
+
+ api.produce(pkg_manager_info)
diff --git a/repos/system_upgrade/common/actors/scanpkgmanager/tests/test_scanpkgmanager.py b/repos/system_upgrade/common/actors/scanpkgmanager/tests/test_scanpkgmanager.py
index 3be6fa2f..e78b532f 100644
--- a/repos/system_upgrade/common/actors/scanpkgmanager/tests/test_scanpkgmanager.py
+++ b/repos/system_upgrade/common/actors/scanpkgmanager/tests/test_scanpkgmanager.py
@@ -9,6 +9,9 @@ from leapp.libraries.common.testutils import CurrentActorMocked, produce_mocked
from leapp.libraries.stdlib import api
CUR_DIR = os.path.dirname(os.path.abspath(__file__))
+PROXY_ADDRESS = 'https://192.168.121.123:3128'
+YUM_CONFIG_PATH = '/etc/yum.conf'
+DNF_CONFIG_PATH = '/etc/dnf/dnf.conf'
def mock_releasever_exists(overrides):
@@ -36,6 +39,8 @@ def test_get_etcreleasever(monkeypatch, etcrelease_exists):
monkeypatch.setattr(scanpkgmanager.api, 'produce', produce_mocked())
monkeypatch.setattr(scanpkgmanager.api, 'current_actor', CurrentActorMocked())
monkeypatch.setattr(scanpkgmanager, '_get_releasever_path', mocked_get_releasever_path)
+ monkeypatch.setattr(scanpkgmanager, '_get_proxy_if_set', lambda x: None)
+ monkeypatch.setattr(pluginscanner, 'scan_enabled_package_manager_plugins', lambda: [])
scanpkgmanager.process()
@@ -44,3 +49,47 @@ def test_get_etcreleasever(monkeypatch, etcrelease_exists):
assert api.produce.model_instances[0].etc_releasever
else:
assert not api.produce.model_instances[0].etc_releasever
+
+
+@pytest.mark.parametrize('proxy_set', [True, False])
+def test_get_proxy_if_set(monkeypatch, proxy_set):
+
+ config_path = '/path/to/config.conf'
+ config_contents = '[main]\n'
+ if proxy_set:
+ config_contents += 'proxy = \t{} '.format(PROXY_ADDRESS)
+
+ def mocked_get_config_contents(path):
+ assert path == config_path
+ return config_contents
+
+ monkeypatch.setattr(scanpkgmanager, '_get_config_contents', mocked_get_config_contents)
+
+ proxy = scanpkgmanager._get_proxy_if_set(config_path)
+
+ if proxy_set:
+ assert proxy == PROXY_ADDRESS
+
+ assert proxy_set == bool(proxy)
+
+
+@pytest.mark.parametrize(
+ ('proxy_set_in_dnf_config', 'proxy_set_in_yum_config', 'expected_output'),
+ [
+ (True, True, [PROXY_ADDRESS]),
+ (True, False, [PROXY_ADDRESS]),
+ (False, False, [])
+ ]
+)
+def test_get_configured_proxies(monkeypatch, proxy_set_in_dnf_config, proxy_set_in_yum_config, expected_output):
+
+ def mocked_get_proxy_if_set(path):
+ proxy = PROXY_ADDRESS if proxy_set_in_yum_config else None
+ if path == DNF_CONFIG_PATH:
+ proxy = PROXY_ADDRESS if proxy_set_in_dnf_config else None
+ return proxy
+
+ monkeypatch.setattr(scanpkgmanager, '_get_proxy_if_set', mocked_get_proxy_if_set)
+
+ configured_proxies = scanpkgmanager.get_configured_proxies()
+ assert configured_proxies == expected_output
diff --git a/repos/system_upgrade/common/actors/targetuserspacecreator/actor.py b/repos/system_upgrade/common/actors/targetuserspacecreator/actor.py
index 7e5c7db7..04fb2e8b 100644
--- a/repos/system_upgrade/common/actors/targetuserspacecreator/actor.py
+++ b/repos/system_upgrade/common/actors/targetuserspacecreator/actor.py
@@ -5,7 +5,9 @@ from leapp.models import RequiredTargetUserspacePackages # deprecated
from leapp.models import TMPTargetRepositoriesFacts # deprecated all the time
from leapp.models import (
CustomTargetRepositoryFile,
+ PkgManagerInfo,
Report,
+ RepositoriesFacts,
RepositoriesMapping,
RHSMInfo,
RHUIInfo,
@@ -36,12 +38,14 @@ class TargetUserspaceCreator(Actor):
CustomTargetRepositoryFile,
RHSMInfo,
RHUIInfo,
+ RepositoriesFacts,
RepositoriesMapping,
RequiredTargetUserspacePackages,
StorageInfo,
TargetRepositories,
TargetUserSpacePreupgradeTasks,
XFSPresence,
+ PkgManagerInfo,
)
produces = (TargetUserSpaceInfo, UsedTargetRepositories, Report, TMPTargetRepositoriesFacts,)
tags = (IPUWorkflowTag, TargetTransactionFactsPhaseTag)
diff --git a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
index c39af66f..00acacd9 100644
--- a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
+++ b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
@@ -12,6 +12,8 @@ from leapp.models import RequiredTargetUserspacePackages # deprecated
from leapp.models import TMPTargetRepositoriesFacts # deprecated
from leapp.models import (
CustomTargetRepositoryFile,
+ PkgManagerInfo,
+ RepositoriesFacts,
RHSMInfo,
RHUIInfo,
StorageInfo,
@@ -166,10 +168,24 @@ def prepare_target_userspace(context, userspace_dir, enabled_repos, packages):
try:
context.call(cmd, callback_raw=utils.logging_handler)
except CalledProcessError as exc:
- raise StopActorExecutionError(
- message='Unable to install RHEL {} userspace packages.'.format(target_major_version),
- details={'details': str(exc), 'stderr': exc.stderr}
- )
+ message = 'Unable to install RHEL {} userspace packages.'.format(target_major_version)
+ details = {'details': str(exc), 'stderr': exc.stderr}
+
+ # If a proxy was set in dnf config, it should be the reason why dnf
+ # failed since leapp does not support updates behind proxy yet.
+ for manager_info in api.consume(PkgManagerInfo):
+ if manager_info.configured_proxies:
+ details['details'] = ("DNF failed to install userspace packages, likely due to the proxy "
+ "configuration detected in the YUM/DNF configuration file.")
+
+ # Similarly if a proxy was set specifically for one of the repositories.
+ for repo_facts in api.consume(RepositoriesFacts):
+ for repo_file in repo_facts.repositories:
+ if any(repo_data.proxy and repo_data.enabled for repo_data in repo_file.data):
+ details['details'] = ("DNF failed to install userspace packages, likely due to the proxy "
+ "configuration detected in a repository configuration file.")
+
+ raise StopActorExecutionError(message=message, details=details)
def _get_all_rhui_pkgs():
diff --git a/repos/system_upgrade/common/models/packagemanagerinfo.py b/repos/system_upgrade/common/models/packagemanagerinfo.py
index ba6391c3..aa450978 100644
--- a/repos/system_upgrade/common/models/packagemanagerinfo.py
+++ b/repos/system_upgrade/common/models/packagemanagerinfo.py
@@ -17,3 +17,8 @@ class PkgManagerInfo(Model):
In case the value is empty string, it means the file exists but it is empty. In such a case the
original configuration is obviously broken.
"""
+
+ configured_proxies = fields.List(fields.String(), default=[])
+ """
+ A sorted list of proxies present in yum and dnf configuration files.
+ """
diff --git a/repos/system_upgrade/common/models/repositoriesfacts.py b/repos/system_upgrade/common/models/repositoriesfacts.py
index 722c579f..cd2124fc 100644
--- a/repos/system_upgrade/common/models/repositoriesfacts.py
+++ b/repos/system_upgrade/common/models/repositoriesfacts.py
@@ -13,6 +13,7 @@ class RepositoryData(Model):
mirrorlist = fields.Nullable(fields.String())
enabled = fields.Boolean(default=True)
additional_fields = fields.Nullable(fields.String())
+ proxy = fields.Nullable(fields.String())
class RepositoryFile(Model):
--
2.38.1

View File

@ -0,0 +1,380 @@
From b4c3de448324a35da8b92905c04cc169430cf4a0 Mon Sep 17 00:00:00 2001
From: PeterMocary <petermocary@gmail.com>
Date: Sun, 26 Jun 2022 13:56:24 +0200
Subject: [PATCH 16/32] Merge of the yumconfigscanner actor into the
scanpkgmanager actor
---
.../actors/checkyumpluginsenabled/actor.py | 8 ++--
.../libraries/checkyumpluginsenabled.py | 6 +--
.../tests/test_checkyumpluginsenabled.py | 6 +--
.../libraries/pluginscanner.py} | 48 +++++++------------
.../libraries/scanpkgmanager.py | 6 ++-
.../tests/test_pluginscanner.py} | 26 +++++-----
.../tests/test_scanpkgmanager.py | 2 +-
.../common/actors/yumconfigscanner/actor.py | 18 -------
.../common/models/packagemanagerinfo.py | 2 +
.../system_upgrade/common/models/yumconfig.py | 8 ----
10 files changed, 48 insertions(+), 82 deletions(-)
rename repos/system_upgrade/common/actors/{yumconfigscanner/libraries/yumconfigscanner.py => scanpkgmanager/libraries/pluginscanner.py} (56%)
rename repos/system_upgrade/common/actors/{yumconfigscanner/tests/test_yumconfigscanner.py => scanpkgmanager/tests/test_pluginscanner.py} (74%)
delete mode 100644 repos/system_upgrade/common/actors/yumconfigscanner/actor.py
delete mode 100644 repos/system_upgrade/common/models/yumconfig.py
diff --git a/repos/system_upgrade/common/actors/checkyumpluginsenabled/actor.py b/repos/system_upgrade/common/actors/checkyumpluginsenabled/actor.py
index c6872fa7..fbc2f8bc 100644
--- a/repos/system_upgrade/common/actors/checkyumpluginsenabled/actor.py
+++ b/repos/system_upgrade/common/actors/checkyumpluginsenabled/actor.py
@@ -1,6 +1,6 @@
from leapp.actors import Actor
from leapp.libraries.actor.checkyumpluginsenabled import check_required_yum_plugins_enabled
-from leapp.models import YumConfig
+from leapp.models import PkgManagerInfo
from leapp.reporting import Report
from leapp.tags import ChecksPhaseTag, IPUWorkflowTag
@@ -11,10 +11,10 @@ class CheckYumPluginsEnabled(Actor):
"""
name = 'check_yum_plugins_enabled'
- consumes = (YumConfig,)
+ consumes = (PkgManagerInfo,)
produces = (Report,)
tags = (ChecksPhaseTag, IPUWorkflowTag)
def process(self):
- yum_config = next(self.consume(YumConfig))
- check_required_yum_plugins_enabled(yum_config)
+ pkg_manager_info = next(self.consume(PkgManagerInfo))
+ check_required_yum_plugins_enabled(pkg_manager_info)
diff --git a/repos/system_upgrade/common/actors/checkyumpluginsenabled/libraries/checkyumpluginsenabled.py b/repos/system_upgrade/common/actors/checkyumpluginsenabled/libraries/checkyumpluginsenabled.py
index 7c7398df..48f38d0a 100644
--- a/repos/system_upgrade/common/actors/checkyumpluginsenabled/libraries/checkyumpluginsenabled.py
+++ b/repos/system_upgrade/common/actors/checkyumpluginsenabled/libraries/checkyumpluginsenabled.py
@@ -10,16 +10,16 @@ REQUIRED_YUM_PLUGINS = {'subscription-manager', 'product-id'}
FMT_LIST_SEPARATOR = '\n - '
-def check_required_yum_plugins_enabled(yum_config):
+def check_required_yum_plugins_enabled(pkg_manager_info):
"""
Checks whether the yum plugins required by the IPU are enabled.
If they are not enabled, a report is produced informing the user about it.
- :param yum_config: YumConfig
+ :param pkg_manager_info: PkgManagerInfo
"""
- missing_required_plugins = REQUIRED_YUM_PLUGINS - set(yum_config.enabled_plugins)
+ missing_required_plugins = REQUIRED_YUM_PLUGINS - set(pkg_manager_info.enabled_plugins)
if skip_rhsm():
missing_required_plugins -= {'subscription-manager', 'product-id'}
diff --git a/repos/system_upgrade/common/actors/checkyumpluginsenabled/tests/test_checkyumpluginsenabled.py b/repos/system_upgrade/common/actors/checkyumpluginsenabled/tests/test_checkyumpluginsenabled.py
index 896d31d5..9bf9a3ba 100644
--- a/repos/system_upgrade/common/actors/checkyumpluginsenabled/tests/test_checkyumpluginsenabled.py
+++ b/repos/system_upgrade/common/actors/checkyumpluginsenabled/tests/test_checkyumpluginsenabled.py
@@ -4,7 +4,7 @@ from leapp import reporting
from leapp.libraries.actor.checkyumpluginsenabled import check_required_yum_plugins_enabled
from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked
from leapp.libraries.stdlib import api
-from leapp.models import YumConfig
+from leapp.models import PkgManagerInfo
from leapp.utils.report import is_inhibitor
@@ -38,7 +38,7 @@ def test__create_report_mocked(monkeypatch):
def test_report_when_missing_required_plugins(monkeypatch):
"""Test whether a report entry is created when any of the required YUM plugins are missing."""
- yum_config = YumConfig(enabled_plugins=['product-id', 'some-user-plugin'])
+ yum_config = PkgManagerInfo(enabled_plugins=['product-id', 'some-user-plugin'])
actor_reports = create_report_mocked()
@@ -62,7 +62,7 @@ def test_nothing_is_reported_when_rhsm_disabled(monkeypatch):
monkeypatch.setattr(api, 'current_actor', actor_mocked)
monkeypatch.setattr(reporting, 'create_report', create_report_mocked())
- yum_config = YumConfig(enabled_plugins=[])
+ yum_config = PkgManagerInfo(enabled_plugins=[])
check_required_yum_plugins_enabled(yum_config)
assert not reporting.create_report.called, 'Report was created even if LEAPP_NO_RHSM was set'
diff --git a/repos/system_upgrade/common/actors/yumconfigscanner/libraries/yumconfigscanner.py b/repos/system_upgrade/common/actors/scanpkgmanager/libraries/pluginscanner.py
similarity index 56%
rename from repos/system_upgrade/common/actors/yumconfigscanner/libraries/yumconfigscanner.py
rename to repos/system_upgrade/common/actors/scanpkgmanager/libraries/pluginscanner.py
index 0b7d5fe6..7bb03996 100644
--- a/repos/system_upgrade/common/actors/yumconfigscanner/libraries/yumconfigscanner.py
+++ b/repos/system_upgrade/common/actors/scanpkgmanager/libraries/pluginscanner.py
@@ -1,26 +1,25 @@
import re
from leapp.libraries.common.config.version import get_source_major_version
-from leapp.libraries.stdlib import api, run
-from leapp.models import YumConfig
+from leapp.libraries.stdlib import run
# When the output spans multiple lines, each of the lines after the first one
# start with a ' <SPACES> : '
-YUM_LOADED_PLUGINS_NEXT_LINE_START = ' +: '
+LOADED_PLUGINS_NEXT_LINE_START = ' +: '
-def _parse_loaded_plugins(yum_output):
+def _parse_loaded_plugins(package_manager_output):
"""
- Retrieves a list of plugins that are being loaded when calling yum.
+ Retrieves a list of plugins that are being loaded when calling dnf/yum.
- :param dict yum_output: The result of running the yum command.
+ :param dict package_manager_output: The result of running the package manager command.
:rtype: list
- :returns: A list of plugins that are being loaded when calling yum.
+ :returns: A list of plugins that are being loaded by the package manager.
"""
- # YUM might break the information about loaded plugins into multiple lines,
+ # Package manager might break the information about loaded plugins into multiple lines,
# we need to concaternate the list ourselves
loaded_plugins_str = ''
- for line in yum_output['stdout']:
+ for line in package_manager_output['stdout']:
if line.startswith('Loaded plugins:'):
# We have found the first line that contains the plugins
plugins_on_this_line = line[16:] # Remove the `Loaded plugins: ` part
@@ -32,7 +31,7 @@ def _parse_loaded_plugins(yum_output):
continue
if loaded_plugins_str:
- if re.match(YUM_LOADED_PLUGINS_NEXT_LINE_START, line):
+ if re.match(LOADED_PLUGINS_NEXT_LINE_START, line):
# The list of plugins continues on this line
plugins_on_this_line = line.lstrip(' :') # Remove the leading spaces and semicolon
@@ -49,39 +48,28 @@ def _parse_loaded_plugins(yum_output):
return loaded_plugins_str.split(', ')
-def scan_enabled_yum_plugins():
+def scan_enabled_package_manager_plugins():
"""
- Runs the `yum` command and parses its output for enabled/loaded plugins.
+ Runs package manager (yum/dnf) command and parses its output for enabled/loaded plugins.
:return: A list of enabled plugins.
:rtype: List
"""
- # We rely on yum itself to report what plugins are used when it is invoked.
- # An alternative approach would be to check /usr/lib/yum-plugins/ (install
- # path for yum plugins) and parse corresponding configurations from
- # /etc/yum/pluginconf.d/
+ # We rely on package manager itself to report what plugins are used when it is invoked.
+ # An alternative approach would be to check the install path for package manager plugins
+ # and parse corresponding plugin configuration files.
if get_source_major_version() == '7':
# in case of yum, set debuglevel=2 to be sure the output is always
# same. The format of data is different for various debuglevels
- yum_cmd = ['yum', '--setopt=debuglevel=2']
+ cmd = ['yum', '--setopt=debuglevel=2']
else:
# the verbose mode in dnf always set particular debuglevel, so the
# output is not affected by the default debug level set on the
# system
- yum_cmd = ['dnf', '-v'] # On RHEL8 we need to supply an extra switch
+ cmd = ['dnf', '-v'] # On RHEL8 we need to supply an extra switch
- yum_output = run(yum_cmd, split=True, checked=False) # The yum command will certainly fail (does not matter).
+ pkg_manager_output = run(cmd, split=True, checked=False) # The command will certainly fail (does not matter).
- return _parse_loaded_plugins(yum_output)
-
-
-def scan_yum_config():
- """
- Scans the YUM configuration and produces :class:`YumConfig` message with the information found.
- """
- config = YumConfig()
- config.enabled_plugins = scan_enabled_yum_plugins()
-
- api.produce(config)
+ return _parse_loaded_plugins(pkg_manager_output)
diff --git a/repos/system_upgrade/common/actors/scanpkgmanager/libraries/scanpkgmanager.py b/repos/system_upgrade/common/actors/scanpkgmanager/libraries/scanpkgmanager.py
index 7c97fb1a..bf7ec0be 100644
--- a/repos/system_upgrade/common/actors/scanpkgmanager/libraries/scanpkgmanager.py
+++ b/repos/system_upgrade/common/actors/scanpkgmanager/libraries/scanpkgmanager.py
@@ -1,6 +1,7 @@
import os
import re
+from leapp.libraries.actor import pluginscanner
from leapp.libraries.common.config.version import get_source_major_version
from leapp.libraries.stdlib import api
from leapp.models import PkgManagerInfo
@@ -43,9 +44,9 @@ def _get_proxy_if_set(manager_config_path):
"""
Get proxy address from specified package manager config.
- :param manager_config_path: path to a package manager config
+ :param str manager_config_path: path to a package manager config
:returns: proxy address or None when not set
- :rtype: String
+ :rtype: str
"""
config = _get_config_contents(manager_config_path)
@@ -79,5 +80,6 @@ def process():
pkg_manager_info = PkgManagerInfo()
pkg_manager_info.etc_releasever = get_etc_releasever()
pkg_manager_info.configured_proxies = get_configured_proxies()
+ pkg_manager_info.enabled_plugins = pluginscanner.scan_enabled_package_manager_plugins()
api.produce(pkg_manager_info)
diff --git a/repos/system_upgrade/common/actors/yumconfigscanner/tests/test_yumconfigscanner.py b/repos/system_upgrade/common/actors/scanpkgmanager/tests/test_pluginscanner.py
similarity index 74%
rename from repos/system_upgrade/common/actors/yumconfigscanner/tests/test_yumconfigscanner.py
rename to repos/system_upgrade/common/actors/scanpkgmanager/tests/test_pluginscanner.py
index 8406ef00..f0260e54 100644
--- a/repos/system_upgrade/common/actors/yumconfigscanner/tests/test_yumconfigscanner.py
+++ b/repos/system_upgrade/common/actors/scanpkgmanager/tests/test_pluginscanner.py
@@ -1,6 +1,6 @@
import pytest
-from leapp.libraries.actor import yumconfigscanner
+from leapp.libraries.actor import pluginscanner
CMD_YUM_OUTPUT = '''Loaded plugins: langpacks, my plugin, subscription-manager, product-id
Usage: yum [options] COMMAND
@@ -16,23 +16,23 @@ Usage: yum [options] COMMAND
def assert_plugins_identified_as_enabled(expected_plugins, identified_plugins):
- fail_description = 'Failed to parse a plugin from the yum output.'
+ fail_description = 'Failed to parse a plugin from the package manager output.'
for expected_enabled_plugin in expected_plugins:
assert expected_enabled_plugin in identified_plugins, fail_description
@pytest.mark.parametrize(
- ('source_major_version', 'yum_command'),
+ ('source_major_version', 'command'),
[
('7', ['yum', '--setopt=debuglevel=2']),
('8', ['dnf', '-v']),
]
)
-def test_scan_enabled_plugins(monkeypatch, source_major_version, yum_command):
- """Tests whether the enabled plugins are correctly retrieved from the yum output."""
+def test_scan_enabled_plugins(monkeypatch, source_major_version, command):
+ """Tests whether the enabled plugins are correctly retrieved from the package manager output."""
def run_mocked(cmd, **kwargs):
- if cmd == yum_command:
+ if cmd == command:
return {
'stdout': CMD_YUM_OUTPUT.split('\n'),
'stderr': 'You need to give some command',
@@ -45,10 +45,10 @@ def test_scan_enabled_plugins(monkeypatch, source_major_version, yum_command):
# The library imports `run` all the way into its namespace (from ...stdlib import run),
# we must overwrite it there then:
- monkeypatch.setattr(yumconfigscanner, 'run', run_mocked)
- monkeypatch.setattr(yumconfigscanner, 'get_source_major_version', get_source_major_version_mocked)
+ monkeypatch.setattr(pluginscanner, 'run', run_mocked)
+ monkeypatch.setattr(pluginscanner, 'get_source_major_version', get_source_major_version_mocked)
- enabled_plugins = yumconfigscanner.scan_enabled_yum_plugins()
+ enabled_plugins = pluginscanner.scan_enabled_package_manager_plugins()
assert_plugins_identified_as_enabled(
['langpacks', 'my plugin', 'subscription-manager', 'product-id'],
enabled_plugins
@@ -63,7 +63,7 @@ def test_scan_enabled_plugins(monkeypatch, source_major_version, yum_command):
(CMD_YUM_OUTPUT_MULTILINE_BREAK_ON_WHITESPACE,)
])
def test_yum_loaded_plugins_multiline_output(yum_output, monkeypatch):
- """Tests whether the library correctly handles yum plugins getting reported on multiple lines."""
+ """Tests whether the library correctly handles plugins getting reported on multiple lines."""
def run_mocked(cmd, **kwargs):
return {
'stdout': yum_output.split('\n'),
@@ -71,10 +71,10 @@ def test_yum_loaded_plugins_multiline_output(yum_output, monkeypatch):
'exit_code': 1
}
- monkeypatch.setattr(yumconfigscanner, 'run', run_mocked)
- monkeypatch.setattr(yumconfigscanner, 'get_source_major_version', lambda: '7')
+ monkeypatch.setattr(pluginscanner, 'run', run_mocked)
+ monkeypatch.setattr(pluginscanner, 'get_source_major_version', lambda: '7')
- enabled_plugins = yumconfigscanner.scan_enabled_yum_plugins()
+ enabled_plugins = pluginscanner.scan_enabled_package_manager_plugins()
assert len(enabled_plugins) == 4, 'Identified more yum plugins than available in the mocked yum output.'
assert_plugins_identified_as_enabled(
diff --git a/repos/system_upgrade/common/actors/scanpkgmanager/tests/test_scanpkgmanager.py b/repos/system_upgrade/common/actors/scanpkgmanager/tests/test_scanpkgmanager.py
index e78b532f..75c5c5ba 100644
--- a/repos/system_upgrade/common/actors/scanpkgmanager/tests/test_scanpkgmanager.py
+++ b/repos/system_upgrade/common/actors/scanpkgmanager/tests/test_scanpkgmanager.py
@@ -3,7 +3,7 @@ import os
import pytest
from leapp.libraries import stdlib
-from leapp.libraries.actor import scanpkgmanager
+from leapp.libraries.actor import pluginscanner, scanpkgmanager
from leapp.libraries.common import testutils
from leapp.libraries.common.testutils import CurrentActorMocked, produce_mocked
from leapp.libraries.stdlib import api
diff --git a/repos/system_upgrade/common/actors/yumconfigscanner/actor.py b/repos/system_upgrade/common/actors/yumconfigscanner/actor.py
deleted file mode 100644
index 95aee415..00000000
--- a/repos/system_upgrade/common/actors/yumconfigscanner/actor.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from leapp.actors import Actor
-from leapp.libraries.actor.yumconfigscanner import scan_yum_config
-from leapp.models import YumConfig
-from leapp.tags import ChecksPhaseTag, IPUWorkflowTag
-
-
-class YumConfigScanner(Actor):
- """
- Scans the configuration of the YUM package manager.
- """
-
- name = 'yum_config_scanner'
- consumes = ()
- produces = (YumConfig,)
- tags = (IPUWorkflowTag, ChecksPhaseTag)
-
- def process(self):
- scan_yum_config()
diff --git a/repos/system_upgrade/common/models/packagemanagerinfo.py b/repos/system_upgrade/common/models/packagemanagerinfo.py
index aa450978..bf969338 100644
--- a/repos/system_upgrade/common/models/packagemanagerinfo.py
+++ b/repos/system_upgrade/common/models/packagemanagerinfo.py
@@ -22,3 +22,5 @@ class PkgManagerInfo(Model):
"""
A sorted list of proxies present in yum and dnf configuration files.
"""
+
+ enabled_plugins = fields.List(fields.String(), default=[])
diff --git a/repos/system_upgrade/common/models/yumconfig.py b/repos/system_upgrade/common/models/yumconfig.py
deleted file mode 100644
index 506ce47e..00000000
--- a/repos/system_upgrade/common/models/yumconfig.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from leapp.models import fields, Model
-from leapp.topics import SystemFactsTopic
-
-
-class YumConfig(Model):
- topic = SystemFactsTopic
-
- enabled_plugins = fields.List(fields.String(), default=[])
--
2.38.1

View File

@ -0,0 +1,30 @@
From 279ebc96c45ab597f9c26903f5b36e2e57ced6fe Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Fri, 30 Sep 2022 11:17:38 +0200
Subject: [PATCH 17/32] firewalldcheckallowzonedrifting: Fix the remediation
cmd
The remediation cmd was incorrect as the cmd is written as string
instead of list, the fix:
['cmd param param'] -> ['cmd', 'paramm', 'param']
JIRA: OAMG-7694
---
.../el8toel9/actors/firewalldcheckallowzonedrifting/actor.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/repos/system_upgrade/el8toel9/actors/firewalldcheckallowzonedrifting/actor.py b/repos/system_upgrade/el8toel9/actors/firewalldcheckallowzonedrifting/actor.py
index 1f2767f5..b7eb5806 100644
--- a/repos/system_upgrade/el8toel9/actors/firewalldcheckallowzonedrifting/actor.py
+++ b/repos/system_upgrade/el8toel9/actors/firewalldcheckallowzonedrifting/actor.py
@@ -46,6 +46,6 @@ class FirewalldCheckAllowZoneDrifting(Actor):
title='Changes in firewalld related to Zone Drifting'),
reporting.Remediation(
hint='Set AllowZoneDrifting=no in /etc/firewalld/firewalld.conf',
- commands=[['sed -i "s/^AllowZoneDrifting=.*/AllowZoneDrifting=no/" '
+ commands=[['sed', '-i', 's/^AllowZoneDrifting=.*/AllowZoneDrifting=no/',
'/etc/firewalld/firewalld.conf']]),
])
--
2.38.1

View File

@ -1,7 +1,7 @@
From 1c6388139695aefb02daa7b5cb13e628f03eab43 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Mon, 17 Oct 2022 12:59:22 +0200
Subject: [PATCH] rhui(azure-sap-apps): consider RHUI client as signed
Subject: [PATCH 18/32] rhui(azure-sap-apps): consider RHUI client as signed
---
.../common/actors/redhatsignedrpmscanner/actor.py | 2 +-
@ -21,5 +21,5 @@ index dd6db7c9..647805cd 100644
rhui.RHUI_CLOUD_MAP[upg_path].get(flavour, {}).get('src_pkg') for flavour in whitelisted_cloud_flavours
}
--
2.37.3
2.38.1

View File

@ -1,7 +1,8 @@
From a2f35c0aa4e00936e58c17a94d4f1507a3287c72 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Mon, 17 Oct 2022 12:59:22 +0200
Subject: [PATCH] rhui(azure-sap-apps): handle EUS SAP Apps content on RHEL8+
Subject: [PATCH 19/32] rhui(azure-sap-apps): handle EUS SAP Apps content on
RHEL8+
---
.../common/actors/cloud/checkrhui/actor.py | 9 ++++++++-
@ -37,5 +38,5 @@ index 822c7535..a56bb1e1 100644
self.produce(RHUIInfo(provider=provider))
self.produce(RequiredTargetUserspacePackages(packages=[info['target_pkg']]))
--
2.37.3
2.38.1

View File

@ -1,7 +1,7 @@
From a06e248faa3b336c09ee6137eee54a1a0256162b Mon Sep 17 00:00:00 2001
From: Vinzenz Feenstra <vfeenstr@redhat.com>
Date: Wed, 19 Oct 2022 21:05:00 +0200
Subject: [PATCH] checksaphana: Move to common
Subject: [PATCH 20/32] checksaphana: Move to common
We need to start handling also el8 to el9 upgrades now.
@ -28,5 +28,5 @@ similarity index 100%
rename from repos/system_upgrade/el7toel8/actors/checksaphana/tests/test_checksaphana.py
rename to repos/system_upgrade/common/actors/checksaphana/tests/test_checksaphana.py
--
2.37.3
2.38.1

View File

@ -1,7 +1,8 @@
From b716765e638156c9a5cb21a474d1203b695acf8d Mon Sep 17 00:00:00 2001
From: Vinzenz Feenstra <vfeenstr@redhat.com>
Date: Wed, 19 Oct 2022 21:42:14 +0200
Subject: [PATCH] checksaphana: Adjust for el7toel8 and el8toel9 requirements
Subject: [PATCH 21/32] checksaphana: Adjust for el7toel8 and el8toel9
requirements
Previously only upgrade from el7toel8 were supported for SAP Hana.
This patch will introduce the adjustments necessary to allow the
@ -104,7 +105,7 @@ index e540ccd1..564d86b8 100644
@@ -134,7 +154,13 @@ def _sp_rev_patchlevel_check(instance):
def _fullfills_hana_min_version(instance):
""" Performs a check whether the version of SAP HANA fullfills the minimal requirements for the target RHEL """
""" Performs a check whether the version of SAP HANA fulfills the minimal requirements for the target RHEL """
- return _major_version_check(instance) and _sp_rev_patchlevel_check(instance)
+ if version.get_target_major_version() == '8':
+ patchlevels = SAP_HANA_RHEL86_REQUIRED_PATCH_LEVELS
@ -272,5 +273,5 @@ index 3f1d4230..6f61d0bf 100644
monkeypatch.setattr(checksaphana.api, 'consume', _consume_mock_sap_hana_info(
v1names=v1names, v2names=v2names, v2lownames=v2lownames, running=True))
--
2.37.3
2.38.1

View File

@ -0,0 +1,105 @@
From 6ec9f0adf2e9197e68a1919c1f69344fb0534eca Mon Sep 17 00:00:00 2001
From: Matej Matuska <mmatuska@redhat.com>
Date: Wed, 19 Oct 2022 14:15:41 +0200
Subject: [PATCH 22/32] Add an actor that enables device_cio_free.service on
s390x
After an IPU the device_cio_free.service systemd service (exclusive to
s390x) is disabled even though the vendor preset is set to disable. The
new actor instruct to enable the service during the IPU.
The service is used to enable devices not explicitly enabled on kernel
command line.
Jira ref.: OAMG-6302
---
.../enableddeviceciofreeservices390/actor.py | 21 ++++++++++++
.../libraries/enabledeviceciofreeservice.py | 8 +++++
.../tests/test_enableddeviceciofreeservice.py | 32 +++++++++++++++++++
3 files changed, 61 insertions(+)
create mode 100644 repos/system_upgrade/el7toel8/actors/enableddeviceciofreeservices390/actor.py
create mode 100644 repos/system_upgrade/el7toel8/actors/enableddeviceciofreeservices390/libraries/enabledeviceciofreeservice.py
create mode 100644 repos/system_upgrade/el7toel8/actors/enableddeviceciofreeservices390/tests/test_enableddeviceciofreeservice.py
diff --git a/repos/system_upgrade/el7toel8/actors/enableddeviceciofreeservices390/actor.py b/repos/system_upgrade/el7toel8/actors/enableddeviceciofreeservices390/actor.py
new file mode 100644
index 00000000..4928710e
--- /dev/null
+++ b/repos/system_upgrade/el7toel8/actors/enableddeviceciofreeservices390/actor.py
@@ -0,0 +1,21 @@
+from leapp.actors import Actor
+from leapp.libraries.actor import enabledeviceciofreeservice
+from leapp.models import SystemdServicesTasks
+from leapp.tags import ChecksPhaseTag, IPUWorkflowTag
+
+
+class EnableDeviceCioFreeService(Actor):
+ """
+ Enables device_cio_free.service systemd service on s390x
+
+ After an upgrade this service ends up disabled even though it's vendor preset is set to enabled.
+ The service is used to enable devices which are not explicitly enabled on the kernel command line.
+ """
+
+ name = 'enable_device_cio_free_service'
+ consumes = ()
+ produces = (SystemdServicesTasks,)
+ tags = (ChecksPhaseTag, IPUWorkflowTag)
+
+ def process(self):
+ enabledeviceciofreeservice.process()
diff --git a/repos/system_upgrade/el7toel8/actors/enableddeviceciofreeservices390/libraries/enabledeviceciofreeservice.py b/repos/system_upgrade/el7toel8/actors/enableddeviceciofreeservices390/libraries/enabledeviceciofreeservice.py
new file mode 100644
index 00000000..97e36f10
--- /dev/null
+++ b/repos/system_upgrade/el7toel8/actors/enableddeviceciofreeservices390/libraries/enabledeviceciofreeservice.py
@@ -0,0 +1,8 @@
+from leapp.libraries.common.config import architecture
+from leapp.libraries.stdlib import api
+from leapp.models import SystemdServicesTasks
+
+
+def process():
+ if architecture.matches_architecture(architecture.ARCH_S390X):
+ api.produce(SystemdServicesTasks(to_enable=['device_cio_free.service']))
diff --git a/repos/system_upgrade/el7toel8/actors/enableddeviceciofreeservices390/tests/test_enableddeviceciofreeservice.py b/repos/system_upgrade/el7toel8/actors/enableddeviceciofreeservices390/tests/test_enableddeviceciofreeservice.py
new file mode 100644
index 00000000..42527595
--- /dev/null
+++ b/repos/system_upgrade/el7toel8/actors/enableddeviceciofreeservices390/tests/test_enableddeviceciofreeservice.py
@@ -0,0 +1,32 @@
+import pytest
+
+from leapp.libraries.actor import enabledeviceciofreeservice
+from leapp.libraries.common.config import architecture
+from leapp.libraries.common.testutils import CurrentActorMocked, produce_mocked
+from leapp.libraries.stdlib import api
+from leapp.models import SystemdServicesTasks
+
+
+def test_task_produced_on_s390(monkeypatch):
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(arch=architecture.ARCH_S390X))
+ monkeypatch.setattr(api, "produce", produce_mocked())
+
+ enabledeviceciofreeservice.process()
+
+ assert api.produce.called
+ assert isinstance(api.produce.model_instances[0], SystemdServicesTasks)
+ assert api.produce.model_instances[0].to_enable == ['device_cio_free.service']
+
+
+@pytest.mark.parametrize('arch', [
+ architecture.ARCH_X86_64,
+ architecture.ARCH_ARM64,
+ architecture.ARCH_PPC64LE,
+])
+def test_task_not_produced_on_non_s390(monkeypatch, arch):
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(arch=arch))
+ monkeypatch.setattr(api, "produce", produce_mocked())
+
+ enabledeviceciofreeservice.process()
+
+ assert not api.produce.called
--
2.38.1

View File

@ -0,0 +1,240 @@
From 3b5f7416d5f680cbeb777ba4ba33a4bd4787d6f6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Renaud=20M=C3=A9trich?= <rmetrich@redhat.com>
Date: Mon, 7 Nov 2022 09:26:45 +0100
Subject: [PATCH 23/32] Add the scanzfcp actor handling the IPU with ZFCP
(s390x)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When having systems configured with ZFCP instead of DASD, the disks
are not seen while rebooting because `/etc/zfcp.conf` is missing
in the initramfs.
When the file exists, it's copied inside the userspace container
and installed in the upgrade initramfs, producing
TargetUserSpaceUpgradeTasks, UpgradeInitramfsTasks
messages.
pstodulk: updated unit-tests in the scanzfcp and scandasd actors
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2140563
Signed-off-by: Renaud Métrich <rmetrich@redhat.com>
---
.../actors/scandasd/libraries/scandasd.py | 4 +-
.../scandasd/tests/unit_test_scandasd.py | 23 +++++---
.../common/actors/scanzfcp/actor.py | 24 ++++++++
.../actors/scanzfcp/libraries/scanzfcp.py | 25 ++++++++
.../scanzfcp/tests/unit_test_scanzfcp.py | 59 +++++++++++++++++++
5 files changed, 124 insertions(+), 11 deletions(-)
create mode 100644 repos/system_upgrade/common/actors/scanzfcp/actor.py
create mode 100644 repos/system_upgrade/common/actors/scanzfcp/libraries/scanzfcp.py
create mode 100644 repos/system_upgrade/common/actors/scanzfcp/tests/unit_test_scanzfcp.py
diff --git a/repos/system_upgrade/common/actors/scandasd/libraries/scandasd.py b/repos/system_upgrade/common/actors/scandasd/libraries/scandasd.py
index 3e1cba66..ff3104d4 100644
--- a/repos/system_upgrade/common/actors/scandasd/libraries/scandasd.py
+++ b/repos/system_upgrade/common/actors/scandasd/libraries/scandasd.py
@@ -18,8 +18,8 @@ def process():
copy_files = [CopyFile(src=DASD_CONF)]
api.produce(UpgradeInitramfsTasks(include_files=[DASD_CONF]))
else:
- api.current_logger().warning(
- "The {} file has not been discovered. DASD not used?"
+ api.current_logger().info(
+ "The {} file has not been discovered. DASD not used."
.format(DASD_CONF)
)
api.produce(TargetUserSpaceUpgradeTasks(copy_files=copy_files, install_rpms=['s390utils-core']))
diff --git a/repos/system_upgrade/common/actors/scandasd/tests/unit_test_scandasd.py b/repos/system_upgrade/common/actors/scandasd/tests/unit_test_scandasd.py
index e4eea10c..af8f951b 100644
--- a/repos/system_upgrade/common/actors/scandasd/tests/unit_test_scandasd.py
+++ b/repos/system_upgrade/common/actors/scandasd/tests/unit_test_scandasd.py
@@ -3,18 +3,18 @@ import os
import pytest
from leapp.libraries.actor import scandasd
-from leapp.libraries.common.config.architecture import ARCH_S390X
-from leapp.libraries.common.testutils import logger_mocked, produce_mocked
+from leapp.libraries.common.config import architecture
+from leapp.libraries.common.testutils import CurrentActorMocked, logger_mocked, produce_mocked
from leapp.models import CopyFile, TargetUserSpaceUpgradeTasks, UpgradeInitramfsTasks
def test_dasd_exists(monkeypatch):
- monkeypatch.setattr(scandasd.architecture, 'matches_architecture', lambda dummy: True)
+ monkeypatch.setattr(scandasd.api, 'current_actor', CurrentActorMocked(arch=architecture.ARCH_S390X))
monkeypatch.setattr(scandasd.api, 'current_logger', logger_mocked())
monkeypatch.setattr(scandasd.api, 'produce', produce_mocked())
monkeypatch.setattr(os.path, 'isfile', lambda dummy: True)
scandasd.process()
- assert not scandasd.api.current_logger.warnmsg
+ assert not scandasd.api.current_logger.infomsg
assert scandasd.api.produce.called == 2
tusut_flag = False
uit_flag = False
@@ -30,12 +30,12 @@ def test_dasd_exists(monkeypatch):
def test_dasd_not_found(monkeypatch):
- monkeypatch.setattr(scandasd.architecture, 'matches_architecture', lambda dummy: True)
+ monkeypatch.setattr(scandasd.api, 'current_actor', CurrentActorMocked(arch=architecture.ARCH_S390X))
monkeypatch.setattr(scandasd.api, 'current_logger', logger_mocked())
monkeypatch.setattr(os.path, 'isfile', lambda dummy: False)
monkeypatch.setattr(scandasd.api, 'produce', produce_mocked())
scandasd.process()
- assert scandasd.api.current_logger.warnmsg
+ assert scandasd.api.current_logger.infomsg
assert scandasd.api.produce.called == 1
assert len(scandasd.api.produce.model_instances) == 1
assert isinstance(scandasd.api.produce.model_instances[0], TargetUserSpaceUpgradeTasks)
@@ -44,11 +44,16 @@ def test_dasd_not_found(monkeypatch):
@pytest.mark.parametrize('isfile', [True, False])
-def test_non_ibmz_arch(monkeypatch, isfile):
- monkeypatch.setattr(scandasd.architecture, 'matches_architecture', lambda dummy: False)
+@pytest.mark.parametrize('arch', [
+ architecture.ARCH_X86_64,
+ architecture.ARCH_ARM64,
+ architecture.ARCH_PPC64LE,
+])
+def test_non_ibmz_arch(monkeypatch, isfile, arch):
+ monkeypatch.setattr(scandasd.api, 'current_actor', CurrentActorMocked(arch=arch))
monkeypatch.setattr(scandasd.api, 'current_logger', logger_mocked())
monkeypatch.setattr(scandasd.api, 'produce', produce_mocked())
monkeypatch.setattr(os.path, 'isfile', lambda dummy: isfile)
scandasd.process()
- assert not scandasd.api.current_logger.warnmsg
+ assert not scandasd.api.current_logger.infomsg
assert not scandasd.api.produce.called
diff --git a/repos/system_upgrade/common/actors/scanzfcp/actor.py b/repos/system_upgrade/common/actors/scanzfcp/actor.py
new file mode 100644
index 00000000..9817fdc8
--- /dev/null
+++ b/repos/system_upgrade/common/actors/scanzfcp/actor.py
@@ -0,0 +1,24 @@
+
+from leapp.actors import Actor
+from leapp.libraries.actor import scanzfcp
+from leapp.models import TargetUserSpaceUpgradeTasks, UpgradeInitramfsTasks
+from leapp.tags import FactsPhaseTag, IPUWorkflowTag
+
+
+class ScanZFCP(Actor):
+ """
+ In case of s390x architecture, check whether ZFCP is used.
+
+ The current check is based just on existence of the /etc/zfcp.conf file.
+ If it exists, produce UpgradeInitramfsTasks msg to ensure the file
+ is available inside the target userspace to be able to generate the
+ upgrade init ramdisk correctly.
+ """
+
+ name = 'scanzfcp'
+ consumes = ()
+ produces = (TargetUserSpaceUpgradeTasks, UpgradeInitramfsTasks)
+ tags = (IPUWorkflowTag, FactsPhaseTag)
+
+ def process(self):
+ scanzfcp.process()
diff --git a/repos/system_upgrade/common/actors/scanzfcp/libraries/scanzfcp.py b/repos/system_upgrade/common/actors/scanzfcp/libraries/scanzfcp.py
new file mode 100644
index 00000000..72f83f8f
--- /dev/null
+++ b/repos/system_upgrade/common/actors/scanzfcp/libraries/scanzfcp.py
@@ -0,0 +1,25 @@
+import os
+
+from leapp.libraries.common.config import architecture
+from leapp.libraries.stdlib import api
+from leapp.models import CopyFile, TargetUserSpaceUpgradeTasks, UpgradeInitramfsTasks
+
+ZFCP_CONF = '/etc/zfcp.conf'
+
+
+def process():
+ if not architecture.matches_architecture(architecture.ARCH_S390X):
+ return
+ copy_files = []
+ if os.path.isfile(ZFCP_CONF):
+ # the file has to be copied into the targetuserspace container first,
+ # then it can be included into the initramfs ==> both messages are
+ # needed to be produced
+ copy_files = [CopyFile(src=ZFCP_CONF)]
+ api.produce(UpgradeInitramfsTasks(include_files=[ZFCP_CONF]))
+ else:
+ api.current_logger().info(
+ "The {} file has not been discovered. ZFCP not used."
+ .format(ZFCP_CONF)
+ )
+ api.produce(TargetUserSpaceUpgradeTasks(copy_files=copy_files, install_rpms=['s390utils-core']))
diff --git a/repos/system_upgrade/common/actors/scanzfcp/tests/unit_test_scanzfcp.py b/repos/system_upgrade/common/actors/scanzfcp/tests/unit_test_scanzfcp.py
new file mode 100644
index 00000000..1b1f840c
--- /dev/null
+++ b/repos/system_upgrade/common/actors/scanzfcp/tests/unit_test_scanzfcp.py
@@ -0,0 +1,59 @@
+import os
+
+import pytest
+
+from leapp.libraries.actor import scanzfcp
+from leapp.libraries.common.config import architecture
+from leapp.libraries.common.testutils import CurrentActorMocked, logger_mocked, produce_mocked
+from leapp.models import CopyFile, TargetUserSpaceUpgradeTasks, UpgradeInitramfsTasks
+
+
+def test_zfcp_exists(monkeypatch):
+ monkeypatch.setattr(scanzfcp.api, 'current_actor', CurrentActorMocked(arch=architecture.ARCH_S390X))
+ monkeypatch.setattr(scanzfcp.api, 'current_logger', logger_mocked())
+ monkeypatch.setattr(scanzfcp.api, 'produce', produce_mocked())
+ monkeypatch.setattr(os.path, 'isfile', lambda dummy: True)
+ scanzfcp.process()
+ assert not scanzfcp.api.current_logger.infomsg
+ assert scanzfcp.api.produce.called == 2
+ tusut_flag = False
+ uit_flag = False
+ for msg in scanzfcp.api.produce.model_instances:
+ if isinstance(msg, TargetUserSpaceUpgradeTasks):
+ assert [CopyFile(src=scanzfcp.ZFCP_CONF)] == msg.copy_files
+ assert msg.install_rpms == ['s390utils-core']
+ tusut_flag = True
+ elif isinstance(msg, UpgradeInitramfsTasks):
+ assert [scanzfcp.ZFCP_CONF] == msg.include_files
+ uit_flag = True
+ assert tusut_flag and uit_flag
+
+
+def test_zfcp_not_found(monkeypatch):
+ monkeypatch.setattr(scanzfcp.api, 'current_actor', CurrentActorMocked(arch=architecture.ARCH_S390X))
+ monkeypatch.setattr(scanzfcp.api, 'current_logger', logger_mocked())
+ monkeypatch.setattr(scanzfcp.os.path, 'isfile', lambda dummy: False)
+ monkeypatch.setattr(scanzfcp.api, 'produce', produce_mocked())
+ scanzfcp.process()
+ assert scanzfcp.api.current_logger.infomsg
+ assert scanzfcp.api.produce.called == 1
+ assert len(scanzfcp.api.produce.model_instances) == 1
+ assert isinstance(scanzfcp.api.produce.model_instances[0], TargetUserSpaceUpgradeTasks)
+ assert scanzfcp.api.produce.model_instances[0].install_rpms == ['s390utils-core']
+ assert not scanzfcp.api.produce.model_instances[0].copy_files
+
+
+@pytest.mark.parametrize('isfile', [True, False])
+@pytest.mark.parametrize('arch', [
+ architecture.ARCH_X86_64,
+ architecture.ARCH_ARM64,
+ architecture.ARCH_PPC64LE,
+])
+def test_non_ibmz_arch(monkeypatch, isfile, arch):
+ monkeypatch.setattr(scanzfcp.api, 'current_actor', CurrentActorMocked(arch=arch))
+ monkeypatch.setattr(scanzfcp.api, 'current_logger', logger_mocked())
+ monkeypatch.setattr(scanzfcp.api, 'produce', produce_mocked())
+ monkeypatch.setattr(os.path, 'isfile', lambda dummy: isfile)
+ scanzfcp.process()
+ assert not scanzfcp.api.current_logger.infomsg
+ assert not scanzfcp.api.produce.called
--
2.38.1

View File

@ -0,0 +1,118 @@
From a6445b391a01bf17d3ad8229ca1185b10479f467 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Renaud=20M=C3=A9trich?= <rmetrich@redhat.com>
Date: Mon, 7 Nov 2022 09:33:32 +0100
Subject: [PATCH 24/32] ziplconverttoblscfg: bind mount /dev & /boot into the
userspace container (s390x)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The conversion of ZIPL to BLS on IBM Z machines failed when
a) the machine was configured using ZFCP instead of DASD
b) /boot was not on a separate partition
In case a), the zipl-switch-to-blscfg script failed as the /dev has
not been propagated to into the el8userspace container. Regarding
that, the /dev did not contain all required devices needed for the
correct conversion.
With this fix, the /dev is bindmounted into the el8userspace container
using the (systemd-nspawn) `--bind` option. The direct bind mounting
via `leapp.libraries.common.mounting.BindMount` cannot be used in this
case as it blocks the correct start of the container.
In case b), the content of /boot has been removed during the upgrade
due to problems when using BindMount on normal directory (that is not
mountpoint). This has been possibly resolved by this commit also,
as the /boot has been propagated using the --bind (sysmd-nspawn)
option as well. (Untested)
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2140563
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1901440
Signed-off-by: Renaud Métrich <rmetrich@redhat.com>
---
.../actors/ziplconverttoblscfg/actor.py | 66 +++++++++----------
1 file changed, 33 insertions(+), 33 deletions(-)
diff --git a/repos/system_upgrade/el7toel8/actors/ziplconverttoblscfg/actor.py b/repos/system_upgrade/el7toel8/actors/ziplconverttoblscfg/actor.py
index e80c335d..441c538b 100644
--- a/repos/system_upgrade/el7toel8/actors/ziplconverttoblscfg/actor.py
+++ b/repos/system_upgrade/el7toel8/actors/ziplconverttoblscfg/actor.py
@@ -38,40 +38,40 @@ class ZiplConvertToBLSCFG(Actor):
# replace the original boot directory inside the container by the host one
# - as we cannot use zipl* pointing anywhere else than default directory
# - no, --bls-directory is not solution
- with mounting.BindMount(source='/boot', target=os.path.join(userspace.path, 'boot')):
+ # also make sure device nodes are available (requirement for zipl-switch-to-blscfg)
+ binds = ['/boot', '/dev']
+ with mounting.NspawnActions(base_dir=userspace.path, binds=binds) as context:
userspace_zipl_conf = os.path.join(userspace.path, 'etc', 'zipl.conf')
if os.path.exists(userspace_zipl_conf):
os.remove(userspace_zipl_conf)
- with mounting.NullMount(target=userspace.path) as userspace:
- with userspace.nspawn() as context:
- context.copy_to('/etc/zipl.conf', '/etc/zipl.conf')
- # zipl needs this one as well
- context.copy_to('/etc/machine-id', '/etc/machine-id')
- try:
- context.call(['/usr/sbin/zipl-switch-to-blscfg'])
- if filecmp.cmp('/etc/zipl.conf', userspace_zipl_conf):
- # When the files are same, zipl failed - see the switch script
- raise OSError('Failed to convert the ZIPL configuration to BLS.')
- context.copy_from('/etc/zipl.conf', '/etc/zipl.conf')
- except OSError as e:
- self.log.error('Could not call zipl-switch-to-blscfg command.',
- exc_info=True)
- raise StopActorExecutionError(
- message='Failed to execute zipl-switch-to-blscfg.',
- details={'details': str(e)}
- )
- except CalledProcessError as e:
- self.log.error('zipl-switch-to-blscfg execution failed,',
- exc_info=True)
- raise StopActorExecutionError(
- message='zipl-switch-to-blscfg execution failed with non zero exit code.',
- details={'details': str(e), 'stdout': e.stdout, 'stderr': e.stderr}
- )
+ context.copy_to('/etc/zipl.conf', '/etc/zipl.conf')
+ # zipl needs this one as well
+ context.copy_to('/etc/machine-id', '/etc/machine-id')
+ try:
+ context.call(['/usr/sbin/zipl-switch-to-blscfg'])
+ if filecmp.cmp('/etc/zipl.conf', userspace_zipl_conf):
+ # When the files are same, zipl failed - see the switch script
+ raise OSError('Failed to convert the ZIPL configuration to BLS.')
+ context.copy_from('/etc/zipl.conf', '/etc/zipl.conf')
+ except OSError as e:
+ self.log.error('Could not call zipl-switch-to-blscfg command.',
+ exc_info=True)
+ raise StopActorExecutionError(
+ message='Failed to execute zipl-switch-to-blscfg.',
+ details={'details': str(e)}
+ )
+ except CalledProcessError as e:
+ self.log.error('zipl-switch-to-blscfg execution failed,',
+ exc_info=True)
+ raise StopActorExecutionError(
+ message='zipl-switch-to-blscfg execution failed with non zero exit code.',
+ details={'details': str(e), 'stdout': e.stdout, 'stderr': e.stderr}
+ )
- # FIXME: we do not want to continue anymore, but we should clean
- # better.
- # NOTE: Basically, just removal of the /boot/loader dir content inside
- # could be enough, but we cannot remove /boot/loader because of boom
- # - - if we remove it, we will remove the snapshot as well
- # - - on the other hand, we shouldn't keep it there if zipl
- # - - has not been converted to BLS
+ # FIXME: we do not want to continue anymore, but we should clean
+ # better.
+ # NOTE: Basically, just removal of the /boot/loader dir content inside
+ # could be enough, but we cannot remove /boot/loader because of boom
+ # - - if we remove it, we will remove the snapshot as well
+ # - - on the other hand, we shouldn't keep it there if zipl
+ # - - has not been converted to BLS
--
2.38.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,227 @@
From dc43277d4cab1f218a2b5d7e7743a1d2423c8c77 Mon Sep 17 00:00:00 2001
From: Matej Matuska <mmatuska@redhat.com>
Date: Wed, 16 Nov 2022 14:01:45 +0100
Subject: [PATCH 26/32] systemd: Move (enable|disable|reenable)_unit functions
to the shared library
The functions are used to enable, disable, or re-enable the given
systemd unit. Originaly they were part of setsystemdservicesstate
actor, however we have realized they are needed in other actors too
in rare cases.
---
.../libraries/setsystemdservicesstate.py | 25 +++++-----
.../tests/test_setsystemdservicesstate.py | 48 +++++++++++-------
.../common/libraries/systemd.py | 50 +++++++++++++++++++
3 files changed, 93 insertions(+), 30 deletions(-)
diff --git a/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/libraries/setsystemdservicesstate.py b/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/libraries/setsystemdservicesstate.py
index 01272438..641605db 100644
--- a/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/libraries/setsystemdservicesstate.py
+++ b/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/libraries/setsystemdservicesstate.py
@@ -1,17 +1,8 @@
-from leapp.libraries.stdlib import api, CalledProcessError, run
+from leapp.libraries.common import systemd
+from leapp.libraries.stdlib import api, CalledProcessError
from leapp.models import SystemdServicesTasks
-def _try_set_service_state(command, service):
- try:
- # it is possible to call this on multiple units at once,
- # but failing to enable one service would cause others to not enable as well
- run(['systemctl', command, service])
- except CalledProcessError as err:
- api.current_logger().error('Failed to {} systemd unit "{}". Message: {}'.format(command, service, str(err)))
- # TODO(mmatuska) produce post-upgrade report
-
-
def process():
services_to_enable = set()
services_to_disable = set()
@@ -25,7 +16,15 @@ def process():
api.current_logger().error(msg)
for service in services_to_enable:
- _try_set_service_state('enable', service)
+ try:
+ systemd.enable_unit(service)
+ except CalledProcessError:
+ # TODO(mmatuska) produce post-upgrade report
+ pass
for service in services_to_disable:
- _try_set_service_state('disable', service)
+ try:
+ systemd.disable_unit(service)
+ except CalledProcessError:
+ # TODO(mmatuska) produce post-upgrade report
+ pass
diff --git a/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/tests/test_setsystemdservicesstate.py b/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/tests/test_setsystemdservicesstate.py
index dd153329..14d07537 100644
--- a/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/tests/test_setsystemdservicesstate.py
+++ b/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/tests/test_setsystemdservicesstate.py
@@ -2,50 +2,60 @@ import pytest
from leapp.libraries import stdlib
from leapp.libraries.actor import setsystemdservicesstate
+from leapp.libraries.common import systemd
from leapp.libraries.common.testutils import CurrentActorMocked, logger_mocked
from leapp.libraries.stdlib import api, CalledProcessError
from leapp.models import SystemdServicesTasks
-class MockedRun(object):
+class MockedSystemdCmd(object):
def __init__(self):
- self.commands = []
+ self.units = []
- def __call__(self, cmd, *args, **kwargs):
- self.commands.append(cmd)
+ def __call__(self, unit, *args, **kwargs):
+ self.units.append(unit)
return {}
@pytest.mark.parametrize(
- ('msgs', 'expected_calls'),
+ ('msgs', 'expect_enable_units', 'expect_disable_units'),
[
(
[SystemdServicesTasks(to_enable=['hello.service'],
to_disable=['getty.service'])],
- [['systemctl', 'enable', 'hello.service'], ['systemctl', 'disable', 'getty.service']]
+ ['hello.service'],
+ ['getty.service']
),
(
[SystemdServicesTasks(to_disable=['getty.service'])],
- [['systemctl', 'disable', 'getty.service']]
+ [],
+ ['getty.service']
),
(
[SystemdServicesTasks(to_enable=['hello.service'])],
- [['systemctl', 'enable', 'hello.service']]
+ ['hello.service'],
+ []
),
(
[SystemdServicesTasks()],
+ [],
[]
),
]
)
-def test_process(monkeypatch, msgs, expected_calls):
- mocked_run = MockedRun()
- monkeypatch.setattr(setsystemdservicesstate, 'run', mocked_run)
+def test_process(monkeypatch, msgs, expect_enable_units, expect_disable_units):
+ mocked_enable = MockedSystemdCmd()
+ monkeypatch.setattr(systemd, 'enable_unit', mocked_enable)
+
+ mocked_disable = MockedSystemdCmd()
+ monkeypatch.setattr(systemd, 'disable_unit', mocked_disable)
+
monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(msgs=msgs))
setsystemdservicesstate.process()
- assert mocked_run.commands == expected_calls
+ assert mocked_enable.units == expect_enable_units
+ assert mocked_disable.units == expect_disable_units
def test_process_invalid(monkeypatch):
@@ -57,7 +67,7 @@ def test_process_invalid(monkeypatch):
msgs = [SystemdServicesTasks(to_enable=['invalid.service'])]
- monkeypatch.setattr(setsystemdservicesstate, 'run', mocked_run)
+ monkeypatch.setattr(systemd, 'run', mocked_run)
monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(msgs=msgs))
monkeypatch.setattr(api, 'current_logger', logger_mocked())
@@ -69,10 +79,14 @@ def test_process_invalid(monkeypatch):
def test_enable_disable_conflict_logged(monkeypatch):
- msgs = [SystemdServicesTasks(to_enable=['hello.service'],
- to_disable=['hello.service'])]
- mocked_run = MockedRun()
- monkeypatch.setattr(setsystemdservicesstate, 'run', mocked_run)
+ msgs = [SystemdServicesTasks(to_enable=['hello.service'], to_disable=['hello.service'])]
+
+ mocked_enable = MockedSystemdCmd()
+ monkeypatch.setattr(systemd, 'enable_unit', mocked_enable)
+
+ mocked_disable = MockedSystemdCmd()
+ monkeypatch.setattr(systemd, 'disable_unit', mocked_disable)
+
monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(msgs=msgs))
monkeypatch.setattr(api, 'current_logger', logger_mocked())
diff --git a/repos/system_upgrade/common/libraries/systemd.py b/repos/system_upgrade/common/libraries/systemd.py
index bbf71af7..c709f233 100644
--- a/repos/system_upgrade/common/libraries/systemd.py
+++ b/repos/system_upgrade/common/libraries/systemd.py
@@ -32,6 +32,56 @@ def get_broken_symlinks():
raise
+def _try_call_unit_command(command, unit):
+ try:
+ # it is possible to call this on multiple units at once,
+ # but failing to enable one service would cause others to not enable as well
+ run(['systemctl', command, unit])
+ except CalledProcessError as err:
+ msg = 'Failed to {} systemd unit "{}". Message: {}'.format(command, unit, str(err))
+ api.current_logger().error(msg)
+ raise err
+
+
+def enable_unit(unit):
+ """
+ Enable a systemd unit
+
+ It is strongly recommended to produce SystemdServicesTasks message instead,
+ unless it is absolutely necessary to handle failure yourself.
+
+ :param unit: The systemd unit to enable
+ :raises CalledProcessError: In case of failure
+ """
+ _try_call_unit_command('enable', unit)
+
+
+def disable_unit(unit):
+ """
+ Disable a systemd unit
+
+ It is strongly recommended to produce SystemdServicesTasks message instead,
+ unless it is absolutely necessary to handle failure yourself.
+
+ :param unit: The systemd unit to disable
+ :raises CalledProcessError: In case of failure
+ """
+ _try_call_unit_command('disable', unit)
+
+
+def reenable_unit(unit):
+ """
+ Re-enable a systemd unit
+
+ It is strongly recommended to produce SystemdServicesTasks message, unless it
+ is absolutely necessary to handle failure yourself.
+
+ :param unit: The systemd unit to re-enable
+ :raises CalledProcessError: In case of failure
+ """
+ _try_call_unit_command('reenable', unit)
+
+
def get_service_files():
"""
Get list of unit files of systemd services on the system
--
2.38.1

View File

@ -0,0 +1,253 @@
From 7a61c281946ffa0436da8f8837074f17e2103361 Mon Sep 17 00:00:00 2001
From: Matej Matuska <mmatuska@redhat.com>
Date: Wed, 16 Nov 2022 14:11:39 +0100
Subject: [PATCH 27/32] Fix broken or incorrect systemd symlinks
Introduce repairsystemdsymlinks actor.
During the in-place upgrade process, it usually happens that some
symlinks become incorrect - symlinks are broken, or they are defined
in a wrong directory (e.g. when they are supposed to be defined in a
different systemd target). This has various reasons, but usually it's
caused by missing rpm scriptlets in particular rpms.
This change corrects only systemd symlinks are (newly) broken during
the in-place upgrade. Symlinks that have been already broken before
the in-place upgrade are ignored.
Symlinks are handled in the following fashion, if the symlink points to:
- a removed unit, such a symlink is deleted
- a unit whose installation has been changed (e.g. changed WantedBy),
such symlinks are fixed (re-enabled using systemctl)
JIRA:
OAMG-5342
OAMG-5344
OAMG-6519 (possibly related)
OAMG-7755
Bugzillas:
https://bugzilla.redhat.com/show_bug.cgi?id=1988457
https://bugzilla.redhat.com/show_bug.cgi?id=1988449
https://bugzilla.redhat.com/show_bug.cgi?id=2055117 (possibly fixed)
---
.../systemd/repairsystemdsymlinks/actor.py | 25 +++++
.../libraries/repairsystemdsymlinks.py | 76 ++++++++++++++++
.../tests/test_repairsystemdsymlinks.py | 91 +++++++++++++++++++
3 files changed, 192 insertions(+)
create mode 100644 repos/system_upgrade/common/actors/systemd/repairsystemdsymlinks/actor.py
create mode 100644 repos/system_upgrade/common/actors/systemd/repairsystemdsymlinks/libraries/repairsystemdsymlinks.py
create mode 100644 repos/system_upgrade/common/actors/systemd/repairsystemdsymlinks/tests/test_repairsystemdsymlinks.py
diff --git a/repos/system_upgrade/common/actors/systemd/repairsystemdsymlinks/actor.py b/repos/system_upgrade/common/actors/systemd/repairsystemdsymlinks/actor.py
new file mode 100644
index 00000000..29134373
--- /dev/null
+++ b/repos/system_upgrade/common/actors/systemd/repairsystemdsymlinks/actor.py
@@ -0,0 +1,25 @@
+from leapp.actors import Actor
+from leapp.libraries.actor import repairsystemdsymlinks
+from leapp.models import SystemdBrokenSymlinksSource, SystemdBrokenSymlinksTarget, SystemdServicesInfoSource
+from leapp.tags import ApplicationsPhaseTag, IPUWorkflowTag
+
+
+class RepairSystemdSymlinks(Actor):
+ """
+ Fix broken or incorrect systemd symlinks
+
+ Symlinks are handled in the following fashion, if the symlink points to:
+ - a removed unit, such a symlink is deleted
+ - a unit whose installation has been changed (e.g. changed WantedBy),
+ such symlinks are fixed (re-enabled using systemctl)
+
+ Symlinks that have been already broken before the in-place upgrade are ignored.
+ """
+
+ name = 'repair_systemd_symlinks'
+ consumes = (SystemdBrokenSymlinksSource, SystemdBrokenSymlinksTarget, SystemdServicesInfoSource)
+ produces = ()
+ tags = (ApplicationsPhaseTag, IPUWorkflowTag)
+
+ def process(self):
+ repairsystemdsymlinks.process()
diff --git a/repos/system_upgrade/common/actors/systemd/repairsystemdsymlinks/libraries/repairsystemdsymlinks.py b/repos/system_upgrade/common/actors/systemd/repairsystemdsymlinks/libraries/repairsystemdsymlinks.py
new file mode 100644
index 00000000..884b001e
--- /dev/null
+++ b/repos/system_upgrade/common/actors/systemd/repairsystemdsymlinks/libraries/repairsystemdsymlinks.py
@@ -0,0 +1,76 @@
+import os
+
+from leapp.exceptions import StopActorExecutionError
+from leapp.libraries.common import systemd
+from leapp.libraries.common.config.version import get_target_major_version
+from leapp.libraries.stdlib import api, CalledProcessError, run
+from leapp.models import SystemdBrokenSymlinksSource, SystemdBrokenSymlinksTarget, SystemdServicesInfoSource
+
+_INSTALLATION_CHANGED_EL8 = ['rngd.service', 'sysstat.service']
+_INSTALLATION_CHANGED_EL9 = []
+
+
+def _get_installation_changed_units():
+ version = get_target_major_version()
+ if version == '8':
+ return _INSTALLATION_CHANGED_EL8
+ if version == '9':
+ return _INSTALLATION_CHANGED_EL9
+
+ return []
+
+
+def _service_enabled_source(service_info, name):
+ service_file = next((s for s in service_info.service_files if s.name == name), None)
+ return service_file and service_file.state == 'enabled'
+
+
+def _is_unit_enabled(unit):
+ try:
+ ret = run(['systemctl', 'is-enabled', unit], split=True)['stdout']
+ return ret and ret[0] == 'enabled'
+ except (OSError, CalledProcessError):
+ return False
+
+
+def _handle_newly_broken_symlinks(symlinks, service_info):
+ for symlink in symlinks:
+ unit = os.path.basename(symlink)
+ try:
+ if not _is_unit_enabled(unit):
+ # removes the broken symlink
+ systemd.disable_unit(unit)
+ elif _service_enabled_source(service_info, unit) and _is_unit_enabled(unit):
+ # removes the old symlinks and creates the new ones
+ systemd.reenable_unit(unit)
+ except CalledProcessError:
+ # TODO(mmatuska): Produce post-upgrade report: failed to handle broken symlink (and suggest a fix?)
+ pass
+
+
+def _handle_bad_symlinks(service_files):
+ install_changed_units = _get_installation_changed_units()
+ potentially_bad = [s for s in service_files if s.name in install_changed_units]
+
+ for unit_file in potentially_bad:
+ if unit_file.state == 'enabled' and _is_unit_enabled(unit_file.name):
+ systemd.reenable_unit(unit_file.name)
+
+
+def process():
+ service_info_source = next(api.consume(SystemdServicesInfoSource), None)
+ if not service_info_source:
+ raise StopActorExecutionError("Expected SystemdServicesInfoSource message, but got None")
+
+ source_info = next(api.consume(SystemdBrokenSymlinksSource), None)
+ target_info = next(api.consume(SystemdBrokenSymlinksTarget), None)
+
+ if source_info and target_info:
+ newly_broken = []
+ newly_broken = [s for s in target_info.broken_symlinks if s not in source_info.broken_symlinks]
+ if not newly_broken:
+ return
+
+ _handle_newly_broken_symlinks(newly_broken, service_info_source)
+
+ _handle_bad_symlinks(service_info_source.service_files)
diff --git a/repos/system_upgrade/common/actors/systemd/repairsystemdsymlinks/tests/test_repairsystemdsymlinks.py b/repos/system_upgrade/common/actors/systemd/repairsystemdsymlinks/tests/test_repairsystemdsymlinks.py
new file mode 100644
index 00000000..2394df5e
--- /dev/null
+++ b/repos/system_upgrade/common/actors/systemd/repairsystemdsymlinks/tests/test_repairsystemdsymlinks.py
@@ -0,0 +1,91 @@
+from leapp.libraries.actor import repairsystemdsymlinks
+from leapp.libraries.common import systemd
+from leapp.libraries.common.testutils import CurrentActorMocked, logger_mocked
+from leapp.libraries.stdlib import api, CalledProcessError, run
+from leapp.models import (
+ SystemdBrokenSymlinksSource,
+ SystemdBrokenSymlinksTarget,
+ SystemdServiceFile,
+ SystemdServicesInfoSource
+)
+
+
+class MockedSystemdCmd(object):
+ def __init__(self):
+ self.units = []
+
+ def __call__(self, unit, *args, **kwargs):
+ self.units.append(unit)
+ return {}
+
+
+def test_bad_symslinks(monkeypatch):
+ service_files = [
+ SystemdServiceFile(name='rngd.service', state='enabled'),
+ SystemdServiceFile(name='sysstat.service', state='disabled'),
+ SystemdServiceFile(name='hello.service', state='enabled'),
+ SystemdServiceFile(name='world.service', state='disabled'),
+ ]
+
+ def is_unit_enabled_mocked(unit):
+ return True
+
+ monkeypatch.setattr(repairsystemdsymlinks, '_is_unit_enabled', is_unit_enabled_mocked)
+
+ reenable_mocked = MockedSystemdCmd()
+ monkeypatch.setattr(systemd, 'reenable_unit', reenable_mocked)
+
+ service_info = SystemdServicesInfoSource(service_files=service_files)
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(msgs=[service_info]))
+
+ repairsystemdsymlinks._handle_bad_symlinks(service_info.service_files)
+
+ assert reenable_mocked.units == ['rngd.service']
+
+
+def test_handle_newly_broken_symlink(monkeypatch):
+
+ symlinks = [
+ '/etc/systemd/system/default.target.wants/systemd-readahead-replay.service',
+ '/etc/systemd/system/multi-user.target.wants/vdo.service',
+ '/etc/systemd/system/multi-user.target.wants/hello.service',
+ '/etc/systemd/system/multi-user.target.wants/world.service',
+ '/etc/systemd/system/multi-user.target.wants/foo.service',
+ '/etc/systemd/system/multi-user.target.wants/bar.service',
+ ]
+
+ def is_unit_enabled_mocked(unit):
+ return unit in ('hello.service', 'foo.service')
+
+ expect_disabled = [
+ 'systemd-readahead-replay.service',
+ 'vdo.service',
+ 'world.service',
+ 'bar.service',
+ ]
+
+ expect_reenabled = [
+ 'hello.service',
+ ]
+
+ monkeypatch.setattr(repairsystemdsymlinks, '_is_unit_enabled', is_unit_enabled_mocked)
+
+ reenable_mocked = MockedSystemdCmd()
+ monkeypatch.setattr(systemd, 'reenable_unit', reenable_mocked)
+
+ disable_mocked = MockedSystemdCmd()
+ monkeypatch.setattr(systemd, 'disable_unit', disable_mocked)
+
+ service_files = [
+ SystemdServiceFile(name='systemd-readahead-replay.service', state='enabled'),
+ SystemdServiceFile(name='vdo.service', state='disabled'),
+ SystemdServiceFile(name='hello.service', state='enabled'),
+ SystemdServiceFile(name='world.service', state='disabled'),
+ SystemdServiceFile(name='foo.service', state='disabled'),
+ SystemdServiceFile(name='bar.service', state='enabled'),
+ ]
+ service_info = SystemdServicesInfoSource(service_files=service_files)
+ repairsystemdsymlinks._handle_newly_broken_symlinks(symlinks, service_info)
+
+ assert reenable_mocked.units == expect_reenabled
+ assert disable_mocked.units == expect_disabled
--
2.38.1

View File

@ -0,0 +1,271 @@
From 2713d60a99b60a352b89374dec89f6faa683861d Mon Sep 17 00:00:00 2001
From: Matej Matuska <mmatuska@redhat.com>
Date: Wed, 16 Nov 2022 14:19:36 +0100
Subject: [PATCH 28/32] Add check for systemd symlinks broken before the
upgrade
Broken systemd symlinks are not treated during the in-place upgrade
if they are broken prior the leapp execution. This could lead in
unwanted behaviour on the upgraded system, but it does not have to
- so we do not inhibit the upgrade when such symlinks are detected.
Also, such symlinks could have been created by previous in-place
upgrade, when an automatical fixing of broken symlinks have not been
implemented yet. By this actor we inform people about such issues,
so they can fix it prior the upgrade.
Co-authored-by: Petr Stodulka <pstodulk@redhat.com>
---
.../checksystemdbrokensymlinks/actor.py | 29 +++++
.../libraries/checksystemdbrokensymlinks.py | 106 ++++++++++++++++++
.../tests/test_checksystemdbrokensymlinks.py | 89 +++++++++++++++
3 files changed, 224 insertions(+)
create mode 100644 repos/system_upgrade/common/actors/systemd/checksystemdbrokensymlinks/actor.py
create mode 100644 repos/system_upgrade/common/actors/systemd/checksystemdbrokensymlinks/libraries/checksystemdbrokensymlinks.py
create mode 100644 repos/system_upgrade/common/actors/systemd/checksystemdbrokensymlinks/tests/test_checksystemdbrokensymlinks.py
diff --git a/repos/system_upgrade/common/actors/systemd/checksystemdbrokensymlinks/actor.py b/repos/system_upgrade/common/actors/systemd/checksystemdbrokensymlinks/actor.py
new file mode 100644
index 00000000..257e8c33
--- /dev/null
+++ b/repos/system_upgrade/common/actors/systemd/checksystemdbrokensymlinks/actor.py
@@ -0,0 +1,29 @@
+from leapp.actors import Actor
+from leapp.libraries.actor import checksystemdbrokensymlinks
+from leapp.models import SystemdBrokenSymlinksSource, SystemdServicesInfoSource
+from leapp.reporting import Report
+from leapp.tags import ChecksPhaseTag, IPUWorkflowTag
+
+
+class CheckSystemdBrokenSymlinks(Actor):
+ """
+ Check whether some systemd symlinks are broken
+
+ If some systemd symlinks are broken, report them but do not inhibit the
+ upgrade. The symlinks broken already before the upgrade will not be
+ handled by the upgrade process anyhow. Two different reports are created:
+ - symlinks which have the same filename as an existing enabled systemd
+ service (the symlink doesn't point to an existing unit file, but the
+ service is enabled)
+ - broken symlinks which names do not correspond with any existing systemd
+ unit file (typically when the service is removed but not disabled
+ correctly)
+ """
+
+ name = 'check_systemd_broken_symlinks'
+ consumes = (SystemdBrokenSymlinksSource, SystemdServicesInfoSource)
+ produces = (Report,)
+ tags = (ChecksPhaseTag, IPUWorkflowTag)
+
+ def process(self):
+ checksystemdbrokensymlinks.process()
diff --git a/repos/system_upgrade/common/actors/systemd/checksystemdbrokensymlinks/libraries/checksystemdbrokensymlinks.py b/repos/system_upgrade/common/actors/systemd/checksystemdbrokensymlinks/libraries/checksystemdbrokensymlinks.py
new file mode 100644
index 00000000..23addf72
--- /dev/null
+++ b/repos/system_upgrade/common/actors/systemd/checksystemdbrokensymlinks/libraries/checksystemdbrokensymlinks.py
@@ -0,0 +1,106 @@
+import os
+
+from leapp import reporting
+from leapp.exceptions import StopActorExecutionError
+from leapp.libraries.stdlib import api
+from leapp.models import SystemdBrokenSymlinksSource, SystemdServicesInfoSource
+
+FMT_LIST_SEPARATOR = '\n - '
+
+
+def _report_broken_symlinks(symlinks):
+ summary = (
+ 'Leapp detected broken systemd symlinks on the system that do not'
+ ' correspond to any installed systemd unit.'
+ ' This typically happens when the original systemd unit file has been'
+ ' removed (e.g. an rpm removal) or renamed and the system configration'
+ ' has not been properly modified.'
+ ' These symlinks will not be handled during the in-place upgrade'
+ ' as they are already broken.'
+ ' The list of detected broken systemd symlinks:{}{}'
+ .format(FMT_LIST_SEPARATOR, FMT_LIST_SEPARATOR.join(sorted(symlinks)))
+ )
+
+ command = ['/usr/bin/rm'] + symlinks
+
+ hint = (
+ 'Remove the invalid symlinks before the upgrade.'
+ )
+
+ reporting.create_report([
+ reporting.Title(
+ 'Detected broken systemd symlinks for non-existing services'
+ ),
+ reporting.Summary(summary),
+ reporting.Remediation(hint=hint, commands=[command]),
+ reporting.Severity(reporting.Severity.LOW),
+ reporting.Tags([reporting.Tags.FILESYSTEM]),
+ ])
+
+
+def _report_enabled_services_broken_symlinks(symlinks):
+ summary = (
+ 'Leapp detected broken systemd symlinks on the system that correspond'
+ ' to existing systemd units, but on different paths. This could lead'
+ ' in future to unexpected behaviour. Also, these symlinks will not be'
+ ' handled during the in-place upgrade as they are already broken.'
+ ' The list of detected broken symlinks:{}{}'
+ .format(FMT_LIST_SEPARATOR, FMT_LIST_SEPARATOR.join(sorted(symlinks)))
+ )
+
+ hint = (
+ 'Fix the broken symlinks before the upgrade or remove them. For this'
+ ' purpose, you can re-enable or disable the related systemd services'
+ ' using the systemctl tool.'
+ )
+
+ reporting.create_report([
+ reporting.Title(
+ 'Detected broken systemd symlinks for existing services'
+ ),
+ reporting.Summary(summary),
+ reporting.Remediation(hint=hint),
+ reporting.Severity(reporting.Severity.MEDIUM),
+ reporting.Tags([reporting.Tags.FILESYSTEM]),
+ ])
+
+
+def _is_enabled(unit, service_files):
+ # FIXME(pstodulk): currently our msgs contain only information about systemd
+ # services. If the unit (broken symlink) refers to timers, etc. They will
+ # be treated now as disabled (read: symlink is broken and there is not
+ # a corresponding unit-file on the system). Considering it for now as
+ # minor issue that will be resolved in future.
+ # NOTE: One of possible solution is to put the information about enabled broken
+ # symlinks to the msg, so it can be just consumed.
+ for service_file in service_files:
+ if service_file.name == unit:
+ return service_file.state == 'enabled'
+ return False
+
+
+def process():
+ broken_symlinks_info = next(api.consume(SystemdBrokenSymlinksSource), None)
+ if not broken_symlinks_info:
+ # nothing to do
+ return
+ services = next(api.consume(SystemdServicesInfoSource), None)
+ if not services:
+ # This is just a seatbelt. It's not expected this msg will be missing.
+ # Skipping tests.
+ raise StopActorExecutionError('Missing SystemdServicesInfoSource message.')
+
+ enabled_to_report = []
+ to_report = []
+ for broken_symlink in broken_symlinks_info.broken_symlinks:
+ unit = os.path.basename(broken_symlink)
+ if _is_enabled(unit, services.service_files):
+ enabled_to_report.append(broken_symlink)
+ else:
+ to_report.append(broken_symlink)
+
+ if enabled_to_report:
+ _report_enabled_services_broken_symlinks(enabled_to_report)
+
+ if to_report:
+ _report_broken_symlinks(to_report)
diff --git a/repos/system_upgrade/common/actors/systemd/checksystemdbrokensymlinks/tests/test_checksystemdbrokensymlinks.py b/repos/system_upgrade/common/actors/systemd/checksystemdbrokensymlinks/tests/test_checksystemdbrokensymlinks.py
new file mode 100644
index 00000000..2364f7a5
--- /dev/null
+++ b/repos/system_upgrade/common/actors/systemd/checksystemdbrokensymlinks/tests/test_checksystemdbrokensymlinks.py
@@ -0,0 +1,89 @@
+import pytest
+
+from leapp import reporting
+from leapp.libraries.actor import checksystemdbrokensymlinks
+from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked
+from leapp.libraries.stdlib import api
+from leapp.models import SystemdBrokenSymlinksSource, SystemdServiceFile, SystemdServicesInfoSource
+
+
+def test_report_broken_symlinks(monkeypatch):
+
+ symlinks = [
+ '/etc/systemd/system/multi-user.target.wants/hello.service',
+ '/etc/systemd/system/multi-user.target.wants/world.service',
+ ]
+
+ created_reports = create_report_mocked()
+ monkeypatch.setattr(reporting, 'create_report', created_reports)
+
+ checksystemdbrokensymlinks._report_broken_symlinks(symlinks)
+
+ assert created_reports.called
+ assert all([s in created_reports.report_fields['summary'] for s in symlinks])
+
+
+def test_report_enabled_services_broken_symlinks(monkeypatch):
+ symlinks = [
+ '/etc/systemd/system/multi-user.target.wants/foo.service',
+ '/etc/systemd/system/multi-user.target.wants/bar.service',
+ ]
+
+ created_reports = create_report_mocked()
+ monkeypatch.setattr(reporting, 'create_report', created_reports)
+
+ checksystemdbrokensymlinks._report_enabled_services_broken_symlinks(symlinks)
+
+ assert created_reports.called
+ assert all([s in created_reports.report_fields['summary'] for s in symlinks])
+
+
+class ReportBrokenSymlinks(object):
+ def __init__(self):
+ self.symlinks = []
+
+ def __call__(self, unit, *args, **kwargs):
+ self.symlinks.append(unit)
+ return {}
+
+
+def test_broken_symlinks_reported(monkeypatch):
+ broken_symlinks = SystemdBrokenSymlinksSource(broken_symlinks=[
+ '/etc/systemd/system/multi-user.target.wants/foo.service',
+ '/etc/systemd/system/multi-user.target.wants/bar.service',
+ '/etc/systemd/system/multi-user.target.wants/hello.service',
+ '/etc/systemd/system/multi-user.target.wants/world.service',
+ ])
+ systemd_services = SystemdServicesInfoSource(service_files=[
+ SystemdServiceFile(name='foo.service', state='enabled'),
+ SystemdServiceFile(name='bar.service', state='enabled'),
+ SystemdServiceFile(name='hello.service', state='disabled'),
+ ])
+ broken = []
+ enabled_broken = []
+
+ def _report_broken_symlinks_mocked(symlinks):
+ broken.extend(symlinks)
+
+ def _report_enabled_services_broken_symlinks_mocked(symlinks):
+ enabled_broken.extend(symlinks)
+
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(msgs=[broken_symlinks, systemd_services]))
+ monkeypatch.setattr(checksystemdbrokensymlinks, '_report_broken_symlinks', _report_broken_symlinks_mocked)
+ monkeypatch.setattr(
+ checksystemdbrokensymlinks,
+ '_report_enabled_services_broken_symlinks',
+ _report_enabled_services_broken_symlinks_mocked
+ )
+
+ checksystemdbrokensymlinks.process()
+
+ assert broken == [
+ '/etc/systemd/system/multi-user.target.wants/hello.service',
+ '/etc/systemd/system/multi-user.target.wants/world.service',
+ ]
+
+ assert enabled_broken == [
+ '/etc/systemd/system/multi-user.target.wants/foo.service',
+ '/etc/systemd/system/multi-user.target.wants/bar.service',
+ ]
--
2.38.1

View File

@ -0,0 +1,87 @@
From 4e2767e0eab5fe99b9e99dfea8a8425a1297574b Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Wed, 16 Nov 2022 14:10:48 +0100
Subject: [PATCH 29/32] checksystemdservicestasks: update docstrings + extend
tests
---
.../systemd/checksystemdservicetasks/actor.py | 11 +++++------
.../tests/test_checksystemdservicestasks.py | 16 +++++++++++++++-
2 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/actor.py b/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/actor.py
index 2df995ee..547a13df 100644
--- a/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/actor.py
+++ b/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/actor.py
@@ -7,17 +7,16 @@ from leapp.tags import IPUWorkflowTag, TargetTransactionChecksPhaseTag
class CheckSystemdServicesTasks(Actor):
"""
- Inhibits upgrade if SystemdServicesTasks tasks are in conflict
+ Inhibit the upgrade if SystemdServicesTasks tasks are in conflict
- There is possibility, that SystemdServicesTasks messages with conflicting
- requested service states could be produced. For example a service is
- requested to be both enabled and disabled. This actor inhibits upgrade in
- such cases.
+ SystemdServicesTasks messages with conflicting requested service states
+ could be produced. For example a service could be requested to be both
+ - enabled and disabled. This actor inhibits upgrade in such cases.
Note: We expect that SystemdServicesTasks could be produced even after the
TargetTransactionChecksPhase (e.g. during the ApplicationPhase). The
purpose of this actor is to report collisions in case we can already detect
- them. In case of conflicts caused by produced messages later we just log
+ them. In case of conflicts caused by messages produced later we just log
the collisions and the services will end up disabled.
"""
diff --git a/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/tests/test_checksystemdservicestasks.py b/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/tests/test_checksystemdservicestasks.py
index 36ded92f..88c278d6 100644
--- a/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/tests/test_checksystemdservicestasks.py
+++ b/repos/system_upgrade/common/actors/systemd/checksystemdservicetasks/tests/test_checksystemdservicestasks.py
@@ -5,6 +5,7 @@ from leapp.libraries.actor import checksystemdservicetasks
from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked
from leapp.libraries.stdlib import api
from leapp.models import SystemdServicesTasks
+from leapp.utils.report import is_inhibitor
@pytest.mark.parametrize(
@@ -44,6 +45,18 @@ from leapp.models import SystemdServicesTasks
],
True
),
+ (
+ [
+ SystemdServicesTasks(to_enable=['hello.service']),
+ SystemdServicesTasks(to_disable=['world.service']),
+ SystemdServicesTasks(to_enable=['hello.service', 'kitty.service'])
+ ],
+ False
+ ),
+ (
+ [],
+ False
+ )
]
)
def test_conflicts_detected(monkeypatch, tasks, should_inhibit):
@@ -55,6 +68,7 @@ def test_conflicts_detected(monkeypatch, tasks, should_inhibit):
checksystemdservicetasks.check_conflicts()
assert bool(created_reports.called) == should_inhibit
+ assert is_inhibitor(created_reports.report_fields) == should_inhibit
@pytest.mark.parametrize(
@@ -84,5 +98,5 @@ def test_coflict_reported(monkeypatch, tasks, expected_reported):
checksystemdservicetasks.check_conflicts()
- report_summary = reporting.create_report.report_fields['summary']
+ report_summary = created_reports.report_fields['summary']
assert all(service in report_summary for service in expected_reported)
--
2.38.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,702 @@
From 4dac9dc9d8f7c48626ea78d2d3bf128efdcb610d Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Wed, 16 Nov 2022 20:09:47 +0100
Subject: [PATCH 31/32] Add prod certs for 8.8 & 9.2 (Beta + GA)
Signed-off-by: Petr Stodulka <pstodulk@redhat.com>
---
.../common/files/prod-certs/8.8/279.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/8.8/362.pem | 36 +++++++++++++++++++
.../common/files/prod-certs/8.8/363.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/8.8/419.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/8.8/433.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/8.8/479.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/8.8/486.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/8.8/72.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/9.2/279.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/9.2/362.pem | 36 +++++++++++++++++++
.../common/files/prod-certs/9.2/363.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/9.2/419.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/9.2/433.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/9.2/479.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/9.2/486.pem | 35 ++++++++++++++++++
.../common/files/prod-certs/9.2/72.pem | 35 ++++++++++++++++++
16 files changed, 562 insertions(+)
create mode 100644 repos/system_upgrade/common/files/prod-certs/8.8/279.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/8.8/362.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/8.8/363.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/8.8/419.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/8.8/433.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/8.8/479.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/8.8/486.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/8.8/72.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.2/279.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.2/362.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.2/363.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.2/419.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.2/433.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.2/479.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.2/486.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.2/72.pem
diff --git a/repos/system_upgrade/common/files/prod-certs/8.8/279.pem b/repos/system_upgrade/common/files/prod-certs/8.8/279.pem
new file mode 100644
index 00000000..8ca3cea1
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/8.8/279.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGJTCCBA2gAwIBAgIJALDxRLt/tVMfMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIyMDcxMjA2NTM1MFoXDTQyMDcw
+NzA2NTM1MFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFtlYzg2NTc3
+MC01NGViLTQ5NjEtYmJjMC1iZWVhOWI2ZGYyNjZdMIICIjANBgkqhkiG9w0BAQEF
+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
+AQQBkggJAYIXAgQFDAM4LjgwGQYMKwYBBAGSCAkBghcDBAkMB3BwYzY0bGUwJwYM
+KwYBBAGSCAkBghcEBBcMFXJoZWwtOCxyaGVsLTgtcHBjNjRsZTANBgkqhkiG9w0B
+AQsFAAOCAgEARI585ue/LavAlcpIOCiwxmNv/djPG3XFU0bPoTym/gycwppJPh3Z
+2wfXQMumgmp6C07yui1ybbVIzftwBMU46z+VGqYyFAvFGXLdYndQ0EJpyZkov5F+
+zd6XQlrzIrJu9G9k/bwWXld+7mIBgmWTPjv+TA4wlya9r6NSMW/xSxVm5Xm9SThy
+rvwN8ElK2+BjmyEVByNWphoagNQnKg1hkWsajNGlTKM1x+w1of941uDdBaXbyKVE
+JbYX5klal0DnqqYt8Fgj4vCDMJ635yhnwHgo5MginZZMQFZutHS8NjV2wMvYx1yY
+oLhPo6fA572tTRAEGbZ8HnlU9FrBwP938fvFDHy3hQuRUjrE5qtE+sWnwnmVMgNB
+oMUBy5hZN35VX/s0yQ25CXUqrVof1H2ZmLmRNX+c9Du/vZ2R4cjJpPu+9om4a848
+Dt4IKfaScsVISErkVvOYH7RCB0o/y3vzahou8fA3lL3Mu4D4Vlyv59Xajsnuwbu/
+5+3OYZ87h50NlbOLbV0668NztVzRppZ9aoZGVFyhcDdFc5y0uG2schWHSYOIJgJp
+8L3M9PL0FgdyEHAZD2Jyu8l+lhc+oIc41JXjW0GZhCZ9Uvw7x3apurdHk9IU5Ord
+9IugAJ1qN7veRstmb4rCVS8c/gxR24wCRGcDD3eIgvBwmgdFi09DLTA=
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/8.8/362.pem b/repos/system_upgrade/common/files/prod-certs/8.8/362.pem
new file mode 100644
index 00000000..502e9d16
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/8.8/362.pem
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIGNDCCBBygAwIBAgIJALDxRLt/tVM1MA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIyMDcxMjA2NTYyNFoXDTQyMDcw
+NzA2NTYyNFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFtiOTdkODkx
+NC1jNjJhLTRhNDAtOTFiZi1hZjdlNTM3MmVjOGVdMIICIjANBgkqhkiG9w0BAQEF
+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
+GgYMKwYBBAGSCAkBgmoCBAoMCDguOCBCZXRhMBkGDCsGAQQBkggJAYJqAwQJDAdw
+cGM2NGxlMCwGDCsGAQQBkggJAYJqBAQcDBpyaGVsLTgscmhlbC04LWJldGEtcHBj
+NjRsZTANBgkqhkiG9w0BAQsFAAOCAgEAcQBzf0ndflW+503jCYyZS1enHucWjgIi
+EqtX4s1mkLuLXyiR7LcSNq56jyRjztyab2ydA77/C/iWaDzXEEXqlO+rrHBfw4u+
+aJ3Pp0p8mYC+srWMO0wuVeRJeBkbDkXzoGmm/DkzMjGnTZB9/O0hkQ3+dnHLbf8I
+IC9lWen7Rcn+pSp2v8jz7zpZ3qrfBb2Q62KuPL6xwCfw+CVrl+PuChjz373i12CH
+9F7XG/RtVI1B+9qh4yLtTB13hPaAzIkGW3yTA+NOBoVexxZSka7ZfJFFXpmnI7Ot
+4NGi3L6aTGYGRNsHaDX1JsVd4vXC4LFca7YeKBW2aIGjt5ZSThE1tfIgXCgEm7uS
+UUB5lQiQ/9H67Vl8r4/LsUItdD9NmRdpTWT3NB8vbenqLL7QG91ra3uMR4vA9l0j
+Ei7v0WGWjpeiQbbRjzMkRgQKmeW/3M41ShUW4MNg9sFObw6eZqMJnH1BV9N/1e1k
+CpP6drmYE8qb8rVc66FIFS77JB6xmeLRK5Bq4yAtyA7PsM7r4RytgmVpVa4zoMEi
+JSboaBN9IMawvA7m4B/+fQZAy86pD168eOTBoP8G4RswFSLZCeIohFgorG0VEmEx
+CcJDxa9+ud/xFJfJQ9ILHJXYj8+SCO73LUQ1D0z9MPtKqDEk/7Rl+b6EziBzmDyO
+xYae2xpfO4E=
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/8.8/363.pem b/repos/system_upgrade/common/files/prod-certs/8.8/363.pem
new file mode 100644
index 00000000..54e14706
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/8.8/363.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGJjCCBA6gAwIBAgIJALDxRLt/tVM0MA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIyMDcxMjA2NTYxOVoXDTQyMDcw
+NzA2NTYxOVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs4NDk1OTc3
+Yi0yZDU1LTQwZDItOWZjOC0yOTI5ZjJlZWZiNDRdMIICIjANBgkqhkiG9w0BAQEF
+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
+AgQKDAg4LjggQmV0YTAZBgwrBgEEAZIICQGCawMECQwHYWFyY2g2NDAsBgwrBgEE
+AZIICQGCawQEHAwacmhlbC04LHJoZWwtOC1iZXRhLWFhcmNoNjQwDQYJKoZIhvcN
+AQELBQADggIBAMEjuJ3qX1Ggyt5axDU3Ub+YJy+JJoBPk/nxpoDWBmZLmGAhW5pa
+sjP6xL/1CLcdWe4bFDbZDdtbXEPStZ0WraNmO0nQgUJFFx7RJ1hd5CUzCi8j3uGh
+M9+YDrr4MbQJSO0Wc55m23E6V9Lug6cA/rCzBWzwxD1W1K7q26CAiWT5l0qBZJmI
+VozYzqTk941GYipukb7vbScDFFafoNMyysEYQckRKRhhIZrr0z3p9ZdFgKFVvy4b
+rYX4/W5MdsAetlzTBrsfxazSOYw/97mnPxDCIjEue2V1A1z5D5HlHotQcbq4OXff
+3aHVbhsYbLbGUhULo/HfBxA1tFSJ9QpsEDu+yvP0032non7xEDB4IvypZ0ay2qK7
+ArrSFGAyUIVrdIopspPxRikPfc+DcmPflO9vePRTT95tK0O6iObFM9azNmphp2e9
+9Bzz1A2CjctjA7z4MIP6lPVGbWhD53qRbJs3bkMjqDDCUdE+vEnCuLdronlMlzQ1
+KVGvRgnKNrAI9ORY24bz/AsGTseZp9jN4IKKnj0ZSq+SjZih/eMP1lNFHjQda/9/
+gUoeAz3oAd1KQe011R81rS/HnL4QTRqkQiMeEahrx8q0xFwgk3wsk8voFGTBGyEO
+qnVIkzgrzXSQvM3neGlnBVkLzYS2okgFtJzglqAvUUqqfj34J3d91TWF
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/8.8/419.pem b/repos/system_upgrade/common/files/prod-certs/8.8/419.pem
new file mode 100644
index 00000000..fd9944a9
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/8.8/419.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGFzCCA/+gAwIBAgIJALDxRLt/tVMeMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIyMDcxMjA2NTM0NloXDTQyMDcw
+NzA2NTM0NlowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFtkODg3ZTU0
+NC0wMDBkLTQ2MTYtODk3Zi1kYmIzMDg1MzM4ODVdMIICIjANBgkqhkiG9w0BAQEF
+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
+OC44MBkGDCsGAQQBkggJAYMjAwQJDAdhYXJjaDY0MCcGDCsGAQQBkggJAYMjBAQX
+DBVyaGVsLTgscmhlbC04LWFhcmNoNjQwDQYJKoZIhvcNAQELBQADggIBAFoEXLlm
+Vxi4qkcugC++o4LrGD8l1pGWL6J7JQ7cFpiCIMtmh0EXx8Tc4511u9SqzIR6uaSI
+D23jUfndGTGsfqYW/jclr5ayoN8IKL7Km18Wc9sb2DErZ98wDDlkIq1s9Wl5TthE
+Eq1Ae81rCnK2R85IUQa7IIB26aSnSwV3DNd1nYPLewzgN8rpF21wKqcN6HowIzbg
+U06sdKCuBA/fnnk/3SInambZAl/eqtHMgmQjgNHzt+qFhno0JqhllevXYn7Gx3Pu
+qJ9UMCTLZM4OEjnNfA0f1VX1CUzf1Fz5ukvChxX4cx2pKNl8q6w+R+2A3fcSkvv2
+BHMDI00F0M22AEeZQE2ECG4/s8G2dRu2Dzp1kmBH26pSs9FTB3fTPXW2kyXPpOT/
+jv2x1jFsza0GXoMJ7t7JEV5Mx9wcC3pguxEnJeCBqejoHTcG1xuWxFhlXmkNuiyD
+/Try5lCEmOvQYyE4FrJGezkpWBab5m2426hByTnpuHYvDsqAPDjUY0HoFUtxwqwA
+kVxUQzf3GxXu5FoFq36BxiWG7e0d4OJzwMK5DI00r/rs2tUlLCfNozDdbN5rBMlR
+1RIrGctY4LDfgr8sXXEK+54nAP11me16/Z4odkQbkv+WZ9z5i4573wei88kTg49X
+Dn64lKrB2B5dKq7vjemcDO3qFp0RAyc2PGUc
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/8.8/433.pem b/repos/system_upgrade/common/files/prod-certs/8.8/433.pem
new file mode 100644
index 00000000..1c6772ca
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/8.8/433.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGKTCCBBGgAwIBAgIJALDxRLt/tVM2MA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIyMDcxMjA2NTYyOVoXDTQyMDcw
+NzA2NTYyOVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs1YjllMDEy
+Yy1jM2ZkLTQ0MTgtYWY0OC01Y2FkNWE4YTBjMjBdMIICIjANBgkqhkiG9w0BAQEF
+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
+AZIICQGDMQIECgwIOC44IEJldGEwFwYMKwYBBAGSCAkBgzEDBAcMBXMzOTB4MCoG
+DCsGAQQBkggJAYMxBAQaDBhyaGVsLTgscmhlbC04LWJldGEtczM5MHgwDQYJKoZI
+hvcNAQELBQADggIBAEcUjx4IcWFemLJqpxFJm7nP9j/4ZqTjEa9Q7oDHNOOWM1NG
+HL9wJe/5Y/TCUGJvf4JiIUPNnfkaXXZDKqR7mbpLyb83BSAhgCBekdXvb/n+5QKI
+AAYyliEPtWkAIh0aP/nLYDEZ9aJoKIoDs9tp7uAQ/1fGPqN5lIvr7CO7HjIo7xrm
+5S4C3b+DlXp3GB74kb89r1XM3/1cmFmVz8js5KGg7JOVBUqxKQsjF7y8OGgGONiy
+xfkDFIvX+vyNli6xiXpsRH+CkSRckioTOsV8WawA0Ae89QNTVdN7xNXSugrIXSRd
+fyULDx9v+jihJuEyzMYbpvj3fmenrpcbckACsCHWGtRlvdAgYcF0TrFYsYthd2Gc
+wpR/XLn2SRu0Hx5ZbfqqhrJo765wYRPfTMVLilCPiw71d7DP0m6hrNzxX/Sp8K4e
+w/RxKaC5p/aV27dGSe83udnAXA2IgjfaJz6adnD36YfWUYIRVEg/tX2nlpDROz7Y
+saVj5Lq6wzFdt6mIVIQ6A4lM1zldHNyDv69gVDOlOgtklO94z41eJkPu5MbDG2fG
+xlVRgjiAsERNvHEXfnVb0iz/b2ymmM7HIVDowlIVhyJBkNKUW1invXOvf+AGZzQf
+LS4Db1q+P7HJZnrQf1EzgDKjTm8Kdv2CqKXpBnhDsXUXZZPbNl4txG4yIGHI
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/8.8/479.pem b/repos/system_upgrade/common/files/prod-certs/8.8/479.pem
new file mode 100644
index 00000000..2ecca847
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/8.8/479.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGFTCCA/2gAwIBAgIJALDxRLt/tVMhMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIyMDcxMjA2NTQwMFoXDTQyMDcw
+NzA2NTQwMFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFswOWI2ZGRm
+MC03ODFkLTRjMjctYjZkZi0xMWQ2MmE5YmJkMDFdMIICIjANBgkqhkiG9w0BAQEF
+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
+OC44MBgGDCsGAQQBkggJAYNfAwQIDAZ4ODZfNjQwJgYMKwYBBAGSCAkBg18EBBYM
+FHJoZWwtOCxyaGVsLTgteDg2XzY0MA0GCSqGSIb3DQEBCwUAA4ICAQBhvgRzUrOb
+VRVPq2cG/Sto2KzpuIjauYhvuYLCNItw3cOqKaUy5ThOeYkLpddyzPjjlb/jQZi2
+dUybQjF3lrRpfgMmvRuapvhXWsCQuwq63JjqUaRNuPRrjxlwUqX2ibQSw0ZpPhlj
+vw3usTbLb04zd+RLb9e897tVMxWEWcyfyakMAI2/zV4UXhCZiFoaIA1EQqIyZIhK
+ukCnMYt9m/1KwK9yNYd6yzwYxqDe1aK4Z7J57G0FBpr57JXbZrE1KHpWQawusnFB
+t+2gGTxVOyDIrMuszV93GrrzPTyn+BasVS6UMwpUPQDOFJB9y7AKNSFkhZPUZRPW
+pmJUB4+Z5KGS+Of+g0Sp1huMnCvmEre1mP3pJTBhXmut1X1r/JJI041e46qnE7KO
+wHOz/cimduPgp2Sthc0OY3jZyZU1ibrFld9QFW1vVz7jO0j28T+JInzq+ji4NHdm
+0rGnAxp6S3L6HQBqiliO62ehyG3PnK2UvQyAz3sTnT7qL6qeOvvBSQvJqyQeF33y
+a85oEvAX3air6KuIVJTlXsS4E5EyTKYaX/5BqmrfzZ94ImcnO+5OF0SMOirCG3ik
+uWRGS9+I+0p+I7G9FjDduy8Cm1MYwEC8yB2/CFGEKgsMjXEyMkXMX4hzndnwE1G7
+edrVZJxTtwuyDtMvE6jeBziapQXSDNv/2A==
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/8.8/486.pem b/repos/system_upgrade/common/files/prod-certs/8.8/486.pem
new file mode 100644
index 00000000..c5108d61
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/8.8/486.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGJDCCBAygAwIBAgIJALDxRLt/tVM3MA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIyMDcxMjA2NTYzM1oXDTQyMDcw
+NzA2NTYzM1owRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs3ZmU5MDgy
+Mi00NzFiLTRmNDctOGZmNC1jYzVkMGE0MjFmZjJdMIICIjANBgkqhkiG9w0BAQEF
+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
+AgQKDAg4LjggQmV0YTAYBgwrBgEEAZIICQGDZgMECAwGeDg2XzY0MCsGDCsGAQQB
+kggJAYNmBAQbDBlyaGVsLTgscmhlbC04LWJldGEteDg2XzY0MA0GCSqGSIb3DQEB
+CwUAA4ICAQChnxZRwBX1DK/dONKHIsXkbpKdP4xzTF79tt6o6oueR313wGEeC+uS
+SRdbK8HiNC+J8hpgUz3g2RMmoxE7lObm2gkpEtOh7b6dOTOSL+LrmUhm8Ly5Ts4X
+ExY4I5pctcTXx8PaODIPQjpHIrFSqKYtxT9y0z43StUSmM310sg45H+qSM1ilepe
+WTIcDjLldUPNiaHDvu8wqE77khPnoVaP9dZUO7dNkhPkCR0ECN4Q1YrJhUZro9M0
+/pQ5700ev5Sw48Iu8iBW/h6wjpuD8cEFA4eYxRE0T8nVSvPILqK1mt8arGFP8Vch
+d6VIyv503eRwVbq9LQE8WOpC+c53ZmJYe/L5OlJU6oRlTK1ePEKZUaLsPfwHnVXC
+2e7IynDmkG2D2PE2J3br8bIVSmxCoxCp7mH2nwKJGE4EVquTnBfdwS3uCzfHX3p8
+5LGNS460tdymPZF8y4TeL+BAKZYg+l6mLx79ob044OCxsQQbcLY8v50XsTiRpGqH
+ZPLLzastYROQWvI5OhzhXE88HN0CLKCTNPlUeFmFwOw/FYWKjQtwcceuNMmMjeAe
+IZ5MrMyPf0x+MSmlIaPONn5uHmeMp7yvazdgTAkvIsBwq2cuqqFk7xfnqk0iX3zd
+kE4mKzWMJ6Fa3C+yOroNEIJz+AAiD3mgPln7CleKtXRKrvVkyxKa0g==
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/8.8/72.pem b/repos/system_upgrade/common/files/prod-certs/8.8/72.pem
new file mode 100644
index 00000000..703d0ad7
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/8.8/72.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGFjCCA/6gAwIBAgIJALDxRLt/tVMgMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIyMDcxMjA2NTM1NVoXDTQyMDcw
+NzA2NTM1NVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs4YWFkYmY2
+OS0xYTA1LTRjOGYtYTc5MS04YWRlOGZiNThkMzRdMIICIjANBgkqhkiG9w0BAQEF
+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
+AgQFDAM4LjgwFgYLKwYBBAGSCAkBSAMEBwwFczM5MHgwJAYLKwYBBAGSCAkBSAQE
+FQwTcmhlbC04LHJoZWwtOC1zMzkweDANBgkqhkiG9w0BAQsFAAOCAgEAbNQpBfvJ
+GequSRt4hkr4qSqM3TOsVkr6/DpM2CVHsIF6irb5sJaHjwNomw0C6ecE76j9Rm2f
+dK/TCo6vPdSvAcATwyfXBiPvRc+bT4oETBf7FqqMRwPRf35ftBL/4J1JVb/d2rFF
+hO/cu4sLTItSwlnvSuOqMDqmCpa4OfMPdTj16v7iJEkN1gMEIbi7uQdZiusO7En5
+s/w4Dreok+Q98jAKrHHuCoIKAfxMKB+1YPDN6FYfVqMbngnX8X+G4ysED5OWa47b
+qLMh1+VDKBbNmDAYx7PMEDjG3Hb4S6g+Uc5d6MxPccXwKoJTbA6vSuTTVvPL5ex5
+s1NPW50W39oPyV9818qHSmFt4RN+3dxXquBNPePKMugXU/77XKo4zeYE+zGucEph
+HaYbmfDNWp74ZG4qf6wTi91NlkkNiaihLbD17ez3AkWH9qXP37RzJ289eIcu42i5
+uDc82NKakJc4hR5h92Psc7J602gcOl2d23syFrvpMmPqVSjLYMir3ImpwIe7Pn3i
+hgywwGB1QPEnoSc3dPk8FmmFST/ULaU/Ktlc0PwxpirbLO3OTQR3/y4zqxSATWMJ
+Qs4L0ouTwzVJ633+mu+4xIO3wzvtNXHI5Q1mw78D3Xzx5B3Qu7QOkPiNQOKkmKcg
+rzKkOicYZ2gIk0hWdcb7gCJMS1h+8x6FPnE=
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.2/279.pem b/repos/system_upgrade/common/files/prod-certs/9.2/279.pem
new file mode 100644
index 00000000..8bd078f3
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.2/279.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGJTCCBA2gAwIBAgIJALDxRLt/tU8JMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIyMDcxOTEyNDA0N1oXDTQyMDcx
+NDEyNDA0N1owRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs3ZTA5MmI3
+My1hYmYzLTQ5N2QtYWI4Yi03MDg1NWE0OTVjMGNdMIICIjANBgkqhkiG9w0BAQEF
+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
+AQQBkggJAYIXAgQFDAM5LjIwGQYMKwYBBAGSCAkBghcDBAkMB3BwYzY0bGUwJwYM
+KwYBBAGSCAkBghcEBBcMFXJoZWwtOSxyaGVsLTktcHBjNjRsZTANBgkqhkiG9w0B
+AQsFAAOCAgEAAQNrWf/OVdfqx1Ln9b+8EI812sNt+e3TbIT9Qs/jFQ0FeQGZcYsA
+yBkB2uE9D6eBdTfteSk9LGazf7FYsvCCgv+V938qm1cfM+Y6UoUY6kE965w0DLgJ
+Cre/yRP8k3VzBTl5luLt9QX2x3jY/jVGdBKm1L3fJdfgSQQLEikJK+z/Eweiwmfq
+1lB/G9kIDNof3Jmm+TEBI9ToMg1zZBbmAudZGKp/jyDTo0Hnnfbr+TaPAYR8LD8A
+lQNWs2WqKakTLdqm3zKqKBTm0L35KEmBLNK6Gu+43CjBjXd5IGctumUJ7Bklgxm2
+JqFT14jERJrE/YLTmu2JcMz/VzbleRQ5jtl/RmKEnUD3GgyaMujtVu2TOMxB0i8v
+Ovi7Okdf3/VA83T9noW9EYbYFdq+o00oyAxFqQPASYRLVPsyX86OUe5tXo+s1w3D
+fG7sPRP7fvAjWLL+u+BT9V9GppxF1OHbdBitKY/7KocbejkEpTAHVF2y4SJ96aDg
+BXIsf7J78hpyAYdEhbL79djygH5iZloGapJzKHVSQ55Smaj6uIj5RkEAZTjdPmIE
+PGqv74eMswYI6K/B2eHwZmuFaTtgrHfAtgl4jKEnc3qaaaDRpaXAjM25FiZavcC4
+1pr59D/wDv+kRzRK9Qy3iuyDsboeYnU30qPdrry5SCx4qsi80VxSRMM=
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.2/362.pem b/repos/system_upgrade/common/files/prod-certs/9.2/362.pem
new file mode 100644
index 00000000..e783c625
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.2/362.pem
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIGNDCCBBygAwIBAgIJALDxRLt/tU8fMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIyMDcxOTEyNDQ0OVoXDTQyMDcx
+NDEyNDQ0OVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs0Y2YzNmI4
+OC0xM2QyLTQyZWYtYWM2NS1iYWQ1ZTc0ODc2ZWFdMIICIjANBgkqhkiG9w0BAQEF
+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
+GgYMKwYBBAGSCAkBgmoCBAoMCDkuMiBCZXRhMBkGDCsGAQQBkggJAYJqAwQJDAdw
+cGM2NGxlMCwGDCsGAQQBkggJAYJqBAQcDBpyaGVsLTkscmhlbC05LWJldGEtcHBj
+NjRsZTANBgkqhkiG9w0BAQsFAAOCAgEArjsodDEcCbXin1wyhdjpSQhZEmgtO9hX
+myaAAdOaWWrOKV6rSLEL2EhmeT/zCOPdmoErKHQrcdKutr6z9Bw06K1qiFwnfd/5
+SJJtkNBNJFtpTGDZHDG6GSbRg7hA9YbrqSoX6c5UYDX6VcUv9gNXlTIxyIT86kCV
+i4QcS9hH7HvTTtfCnO7W2j47w3sGqt/mLYQWSa2ZzMzbGpBty1tLO5lux9+HVH9z
+aRiiKCHrGXBbo6PiHjcl/Ikxc3rJRLWwI3q5tegC+MjyC2tmQdc1hhXKwZj51EMt
+B+s4bLYv3WmVlcaheN6//aHz+cO6xw6OBVgUt62xBG4XprT7tbTVY1bS7+pQZm0C
+y3eUZxkfofb5k7mJqGxebNGuXZWS1yJuaPc4AGyYvnqskKE6bsJbET71zS2qZnSU
+MqYjVJ0LdoSFgNsgebbG63GovYFJYB/4cFGk2l+21D5bOXTb4CbJmEgBsVzoRXuH
+/YeJSZ++h2Y78hjxFMXeztM5TaN2d/FPm41jN9fDeCwN0XZAhVLtvrizobEj/rZF
+fF3om6ETcg7cRn7l00zsQGZeAjMDYXjQprcj074ER2Oz+6/nGuOlgBXgn76jm/2E
+oomPas/YcyxOrG1V4oZAzyedOCuU+51iJK3qJXMYG/a4X8TXv5sKu/DpfLpIbaze
+oRQ+8ay5+ys=
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.2/363.pem b/repos/system_upgrade/common/files/prod-certs/9.2/363.pem
new file mode 100644
index 00000000..2afb74db
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.2/363.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGJjCCBA6gAwIBAgIJALDxRLt/tU8eMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIyMDcxOTEyNDQ0NVoXDTQyMDcx
+NDEyNDQ0NVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFtmYjE2MTNh
+OS04YjcyLTRiOTUtOGE0Yy0zNmNiZTVmMjg2MGNdMIICIjANBgkqhkiG9w0BAQEF
+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
+AgQKDAg5LjIgQmV0YTAZBgwrBgEEAZIICQGCawMECQwHYWFyY2g2NDAsBgwrBgEE
+AZIICQGCawQEHAwacmhlbC05LHJoZWwtOS1iZXRhLWFhcmNoNjQwDQYJKoZIhvcN
+AQELBQADggIBAK9GawETqhJTkT0VUEQt9Kn4s92TRaEMB4/X5pWDOG4BBQu5T3LV
+9xKelt6eVXPLvjytY3EgCZxm5xc+1zE/Gf9yypgH0vtNFqOr+/U9fn6YOfAwvDqo
+2ozNAmA11m5TKi57IGhQJGTaxJdKdOk3NEuwMcD1TfQqDtqMF27OnWdO501URJJW
+e52b0NraoeF6OicDKLgxc31fv457CcwT3k/GyAgmR31PXWkoySiB+Np/xf0uJQvf
+2iI1V4iqfcygMqniJsjEi2IMcLXBxs9DdFRPDMeVkmO3JKXCFjV+sHZB9LbsRh1o
+LTnAnEvfWx1nWUc3t9lwS54HlSKfOyPt/c+tPiXCHa19p+Z8gqk7KyztTMB1JeIE
+0HdjFfwino66rcEshfBEe3mq3ohY4Yq79PACKmbVVqYanBiRAvoR7j7cZROvEmGJ
+pq9qUZ91w4OwDx5G/IIUZVafGkVAiLACK3ACala4CQZmB/UKSihwnPiWXj7sdnYz
+CjEyk/z9q2zaFvB/H3fQdol0Vy66eQ+DPRO+eMnppCvG6SI5nah0ZJSnfmR+26Mc
+IeR2KzRoN1kwVMzMh3qOpSaneDOQTQONzzzmeOqVQohRbz9cfYZor99l8/LLXce6
+sH9LlaFP3aHoB5cdGyirTsB8Z65x/1y/4UrqdwdfO0o+DZH8kkhJ9roH
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.2/419.pem b/repos/system_upgrade/common/files/prod-certs/9.2/419.pem
new file mode 100644
index 00000000..f35743dc
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.2/419.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGFzCCA/+gAwIBAgIJALDxRLt/tU8IMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIyMDcxOTEyNDA0MloXDTQyMDcx
+NDEyNDA0MlowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFthYzI5ZTA3
+Ni1mY2ViLTRhMTEtYjM3Yi03M2YxOGFiOTAzMmRdMIICIjANBgkqhkiG9w0BAQEF
+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
+OS4yMBkGDCsGAQQBkggJAYMjAwQJDAdhYXJjaDY0MCcGDCsGAQQBkggJAYMjBAQX
+DBVyaGVsLTkscmhlbC05LWFhcmNoNjQwDQYJKoZIhvcNAQELBQADggIBAGxyb6Sk
+QPbMUsdNVwMo5lL7yR/O8JsKfMgwnXgp4szymjgCRdYKAmk/TeceuHnM+1YxxyN2
+n11Oy67Vlcchpy5Vo9m1GjSk3oQ0biyJgSgMEoHdWPCwFYDTABMK5U/4Df7wBw/q
+4TvnaX5EhYO4nQo7Pc0A4eFOvyeKv6lTw0Rv5WNHFCMZSQLdPSpGLHZYMF0lyl/p
+yAQHpSkDFaB1mMvQLu9r7FbeRm2M8eyaRp1Ok4Ypxr2yXoBUQm3YPCpBBIwnqyD5
+trnpYkjncxe9q2DSRpYgRLEmu+2Qm5WbrJ0zZKYcs/jZbaH5mrWvNCLy5u3h442V
+vHEX+ITDyuB0507ORxOpyt+k2+JenEcYNg7aHn/fUnsWjutGfEY4aDIVOnZxAf31
+DLDJXPH4/jjO9dd/4fKykgLP8OUq5x+VXAtufpyDUyYVqXnIXwfUPN0NSl8gtUKJ
+ruHJ7gNyYqdopMquuOWb/Mew2DnwXFA9b3goYBbdaCzkt7k9Zdafzz6Mu1NnxUkf
+tMyJOmPBCZSDHRilTA/dA+8Lvj+2H6q7aEFzLv1saAoktxB/fggpBJm3jRs4dy3T
+xbcWnF++VANF6LQ+5bI8dxX6/FC5/zjJd1oEoiIS7dcFUZ0uf6x5aBuzjB+c2G0C
+MnR4x3OKYQl6cy3pFJkQNgLoAHXVRsNOmVe6
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.2/433.pem b/repos/system_upgrade/common/files/prod-certs/9.2/433.pem
new file mode 100644
index 00000000..8af44fae
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.2/433.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGKTCCBBGgAwIBAgIJALDxRLt/tU8gMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIyMDcxOTEyNDQ1NFoXDTQyMDcx
+NDEyNDQ1NFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs1Y2E3YWM5
+Ny0yMmZhLTRmZDUtODU3My04NTc1YjAxOWQ5N2RdMIICIjANBgkqhkiG9w0BAQEF
+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
+AZIICQGDMQIECgwIOS4yIEJldGEwFwYMKwYBBAGSCAkBgzEDBAcMBXMzOTB4MCoG
+DCsGAQQBkggJAYMxBAQaDBhyaGVsLTkscmhlbC05LWJldGEtczM5MHgwDQYJKoZI
+hvcNAQELBQADggIBAM/RY5sRACnyRmPKq0fGBuApNJU/m8q116Ls6FSpgZiz5xa5
+qUaWW2UHn/oFdXd7A3kaLL/9VbrFVfuC/wiz+te0EqHy2NPwlGgKmbVjFZn4PcoG
+YzTopv5bwr90WONkLt7jDbhls8ZbGgPY6qUDA2TbtvHPDNPIM9ukoin9BrurksUS
+XJ9UsV3jHV9yye/u6nM5FZmc9E0IagoS/asd0B3Y3egkbCn5bcfyYvV2Y8cn5/gg
+SucFU1KIwxLOs+J61RfaFh5O/22ZJtPG/7zMYXPk/Luas0YZUEiVFjc4BWQRmM94
+dF142BpwOX9L5LBMtMhuB0sWpov7wlQamFiP2ZtsVLQgoqFKW3MXHZNy3f1FQM10
+ei9lglw7qrhoeKj7UtedL4zJREtr4fhG3TzLhDqa8GvIEr+JAPtg2eRslO6uu67e
+RdE2AIYY6HWKQ5FcEfkCdW/hFFeVr0MjvBgQCYJlO8fmHxgOAQSKjjAzyRVAcjTk
+x+8v69ucZ3uMZb6oFUZH+p67XuduCm3sQCFk+Ilscr/8E/MNB4x0bPCIXLK6T3aQ
+9JKBxofBKtTSzyxEFEXqYLYJyQrAKXVpOgOrAMmeLHwA3IoikVG1x6/GwVuYTBUA
+B0lW/aO8mL0caQyebnE4fpYef5GzrtvOt2rGB54N/3AipD5dOW/AeYP/Wcj0
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.2/479.pem b/repos/system_upgrade/common/files/prod-certs/9.2/479.pem
new file mode 100644
index 00000000..7ed95967
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.2/479.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGFTCCA/2gAwIBAgIJALDxRLt/tU8LMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIyMDcxOTEyNDA1NloXDTQyMDcx
+NDEyNDA1NlowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs0ZmU2ODU0
+NC0yYjYwLTRiOGYtODdhYS02MzkxNWJkNGMyMjhdMIICIjANBgkqhkiG9w0BAQEF
+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
+OS4yMBgGDCsGAQQBkggJAYNfAwQIDAZ4ODZfNjQwJgYMKwYBBAGSCAkBg18EBBYM
+FHJoZWwtOSxyaGVsLTkteDg2XzY0MA0GCSqGSIb3DQEBCwUAA4ICAQA0Sgnj5BjL
+2p4U7R/TOMhkP/7Tm4AkdmMvhkUb7c0tZhY3jJaJJt2U9IBTd8sN5Z/mb3Zr03dQ
+8gOb5mpfMGVrwoMjgDhZniRJ6/0yPKrgiRbGijHS6mXkU4dkzh6N/HyBjpQUuOaK
+5isXArEx7kv3k0Hun2DPdw8oBhXgH7x0TL3K3Yz+VXiX6Tcn4tlMTTBuR8NngP57
+V9xmtLncR8rSdNr8j7cxAoXGaSPlE4K0cTGz87gAja6702CVk8ueB8bU68S47ZEK
+xLDcj1iWiVjYiZSFO7gWFavrlitEE+yW8c6oLVVXKfA8TxrJ1VuSTqU+fOojx5sM
+qtNqeMPLzz80M6dNrfuOJ+FHuwXu6Ytj8u/u24ds12TU7NCV9YLyfB2NDhueALtr
+/6OKlANU4DdxdL3947KGnnQZLpEpDpvsgOUBFGOivNIbHt0QXpV9tnMwsWx6tQ82
+exnin3PJBkR2rg5/xv9ZXNb4WdYA3FwLsyej9gM7S4rFgMZzr7n2S5Dd8v9kRYHl
+JGUdY3LsY+SfxyYNalJirt3JxeIuLg0QZIXQP0BwBX92zZb+Zw4MxI1AcJvxsGkf
+7vGqTnIlPPER+IdK6SNeF3yJ4FQb6U1WMAyw0yqFPm4s7asaV/aULZu6+p13NlKZ
+r331U/otUJX8S2irN9kUt/oKdV/MVlgsFg==
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.2/486.pem b/repos/system_upgrade/common/files/prod-certs/9.2/486.pem
new file mode 100644
index 00000000..c786ea82
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.2/486.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGJDCCBAygAwIBAgIJALDxRLt/tU8hMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIyMDcxOTEyNDQ1OFoXDTQyMDcx
+NDEyNDQ1OFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFsyMzg4MDQx
+Yy1iYWMxLTRmZGEtYWJjZS0zNWNkMGY5MzQxMDRdMIICIjANBgkqhkiG9w0BAQEF
+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
+AgQKDAg5LjIgQmV0YTAYBgwrBgEEAZIICQGDZgMECAwGeDg2XzY0MCsGDCsGAQQB
+kggJAYNmBAQbDBlyaGVsLTkscmhlbC05LWJldGEteDg2XzY0MA0GCSqGSIb3DQEB
+CwUAA4ICAQAHqIuoFbUAfhRFzLGeuTaJVidWk7nbmwyGKOHBDHannogHXSxJM5nt
+Ct5vFqG7uC0UE0JgUPz/q2o6iFhro3slfvWHA1sW83XN+yiaTtDIQl8Y7O7n4wJ1
+NXH7mRC/L+58P1/HJ3gEaBdBfKiHte6J8FPonuRkfJrREiPgo+B9zNf0BEjl6xqr
+7SgfJZMO257Lkg3/Tl4amZ8M/cm/P/Z+kprfvUDsJzBQJ1z7qhriUuXFJfS799mG
++UV/wO0ZtdhGaHAXR28/MmtearogcM9rhp9DfdqmKdhktIcoHBuDXLUxnwUhX+W3
+AJTNf7YwyYUKEHzhPLJH8v0JH8N/Cfd2PQHrQ1zni0D3BXTygHrbDEWZDm+3jSOF
+joyEIFHlWIb7eF67a7x/7iiS2op07E0Ka3h3SYHy/l+WvqPg8O28Zz3U6o1dCtBT
+odDtz9FVcGJ1MhMZ3F71XvM+TNEASJW1aK0bRoJMUXZ1krtHWUCsZuea3X5JAOey
+CycnOcUkvu8tzIOmgaqPmeolG/tKdlEY90Sc8XLw/KWsW0tfqqU9weppoZnCqPyp
+8YQiUEumjpGOtZUJRvootlBN9CQH8ilCOl1c4CsGdcmnXwnC0Z8gYzM+HhcqYenD
+Y+O3lNd3WsLoQrGfj2dMYWnKFOLKJovaYpOXiQOW6ghpM5bWdqVIuQ==
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.2/72.pem b/repos/system_upgrade/common/files/prod-certs/9.2/72.pem
new file mode 100644
index 00000000..dabf8506
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.2/72.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGFjCCA/6gAwIBAgIJALDxRLt/tU8KMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIyMDcxOTEyNDA1MVoXDTQyMDcx
+NDEyNDA1MVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs1YWUwNTdk
+ZC1kMWI3LTQ4NzEtYTA5MS0wYzY4MzcxMTkyZDldMIICIjANBgkqhkiG9w0BAQEF
+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
+AgQFDAM5LjIwFgYLKwYBBAGSCAkBSAMEBwwFczM5MHgwJAYLKwYBBAGSCAkBSAQE
+FQwTcmhlbC05LHJoZWwtOS1zMzkweDANBgkqhkiG9w0BAQsFAAOCAgEApFHsXGnC
+mGFM6yMkJYDGxYGDdsOY0xl0IMT6m2bvMRlbcykLhOL/CxwjZsS/mGPeHG4Q44+e
+pq+xMh3013klRN9iZoKFHSBTuXHDxzjjEPYR414O7FehNB82f3GlkLv6z57WeAxw
+wAqPvFcsIACzVEDOvSWQzn5aDEJURHT2caax/Psm+NT5nBneueySIOe5FDZmpgDJ
+7xqnUCaniM8RN4YlNQLm8V5wM9akiIhp/60Pq4bqSvlN23vOQ/QOTUtGyGlBtsGs
+LVhR0ssaTKlHbA+1xntZkEjNI229PcFFYeWXw5Fn/18l/ulfGCmbOMuRfDpC15Wl
+dLGETkpUVcflhJOloYcaPi+6RSXEMqyMSgLfN0k1IDJdV2Gh0Ok+HUYlxgPZ07+Q
+OW2jky9+tC2kLDh424J1sZUB+M/ONGJGHwXBHsIqMcbhVzDpGpHkQoMt6jDWw+li
+mHmwmSqKGxH/uhnVepSH6iJi4pF16YhrteW4wjtmrFFp7RsvxggqfHL8IgZSZ/Es
+pvTqSygWCU6hHoHdQdIrVph1VYSpvNyaEsopj+4F8oHSzC+sXQ+4iJ++CpCFised
+pG34sx+vFi/kcRnYnd8z20dbSVeH2j2+WSaYiV53mxUdA/Hp9XEn2u7p8WWIcv79
+21f+YSbmvDuP6xg5D/l9lg1q6FljH6NcpBE=
+-----END CERTIFICATE-----
--
2.38.1

View File

@ -0,0 +1,52 @@
From 7aab954d2ed9fcdd67ceb4c6a783fafbd6021c8a Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Wed, 16 Nov 2022 20:19:34 +0100
Subject: [PATCH 32/37] Introduce new upgrade paths 8.8/9.2
The new enabled upgrade paths are:
RHEL 7.9 -> 8.8, 8.6 (default: 8.8)
RHEL 8.8 -> 9.2
Keeping some previous upgrade paths still opened, but expecting
dropping them before the release.
---
repos/system_upgrade/common/files/upgrade_paths.json | 7 ++++---
repos/system_upgrade/common/libraries/config/version.py | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/repos/system_upgrade/common/files/upgrade_paths.json b/repos/system_upgrade/common/files/upgrade_paths.json
index 11d52423..c48d916f 100644
--- a/repos/system_upgrade/common/files/upgrade_paths.json
+++ b/repos/system_upgrade/common/files/upgrade_paths.json
@@ -1,11 +1,12 @@
{
"default": {
"7.6": ["8.4", "8.6"],
- "7.9": ["8.4", "8.6"],
+ "7.9": ["8.6", "8.8"],
"8.6": ["9.0"],
"8.7": ["9.0"],
- "7": ["8.4", "8.6"],
- "8": ["9.0"]
+ "8.8": ["9.2"],
+ "7": ["8.6", "8.8"],
+ "8": ["9.2"]
},
"saphana": {
"7.9": ["8.2", "8.6"],
diff --git a/repos/system_upgrade/common/libraries/config/version.py b/repos/system_upgrade/common/libraries/config/version.py
index e148932a..7104bdc5 100644
--- a/repos/system_upgrade/common/libraries/config/version.py
+++ b/repos/system_upgrade/common/libraries/config/version.py
@@ -14,7 +14,7 @@ OP_MAP = {
_SUPPORTED_VERSIONS = {
# Note: 'rhel-alt' is detected when on 'rhel' with kernel 4.x
'7': {'rhel': ['7.9'], 'rhel-alt': ['7.6'], 'rhel-saphana': ['7.9']},
- '8': {'rhel': ['8.6', '8.7'], 'rhel-saphana': ['8.6']},
+ '8': {'rhel': ['8.6', '8.7', '8.8'], 'rhel-saphana': ['8.6']},
}
--
2.38.1

View File

@ -0,0 +1,46 @@
From d6ddc8e6250bf3c07633a84b81e8f4b66c23c0e5 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Fri, 25 Nov 2022 17:11:26 +0100
Subject: [PATCH 33/37] testutils: Implement get_common_tool_path method
---
repos/system_upgrade/common/libraries/testutils.py | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/repos/system_upgrade/common/libraries/testutils.py b/repos/system_upgrade/common/libraries/testutils.py
index fc20aa3b..c538af1a 100644
--- a/repos/system_upgrade/common/libraries/testutils.py
+++ b/repos/system_upgrade/common/libraries/testutils.py
@@ -75,7 +75,9 @@ class CurrentActorMocked(object): # pylint:disable=R0904
release = namedtuple('OS_release', ['release_id', 'version_id'])(release_id, src_ver)
self._common_folder = '../../files'
+ 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)
@@ -87,6 +89,9 @@ class CurrentActorMocked(object): # pylint:disable=R0904
def get_common_folder_path(self, folder):
return os.path.join(self._common_folder, folder)
+ def get_common_tool_path(self, name):
+ return os.path.join(self._common_tools_folder, name)
+
def consume(self, model):
return iter(filter( # pylint:disable=W0110,W1639
lambda msg: isinstance(msg, model), self._msgs
@@ -149,9 +154,6 @@ class CurrentActorMocked(object): # pylint:disable=R0904
def get_tool_path(self, name):
raise NotImplementedError
- def get_common_tool_path(self, name):
- raise NotImplementedError
-
def get_actor_tool_path(self, name):
raise NotImplementedError
--
2.38.1

View File

@ -0,0 +1,91 @@
From f1c00a3823751d3fccaba3c98be86eba2b16930c Mon Sep 17 00:00:00 2001
From: Petr Stodulka <xstodu05@gmail.com>
Date: Sat, 26 Nov 2022 12:27:46 +0100
Subject: [PATCH 34/37] targetuserspacecreator: improve copy of /etc/pki
(rpm-gpg)
The original solution copied /etc/pki from the host into the
target userspace container if the upgrade has been performed with
RHSM, which causes several negative impacts:
a) certificates are missing inside the container when upgrading
without RHSM (still issue)
- Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2040706
b) the target OS certificates are replaced by the original OS
certificates when upgrading with RHSM (partially fixed)
This commit partially fixes the case b), so we preserve target
certificates inside the container only from the /etc/pki/rpm-gpg
directory when upgrading with RHSM. If files or directories with
the same name exists inside, prefered are those from the target OS.
For the full fix of this case. The full fix should preserve
all certificates owned by packages inside the container, and only
"new files" from the host should be applied. This is also prerequisite
to be able to fix the case a).
To be able to fix the case a) we would need to make this behaviour
unconditional (not dependent on the use of RHSM). Which most likely
should resolve the bug 2040706. Which needs the full fix of the case
b) first, as described above. The unconditional copy of /etc/pki
currently breaks upgrades on systems using RHUI (at least on
Azure for IPU 8 -> 9, other clouds could be affected also).
So postponing the sollution to a followup PR.
---
.../libraries/userspacegen.py | 32 +++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
index 5a6a80f2..0415f0fe 100644
--- a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
+++ b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
@@ -235,6 +235,33 @@ def _get_files_owned_by_rpms(context, dirpath, pkgs=None):
return files_owned_by_rpms
+def _copy_certificates(context, target_userspace):
+ """
+ Copy the needed cetificates into the container, but preserve original ones
+
+ Some certificates are already installed in the container and those are
+ default certificates for the target OS. We know we should preserve at
+ least certificates located at rpm-gpg directory. So preserve these for
+ now at least.
+ """
+ target_pki = os.path.join(target_userspace, 'etc', 'pki')
+ backup_pki = os.path.join(target_userspace, 'etc', 'pki.backup')
+
+ # FIXME(pstodulk): search for all files owned by RPMs inside the container
+ # before the mv, and all such files restore
+ # - this is requirement to not break IPU with RHUI when making the copy
+ # of certificates unconditional
+ run(['mv', target_pki, backup_pki])
+ context.copytree_from('/etc/pki', target_pki)
+
+ # TODO(pstodulk): restore the files owned by rpms instead of the code below
+ for fname in os.listdir(os.path.join(backup_pki, 'rpm-gpg')):
+ src_path = os.path.join(backup_pki, 'rpm-gpg', fname)
+ dst_path = os.path.join(target_pki, 'rpm-gpg', fname)
+ run(['rm', '-rf', dst_path])
+ run(['cp', '-a', src_path, dst_path])
+
+
def _prep_repository_access(context, target_userspace):
"""
Prepare repository access by copying all relevant certificates and configuration files to the userspace
@@ -243,9 +270,10 @@ def _prep_repository_access(context, target_userspace):
target_yum_repos_d = os.path.join(target_etc, 'yum.repos.d')
backup_yum_repos_d = os.path.join(target_etc, 'yum.repos.d.backup')
if not rhsm.skip_rhsm():
- run(['rm', '-rf', os.path.join(target_etc, 'pki')])
+ # TODO: make the _copy_certificates unconditional. keeping it conditional
+ # due to issues causing on RHUI
+ _copy_certificates(context, target_userspace)
run(['rm', '-rf', os.path.join(target_etc, 'rhsm')])
- context.copytree_from('/etc/pki', os.path.join(target_etc, 'pki'))
context.copytree_from('/etc/rhsm', os.path.join(target_etc, 'rhsm'))
# NOTE: we cannot just remove the original target yum.repos.d dir
# as e.g. in case of RHUI a special RHUI repofiles are installed by a pkg
--
2.38.1

View File

@ -0,0 +1,75 @@
From 9628970bf0d5a7db6553c57b55f4623c91330228 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Thu, 24 Nov 2022 12:48:51 +0100
Subject: [PATCH 35/37] DNFWorkaround: extend the model by script_args
The original model provided a possibility to execute a script
that will handle problems before the DNF / RPM transaction,
in correct contexts (overlay, host system, ..) before any use
of the upgrade dnf plugin.
But current solution provided only the script_path field, which
suggests it should contain only the path to the script. The executed
command (inside a context) looked like this:
bash -c script_path
However we have realized we need to be able to execute a script
with additional arguments. Regarding that, introducing
the script_args field. SO the final command looks like this:
bash -c 'script_path arg1 arg2..'
when script_args are specified. The default is set to an empty
list.
---
.../common/libraries/dnfplugin.py | 9 ++++++++-
.../common/models/dnfworkaround.py | 18 ++++++++++++++++--
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/repos/system_upgrade/common/libraries/dnfplugin.py b/repos/system_upgrade/common/libraries/dnfplugin.py
index 0a546637..0ef9ea9b 100644
--- a/repos/system_upgrade/common/libraries/dnfplugin.py
+++ b/repos/system_upgrade/common/libraries/dnfplugin.py
@@ -241,7 +241,14 @@ def apply_workarounds(context=None):
for workaround in api.consume(DNFWorkaround):
try:
api.show_message('Applying transaction workaround - {}'.format(workaround.display_name))
- context.call(['/bin/bash', '-c', workaround.script_path])
+ if workaround.script_args:
+ cmd_str = '{script} {args}'.format(
+ script=workaround.script_path,
+ args=' '.join(workaround.script_args)
+ )
+ else:
+ cmd_str = workaround.script_path
+ context.call(['/bin/bash', '-c', cmd_str])
except (OSError, CalledProcessError) as e:
raise StopActorExecutionError(
message=('Failed to execute script to apply transaction workaround {display_name}.'
diff --git a/repos/system_upgrade/common/models/dnfworkaround.py b/repos/system_upgrade/common/models/dnfworkaround.py
index c921c5fc..4a813dcd 100644
--- a/repos/system_upgrade/common/models/dnfworkaround.py
+++ b/repos/system_upgrade/common/models/dnfworkaround.py
@@ -15,6 +15,20 @@ class DNFWorkaround(Model):
topic = SystemInfoTopic
script_path = fields.String()
- """ Absolute path to a bash script to execute """
+ """
+ Absolute path to a bash script to execute
+ """
+
+ script_args = fields.List(fields.String(), default=[])
+ """
+ Arguments with which the script should be executed
+
+ In case that an argument contains a whitespace or an escapable character,
+ the argument must be already treated correctly. e.g.
+ `script_args = ['-i', 'my\\ string']
+ """
+
display_name = fields.String()
- """ Name to display for this script when executed """
+ """
+ Name to display for this script when executed
+ """
--
2.38.1

View File

@ -0,0 +1,57 @@
From 2277012bc6aab1f473eda8070b48d75487a41bb7 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Thu, 24 Nov 2022 17:57:12 +0100
Subject: [PATCH 36/37] Introduce theimportrpmgpgkeys tool script
The script can be used to import gpg keys from a particular file
or files inside a directory. Expected to be executed like:
importrpmgpgkey <absolute-path>
---
.../common/tools/importrpmgpgkeys | 35 +++++++++++++++++++
1 file changed, 35 insertions(+)
create mode 100755 repos/system_upgrade/common/tools/importrpmgpgkeys
diff --git a/repos/system_upgrade/common/tools/importrpmgpgkeys b/repos/system_upgrade/common/tools/importrpmgpgkeys
new file mode 100755
index 00000000..79e5c580
--- /dev/null
+++ b/repos/system_upgrade/common/tools/importrpmgpgkeys
@@ -0,0 +1,35 @@
+#!/usr/bin/bash -ef
+
+log_error() {
+ echo >&2 "Error: $1"
+}
+
+log_info() {
+ echo >&2 "Info: $1"
+}
+
+if [ "$#" -eq 0 ]; then
+ log_error "Missing the required path to the directory with trusted GPG keys."
+ exit 1
+elif [ "$#" -ge 2 ]; then
+ log_error "Expected only one argument, received $#. Possibly unescaped whitespaces? '$*'"
+ exit 1
+fi
+
+if [ ! -e "$1" ]; then
+ log_error "The $1 directory does not exist."
+ exit 1
+fi
+
+error_flag=0
+IFS=$'\n'
+# shellcheck disable=SC2044
+for key_file in $(find -L "$1" -type f); do
+ log_info "Importing GPG keys from: $key_file"
+ rpm --import "$key_file" || {
+ error_flag=2
+ log_error "Unable to import GPG keys from: $key_file"
+ }
+done
+
+exit $error_flag
--
2.38.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,68 @@
From 56da8453683c529c62823aedda2d3b81d1a55a0f Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Tue, 29 Nov 2022 22:18:50 +0100
Subject: [PATCH] missinggpgkey: polish the report msg
---
.../libraries/missinggpgkey.py | 26 ++++++++++++++-----
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/repos/system_upgrade/common/actors/missinggpgkeysinhibitor/libraries/missinggpgkey.py b/repos/system_upgrade/common/actors/missinggpgkeysinhibitor/libraries/missinggpgkey.py
index b8b28df2..7f038ee0 100644
--- a/repos/system_upgrade/common/actors/missinggpgkeysinhibitor/libraries/missinggpgkey.py
+++ b/repos/system_upgrade/common/actors/missinggpgkeysinhibitor/libraries/missinggpgkey.py
@@ -21,6 +21,7 @@ from leapp.models import (
from leapp.utils.deprecation import suppress_deprecation
GPG_CERTS_FOLDER = 'rpm-gpg'
+FMT_LIST_SEPARATOR = '\n - '
def _gpg_show_keys(key_path):
@@ -251,16 +252,29 @@ def _report_missing_keys(missing_keys):
# TODO(pstodulk): polish the report, use FMT_LIST_SEPARATOR
# the list of keys should be mentioned in the summary
summary = (
- "Some of the target repositories require GPG keys that are missing from the current"
- " RPM DB. Leapp will not be able to verify packages from these repositories during the upgrade process."
+ 'Some of the target repositories require GPG keys that are not installed'
+ ' in the current RPM DB or are not stored in the {trust_dir} directory.'
+ ' Leapp is not able to guarantee validity of such gpg keys and manual'
+ ' review is required, so any spurious keys are not imported in the system'
+ ' during the in-place upgrade.'
+ ' The following additional gpg keys are required to be imported during'
+ ' the upgrade:{sep}{key_list}'
+ .format(
+ trust_dir=_get_path_to_gpg_certs(),
+ sep=FMT_LIST_SEPARATOR,
+ key_list=FMT_LIST_SEPARATOR.join(missing_keys)
+ )
)
hint = (
- "Please, review the following list and import the GPG keys before "
- "continuing the upgrade:\n * {}".format('\n * '.join(missing_keys))
+ 'Check the listed GPG keys they are valid and import them into the'
+ ' host RPM DB or store them inside the {} directory prior the upgrade.'
+ ' If you want to proceed the in-place upgrade without checking any RPM'
+ ' signatures, execute leapp with the `--nogpgcheck` option.'
+ .format(_get_path_to_gpg_certs())
)
reporting.create_report(
[
- reporting.Title("Missing GPG key from target system repository"),
+ reporting.Title('Detected unknown GPG keys for target system repositories'),
reporting.Summary(summary),
reporting.Severity(reporting.Severity.HIGH),
reporting.Groups([reporting.Groups.REPOSITORY, reporting.Groups.INHIBITOR]),
@@ -351,7 +365,7 @@ def process():
if not fps:
# TODO: for now. I think it should be treated better
api.current_logger().warning(
- "Cannot get any gpg key from the file: {}".format(gpgkey_url)
+ 'Cannot get any gpg key from the file: {}'.format(gpgkey_url)
)
continue
for fp in fps:
--
2.38.1

View File

@ -2,7 +2,7 @@
%global repositorydir %{leapp_datadir}/repositories
%global custom_repositorydir %{leapp_datadir}/custom-repositories
%define leapp_repo_deps 7
%define leapp_repo_deps 8
%if 0%{?rhel} == 7
%define leapp_python_sitelib %{python2_sitelib}
@ -42,25 +42,59 @@ py2_byte_compile "%1" "%2"}
Name: leapp-repository
Version: 0.17.0
Release: 1%{?dist}.2
Release: 5%{?dist}
Summary: Repositories for leapp
License: ASL 2.0
URL: https://oamg.github.io/leapp/
Source0: https://github.com/oamg/%{name}/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz
Source1: deps-pkgs-7.tar.gz
Source1: deps-pkgs-8.tar.gz
# NOTE: Our packages must be noarch. Do no drop this in any way.
BuildArch: noarch
### PATCHES HERE
# Patch0001: filename.patch
Patch0001: 0001-CheckVDO-Ask-user-only-faiulres-and-undetermined-dev.patch
## DO NOT REMOVE THIS PATCH UNLESS THE RUBYGEM-IRB ISSUE IS RESOLVED IN ACTORS!
# See: https://bugzilla.redhat.com/show_bug.cgi?id=2030627
Patch0004: 0004-Enforce-the-removal-of-rubygem-irb-do-not-install-it.patch
Patch0005: 0005-rhui-azure-sap-apps-consider-RHUI-client-as-signed.patch
Patch0006: 0006-rhui-azure-sap-apps-handle-EUS-SAP-Apps-content-on-R.patch
Patch0007: 0007-checksaphana-Move-to-common.patch
Patch0008: 0008-checksaphana-Adjust-for-el7toel8-and-el8toel9-requir.patch
# TMP patches - remove them when rebase
Patch0005: 0005-Disable-isort-check-for-deprecated-imports.patch
Patch0006: 0006-Add-codespell-GitHub-actions-workflow-for-spell-chec.patch
Patch0007: 0007-Mini-updateds-in-the-spec-files.patch
Patch0008: 0008-CheckVDO-Ask-user-only-faiulres-and-undetermined-dev.patch
Patch0009: 0009-Add-actors-for-checking-and-setting-systemd-services.patch
Patch0010: 0010-migratentp-Replace-reports-with-log-messages.patch
Patch0011: 0011-migratentp-Catch-more-specific-exception-from-ntp2ch.patch
Patch0012: 0012-migratentp-Don-t-raise-StopActorExecutionError.patch
Patch0013: 0013-Make-shellcheck-happy-again.patch
Patch0014: 0014-actor-firewalld-support-0.8.z.patch
Patch0015: 0015-Scanpkgmanager-detect-proxy-configuration.patch
Patch0016: 0016-Merge-of-the-yumconfigscanner-actor-into-the-scanpkg.patch
Patch0017: 0017-firewalldcheckallowzonedrifting-Fix-the-remediation-.patch
Patch0018: 0018-rhui-azure-sap-apps-consider-RHUI-client-as-signed.patch
Patch0019: 0019-rhui-azure-sap-apps-handle-EUS-SAP-Apps-content-on-R.patch
Patch0020: 0020-checksaphana-Move-to-common.patch
Patch0021: 0021-checksaphana-Adjust-for-el7toel8-and-el8toel9-requir.patch
Patch0022: 0022-Add-an-actor-that-enables-device_cio_free.service-on.patch
Patch0023: 0023-Add-the-scanzfcp-actor-handling-the-IPU-with-ZFCP-s3.patch
Patch0024: 0024-ziplconverttoblscfg-bind-mount-dev-boot-into-the-use.patch
Patch0025: 0025-Provide-common-information-about-systemd.patch
Patch0026: 0026-systemd-Move-enable-disable-reenable-_unit-functions.patch
Patch0027: 0027-Fix-broken-or-incorrect-systemd-symlinks.patch
Patch0028: 0028-Add-check-for-systemd-symlinks-broken-before-the-upg.patch
Patch0029: 0029-checksystemdservicestasks-update-docstrings-extend-t.patch
Patch0030: 0030-Support-IPU-using-a-target-RHEL-installation-ISO-ima.patch
Patch0031: 0031-Add-prod-certs-for-8.8-9.2-Beta-GA.patch
Patch0032: 0032-Introduce-new-upgrade-paths-8.8-9.2.patch
Patch0033: 0033-testutils-Implement-get_common_tool_path-method.patch
Patch0034: 0034-targetuserspacecreator-improve-copy-of-etc-pki-rpm-g.patch
Patch0035: 0035-DNFWorkaround-extend-the-model-by-script_args.patch
Patch0036: 0036-Introduce-theimportrpmgpgkeys-tool-script.patch
Patch0037: 0037-Enable-gpgcheck-during-IPU-add-nogpgcheck-CLI-option.patch
Patch0038: 0038-missinggpgkey-polish-the-report-msg.patch
%description
@ -100,7 +134,7 @@ Conflicts: leapp-upgrade-el7toel8
%endif
# IMPORTANT: everytime the requirements are changed, increment number by one
# IMPORTANT: every time the requirements are changed, increment number by one
# - same for Provides in deps subpackage
Requires: leapp-repository-dependencies = %{leapp_repo_deps}
@ -112,6 +146,10 @@ Requires: leapp-framework >= 3.1
# tool to be installed as well.
Requires: leapp
# Used to determine RHEL version of a given target RHEL installation image -
# uncompressing redhat-release package from the ISO.
Requires: cpio
# The leapp-repository rpm is renamed to %%{lpr_name}
Obsoletes: leapp-repository < 0.14.0-5
Provides: leapp-repository = %{version}-%{release}
@ -134,7 +172,7 @@ Leapp repositories for the in-place upgrade to the next major version
of the Red Hat Enterprise Linux system.
# This metapackage should contain all RPM dependencies exluding deps on *leapp*
# This metapackage should contain all RPM dependencies excluding deps on *leapp*
# RPMs. This metapackage will be automatically replaced during the upgrade
# to satisfy dependencies with RPMs from target system.
%package -n %{lpr_name}-deps
@ -143,7 +181,7 @@ Summary: Meta-package with system dependencies of %{lpr_name} package
# The package has been renamed, so let's obsoletes the old one
Obsoletes: leapp-repository-deps < 0.14.0-5
# IMPORTANT: everytime the requirements are changed, increment number by one
# IMPORTANT: every time the requirements are changed, increment number by one
# - same for Requires in main package
Provides: leapp-repository-dependencies = %{leapp_repo_deps}
##################################################
@ -194,12 +232,42 @@ Requires: dracut
# APPLY PATCHES HERE
# %%patch0001 -p1
%patch0001 -p1
%patch0004 -p1
%patch0005 -p1
%patch0006 -p1
%patch0007 -p1
%patch0008 -p1
%patch0009 -p1
%patch0010 -p1
%patch0011 -p1
%patch0012 -p1
%patch0013 -p1
%patch0014 -p1
%patch0015 -p1
%patch0016 -p1
%patch0017 -p1
%patch0018 -p1
%patch0019 -p1
%patch0020 -p1
%patch0021 -p1
%patch0022 -p1
%patch0023 -p1
%patch0024 -p1
%patch0025 -p1
%patch0026 -p1
%patch0027 -p1
%patch0028 -p1
%patch0029 -p1
%patch0030 -p1
%patch0031 -p1
%patch0032 -p1
%patch0033 -p1
%patch0034 -p1
%patch0035 -p1
%patch0036 -p1
%patch0037 -p1
%patch0038 -p1
%build
@ -237,6 +305,7 @@ rm -rf %{buildroot}%{repositorydir}/common/actors/testactor
find %{buildroot}%{repositorydir}/common -name "test.py" -delete
rm -rf `find %{buildroot}%{repositorydir} -name "tests" -type d`
find %{buildroot}%{repositorydir} -name "Makefile" -delete
find %{buildroot} -name "*.py.orig" -delete
for DIRECTORY in $(find %{buildroot}%{repositorydir}/ -mindepth 1 -maxdepth 1 -type d);
do
@ -274,12 +343,34 @@ done;
# no files here
%changelog
* Thu Oct 20 2022 Petr Stodulka <pstodulk@redhat.com> - 0.17.0-1.2
- Add checks for the in-place upgrades of RHEL for SAP
- RHUI: Fix the in-place upgrade on Azure for RHEL SAP Applications
- Resolves: rhbz#2125284
* Wed Nov 30 2022 Petr Stodulka <pstodulk@redhat.com> - 0.17.0-5
- Check RPM signatures during the upgrade (first part)
- introduced the --nogpgcheck option to do the upgrade in the original way
- Resolves: rhbz#2143372
* Thu Sep 08 2022 Petr Stodulka <pstodulk@redhat.com> - 0.17.0-1.1
* Wed Nov 16 2022 Petr Stodulka <pstodulk@redhat.com> - 0.17.0-4
- The new upgrade path for RHEL 8.8 -> 9.2
- Require cpio
- Bump leapp-repositori-dependencies to 8
- Fix systemd symlinks that become incorrect during the IPU
- Introduced an option to use an ISO file as a target RHEL version content source
- Provide common information about systemd services
- Introduced possibility to specify what systemd services should be enabled/disabled on the upgraded system
- Detect and report systemd symlinks that are broken before the upgrade
- Resolves: rhbz#2143372
* Wed Sep 07 2022 Petr Stodulka <pstodulk@redhat.com> - 0.17.0-3
- Adding back instruction to not install rubygem-irb during the in-place upgrade
to prevent conflict between files
- Resolves: rhbz#2090995
* Wed Sep 07 2022 Petr Stodulka <pstodulk@redhat.com> - 0.17.0-2
- Update VDO checks to enable user to decide the system state on check failures
and undetermined block devices
- The VDO dialog and related VDO reports have been properly updated
- Resolves: rhbz#2096159
* Wed Aug 24 2022 Petr Stodulka <pstodulk@redhat.com> - 0.17.0-1
- Rebase to v0.17.0
- Support upgrade path RHEL 8.7 -> 9.0 and RHEL SAP 8.6 -> 9.0
- Provide and require leapp-repository-dependencies 7
@ -320,10 +411,7 @@ done;
- Skip comment lines when parsing the GRUB configuration file
- Stop propagating the “debug” and ”enforcing=0” kernel cmdline options into the target kernel cmdline options
- Mass refactoring to be compatible with leapp v0.15.0
- Update VDO checks to enable user to decide the system state on check failures
and undetermined block devices
- The VDO dialog and related VDO reports have been properly updated
- Resolves: rhbz#2125284
- Resolves: rhbz#2090995, rhbz#2040470, rhbz#2092005, rhbz#2093220, rhbz#2095704, rhbz#2096159, rhbz#2100108, rhbz#2100110, rhbz#2103282, rhbz#2106904, rhbz#2110627
* Wed Apr 27 2022 Petr Stodulka <pstodulk@redhat.com> - 0.16.0-6
- Skip comments in /etc/default/grub during the parsing