Compare commits

...

No commits in common. "a8-elevate-0210" and "c8" have entirely different histories.

122 changed files with 112869 additions and 53069 deletions

4
.gitignore vendored
View File

@ -1,2 +1,2 @@
SOURCES/deps-pkgs-11.tar.gz SOURCES/deps-pkgs-13.tar.gz
SOURCES/leapp-repository-0.21.0.tar.gz SOURCES/leapp-repository-0.22.0.tar.gz

View File

@ -1,2 +1,2 @@
8b3fe3a7b52d2e144d374623aa5b0b0add7ab0c7 SOURCES/deps-pkgs-11.tar.gz 3590b33b4a79ebe62f5cfa0eeca7efb41d526498 SOURCES/deps-pkgs-13.tar.gz
9327be3720ccb3f7b285d2199463d7df0c38dfae SOURCES/leapp-repository-0.21.0.tar.gz e23b32573b375337b079dd7a0dc07e9232851b1c SOURCES/leapp-repository-0.22.0.tar.gz

View File

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

View File

@ -1,43 +0,0 @@
From fbc38d4ad1d828e0553579e3719c0e4ed4a2a6bd Mon Sep 17 00:00:00 2001
From: jinkangkang <1547182170@qq.com>
Date: Mon, 19 Aug 2024 18:46:08 +0800
Subject: [PATCH 01/40] rhui(alibaba): add ARM RHEL8 and RHEL9 setup entries
(#1277)
Since leapp's RHUI mechanism filters setups based on the architecture of the source system,
it was not possible to upgrade of ARM-based RHEL systems on Alibaba cloud as there
were no ARM entries in RHUI_SETUPS. This patch adds these entries, making it possible
for EL 8 -> 9 upgrades of ARM systems on Alibaba cloud.
---
repos/system_upgrade/common/libraries/rhui.py | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/repos/system_upgrade/common/libraries/rhui.py b/repos/system_upgrade/common/libraries/rhui.py
index 51694ac2..30de0275 100644
--- a/repos/system_upgrade/common/libraries/rhui.py
+++ b/repos/system_upgrade/common/libraries/rhui.py
@@ -348,6 +348,22 @@ RHUI_SETUPS = {
('content.crt', RHUI_PKI_PRODUCT_DIR)
],
os_version='9'),
+ ],
+ RHUIFamily(RHUIProvider.ALIBABA, arch=arch.ARCH_ARM64, client_files_folder='alibaba'): [
+ mk_rhui_setup(clients={'aliyun_rhui_rhel8'}, leapp_pkg='leapp-rhui-alibaba',
+ mandatory_files=[('leapp-alibaba.repo', YUM_REPOS_PATH)],
+ optional_files=[
+ ('key.pem', RHUI_PKI_DIR),
+ ('content.crt', RHUI_PKI_PRODUCT_DIR)
+ ],
+ os_version='8'),
+ mk_rhui_setup(clients={'aliyun_rhui_rhel9'}, leapp_pkg='leapp-rhui-alibaba',
+ mandatory_files=[('leapp-alibaba.repo', YUM_REPOS_PATH)],
+ optional_files=[
+ ('key.pem', RHUI_PKI_DIR),
+ ('content.crt', RHUI_PKI_PRODUCT_DIR)
+ ],
+ os_version='9'),
]
}
--
2.47.0

View File

@ -1,41 +0,0 @@
From 7e0fb44bb673893d0409903f6a441d0eb2829d22 Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni@golov.de>
Date: Tue, 20 Aug 2024 15:11:02 +0200
Subject: [PATCH 02/40] don't require all versions to be defined for obsoleted
keys
in releases where we do not have any obsoleted keys, we still had to
define an entry (with an empty list), as otherwise the code would fail
instead, we can catch the KeyError and carry on as nothing happened
---
.../libraries/removeobsoleterpmgpgkeys.py | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/repos/system_upgrade/common/actors/removeobsoletegpgkeys/libraries/removeobsoleterpmgpgkeys.py b/repos/system_upgrade/common/actors/removeobsoletegpgkeys/libraries/removeobsoleterpmgpgkeys.py
index 6e84c2e9..bda7efa3 100644
--- a/repos/system_upgrade/common/actors/removeobsoletegpgkeys/libraries/removeobsoleterpmgpgkeys.py
+++ b/repos/system_upgrade/common/actors/removeobsoletegpgkeys/libraries/removeobsoleterpmgpgkeys.py
@@ -12,11 +12,14 @@ def _get_obsolete_keys():
distribution = api.current_actor().configuration.os_release.release_id
obsoleted_keys_map = get_distribution_data(distribution).get('obsoleted-keys', {})
keys = []
- for version in range(7, int(get_target_major_version()) + 1):
- for key in obsoleted_keys_map[str(version)]:
- name, version, release = key.rsplit("-", 2)
- if has_package(InstalledRPM, name, version=version, release=release):
- keys.append(key)
+ try:
+ for version in range(7, int(get_target_major_version()) + 1):
+ for key in obsoleted_keys_map[str(version)]:
+ name, version, release = key.rsplit("-", 2)
+ if has_package(InstalledRPM, name, version=version, release=release):
+ keys.append(key)
+ except KeyError:
+ pass
return keys
--
2.47.0

View File

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

View File

@ -1,226 +0,0 @@
From 9f2f1726d8a5bdd12309a3a3111984f1666b903f Mon Sep 17 00:00:00 2001
From: Matej Matuska <mmatuska@redhat.com>
Date: Thu, 22 Aug 2024 15:52:19 +0200
Subject: [PATCH 03/40] Add RHEL 10.0 prod-certs
Previously we temporarily used the RHEL 9 x86_64 prod cert for others
archs it was missing completely.
Jira: OAMG-11138
---
.../common/files/prod-certs/10.0/279.pem | 37 ++++++++++
.../common/files/prod-certs/10.0/419.pem | 37 ++++++++++
.../common/files/prod-certs/10.0/479.pem | 68 ++++++++++---------
.../common/files/prod-certs/10.0/72.pem | 37 ++++++++++
4 files changed, 146 insertions(+), 33 deletions(-)
create mode 100644 repos/system_upgrade/common/files/prod-certs/10.0/279.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/10.0/419.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/10.0/72.pem
diff --git a/repos/system_upgrade/common/files/prod-certs/10.0/279.pem b/repos/system_upgrade/common/files/prod-certs/10.0/279.pem
new file mode 100644
index 00000000..f62340fc
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/10.0/279.pem
@@ -0,0 +1,37 @@
+-----BEGIN CERTIFICATE-----
+MIIGczCCBFugAwIBAgIUfZodBQY+YRSlyRRiFX1dx4vQ5y4wDQYJKoZIhvcNAQEL
+BQAwga4xCzAJBgNVBAYTAlVTMRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTEWMBQG
+A1UECgwNUmVkIEhhdCwgSW5jLjEYMBYGA1UECwwPUmVkIEhhdCBOZXR3b3JrMS4w
+LAYDVQQDDCVSZWQgSGF0IEVudGl0bGVtZW50IFByb2R1Y3QgQXV0aG9yaXR5MSQw
+IgYJKoZIhvcNAQkBFhVjYS1zdXBwb3J0QHJlZGhhdC5jb20wHhcNMjQwODE1MDYx
+NjQ5WhcNNDQwODE1MDYxNjQ5WjBEMUIwQAYDVQQDDDlSZWQgSGF0IFByb2R1Y3Qg
+SUQgWzA0YTU4NDFkLTVlNmUtNDU1Yy1hZWYwLTdhOTQ0NTBiNjg3Nl0wggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDGP0nTjP4TN3LHVTfeQV+0u/Se01LU
+FJ66GhksOGzXzKSx6kbuFde0eHYIwV8tmZOMDIv2LVezHKRClVB1dMalQXfcLaoF
+AcHmCViz353vzXHynybzMXFs9xbzZMglduBbcStWHy+TmoJsbVwIAAdv4NYyrQQD
+LLVuX8mACCFg0YFG8ok5tN0Kt2liHTYpSoEuRI9ke+joNQkU3fsxcOlV5Cr1W2pG
+OkosvC4R9dvRjsjnEQ6tHeRhs5oEBZW3eZhnW3Qv8p9jaNU51TlYXLIH0+Fsx0uL
+XETzTWP4YmvBwtrGaq+PhRogJHNw8BM/zrNUzUEFBr6WKWRFB6zkfKNnNkOIZi52
+deFuqYuj+fRy5ehAFVWOHNFMzHvUSKJqGaLD5TW8aqQeFA3FvXce03WVwCFQIOvH
+F4y+sCNh1aliWkjJbc2yw9a3VhQeJ0wFIAngpy0h/3V3IT3dpK2XHAL9CfIWxk6Z
+wSwHNUKfP0aZYyXX/pfMFLXINSoHKSXHRMsf7P+wr0D47atkDLWYHIJjBXG9s5mG
+eobEC5OghL4DzW/mEKOwKI5JxUH5yKXfRgG7RwfzlFnQgs2Qd0p2sstZbjCOmEra
+cGfaDaLf7O1/6dAQPalCpn+uG5bv2NzIJmX2Rep7XA50XQLBqHg3r/cvMhcQQrIQ
+nE2pDC01zYhUTwIDAQABo4HxMIHuMAkGA1UdEwQCMAAwQwYMKwYBBAGSCAkBghcB
+BDMMMVJlZCBIYXQgRW50ZXJwcmlzZSBMaW51eCBmb3IgUG93ZXIsIGxpdHRsZSBl
+bmRpYW4wFgYMKwYBBAGSCAkBghcCBAYMBDEwLjAwGQYMKwYBBAGSCAkBghcDBAkM
+B3BwYzY0bGUwKQYMKwYBBAGSCAkBghcEBBkMF3JoZWwtMTAscmhlbC0xMC1wcGM2
+NGxlMB0GA1UdDgQWBBRh6iC1NXyvZ2Q6/2sI5hB40M0flTAfBgNVHSMEGDAWgBSW
+/bscQED/QIStsh8LJsHDam/WfDANBgkqhkiG9w0BAQsFAAOCAgEAv6ySsgygc2z2
+kQJeu9sdvBNFKe+gEtXbPu6+rZKPPosW3cggMJCnsZgki3nUogovz0Z3MPkbmRz+
+GJwVjiVBnfUQLoORSDYwqYZB4WRoqszW/dytd7/64IehvD/JZo3Oa8BNYRSG/Ukh
+7iUIT8ryFIH1DTUIersVObINN2gk3hC2JJXoTfNqIYG+4OAEUE7/F4CptRAGbgH/
+4/9vfe2KNXvPMoWvILpXpD5w8t9Xh0Wl97N1W7+FLVRwQHAQ2/yBTu/sY27FvVSl
+0o+SBSvjTKIi+9QslRpi0QCVza5WxHTiO8nzYgzFjfMkt6lzK74puf3VJavpqkQ9
+dVfyp36A3Fh6vDsiNxhsfKrp8z2JnKA3vdslsH7cOHCIFYHXiqeaP654t4oGeESD
+EPfS6PpXSyi47Kd/qjA2srgpXNQl2yMd0ih6NoHaoSYXFfb4LX6cWFGcT/AWZsaC
+xv2pN9J0KhF2loLp8SK19FESc0rJShkAacTcxeYjuDYbvLtJi4Z5aWWVU421rMSs
+X9IdiWa4WL70ZaDK5cP54S4zZNsVDKniUzNXwPltDCpqefy8ka4o5QlWNreBrXXW
+6cy8I6L2om7xZ5hAZ3CB7nUZe9QE/LXnHqK3cQetvd5Q2LMnp6gVtgQ4a+7vD9xz
+ExLtbBZjvGJFudimMmOxvn/J5+GMmm4=
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/10.0/419.pem b/repos/system_upgrade/common/files/prod-certs/10.0/419.pem
new file mode 100644
index 00000000..08cb5b02
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/10.0/419.pem
@@ -0,0 +1,37 @@
+-----BEGIN CERTIFICATE-----
+MIIGZTCCBE2gAwIBAgIUWARL99TkK+hxtTJkE5icdHXLfY0wDQYJKoZIhvcNAQEL
+BQAwga4xCzAJBgNVBAYTAlVTMRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTEWMBQG
+A1UECgwNUmVkIEhhdCwgSW5jLjEYMBYGA1UECwwPUmVkIEhhdCBOZXR3b3JrMS4w
+LAYDVQQDDCVSZWQgSGF0IEVudGl0bGVtZW50IFByb2R1Y3QgQXV0aG9yaXR5MSQw
+IgYJKoZIhvcNAQkBFhVjYS1zdXBwb3J0QHJlZGhhdC5jb20wHhcNMjQwODE1MDYx
+NjQ5WhcNNDQwODE1MDYxNjQ5WjBEMUIwQAYDVQQDDDlSZWQgSGF0IFByb2R1Y3Qg
+SUQgW2Y3ZWFmNGU2LTYwZGYtNDMyNC04N2I0LTdhNGUzZGVkZmViNV0wggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDGP0nTjP4TN3LHVTfeQV+0u/Se01LU
+FJ66GhksOGzXzKSx6kbuFde0eHYIwV8tmZOMDIv2LVezHKRClVB1dMalQXfcLaoF
+AcHmCViz353vzXHynybzMXFs9xbzZMglduBbcStWHy+TmoJsbVwIAAdv4NYyrQQD
+LLVuX8mACCFg0YFG8ok5tN0Kt2liHTYpSoEuRI9ke+joNQkU3fsxcOlV5Cr1W2pG
+OkosvC4R9dvRjsjnEQ6tHeRhs5oEBZW3eZhnW3Qv8p9jaNU51TlYXLIH0+Fsx0uL
+XETzTWP4YmvBwtrGaq+PhRogJHNw8BM/zrNUzUEFBr6WKWRFB6zkfKNnNkOIZi52
+deFuqYuj+fRy5ehAFVWOHNFMzHvUSKJqGaLD5TW8aqQeFA3FvXce03WVwCFQIOvH
+F4y+sCNh1aliWkjJbc2yw9a3VhQeJ0wFIAngpy0h/3V3IT3dpK2XHAL9CfIWxk6Z
+wSwHNUKfP0aZYyXX/pfMFLXINSoHKSXHRMsf7P+wr0D47atkDLWYHIJjBXG9s5mG
+eobEC5OghL4DzW/mEKOwKI5JxUH5yKXfRgG7RwfzlFnQgs2Qd0p2sstZbjCOmEra
+cGfaDaLf7O1/6dAQPalCpn+uG5bv2NzIJmX2Rep7XA50XQLBqHg3r/cvMhcQQrIQ
+nE2pDC01zYhUTwIDAQABo4HjMIHgMAkGA1UdEwQCMAAwNQYMKwYBBAGSCAkBgyMB
+BCUMI1JlZCBIYXQgRW50ZXJwcmlzZSBMaW51eCBmb3IgQVJNIDY0MBYGDCsGAQQB
+kggJAYMjAgQGDAQxMC4wMBkGDCsGAQQBkggJAYMjAwQJDAdhYXJjaDY0MCkGDCsG
+AQQBkggJAYMjBAQZDBdyaGVsLTEwLHJoZWwtMTAtYWFyY2g2NDAdBgNVHQ4EFgQU
+YeogtTV8r2dkOv9rCOYQeNDNH5UwHwYDVR0jBBgwFoAUlv27HEBA/0CErbIfCybB
+w2pv1nwwDQYJKoZIhvcNAQELBQADggIBAIpdcHN7RN18pg5ELfc55Sj58ivL5N25
+19KprqbM7aVum32abw7/Qksfs6maGQpU6Hh/UqhJlGQ2bN48jZ/kdMKor4agSQ/T
+iwr3b8RBJFPVCuqQJXIe4g3iRbHfnIjGxgoMgv36j58PENoEnpPtR7ZtHMyqQ2SO
+m1WRQhY5tJ4Fk/Zkx/trxlNvmsTAjNRa530kqG4TfiMVvWNaVdxHsjMv0lXLJRXx
+KT6+iHt2QBs2No5O8cjlXr/CzfGrB5TlBNrsHqhO0Llmw28KpcWGYGdexKdIHrDG
+A/K0Pr21yRstUWN39jz/tdEqt1q8T7/it3oM976keQmFAxBa/CpyEG5Y6FKw9+F0
+LtkAyI3XGHK7LbCOE67s7u0/BfgQvww1FqztVnVZ4sXlagj/IuYPJBhfGDe/6tik
+laqP8FtR6xJdSra2YQMBc0kZb0Sv1uy7pGofNSvLM5L76XqiwKoDVo/eAcl60OWY
+rF86pEDLGDmdJBLJKX2/77pzpQpZ9Yvc4vWwoZrP4gRKBuWF28aLH0OsWzdsfdMG
+9+DrcO/58slMbWng1ZzOQyEjp7x1kto5sa5m2q8LMo06ETYT8ps5A0hyltBz1yAt
+JEBS4Y14YlF6Px67aTak07MNo7AaaphuD47D2Sy3pwHa+vOx4nv/G33+G0iOm3Lr
+zVAjwlfLIUB9
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/10.0/479.pem b/repos/system_upgrade/common/files/prod-certs/10.0/479.pem
index 1ea1cd3d..d89f6188 100644
--- a/repos/system_upgrade/common/files/prod-certs/10.0/479.pem
+++ b/repos/system_upgrade/common/files/prod-certs/10.0/479.pem
@@ -1,35 +1,37 @@
-----BEGIN CERTIFICATE-----
-MIIGFTCCA/2gAwIBAgIJALDxRLt/tVDQMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
-VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
-YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
-IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
-ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTIzMDcxOTE2MzQwOFoXDTQzMDcx
-OTE2MzQwOFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFsxZDg0ZDQ5
-Ny1jZmNmLTQxNjEtOTM0YS0zNzk2MDU4M2ZmZGZdMIICIjANBgkqhkiG9w0BAQEF
-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
-OS40MBgGDCsGAQQBkggJAYNfAwQIDAZ4ODZfNjQwJgYMKwYBBAGSCAkBg18EBBYM
-FHJoZWwtOSxyaGVsLTkteDg2XzY0MA0GCSqGSIb3DQEBCwUAA4ICAQCGUDPFBrLs
-sK/RITJothRhKhKNX3zu9TWRG0WKxszCx/y7c4yEfH1TV/yd7BNB2RubaoayWz8E
-TQjcRW8BnVu9JrlbdpWJm4eN+dOOpcESPilLnkz4Tr0WYDsT1/jk/uiorK4h21S0
-EwMicuSuEmm0OUEX0zj2X/IyveFRtpJpH/JktznCkvexysc1JRzqMCbal8GipRX9
-Xf7Oko6QiaUpu5GDLN2OXhizYHdR2f3l+Sn2cScsbi3fSVv+DLsnaz6J0kZ4U8q3
-lYk/ZYifJjG+/7cv3e+usixpmK/qYlpOvunUDnqOkDfUs4/4bZjH8e8CdqJk4YvU
-RRtLr7muXEJsaqF7lxAViXnKxT/z/+1kOgN/+Oyzjs4QDsk2HQpWHFgNYSSG9Mmz
-PUS8tk2T0j5sN55X7QRRl5c0oqrBU5XaWyL26QcfONYcR8dBaKawjxg8CI9KzsYY
-sb2jjS+fBkB1OI2c6z4OZRd+0N6FQ6gq++KiXOLFvi/QSFNi9Veb56c5tR2l6fBk
-0pSH06Gg2s0aQg20NdMIr+HaYsVdJRsE1FgQ2tlfFx9rGkcqhgwV3Za/abgtRb2o
-YVwps28DLm41DXf5DnXK+BXFHrtR/3YAZtga+R7OL/RvcF0kc2kudlxqd/8Y33uL
-nqnoATy31FTW4J4rEfanJTQgTpatZmbaLQ==
+MIIGYzCCBEugAwIBAgIUL5D34AcwqLAbqlUcxntHUCtEVxQwDQYJKoZIhvcNAQEL
+BQAwga4xCzAJBgNVBAYTAlVTMRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTEWMBQG
+A1UECgwNUmVkIEhhdCwgSW5jLjEYMBYGA1UECwwPUmVkIEhhdCBOZXR3b3JrMS4w
+LAYDVQQDDCVSZWQgSGF0IEVudGl0bGVtZW50IFByb2R1Y3QgQXV0aG9yaXR5MSQw
+IgYJKoZIhvcNAQkBFhVjYS1zdXBwb3J0QHJlZGhhdC5jb20wHhcNMjQwODE1MDYx
+NjQ5WhcNNDQwODE1MDYxNjQ5WjBEMUIwQAYDVQQDDDlSZWQgSGF0IFByb2R1Y3Qg
+SUQgWzk5NDZhMmY5LTI4NDMtNDJhOS1iNzhlLTIzM2E5ODIwYjVhZV0wggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDGP0nTjP4TN3LHVTfeQV+0u/Se01LU
+FJ66GhksOGzXzKSx6kbuFde0eHYIwV8tmZOMDIv2LVezHKRClVB1dMalQXfcLaoF
+AcHmCViz353vzXHynybzMXFs9xbzZMglduBbcStWHy+TmoJsbVwIAAdv4NYyrQQD
+LLVuX8mACCFg0YFG8ok5tN0Kt2liHTYpSoEuRI9ke+joNQkU3fsxcOlV5Cr1W2pG
+OkosvC4R9dvRjsjnEQ6tHeRhs5oEBZW3eZhnW3Qv8p9jaNU51TlYXLIH0+Fsx0uL
+XETzTWP4YmvBwtrGaq+PhRogJHNw8BM/zrNUzUEFBr6WKWRFB6zkfKNnNkOIZi52
+deFuqYuj+fRy5ehAFVWOHNFMzHvUSKJqGaLD5TW8aqQeFA3FvXce03WVwCFQIOvH
+F4y+sCNh1aliWkjJbc2yw9a3VhQeJ0wFIAngpy0h/3V3IT3dpK2XHAL9CfIWxk6Z
+wSwHNUKfP0aZYyXX/pfMFLXINSoHKSXHRMsf7P+wr0D47atkDLWYHIJjBXG9s5mG
+eobEC5OghL4DzW/mEKOwKI5JxUH5yKXfRgG7RwfzlFnQgs2Qd0p2sstZbjCOmEra
+cGfaDaLf7O1/6dAQPalCpn+uG5bv2NzIJmX2Rep7XA50XQLBqHg3r/cvMhcQQrIQ
+nE2pDC01zYhUTwIDAQABo4HhMIHeMAkGA1UdEwQCMAAwNQYMKwYBBAGSCAkBg18B
+BCUMI1JlZCBIYXQgRW50ZXJwcmlzZSBMaW51eCBmb3IgeDg2XzY0MBYGDCsGAQQB
+kggJAYNfAgQGDAQxMC4wMBgGDCsGAQQBkggJAYNfAwQIDAZ4ODZfNjQwKAYMKwYB
+BAGSCAkBg18EBBgMFnJoZWwtMTAscmhlbC0xMC14ODZfNjQwHQYDVR0OBBYEFGHq
+ILU1fK9nZDr/awjmEHjQzR+VMB8GA1UdIwQYMBaAFJb9uxxAQP9AhK2yHwsmwcNq
+b9Z8MA0GCSqGSIb3DQEBCwUAA4ICAQAa+c2/Usg6JToULhYTdLhf15Hk6xxdlwT7
+zZlnZLbuAKtaDqP1NiSiX0Z/lMJzFfW0B/zyWLy8uiXLYmF5V28f8yWK0Nksx2v7
+I7u6ZZN2dKDQZKsEoP0g3ptvVRWn9h5otS7yPkOK4Dzj04yJqOSGP9bp6OHEhm1S
+x4ErITkN/3MXOf9vT+I6wydVKsw4fdlWgVjmBd90bzVTnv4dWtJio+le+9ad9RSf
+M3aD5ufiELeRKMp6ExnC/cnoWtuH+b4BJ37TQ3Kpn3fDtbrzVvQH/dpqZ7P33yqg
+PnBEXOiLimDnnmDJ9ImQ1pVTrKJMxaj1Mk6onERe36n/iAsj+BwZvBiv7UaLPMnW
+nJGg+LQ4iUZrGWYD4N9Ou++nvsR8dCWRhXSuXensfli3lL/W0P62yzfYCyqOYeL1
+msDcCmBEWJUtAaeAbASUIVx02JWPPmMSUqWs8xOecQjzoGuCQg4JM/UfsZzxepw0
+bs9YSUVw8J9R2d4kuze65qDTMRg+cK2LX1xg1KkR/UWZOGxHHJAfwGWdPwSkiOPQ
+MVJ7LJjvozebHWSuiSxk+GWWr+NdxIJrFRGbivXyAkmqMRrPe1VLVxWwCdyud9o8
+b2WbFgrNS2jOnHwldtM2ZAhrF5W4ckvVL7hLp2JoQnJfCcWson9NK6Y2M4bNwQnC
+ihxphLzOAw==
-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/10.0/72.pem b/repos/system_upgrade/common/files/prod-certs/10.0/72.pem
new file mode 100644
index 00000000..e0274f9c
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/10.0/72.pem
@@ -0,0 +1,37 @@
+-----BEGIN CERTIFICATE-----
+MIIGZDCCBEygAwIBAgIUSTvcD4Wsduixh8PFmwk6aI0KTEcwDQYJKoZIhvcNAQEL
+BQAwga4xCzAJBgNVBAYTAlVTMRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTEWMBQG
+A1UECgwNUmVkIEhhdCwgSW5jLjEYMBYGA1UECwwPUmVkIEhhdCBOZXR3b3JrMS4w
+LAYDVQQDDCVSZWQgSGF0IEVudGl0bGVtZW50IFByb2R1Y3QgQXV0aG9yaXR5MSQw
+IgYJKoZIhvcNAQkBFhVjYS1zdXBwb3J0QHJlZGhhdC5jb20wHhcNMjQwODE1MDYx
+NjQ5WhcNNDQwODE1MDYxNjQ5WjBEMUIwQAYDVQQDDDlSZWQgSGF0IFByb2R1Y3Qg
+SUQgW2VjN2EwZDQyLTgzNjItNDg2YS04ZjcyLTc3YThiOWU2MjM0YV0wggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDGP0nTjP4TN3LHVTfeQV+0u/Se01LU
+FJ66GhksOGzXzKSx6kbuFde0eHYIwV8tmZOMDIv2LVezHKRClVB1dMalQXfcLaoF
+AcHmCViz353vzXHynybzMXFs9xbzZMglduBbcStWHy+TmoJsbVwIAAdv4NYyrQQD
+LLVuX8mACCFg0YFG8ok5tN0Kt2liHTYpSoEuRI9ke+joNQkU3fsxcOlV5Cr1W2pG
+OkosvC4R9dvRjsjnEQ6tHeRhs5oEBZW3eZhnW3Qv8p9jaNU51TlYXLIH0+Fsx0uL
+XETzTWP4YmvBwtrGaq+PhRogJHNw8BM/zrNUzUEFBr6WKWRFB6zkfKNnNkOIZi52
+deFuqYuj+fRy5ehAFVWOHNFMzHvUSKJqGaLD5TW8aqQeFA3FvXce03WVwCFQIOvH
+F4y+sCNh1aliWkjJbc2yw9a3VhQeJ0wFIAngpy0h/3V3IT3dpK2XHAL9CfIWxk6Z
+wSwHNUKfP0aZYyXX/pfMFLXINSoHKSXHRMsf7P+wr0D47atkDLWYHIJjBXG9s5mG
+eobEC5OghL4DzW/mEKOwKI5JxUH5yKXfRgG7RwfzlFnQgs2Qd0p2sstZbjCOmEra
+cGfaDaLf7O1/6dAQPalCpn+uG5bv2NzIJmX2Rep7XA50XQLBqHg3r/cvMhcQQrIQ
+nE2pDC01zYhUTwIDAQABo4HiMIHfMAkGA1UdEwQCMAAwOwYLKwYBBAGSCAkBSAEE
+LAwqUmVkIEhhdCBFbnRlcnByaXNlIExpbnV4IGZvciBJQk0geiBTeXN0ZW1zMBUG
+CysGAQQBkggJAUgCBAYMBDEwLjAwFgYLKwYBBAGSCAkBSAMEBwwFczM5MHgwJgYL
+KwYBBAGSCAkBSAQEFwwVcmhlbC0xMCxyaGVsLTEwLXMzOTB4MB0GA1UdDgQWBBRh
+6iC1NXyvZ2Q6/2sI5hB40M0flTAfBgNVHSMEGDAWgBSW/bscQED/QIStsh8LJsHD
+am/WfDANBgkqhkiG9w0BAQsFAAOCAgEAsj4qPVsDkFrfuVDn8JCJ7tIH5WhaOzL6
+3GBsQIKGd8a1WscPfSpr/phNSBPWFyvV2b+0HzblYzBZbx6ExykTDLh5L01nPM0s
++hqPxZgF/kcTbLWmAanl32R9+Gs2P2JN1CaCclXgM4USEagBWYeMhJSmQR3bOnSe
+Jjm3tjvhnbIQd6xgPpTjrqZ35z1BW0P0qQFdBbB0k+MfPkhYKEr+Vfn0rU8vk4UP
+F9sY9HkZLqIBxlXeTUerNZvHSuOy2KgoS4l25/QwUutHnnSGZZpARiU1XYNcynVL
+r5COHlb6TYkeRhSAm6RVM4XPYoFgN6cbhY1orwFC2/0i30EnsTMB6ctnLKCf7qgM
+GDG2W7ct0m6koA7s2TGmgp33DPw9adX7qgIV0OjLzBYJ1fyVv3sYlOKRuyDz0l+N
+u6Rnv1ecNUspWn+5ogBbdgwU6yah6oo/fJIWm62U38UGH5ic+/7sBnga8q5sDI90
++h+nlTIAnD0ICzjEDASiLlYft+hQ9pOt/rgEIrPeKTe+fbefUIXJ5h343E51POnY
+uZRXcirc33QL/PgBRce1taIXjsRD+FSJM0tx/vf8H9j0rzSAxDoXJNsdq4/32scy
+6Zk2fgtm80xxIzju84jXVUrSBRMpWD9I+FZId4IE7tQhwKNi1b7DdNeaQLfaoq8U
+1PEea/tQDSA=
+-----END CERTIFICATE-----
--
2.47.0

View File

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

View File

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

View File

@ -1,100 +0,0 @@
From bf302fc794957a88bc4785f4dd2505b8d71012e0 Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni@golov.de>
Date: Wed, 21 Aug 2024 07:52:02 +0200
Subject: [PATCH 04/40] properly scope try/except when loading obsoleted keys
We want to load all possible keys, even *after* a KeyError happenend
Fixes: 7e0fb44bb673893d0409903f6a441d0eb2829d22
---
.../libraries/removeobsoleterpmgpgkeys.py | 8 +--
.../tests/test_removeobsoleterpmgpgkeys.py | 50 +++++++++++++++++++
2 files changed, 54 insertions(+), 4 deletions(-)
diff --git a/repos/system_upgrade/common/actors/removeobsoletegpgkeys/libraries/removeobsoleterpmgpgkeys.py b/repos/system_upgrade/common/actors/removeobsoletegpgkeys/libraries/removeobsoleterpmgpgkeys.py
index bda7efa3..198c4368 100644
--- a/repos/system_upgrade/common/actors/removeobsoletegpgkeys/libraries/removeobsoleterpmgpgkeys.py
+++ b/repos/system_upgrade/common/actors/removeobsoletegpgkeys/libraries/removeobsoleterpmgpgkeys.py
@@ -12,14 +12,14 @@ def _get_obsolete_keys():
distribution = api.current_actor().configuration.os_release.release_id
obsoleted_keys_map = get_distribution_data(distribution).get('obsoleted-keys', {})
keys = []
- try:
- for version in range(7, int(get_target_major_version()) + 1):
+ for version in range(7, int(get_target_major_version()) + 1):
+ try:
for key in obsoleted_keys_map[str(version)]:
name, version, release = key.rsplit("-", 2)
if has_package(InstalledRPM, name, version=version, release=release):
keys.append(key)
- except KeyError:
- pass
+ except KeyError:
+ pass
return keys
diff --git a/repos/system_upgrade/common/actors/removeobsoletegpgkeys/tests/test_removeobsoleterpmgpgkeys.py b/repos/system_upgrade/common/actors/removeobsoletegpgkeys/tests/test_removeobsoleterpmgpgkeys.py
index 4d9a0e84..b78174cc 100644
--- a/repos/system_upgrade/common/actors/removeobsoletegpgkeys/tests/test_removeobsoleterpmgpgkeys.py
+++ b/repos/system_upgrade/common/actors/removeobsoletegpgkeys/tests/test_removeobsoleterpmgpgkeys.py
@@ -76,6 +76,56 @@ def test_get_obsolete_keys(monkeypatch, version, expected):
assert set(keys) == set(expected)
+@pytest.mark.parametrize(
+ "version, obsoleted_keys, expected",
+ [
+ (10, None, []),
+ (10, {}, []),
+ (10, {"8": ["gpg-pubkey-888-abc"], "10": ["gpg-pubkey-10-10"]}, ["gpg-pubkey-888-abc", "gpg-pubkey-10-10"]),
+ (9, {"8": ["gpg-pubkey-888-abc"], "9": ["gpg-pubkey-999-def"]}, ["gpg-pubkey-999-def", "gpg-pubkey-888-abc"]),
+ (8, {"8": ["gpg-pubkey-888-abc"], "9": ["gpg-pubkey-999-def"]}, ["gpg-pubkey-888-abc"])
+ ]
+)
+def test_get_obsolete_keys_incomplete_data(monkeypatch, version, obsoleted_keys, expected):
+ def get_target_major_version_mocked():
+ return version
+
+ def get_distribution_data_mocked(_distro):
+ if obsoleted_keys is None:
+ return {}
+ return {'obsoleted-keys': obsoleted_keys}
+
+ def has_package_mocked(*args, **kwargs):
+ return True
+
+ monkeypatch.setattr(
+ removeobsoleterpmgpgkeys,
+ "get_target_major_version",
+ get_target_major_version_mocked,
+ )
+
+ monkeypatch.setattr(
+ removeobsoleterpmgpgkeys,
+ "get_distribution_data",
+ get_distribution_data_mocked,
+ )
+
+ monkeypatch.setattr(
+ removeobsoleterpmgpgkeys,
+ "has_package",
+ has_package_mocked,
+ )
+
+ monkeypatch.setattr(
+ api,
+ "current_actor",
+ CurrentActorMocked(),
+ )
+
+ keys = removeobsoleterpmgpgkeys._get_obsolete_keys()
+ assert set(keys) == set(expected)
+
+
@pytest.mark.parametrize(
"keys, should_register",
[
--
2.47.0

View File

@ -1,283 +0,0 @@
From 9d49f4675c2b7b18ba7b344bb0032a5538782560 Mon Sep 17 00:00:00 2001
From: Vojtech Sokol <vsokol@redhat.com>
Date: Mon, 2 Sep 2024 17:21:36 +0200
Subject: [PATCH 05/40] Update references from master branch to main
Focus was on making the CI and GitHub actions work after the default
branch was switched from master to main.
See: OAMG-4907
---
.github/workflows/codespell.yml | 4 ++--
.github/workflows/differential-shellcheck.yml | 4 ++--
.github/workflows/pr-welcome-msg.yml | 2 +-
.github/workflows/tmt-tests.yml | 16 ++++++++--------
.github/workflows/unit-tests.yml | 12 ++++++------
.packit.yaml | 10 +++++-----
Makefile | 14 +++++++-------
7 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml
index 673cef17..1195d8d1 100644
--- a/.github/workflows/codespell.yml
+++ b/.github/workflows/codespell.yml
@@ -3,10 +3,10 @@ name: Codespell
on:
push:
branches:
- - master
+ - main
pull_request:
branches:
- - master
+ - main
jobs:
codespell:
diff --git a/.github/workflows/differential-shellcheck.yml b/.github/workflows/differential-shellcheck.yml
index f1ed5f6a..e1bafb93 100644
--- a/.github/workflows/differential-shellcheck.yml
+++ b/.github/workflows/differential-shellcheck.yml
@@ -4,7 +4,7 @@
name: Differential ShellCheck
on:
pull_request:
- branches: [master]
+ branches: [main]
permissions:
contents: read
@@ -17,7 +17,7 @@ jobs:
security-events: write
pull-requests: write
- steps:
+ steps:
- name: Repository checkout
uses: actions/checkout@v4
with:
diff --git a/.github/workflows/pr-welcome-msg.yml b/.github/workflows/pr-welcome-msg.yml
index ff9414d2..0102c41f 100644
--- a/.github/workflows/pr-welcome-msg.yml
+++ b/.github/workflows/pr-welcome-msg.yml
@@ -28,7 +28,7 @@ jobs:
However, here are additional useful commands for packit:
- **`/packit test`** to re-run manually the default tests
- **`/packit retest-failed`** to re-run failed tests manually
- - **`/packit test oamg/leapp#42`** to run tests with leapp builds for the leapp PR#42 (default is latest upstream - master - build)
+ - **`/packit test oamg/leapp#42`** to run tests with leapp builds for the leapp PR#42 (default is latest upstream - main - build)
Note that first time contributors cannot run tests automatically - they need to be started by a reviewer.
diff --git a/.github/workflows/tmt-tests.yml b/.github/workflows/tmt-tests.yml
index 7e9fd706..1fa00e60 100644
--- a/.github/workflows/tmt-tests.yml
+++ b/.github/workflows/tmt-tests.yml
@@ -12,7 +12,7 @@ jobs:
call_workflow_tests_79to88_integration:
needs: call_workflow_copr_build
- uses: oamg/leapp/.github/workflows/reuse-tests-7to8.yml@master
+ uses: oamg/leapp/.github/workflows/reuse-tests-7to8.yml@main
secrets: inherit
with:
copr_artifacts: ${{ needs.call_workflow_copr_build.outputs.artifacts }}
@@ -26,7 +26,7 @@ jobs:
call_workflow_tests_79to86_integration:
needs: call_workflow_copr_build
- uses: oamg/leapp/.github/workflows/reuse-tests-7to8.yml@master
+ uses: oamg/leapp/.github/workflows/reuse-tests-7to8.yml@main
secrets: inherit
with:
copr_artifacts: ${{ needs.call_workflow_copr_build.outputs.artifacts }}
@@ -40,7 +40,7 @@ jobs:
call_workflow_tests_79to88_sst:
needs: call_workflow_copr_build
- uses: oamg/leapp/.github/workflows/reuse-tests-7to8.yml@master
+ uses: oamg/leapp/.github/workflows/reuse-tests-7to8.yml@main
secrets: inherit
with:
copr_artifacts: ${{ needs.call_workflow_copr_build.outputs.artifacts }}
@@ -55,7 +55,7 @@ jobs:
call_workflow_tests_7to8_aws:
needs: call_workflow_copr_build
- uses: oamg/leapp/.github/workflows/reuse-tests-7to8.yml@master
+ uses: oamg/leapp/.github/workflows/reuse-tests-7to8.yml@main
secrets: inherit
with:
copr_artifacts: ${{ needs.call_workflow_copr_build.outputs.artifacts }}
@@ -71,7 +71,7 @@ jobs:
call_workflow_tests_86to90_integration:
needs: call_workflow_copr_build
- uses: oamg/leapp/.github/workflows/reuse-tests-8to9.yml@master
+ uses: oamg/leapp/.github/workflows/reuse-tests-8to9.yml@main
secrets: inherit
with:
copr_artifacts: ${{ needs.call_workflow_copr_build.outputs.artifacts }}
@@ -85,7 +85,7 @@ jobs:
call_workflow_tests_88to92_integration:
needs: call_workflow_copr_build
- uses: oamg/leapp/.github/workflows/reuse-tests-8to9.yml@master
+ uses: oamg/leapp/.github/workflows/reuse-tests-8to9.yml@main
secrets: inherit
with:
copr_artifacts: ${{ needs.call_workflow_copr_build.outputs.artifacts }}
@@ -101,7 +101,7 @@ jobs:
call_workflow_tests_86to90_sst:
needs: call_workflow_copr_build
- uses: oamg/leapp/.github/workflows/reuse-tests-8to9.yml@master
+ uses: oamg/leapp/.github/workflows/reuse-tests-8to9.yml@main
secrets: inherit
with:
copr_artifacts: ${{ needs.call_workflow_copr_build.outputs.artifacts }}
@@ -116,7 +116,7 @@ jobs:
call_workflow_tests_86to90_aws:
needs: call_workflow_copr_build
- uses: oamg/leapp/.github/workflows/reuse-tests-8to9.yml@master
+ uses: oamg/leapp/.github/workflows/reuse-tests-8to9.yml@main
secrets: inherit
with:
copr_artifacts: ${{ needs.call_workflow_copr_build.outputs.artifacts }}
diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml
index 2a05106e..42b72b8d 100644
--- a/.github/workflows/unit-tests.yml
+++ b/.github/workflows/unit-tests.yml
@@ -2,10 +2,10 @@ name: Unit Tests
on:
push:
branches:
- - master
+ - main
pull_request:
branches:
- - master
+ - main
jobs:
test:
@@ -74,10 +74,10 @@ jobs:
# NOTE(ivasilev) fetch-depth 0 is critical here as leapp deps discovery depends on specific substring in
# commit message and default 1 option will get us just merge commit which has an unrelevant message.
fetch-depth: '0'
- # NOTE(ivasilev) master -> origin/master is used for leapp deps discovery in Makefile via git log master..HEAD
- - name: Set master to origin/master
- if: github.ref != 'refs/heads/master'
+ # NOTE(ivasilev) main -> origin/main is used for leapp deps discovery in Makefile via git log main..HEAD
+ - name: Set main to origin/main
+ if: github.ref != 'refs/heads/main'
run: |
- git branch -f master origin/master
+ git branch -f main origin/main
- name: ${{matrix.scenarios.name}}
run: script -e -c /bin/bash -c 'TERM=xterm podman build --security-opt=seccomp=unconfined -t leapp-tests -f utils/container-tests/Containerfile.${{matrix.scenarios.container}} utils/container-tests && PYTHON_VENV=${{matrix.scenarios.python}} REPOSITORIES=${{matrix.scenarios.repos}} podman run --security-opt=seccomp=unconfined --rm -ti -v ${PWD}:/payload --env=PYTHON_VENV --env=REPOSITORIES leapp-tests'
diff --git a/.packit.yaml b/.packit.yaml
index d91a47e5..fbfd0eea 100644
--- a/.packit.yaml
+++ b/.packit.yaml
@@ -22,7 +22,7 @@ actions:
fix-spec-file:
- bash -c "sed -i -r \"0,/Release:/ s/Release:(\s*)\S*/Release:\1${PACKIT_RPMSPEC_RELEASE}%{?dist}/\" packaging/leapp-repository.spec"
post-upstream-clone:
- # builds from PRs should have lower NVR than those from master branch
+ # builds from PRs should have lower NVR than those from main branch
- bash -c "sed -i \"s/1%{?dist}/0%{?dist}/g\" packaging/leapp-repository.spec"
jobs:
@@ -44,12 +44,12 @@ jobs:
fix-spec-file:
- bash -c "sed -i -r \"0,/Release:/ s/Release:(\s*)\S*/Release:\1${PACKIT_RPMSPEC_RELEASE}%{?dist}/\" packaging/leapp-repository.spec"
post-upstream-clone:
- # builds from PRs should have lower NVR than those from master branch
+ # builds from PRs should have lower NVR than those from main branch
- bash -c "sed -i \"s/1%{?dist}/0%{?dist}/g\" packaging/leapp-repository.spec"
- job: copr_build
trigger: commit
metadata:
- branch: master
+ branch: main
owner: "@oamg"
project: leapp
targets:
@@ -65,7 +65,7 @@ jobs:
fix-spec-file:
- bash -c "sed -i -r \"0,/Release:/ s/Release:(\s*)\S*/Release:\1${PACKIT_RPMSPEC_RELEASE}%{?dist}/\" packaging/leapp-repository.spec"
post-upstream-clone:
- # builds from master branch should start with 100 release, to have high priority
+ # builds from main branch should start with 100 release, to have high priority
- bash -c "sed -i \"s/1%{?dist}/100%{?dist}/g\" packaging/leapp-repository.spec"
- job: copr_build
trigger: release
@@ -85,7 +85,7 @@ jobs:
fix-spec-file:
- bash -c "sed -i -r \"0,/Release:/ s/Release:(\s*)\S*/Release:\1${PACKIT_RPMSPEC_RELEASE}%{?dist}/\" packaging/leapp-repository.spec"
post-upstream-clone:
- # builds from master branch should start with 100 release, to have high priority
+ # builds from main branch should start with 100 release, to have high priority
- bash -c "sed -i \"s/1%{?dist}/100%{?dist}/g\" packaging/leapp-repository.spec"
diff --git a/Makefile b/Makefile
index 5b2bc4d2..8aeef77d 100644
--- a/Makefile
+++ b/Makefile
@@ -64,7 +64,7 @@ endif
# just to reduce number of unwanted builds mark as the upstream one when
# someone will call copr_build without additional parameters
-MASTER_BRANCH=master
+MASTER_BRANCH=main
# In case the PR or MR is defined or in case build is not coming from the
# MATER_BRANCH branch, N_REL=0; (so build is not update of the approved
@@ -76,10 +76,10 @@ SHORT_SHA=`git rev-parse --short HEAD`
BRANCH=`git rev-parse --abbrev-ref HEAD | tr -- '-/' '_'`
# The dependent framework PR connection will be taken from the top commit's depends-on message.
-REQ_LEAPP_PR=$(shell git log master..HEAD | grep -m1 -iE '^[[:space:]]*Depends-On:[[:space:]]*.*[[:digit:]]+[[:space:]]*$$' | grep -Eo '*[[:digit:]]*')
+REQ_LEAPP_PR=$(shell git log main..HEAD | grep -m1 -iE '^[[:space:]]*Depends-On:[[:space:]]*.*[[:digit:]]+[[:space:]]*$$' | grep -Eo '*[[:digit:]]*')
# NOTE(ivasilev) In case of travis relying on top commit is a no go as a top commit will be a merge commit.
ifdef CI
- REQ_LEAPP_PR=$(shell git log master..HEAD | grep -m1 -iE '^[[:space:]]*Depends-On:[[:space:]]*.*[[:digit:]]+[[:space:]]*$$' | grep -Eo '[[:digit:]]*')
+ REQ_LEAPP_PR=$(shell git log main..HEAD | grep -m1 -iE '^[[:space:]]*Depends-On:[[:space:]]*.*[[:digit:]]+[[:space:]]*$$' | grep -Eo '[[:digit:]]*')
endif
# In case anyone would like to add any other suffix, just make it possible
@@ -92,8 +92,8 @@ REQUEST=`if test -n "$$PR"; then echo ".PR$${PR}"; elif test -n "$$MR"; then ech
# Examples:
# 0.201810080027Z.4078402.packaging.PR2
# 0.201810080027Z.4078402.packaging
-# 0.201810080027Z.4078402.master.MR2
-# 1.201810080027Z.4078402.master
+# 0.201810080027Z.4078402.main.MR2
+# 1.201810080027Z.4078402.main
RELEASE="$(N_REL).$(TIMESTAMP).$(SHORT_SHA).$(BRANCH)$(REQUEST)$(_SUFFIX)"
all: help
@@ -302,7 +302,7 @@ install-deps:
pip install --upgrade setuptools; \
pip install --upgrade -r requirements.txt; \
./utils/install_commands.sh $(_PYTHON_VENV); \
- # In case the top commit Depends-On some yet unmerged framework patch - override master leapp with the proper version
+ # In case the top commit Depends-On some yet unmerged framework patch - override main leapp with the proper version
if [[ ! -z "$(REQ_LEAPP_PR)" ]] ; then \
echo "Leapp-repository depends on the yet unmerged pr of the framework #$(REQ_LEAPP_PR), installing it.." && \
$(VENVNAME)/bin/pip install -I "git+https://github.com/oamg/leapp.git@refs/pull/$(REQ_LEAPP_PR)/head"; \
@@ -332,7 +332,7 @@ install-deps-fedora:
pip install --upgrade setuptools; \
pip install --upgrade -r requirements.txt; \
./utils/install_commands.sh $(_PYTHON_VENV); \
- # In case the top commit Depends-On some yet unmerged framework patch - override master leapp with the proper version
+ # In case the top commit Depends-On some yet unmerged framework patch - override main leapp with the proper version
if [[ ! -z "$(REQ_LEAPP_PR)" ]] ; then \
echo "Leapp-repository depends on the yet unmerged pr of the framework #$(REQ_LEAPP_PR), installing it.." && \
$(VENVNAME)/bin/pip install -I "git+https://github.com/oamg/leapp.git@refs/pull/$(REQ_LEAPP_PR)/head"; \
--
2.47.0

View File

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

View File

@ -1,43 +0,0 @@
From 41e32e3aa6394b8397bef9b797892d9fa119d608 Mon Sep 17 00:00:00 2001
From: Yuriy Kohut <yura.kohut@gmail.com>
Date: Thu, 29 Aug 2024 12:36:23 +0300
Subject: [PATCH 06/40] ReadOfKernelArgsError: fix the error: - AttributeError:
module 'leapp.reporting' has no attribute 'Hints'
---
.../kernelcmdlineconfig/libraries/kernelcmdlineconfig.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/repos/system_upgrade/common/actors/kernelcmdlineconfig/libraries/kernelcmdlineconfig.py b/repos/system_upgrade/common/actors/kernelcmdlineconfig/libraries/kernelcmdlineconfig.py
index 238a8aa6..6b261c3b 100644
--- a/repos/system_upgrade/common/actors/kernelcmdlineconfig/libraries/kernelcmdlineconfig.py
+++ b/repos/system_upgrade/common/actors/kernelcmdlineconfig/libraries/kernelcmdlineconfig.py
@@ -175,14 +175,14 @@ def entrypoint(configs=None):
api.current_logger().error(str(e))
if use_cmdline_file():
- report_hint = reporting.Hints(
+ report_hint = (
'After the system has been rebooted into the new version of RHEL, you'
' should take the kernel cmdline arguments from /proc/cmdline (Everything'
' except the BOOT_IMAGE entry and initrd entries) and copy them into'
' /etc/kernel/cmdline before installing any new kernels.'
)
else:
- report_hint = reporting.Hints(
+ report_hint = (
'After the system has been rebooted into the new version of RHEL, you'
' should take the kernel cmdline arguments from /proc/cmdline (Everything'
' except the BOOT_IMAGE entry and initrd entries) and then use the'
@@ -204,7 +204,7 @@ def entrypoint(configs=None):
' not able to set the arguments as the default for kernels installed in'
' the future.'
),
- report_hint,
+ reporting.Remediation(hint=report_hint),
reporting.Severity(reporting.Severity.HIGH),
reporting.Groups([
reporting.Groups.BOOT,
--
2.47.0

View File

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

View File

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

View File

@ -1,44 +0,0 @@
From 88e13fb0545e0d42df2777538a0c6921bab91e33 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Fri, 27 Sep 2024 14:53:01 +0200
Subject: [PATCH 07/40] pylint: exclude rule: too-many-positional-arguments
(code: R0917)
New version of Pylint have the rule for checking of positional
arguments - complaining when more than 4 positional arguments exists.
We do not want to refactor the code to make it happy and the default
value cannot be set right now - that's planned for future Pylint
versions at this moment. So excluding this rule.
For more info:
* https://pylint.readthedocs.io/en/latest/user_guide/messages/refactor/too-many-positional-arguments.html
---
.pylintrc | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/.pylintrc b/.pylintrc
index f78c1c3f..5d75df40 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -41,6 +41,8 @@ disable=
consider-using-from-import,
use-list-literal,
use-dict-literal,
+ too-many-lines, # we do not want to take care about that one
+ too-many-positional-arguments, # we cannot set yet max-possitional-arguments unfortunately
# new for python3 version of pylint
useless-object-inheritance,
consider-using-set-comprehension, # pylint3 force to use comprehension in place we don't want (py2 doesnt have these options, for inline skip)
@@ -57,8 +59,7 @@ disable=
redundant-u-string-prefix, # still have py2 to support
logging-format-interpolation,
logging-not-lazy,
- use-yield-from, # yield from cannot be used until we require python 3.3 or greater
- too-many-lines # we do not want to take care about that one
+ use-yield-from # yield from cannot be used until we require python 3.3 or greater
[FORMAT]
# Maximum number of characters on a single line.
--
2.47.0

View File

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

View File

@ -1,534 +0,0 @@
From 658700d6424e852917b62c190dd23cbb3026b67d Mon Sep 17 00:00:00 2001
From: Iker Pedrosa <ipedrosa@redhat.com>
Date: Mon, 5 Aug 2024 15:15:44 +0200
Subject: [PATCH 08/40] pam_userdb: migrate backend database
pam_userdb module changed its backend database technology from lidb to
gdbm for RHEL10. This requires a set of leapp actors to perform the
database migration automatically when upgrading to RHEL10:
* ScanPamUserDB takes care of scanning the PAM service folder to detect
whether pam_userdb is used and the location of the database in use.
This information is stored in a model.
* CheckPamUserDB checks the databases reported by ScanPamUserDB and
prints a report about them.
* ConvertPamUserDB checks the databases reported by ScanPamUserDB and
converts them to GDBM format.
* RemoveOldPamUserDB checks the databases reported by ScanPamUserDB and
removes them.
All these actors include unit-tests.
Finally, there's also a spec file change to add `libdb-utils` dependency
as it is required to convert pam_userdb databases from BerkeleyDB to
GDBM.
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
---
packaging/leapp-repository.spec | 6 +++
.../actors/pamuserdb/checkpamuserdb/actor.py | 18 ++++++++
.../libraries/checkpamuserdb.py | 28 ++++++++++++
.../tests/test_checkpamuserdb.py | 43 +++++++++++++++++++
.../pamuserdb/convertpamuserdb/actor.py | 18 ++++++++
.../libraries/convertpamuserdb.py | 27 ++++++++++++
.../tests/test_convertpamuserdb.py | 39 +++++++++++++++++
.../pamuserdb/removeoldpamuserdb/actor.py | 18 ++++++++
.../libraries/removeoldpamuserdb.py | 25 +++++++++++
.../tests/test_removeoldpamuserdb.py | 38 ++++++++++++++++
.../actors/pamuserdb/scanpamuserdb/actor.py | 18 ++++++++
.../scanpamuserdb/libraries/scanpamuserdb.py | 29 +++++++++++++
.../tests/files/pam_userdb_basic | 1 +
.../tests/files/pam_userdb_complete | 9 ++++
.../tests/files/pam_userdb_missing | 1 +
.../scanpamuserdb/tests/test_scanpamuserdb.py | 27 ++++++++++++
.../el9toel10/models/pamuserdblocation.py | 14 ++++++
17 files changed, 359 insertions(+)
create mode 100644 repos/system_upgrade/el9toel10/actors/pamuserdb/checkpamuserdb/actor.py
create mode 100644 repos/system_upgrade/el9toel10/actors/pamuserdb/checkpamuserdb/libraries/checkpamuserdb.py
create mode 100644 repos/system_upgrade/el9toel10/actors/pamuserdb/checkpamuserdb/tests/test_checkpamuserdb.py
create mode 100644 repos/system_upgrade/el9toel10/actors/pamuserdb/convertpamuserdb/actor.py
create mode 100644 repos/system_upgrade/el9toel10/actors/pamuserdb/convertpamuserdb/libraries/convertpamuserdb.py
create mode 100644 repos/system_upgrade/el9toel10/actors/pamuserdb/convertpamuserdb/tests/test_convertpamuserdb.py
create mode 100644 repos/system_upgrade/el9toel10/actors/pamuserdb/removeoldpamuserdb/actor.py
create mode 100644 repos/system_upgrade/el9toel10/actors/pamuserdb/removeoldpamuserdb/libraries/removeoldpamuserdb.py
create mode 100644 repos/system_upgrade/el9toel10/actors/pamuserdb/removeoldpamuserdb/tests/test_removeoldpamuserdb.py
create mode 100644 repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/actor.py
create mode 100644 repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/libraries/scanpamuserdb.py
create mode 100644 repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/tests/files/pam_userdb_basic
create mode 100644 repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/tests/files/pam_userdb_complete
create mode 100644 repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/tests/files/pam_userdb_missing
create mode 100644 repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/tests/test_scanpamuserdb.py
create mode 100644 repos/system_upgrade/el9toel10/models/pamuserdblocation.py
diff --git a/packaging/leapp-repository.spec b/packaging/leapp-repository.spec
index 146afc45..0d63ba02 100644
--- a/packaging/leapp-repository.spec
+++ b/packaging/leapp-repository.spec
@@ -211,6 +211,12 @@ Requires: dracut
Requires: NetworkManager-libnm
Requires: python3-gobject-base
+%endif
+
+%if 0%{?rhel} && 0%{?rhel} == 9
+############# RHEL 9 dependencies (when the source system is RHEL 9) ##########
+# Required to convert pam_userdb database from BerkeleyDB to GDBM
+Requires: libdb-utils
%endif
##################################################
# end requirement
diff --git a/repos/system_upgrade/el9toel10/actors/pamuserdb/checkpamuserdb/actor.py b/repos/system_upgrade/el9toel10/actors/pamuserdb/checkpamuserdb/actor.py
new file mode 100644
index 00000000..8fada645
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/pamuserdb/checkpamuserdb/actor.py
@@ -0,0 +1,18 @@
+from leapp.actors import Actor
+from leapp.libraries.actor import checkpamuserdb
+from leapp.models import PamUserDbLocation, Report
+from leapp.tags import ChecksPhaseTag, IPUWorkflowTag
+
+
+class CheckPamUserDb(Actor):
+ """
+ Create report with the location of pam_userdb databases
+ """
+
+ name = 'check_pam_user_db'
+ consumes = (PamUserDbLocation,)
+ produces = (Report,)
+ tags = (ChecksPhaseTag, IPUWorkflowTag)
+
+ def process(self):
+ checkpamuserdb.process()
diff --git a/repos/system_upgrade/el9toel10/actors/pamuserdb/checkpamuserdb/libraries/checkpamuserdb.py b/repos/system_upgrade/el9toel10/actors/pamuserdb/checkpamuserdb/libraries/checkpamuserdb.py
new file mode 100644
index 00000000..05cc71a9
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/pamuserdb/checkpamuserdb/libraries/checkpamuserdb.py
@@ -0,0 +1,28 @@
+from leapp import reporting
+from leapp.exceptions import StopActorExecutionError
+from leapp.libraries.stdlib import api
+from leapp.models import PamUserDbLocation
+
+FMT_LIST_SEPARATOR = "\n - "
+
+
+def process():
+ msg = next(api.consume(PamUserDbLocation), None)
+ if not msg:
+ raise StopActorExecutionError('Expected PamUserDbLocation, but got None')
+
+ if msg.locations:
+ reporting.create_report([
+ reporting.Title('pam_userdb databases will be converted to GDBM'),
+ reporting.Summary(
+ 'On RHEL 10, GDMB is used by pam_userdb as it\'s backend database,'
+ ' replacing BerkeleyDB. Existing pam_userdb databases will be'
+ ' converted to GDBM. The following databases will be converted:'
+ '{sep}{locations}'.format(sep=FMT_LIST_SEPARATOR, locations=FMT_LIST_SEPARATOR.join(msg.locations))),
+ reporting.Severity(reporting.Severity.INFO),
+ reporting.Groups([reporting.Groups.SECURITY, reporting.Groups.AUTHENTICATION])
+ ])
+ else:
+ api.current_logger().debug(
+ 'No pam_userdb databases were located, thus nothing will be converted'
+ )
diff --git a/repos/system_upgrade/el9toel10/actors/pamuserdb/checkpamuserdb/tests/test_checkpamuserdb.py b/repos/system_upgrade/el9toel10/actors/pamuserdb/checkpamuserdb/tests/test_checkpamuserdb.py
new file mode 100644
index 00000000..2e11106b
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/pamuserdb/checkpamuserdb/tests/test_checkpamuserdb.py
@@ -0,0 +1,43 @@
+import pytest
+
+from leapp import reporting
+from leapp.exceptions import StopActorExecutionError
+from leapp.libraries.actor import checkpamuserdb
+from leapp.libraries.common.testutils import create_report_mocked, logger_mocked
+from leapp.libraries.stdlib import api
+from leapp.models import PamUserDbLocation
+
+
+def test_process_no_msg(monkeypatch):
+ def consume_mocked(*args, **kwargs):
+ yield None
+
+ monkeypatch.setattr(api, 'consume', consume_mocked)
+
+ with pytest.raises(StopActorExecutionError):
+ checkpamuserdb.process()
+
+
+def test_process_no_location(monkeypatch):
+ def consume_mocked(*args, **kwargs):
+ yield PamUserDbLocation(locations=[])
+
+ monkeypatch.setattr(api, 'current_logger', logger_mocked())
+ monkeypatch.setattr(api, 'consume', consume_mocked)
+
+ checkpamuserdb.process()
+ assert (
+ 'No pam_userdb databases were located, thus nothing will be converted'
+ in api.current_logger.dbgmsg
+ )
+
+
+def test_process_locations(monkeypatch):
+ def consume_mocked(*args, **kwargs):
+ yield PamUserDbLocation(locations=['/tmp/db1', '/tmp/db2'])
+
+ monkeypatch.setattr(reporting, "create_report", create_report_mocked())
+ monkeypatch.setattr(api, 'consume', consume_mocked)
+
+ checkpamuserdb.process()
+ assert reporting.create_report.called == 1
diff --git a/repos/system_upgrade/el9toel10/actors/pamuserdb/convertpamuserdb/actor.py b/repos/system_upgrade/el9toel10/actors/pamuserdb/convertpamuserdb/actor.py
new file mode 100644
index 00000000..5f8525b6
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/pamuserdb/convertpamuserdb/actor.py
@@ -0,0 +1,18 @@
+from leapp.actors import Actor
+from leapp.libraries.actor import convertpamuserdb
+from leapp.models import PamUserDbLocation
+from leapp.tags import IPUWorkflowTag, PreparationPhaseTag
+
+
+class ConvertPamUserDb(Actor):
+ """
+ Convert the pam_userdb databases to GDBM
+ """
+
+ name = 'convert_pam_user_db'
+ consumes = (PamUserDbLocation,)
+ produces = ()
+ tags = (PreparationPhaseTag, IPUWorkflowTag)
+
+ def process(self):
+ convertpamuserdb.process()
diff --git a/repos/system_upgrade/el9toel10/actors/pamuserdb/convertpamuserdb/libraries/convertpamuserdb.py b/repos/system_upgrade/el9toel10/actors/pamuserdb/convertpamuserdb/libraries/convertpamuserdb.py
new file mode 100644
index 00000000..e55b4102
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/pamuserdb/convertpamuserdb/libraries/convertpamuserdb.py
@@ -0,0 +1,27 @@
+from leapp.exceptions import StopActorExecutionError
+from leapp.libraries.stdlib import api, CalledProcessError, run
+from leapp.models import PamUserDbLocation
+
+
+def _convert_db(db_path):
+ cmd = ['db_converter', '--src', f'{db_path}.db', '--dest', f'{db_path}.gdbm']
+ try:
+ run(cmd)
+ except (CalledProcessError, OSError) as e:
+ # As the db_converter does not remove the original DB after conversion or upon failure,
+ # interrupt the upgrade, keeping the original DBs.
+ # If all DBs are successfully converted, the leftover DBs are removed in the removeoldpamuserdb actor.
+ raise StopActorExecutionError(
+ 'Cannot convert pam_userdb database.',
+ details={'details': '{}: {}'.format(str(e), e.stderr)}
+ )
+
+
+def process():
+ msg = next(api.consume(PamUserDbLocation), None)
+ if not msg:
+ raise StopActorExecutionError('Expected PamUserDbLocation, but got None')
+
+ if msg.locations:
+ for location in msg.locations:
+ _convert_db(location)
diff --git a/repos/system_upgrade/el9toel10/actors/pamuserdb/convertpamuserdb/tests/test_convertpamuserdb.py b/repos/system_upgrade/el9toel10/actors/pamuserdb/convertpamuserdb/tests/test_convertpamuserdb.py
new file mode 100644
index 00000000..46505492
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/pamuserdb/convertpamuserdb/tests/test_convertpamuserdb.py
@@ -0,0 +1,39 @@
+import os
+
+import pytest
+
+from leapp.exceptions import StopActorExecutionError
+from leapp.libraries.actor import convertpamuserdb
+from leapp.libraries.common.testutils import logger_mocked
+from leapp.libraries.stdlib import api, CalledProcessError
+
+CUR_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+def test_convert_db_success(monkeypatch):
+ location = os.path.join(CUR_DIR, '/files/db1')
+
+ def run_mocked(cmd, **kwargs):
+ assert cmd == ['db_converter', '--src', f'{location}.db', '--dest', f'{location}.gdbm']
+
+ monkeypatch.setattr(api, 'current_logger', logger_mocked())
+ monkeypatch.setattr(convertpamuserdb, 'run', run_mocked)
+ convertpamuserdb._convert_db(location)
+ assert len(api.current_logger.errmsg) == 0
+
+
+def test_convert_db_failure(monkeypatch):
+ location = os.path.join(CUR_DIR, '/files/db1')
+
+ def run_mocked(cmd, **kwargs):
+ raise CalledProcessError(
+ message='A Leapp Command Error occurred.',
+ command=cmd,
+ result={'exit_code': 1}
+ )
+
+ monkeypatch.setattr(api, 'current_logger', logger_mocked())
+ monkeypatch.setattr(convertpamuserdb, 'run', run_mocked)
+ with pytest.raises(StopActorExecutionError) as err:
+ convertpamuserdb._convert_db(location)
+ assert str(err.value) == 'Cannot convert pam_userdb database.'
diff --git a/repos/system_upgrade/el9toel10/actors/pamuserdb/removeoldpamuserdb/actor.py b/repos/system_upgrade/el9toel10/actors/pamuserdb/removeoldpamuserdb/actor.py
new file mode 100644
index 00000000..39a00855
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/pamuserdb/removeoldpamuserdb/actor.py
@@ -0,0 +1,18 @@
+from leapp.actors import Actor
+from leapp.libraries.actor import removeoldpamuserdb
+from leapp.models import PamUserDbLocation
+from leapp.tags import ApplicationsPhaseTag, IPUWorkflowTag
+
+
+class RemoveOldPamUserDb(Actor):
+ """
+ Remove old pam_userdb databases
+ """
+
+ name = 'remove_old_pam_user_db'
+ consumes = (PamUserDbLocation,)
+ produces = ()
+ tags = (ApplicationsPhaseTag, IPUWorkflowTag)
+
+ def process(self):
+ removeoldpamuserdb.process()
diff --git a/repos/system_upgrade/el9toel10/actors/pamuserdb/removeoldpamuserdb/libraries/removeoldpamuserdb.py b/repos/system_upgrade/el9toel10/actors/pamuserdb/removeoldpamuserdb/libraries/removeoldpamuserdb.py
new file mode 100644
index 00000000..5fc4cb4d
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/pamuserdb/removeoldpamuserdb/libraries/removeoldpamuserdb.py
@@ -0,0 +1,25 @@
+from leapp.exceptions import StopActorExecutionError
+from leapp.libraries.stdlib import api, CalledProcessError, run
+from leapp.models import PamUserDbLocation
+
+
+def _remove_db(db_path):
+ cmd = ['rm', '-f', f'{db_path}.db']
+ try:
+ run(cmd)
+ except (CalledProcessError, OSError) as e:
+ api.current_logger().error(
+ 'Failed to remove {}.db: {}'.format(
+ db_path, e
+ )
+ )
+
+
+def process():
+ msg = next(api.consume(PamUserDbLocation), None)
+ if not msg:
+ raise StopActorExecutionError('Expected PamUserDbLocation, but got None')
+
+ if msg.locations:
+ for location in msg.locations:
+ _remove_db(location)
diff --git a/repos/system_upgrade/el9toel10/actors/pamuserdb/removeoldpamuserdb/tests/test_removeoldpamuserdb.py b/repos/system_upgrade/el9toel10/actors/pamuserdb/removeoldpamuserdb/tests/test_removeoldpamuserdb.py
new file mode 100644
index 00000000..2c1d5c75
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/pamuserdb/removeoldpamuserdb/tests/test_removeoldpamuserdb.py
@@ -0,0 +1,38 @@
+import os
+
+from leapp.libraries.actor import removeoldpamuserdb
+from leapp.libraries.common.testutils import logger_mocked
+from leapp.libraries.stdlib import api, CalledProcessError
+
+CUR_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+def test_remove_db_success(monkeypatch):
+ location = os.path.join(CUR_DIR, '/files/db1')
+
+ def run_mocked(cmd, **kwargs):
+ assert cmd == ['rm', '-f', f'{location}.db']
+
+ monkeypatch.setattr(api, 'current_logger', logger_mocked())
+ monkeypatch.setattr(removeoldpamuserdb, 'run', run_mocked)
+ removeoldpamuserdb._remove_db(location)
+ assert len(api.current_logger.errmsg) == 0
+
+
+def test_remove_db_failure(monkeypatch):
+ location = os.path.join(CUR_DIR, '/files/db1')
+
+ def run_mocked(cmd, **kwargs):
+ raise CalledProcessError(
+ message='A Leapp Command Error occurred.',
+ command=cmd,
+ result={'exit_code': 1}
+ )
+
+ monkeypatch.setattr(api, 'current_logger', logger_mocked())
+ monkeypatch.setattr(removeoldpamuserdb, 'run', run_mocked)
+ removeoldpamuserdb._remove_db(location)
+ assert (
+ 'Failed to remove /files/db1.db'
+ not in api.current_logger.errmsg
+ )
diff --git a/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/actor.py b/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/actor.py
new file mode 100644
index 00000000..b6b35f1a
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/actor.py
@@ -0,0 +1,18 @@
+from leapp.actors import Actor
+from leapp.libraries.actor import scanpamuserdb
+from leapp.models import PamUserDbLocation
+from leapp.tags import FactsPhaseTag, IPUWorkflowTag
+
+
+class ScanPamUserDb(Actor):
+ """
+ Scan the PAM service folder for the location of pam_userdb databases
+ """
+
+ name = 'scan_pam_user_db'
+ consumes = ()
+ produces = (PamUserDbLocation,)
+ tags = (FactsPhaseTag, IPUWorkflowTag)
+
+ def process(self):
+ self.produce(scanpamuserdb.parse_pam_config_folder('/etc/pam.d/'))
diff --git a/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/libraries/scanpamuserdb.py b/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/libraries/scanpamuserdb.py
new file mode 100644
index 00000000..0f668c02
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/libraries/scanpamuserdb.py
@@ -0,0 +1,29 @@
+import os
+import re
+
+from leapp.models import PamUserDbLocation
+
+
+def _parse_pam_config_file(conf_file):
+ with open(conf_file, 'r') as file:
+ for line in file:
+ if 'pam_userdb' in line:
+ match = re.search(r'db=(\S+)', line)
+ if match:
+ return match.group(1)
+
+ return None
+
+
+def parse_pam_config_folder(conf_folder):
+ locations = set()
+
+ for file_name in os.listdir(conf_folder):
+ file_path = os.path.join(conf_folder, file_name)
+
+ if os.path.isfile(file_path):
+ location = _parse_pam_config_file(file_path)
+ if location is not None:
+ locations.add(location)
+
+ return PamUserDbLocation(locations=list(locations))
diff --git a/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/tests/files/pam_userdb_basic b/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/tests/files/pam_userdb_basic
new file mode 100644
index 00000000..f115147b
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/tests/files/pam_userdb_basic
@@ -0,0 +1 @@
+auth required pam_userdb.so db=/tmp/db1
diff --git a/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/tests/files/pam_userdb_complete b/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/tests/files/pam_userdb_complete
new file mode 100644
index 00000000..84e40b48
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/tests/files/pam_userdb_complete
@@ -0,0 +1,9 @@
+auth required pam_env.so
+auth required pam_faildelay.so delay=2000000
+auth sufficient pam_fprintd.so
+auth [default=1 ignore=ignore success=ok] pam_usertype.so isregular
+auth [default=1 ignore=ignore success=ok] pam_localuser.so
+auth required pam_userdb.so db=/tmp/db2
+auth [default=1 ignore=ignore success=ok] pam_usertype.so isregular
+auth sufficient pam_sss.so forward_pass
+auth required pam_deny.so
diff --git a/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/tests/files/pam_userdb_missing b/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/tests/files/pam_userdb_missing
new file mode 100644
index 00000000..764947fc
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/tests/files/pam_userdb_missing
@@ -0,0 +1 @@
+auth sufficient pam_unix.so nullok
diff --git a/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/tests/test_scanpamuserdb.py b/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/tests/test_scanpamuserdb.py
new file mode 100644
index 00000000..3b752d87
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/pamuserdb/scanpamuserdb/tests/test_scanpamuserdb.py
@@ -0,0 +1,27 @@
+import os
+
+import pytest
+
+from leapp.libraries.actor import scanpamuserdb
+
+CUR_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+@pytest.mark.parametrize(
+ "inp,exp_out",
+ [
+ ("files/pam_userdb_missing", None),
+ ("files/pam_userdb_basic", "/tmp/db1"),
+ ("files/pam_userdb_complete", "/tmp/db2"),
+ ],
+)
+def test_parse_pam_config_file(inp, exp_out):
+ file = scanpamuserdb._parse_pam_config_file(os.path.join(CUR_DIR, inp))
+ assert file == exp_out
+
+
+def test_parse_pam_config_folder():
+ msg = scanpamuserdb.parse_pam_config_folder(os.path.join(CUR_DIR, "files/"))
+ assert len(msg.locations) == 2
+ assert "/tmp/db1" in msg.locations
+ assert "/tmp/db2" in msg.locations
diff --git a/repos/system_upgrade/el9toel10/models/pamuserdblocation.py b/repos/system_upgrade/el9toel10/models/pamuserdblocation.py
new file mode 100644
index 00000000..d15b2041
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/models/pamuserdblocation.py
@@ -0,0 +1,14 @@
+from leapp.models import fields, Model
+from leapp.topics import SystemInfoTopic
+
+
+class PamUserDbLocation(Model):
+ """
+ Provides a list of all database files for pam_userdb
+ """
+ topic = SystemInfoTopic
+
+ locations = fields.List(fields.String(), default=[])
+ """
+ The list with the full path to the database files.
+ """
--
2.47.0

View File

@ -1,31 +0,0 @@
From d6e57eec3ded2887008055442ba906a92c572a01 Mon Sep 17 00:00:00 2001
From: Matej Matuska <mmatuska@redhat.com>
Date: Thu, 10 Oct 2024 14:03:36 +0200
Subject: [PATCH 09/40] Replace mirror.centos.org with vault.centos.org Centos
7 Containerfile
As mirror.centos.org is dead, replace mirrorlist with baseurl pointing
to vault.centos.org in utils/container-builds/Containerfile.centos7.
---
utils/container-builds/Containerfile.centos7 | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/utils/container-builds/Containerfile.centos7 b/utils/container-builds/Containerfile.centos7
index 70ac3df1..af00eddb 100644
--- a/utils/container-builds/Containerfile.centos7
+++ b/utils/container-builds/Containerfile.centos7
@@ -2,6 +2,11 @@ FROM centos:7
VOLUME /repo
+# mirror.centos.org is dead, comment out mirrorlist and set baseurl to vault.centos.org
+RUN sed -i s/mirror.centos.org/vault.centos.org/ /etc/yum.repos.d/CentOS-*.repo
+RUN sed -i s/^#\s*baseurl=http/baseurl=http/ /etc/yum.repos.d/CentOS-*.repo
+RUN sed -i s/^mirrorlist=http/#mirrorlist=http/ /etc/yum.repos.d/CentOS-*.repo
+
RUN yum update -y && \
yum install -y rpm-build python-devel make git
--
2.47.0

View File

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

View File

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

View File

@ -1,35 +0,0 @@
From b997e4eeb835809d1fbfd1a0b9a6114c133bf0b4 Mon Sep 17 00:00:00 2001
From: Matej Matuska <mmatuska@redhat.com>
Date: Thu, 10 Oct 2024 15:28:48 +0200
Subject: [PATCH 10/40] kernelcmdlineconfig: Add Report to produces tuple
The missing `leapp.reporting.Report` class is added to
kernelcmdlineconfig actor `produces` tuple.
---
.../system_upgrade/common/actors/kernelcmdlineconfig/actor.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/repos/system_upgrade/common/actors/kernelcmdlineconfig/actor.py b/repos/system_upgrade/common/actors/kernelcmdlineconfig/actor.py
index b44fd835..3585a14e 100644
--- a/repos/system_upgrade/common/actors/kernelcmdlineconfig/actor.py
+++ b/repos/system_upgrade/common/actors/kernelcmdlineconfig/actor.py
@@ -4,6 +4,7 @@ from leapp.actors import Actor
from leapp.exceptions import StopActorExecutionError
from leapp.libraries.actor import kernelcmdlineconfig
from leapp.models import FirmwareFacts, InstalledTargetKernelInfo, KernelCmdlineArg, TargetKernelCmdlineArgTasks
+from leapp.reporting import Report
from leapp.tags import FinalizationPhaseTag, IPUWorkflowTag
@@ -14,7 +15,7 @@ class KernelCmdlineConfig(Actor):
name = 'kernelcmdlineconfig'
consumes = (KernelCmdlineArg, InstalledTargetKernelInfo, FirmwareFacts, TargetKernelCmdlineArgTasks)
- produces = ()
+ produces = (Report,)
tags = (FinalizationPhaseTag, IPUWorkflowTag)
def process(self):
--
2.47.0

View File

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

View File

@ -1,204 +0,0 @@
From c2c96affa7b20c82969419ce49b65cbf646a0c32 Mon Sep 17 00:00:00 2001
From: Matej Matuska <mmatuska@redhat.com>
Date: Fri, 18 Oct 2024 12:43:19 +0200
Subject: [PATCH 11/40] kernelcmdlineconfig: Use args from first entry when
multiple entries are listed
Instead of erroring out when grubby lists multiple entries for the
default kernel, always use the `args=` and `root=` from the first one and create
a post-upgrade report. The report instruct user to ensure those are the
correct ones or to correct them.
This can happen, for example, if MAKEDEBUG=yes is set in
/etc/sysconfing/kernel.
Jira: RHEL-46911
---
.../libraries/kernelcmdlineconfig.py | 79 ++++++++++++++++---
.../tests/test_kernelcmdlineconfig.py | 48 ++++++++++-
2 files changed, 116 insertions(+), 11 deletions(-)
diff --git a/repos/system_upgrade/common/actors/kernelcmdlineconfig/libraries/kernelcmdlineconfig.py b/repos/system_upgrade/common/actors/kernelcmdlineconfig/libraries/kernelcmdlineconfig.py
index 6b261c3b..19c50f3c 100644
--- a/repos/system_upgrade/common/actors/kernelcmdlineconfig/libraries/kernelcmdlineconfig.py
+++ b/repos/system_upgrade/common/actors/kernelcmdlineconfig/libraries/kernelcmdlineconfig.py
@@ -109,10 +109,55 @@ def _extract_grubby_value(record):
return matches.group(2)
+def report_multple_entries_for_default_kernel():
+ if use_cmdline_file():
+ report_hint = (
+ 'After the system has been rebooted into the new version of RHEL,'
+ ' check that configured default kernel cmdline arguments in /etc/kernel/cmdline '
+ ' are correct. In case that different arguments are expected, update the file as needed.'
+ )
+ else:
+ report_hint = (
+ 'After the system has been rebooted into the new version of RHEL,'
+ ' check that configured default kernel cmdline arguments are set as expected, using'
+ ' the `grub2-editenv list` command. '
+ ' If different default arguments are expected, update them using grub2-editenv.\n'
+ ' For example, consider that current booted kernel has correct kernel cmdline'
+ ' arguments and /proc/cmdline contains:\n\n'
+ ' BOOT_IMAGE=(hd0,msdos1)/vmlinuz-4.18.0-425.3.1.el8.x86_64'
+ ' root=/dev/mapper/rhel_ibm--root ro console=tty0'
+ ' console=ttyS0,115200 rd_NO_PLYMOUTH\n\n'
+ ' then run the following grub2-editenv command:\n\n'
+ ' # grub2-editenv - set "kernelopts=root=/dev/mapper/rhel_ibm--root'
+ ' ro console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH"'
+ )
+
+ reporting.create_report([
+ reporting.Title('Ensure that expected default kernel cmdline arguments are set'),
+ reporting.Summary(
+ 'During the upgrade we needed to modify the kernel command line arguments.'
+ ' However, multiple bootloader entries with different arguments were found for the default'
+ ' kernel (perhaps MAKEDEBUG=yes is set in /etc/sysconfig/kernel).'
+ ' Leapp used the arguments from the first found entry of the target kernel'
+ ' and set it as the new default kernel cmdline arguments for kernels installed in the future.'
+ ),
+ reporting.Remediation(hint=report_hint),
+ reporting.Severity(reporting.Severity.HIGH),
+ reporting.Groups([
+ reporting.Groups.BOOT,
+ reporting.Groups.KERNEL,
+ reporting.Groups.POST,
+ ]),
+ reporting.RelatedResource('file', '/etc/kernel/cmdline'),
+ ])
+
+
def retrieve_args_for_default_kernel(kernel_info):
# Copy the args for the default kernel to all kernels.
kernel_args = None
kernel_root = None
+ detected_multiple_entries = False
+
cmd = ['grubby', '--info', kernel_info.kernel_img_path]
output = stdlib.run(cmd, split=False)
for record in output['stdout'].splitlines():
@@ -122,19 +167,30 @@ def retrieve_args_for_default_kernel(kernel_info):
temp_kernel_args = _extract_grubby_value(record)
if kernel_args:
- api.current_logger().warning('Grubby output is malformed:'
- ' `args=` is listed more than once.')
if kernel_args != temp_kernel_args:
- raise ReadOfKernelArgsError('Grubby listed `args=` multiple'
- ' times with different values.')
- kernel_args = _extract_grubby_value(record)
+ api.current_logger().warning(
+ 'Grubby output listed `args=` multiple times with different values,'
+ ' continuing with the first result'
+ )
+ detected_multiple_entries = True
+ else:
+ api.current_logger().warning('Grubby output listed `args=` more than once')
+ else:
+ kernel_args = temp_kernel_args
elif record.startswith('root='):
- api.current_logger().warning('Grubby output is malformed:'
- ' `root=` is listed more than once.')
+ temp_kernel_root = _extract_grubby_value(record)
+
if kernel_root:
- raise ReadOfKernelArgsError('Grubby listed `root=` multiple'
- ' times with different values')
- kernel_root = _extract_grubby_value(record)
+ if kernel_root != temp_kernel_root:
+ api.current_logger().warning(
+ 'Grubby output listed `root=` multiple times with different values,'
+ ' continuing with the first result'
+ )
+ detected_multiple_entries = True
+ else:
+ api.current_logger().warning('Grubby output listed `root=` more than once')
+ else:
+ kernel_root = temp_kernel_root
if not kernel_args or not kernel_root:
raise ReadOfKernelArgsError(
@@ -142,6 +198,9 @@ def retrieve_args_for_default_kernel(kernel_info):
' kernels: root={}, args={}'.format(kernel_root, kernel_args)
)
+ if detected_multiple_entries:
+ report_multple_entries_for_default_kernel()
+
return kernel_root, kernel_args
diff --git a/repos/system_upgrade/common/actors/kernelcmdlineconfig/tests/test_kernelcmdlineconfig.py b/repos/system_upgrade/common/actors/kernelcmdlineconfig/tests/test_kernelcmdlineconfig.py
index ffe4b046..e5759a7b 100644
--- a/repos/system_upgrade/common/actors/kernelcmdlineconfig/tests/test_kernelcmdlineconfig.py
+++ b/repos/system_upgrade/common/actors/kernelcmdlineconfig/tests/test_kernelcmdlineconfig.py
@@ -4,11 +4,12 @@ from collections import namedtuple
import pytest
+from leapp import reporting
from leapp.exceptions import StopActorExecutionError
from leapp.libraries import stdlib
from leapp.libraries.actor import kernelcmdlineconfig
from leapp.libraries.common.config import architecture
-from leapp.libraries.common.testutils import CurrentActorMocked
+from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked
from leapp.libraries.stdlib import api
from leapp.models import InstalledTargetKernelInfo, KernelCmdlineArg, TargetKernelCmdlineArgTasks
@@ -183,6 +184,51 @@ def test_kernelcmdline_config_no_version(monkeypatch):
assert not mocked_run.commands
+SECOND_KERNEL_ARGS = (
+ 'ro rootflags=subvol=root'
+ ' resume=/dev/mapper/luks-2c0df999-81ec-4a35-a1f9-b93afee8c6ad'
+ ' rd.luks.uuid=luks-90a6412f-c588-46ca-9118-5aca35943d25'
+ ' rd.luks.uuid=luks-2c0df999-81ec-4a35-a1f9-b93afee8c6ad'
+)
+SECOND_KERNEL_ROOT = 'UUID=1aa15850-2685-418d-95a6-f7266a2de83b'
+
+
+@pytest.mark.parametrize(
+ 'second_grubby_output',
+ (
+ TEMPLATE_GRUBBY_INFO_OUTPUT.format(SECOND_KERNEL_ARGS, SECOND_KERNEL_ROOT),
+ TEMPLATE_GRUBBY_INFO_OUTPUT.format(SAMPLE_KERNEL_ARGS, SECOND_KERNEL_ROOT),
+ TEMPLATE_GRUBBY_INFO_OUTPUT.format(SECOND_KERNEL_ARGS, SAMPLE_KERNEL_ROOT),
+ )
+)
+def test_kernelcmdline_config_mutiple_args(monkeypatch, second_grubby_output):
+ kernel_img_path = '/boot/vmlinuz-X'
+ kernel_info = InstalledTargetKernelInfo(pkg_nevra=TARGET_KERNEL_NEVRA,
+ uname_r='',
+ kernel_img_path=kernel_img_path,
+ initramfs_path='/boot/initramfs-X')
+
+ # For this test, we need to check we get the proper report if grubby --info
+ # outputs multiple different `root=` or `args=`
+ # and that the first ones are used
+ grubby_info_output = "\n".join((SAMPLE_GRUBBY_INFO_OUTPUT, second_grubby_output))
+
+ mocked_run = MockedRun(
+ outputs={" ".join(("grubby", "--info", kernel_img_path)): grubby_info_output,
+ }
+ )
+ monkeypatch.setattr(stdlib, 'run', mocked_run)
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked())
+ monkeypatch.setattr(reporting, "create_report", create_report_mocked())
+
+ root, args = kernelcmdlineconfig.retrieve_args_for_default_kernel(kernel_info)
+ assert root == SAMPLE_KERNEL_ROOT
+ assert args == SAMPLE_KERNEL_ARGS
+ assert reporting.create_report.called == 1
+ expected_title = 'Ensure that expected default kernel cmdline arguments are set'
+ assert expected_title in reporting.create_report.report_fields['title']
+
+
def test_kernelcmdline_config_malformed_args(monkeypatch):
kernel_img_path = '/boot/vmlinuz-X'
kernel_info = InstalledTargetKernelInfo(pkg_nevra=TARGET_KERNEL_NEVRA,
--
2.47.0

View File

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

View File

@ -1,216 +0,0 @@
From 053137c50d1b060f9e6e6e45d82196b1045391b7 Mon Sep 17 00:00:00 2001
From: mhecko <mhecko@redhat.com>
Date: Thu, 4 Apr 2024 14:22:48 +0200
Subject: [PATCH 12/40] check_microarch: refactor to handle possible future
reqs
---
.../actors/checkmicroarchitecture/actor.py | 0
.../libraries/checkmicroarchitecture.py | 73 +++++++++++++++++++
.../tests/test_checkmicroarchitecture.py | 21 ++++--
.../libraries/checkmicroarchitecture.py | 46 ------------
4 files changed, 87 insertions(+), 53 deletions(-)
rename repos/system_upgrade/{el8toel9 => common}/actors/checkmicroarchitecture/actor.py (100%)
create mode 100644 repos/system_upgrade/common/actors/checkmicroarchitecture/libraries/checkmicroarchitecture.py
rename repos/system_upgrade/{el8toel9 => common}/actors/checkmicroarchitecture/tests/test_checkmicroarchitecture.py (79%)
delete mode 100644 repos/system_upgrade/el8toel9/actors/checkmicroarchitecture/libraries/checkmicroarchitecture.py
diff --git a/repos/system_upgrade/el8toel9/actors/checkmicroarchitecture/actor.py b/repos/system_upgrade/common/actors/checkmicroarchitecture/actor.py
similarity index 100%
rename from repos/system_upgrade/el8toel9/actors/checkmicroarchitecture/actor.py
rename to repos/system_upgrade/common/actors/checkmicroarchitecture/actor.py
diff --git a/repos/system_upgrade/common/actors/checkmicroarchitecture/libraries/checkmicroarchitecture.py b/repos/system_upgrade/common/actors/checkmicroarchitecture/libraries/checkmicroarchitecture.py
new file mode 100644
index 00000000..cc617203
--- /dev/null
+++ b/repos/system_upgrade/common/actors/checkmicroarchitecture/libraries/checkmicroarchitecture.py
@@ -0,0 +1,73 @@
+from collections import namedtuple
+
+from leapp import reporting
+from leapp.libraries.common.config.architecture import ARCH_X86_64, matches_architecture
+from leapp.libraries.common.config.version import get_target_major_version
+from leapp.libraries.stdlib import api
+from leapp.models import CPUInfo
+
+X86_64_BASELINE_FLAGS = ['cmov', 'cx8', 'fpu', 'fxsr', 'mmx', 'syscall', 'sse', 'sse2']
+X86_64_V2_FLAGS = ['cx16', 'lahf_lm', 'popcnt', 'pni', 'sse4_1', 'sse4_2', 'ssse3']
+
+MicroarchInfo = namedtuple('MicroarchInfo', ('required_flags', 'extra_report_fields', 'microarch_ver'))
+
+
+def _inhibit_upgrade(missing_flags, target_rhel, microarch_ver, extra_report_fields=None):
+ title = 'Current x86-64 microarchitecture is unsupported in {0}'.format(target_rhel)
+ summary = ('{0} has a higher CPU requirement than older versions, it now requires a CPU '
+ 'compatible with {1} instruction set or higher.\n\n'
+ 'Missings flags detected are: {2}\n'.format(target_rhel, microarch_ver, ', '.join(missing_flags)))
+
+ report_fields = [
+ reporting.Title(title),
+ reporting.Summary(summary),
+ reporting.Severity(reporting.Severity.HIGH),
+ reporting.Groups([reporting.Groups.INHIBITOR]),
+ reporting.Groups([reporting.Groups.SANITY]),
+ reporting.Remediation(hint=('If case of using virtualization, virtualization platforms often allow '
+ 'configuring a minimum denominator CPU model for compatibility when migrating '
+ 'between different CPU models. Ensure that minimum requirements are not below '
+ 'that of {0}\n').format(target_rhel)),
+ ]
+
+ if extra_report_fields:
+ report_fields += extra_report_fields
+
+ reporting.create_report(report_fields)
+
+
+def process():
+ """
+ Check whether the processor matches the required microarchitecture.
+ """
+
+ if not matches_architecture(ARCH_X86_64):
+ api.current_logger().info('Architecture not x86-64. Skipping microarchitecture test.')
+ return
+
+ cpuinfo = next(api.consume(CPUInfo))
+
+ rhel9_microarch_article = reporting.ExternalLink(
+ title='Building Red Hat Enterprise Linux 9 for the x86-64-v2 microarchitecture level',
+ url='https://red.ht/rhel-9-intel-microarchitectures'
+ )
+
+ rhel_major_to_microarch_reqs = {
+ '9': MicroarchInfo(microarch_ver='x86-64-v2',
+ required_flags=(X86_64_BASELINE_FLAGS + X86_64_V2_FLAGS),
+ extra_report_fields=[rhel9_microarch_article]),
+ }
+
+ microarch_info = rhel_major_to_microarch_reqs.get(get_target_major_version())
+ if not microarch_info:
+ api.current_logger().info('No known microarchitecture requirements are known for target RHEL%s.',
+ get_target_major_version())
+ return
+
+ missing_flags = [flag for flag in microarch_info.required_flags if flag not in cpuinfo.flags]
+ api.current_logger().debug('Required flags missing: %s', missing_flags)
+ if missing_flags:
+ _inhibit_upgrade(missing_flags,
+ 'RHEL{0}'.format(get_target_major_version()),
+ microarch_info.microarch_ver,
+ extra_report_fields=microarch_info.extra_report_fields)
diff --git a/repos/system_upgrade/el8toel9/actors/checkmicroarchitecture/tests/test_checkmicroarchitecture.py b/repos/system_upgrade/common/actors/checkmicroarchitecture/tests/test_checkmicroarchitecture.py
similarity index 79%
rename from repos/system_upgrade/el8toel9/actors/checkmicroarchitecture/tests/test_checkmicroarchitecture.py
rename to repos/system_upgrade/common/actors/checkmicroarchitecture/tests/test_checkmicroarchitecture.py
index b7c850d9..b0624f2b 100644
--- a/repos/system_upgrade/el8toel9/actors/checkmicroarchitecture/tests/test_checkmicroarchitecture.py
+++ b/repos/system_upgrade/common/actors/checkmicroarchitecture/tests/test_checkmicroarchitecture.py
@@ -25,7 +25,13 @@ def test_not_x86_64_passes(monkeypatch, arch):
assert not reporting.create_report.called
-def test_valid_microarchitecture(monkeypatch):
+@pytest.mark.parametrize(
+ ('target_ver', 'cpu_flags'),
+ [
+ ('9.0', checkmicroarchitecture.X86_64_BASELINE_FLAGS + checkmicroarchitecture.X86_64_V2_FLAGS)
+ ]
+)
+def test_valid_microarchitecture(monkeypatch, target_ver, cpu_flags):
"""
Test no report is generated on a valid microarchitecture
"""
@@ -33,9 +39,8 @@ def test_valid_microarchitecture(monkeypatch):
monkeypatch.setattr(reporting, "create_report", create_report_mocked())
monkeypatch.setattr(api, 'current_logger', logger_mocked())
- required_flags = checkmicroarchitecture.X86_64_BASELINE_FLAGS + checkmicroarchitecture.X86_64_V2_FLAGS
- monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(arch=ARCH_X86_64,
- msgs=[CPUInfo(flags=required_flags)]))
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(arch=ARCH_X86_64, dst_ver=target_ver,
+ msgs=[CPUInfo(flags=cpu_flags)]))
checkmicroarchitecture.process()
@@ -43,14 +48,16 @@ def test_valid_microarchitecture(monkeypatch):
assert not reporting.create_report.called
-def test_invalid_microarchitecture(monkeypatch):
+@pytest.mark.parametrize('target_ver', ['9.0'])
+def test_invalid_microarchitecture(monkeypatch, target_ver):
"""
Test report is generated on x86-64 architecture with invalid microarchitecture and the upgrade is inhibited
"""
monkeypatch.setattr(reporting, "create_report", create_report_mocked())
monkeypatch.setattr(api, 'current_logger', logger_mocked())
- monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(arch=ARCH_X86_64, msgs=[CPUInfo()]))
+ monkeypatch.setattr(api, 'current_actor',
+ CurrentActorMocked(arch=ARCH_X86_64, msgs=[CPUInfo()], dst_ver=target_ver))
checkmicroarchitecture.process()
@@ -60,6 +67,6 @@ def test_invalid_microarchitecture(monkeypatch):
assert 'Architecture not x86-64. Skipping microarchitecture test.' not in api.current_logger().infomsg
assert reporting.create_report.called == 1
assert 'microarchitecture is unsupported' in produced_title
- assert 'RHEL9 has a higher CPU requirement' in produced_summary
+ assert 'has a higher CPU requirement' in produced_summary
assert reporting.create_report.report_fields['severity'] == reporting.Severity.HIGH
assert is_inhibitor(reporting.create_report.report_fields)
diff --git a/repos/system_upgrade/el8toel9/actors/checkmicroarchitecture/libraries/checkmicroarchitecture.py b/repos/system_upgrade/el8toel9/actors/checkmicroarchitecture/libraries/checkmicroarchitecture.py
deleted file mode 100644
index 9c083d7e..00000000
--- a/repos/system_upgrade/el8toel9/actors/checkmicroarchitecture/libraries/checkmicroarchitecture.py
+++ /dev/null
@@ -1,46 +0,0 @@
-from leapp import reporting
-from leapp.libraries.common.config.architecture import ARCH_X86_64, matches_architecture
-from leapp.libraries.stdlib import api
-from leapp.models import CPUInfo
-
-X86_64_BASELINE_FLAGS = ['cmov', 'cx8', 'fpu', 'fxsr', 'mmx', 'syscall', 'sse', 'sse2']
-X86_64_V2_FLAGS = ['cx16', 'lahf_lm', 'popcnt', 'pni', 'sse4_1', 'sse4_2', 'ssse3']
-
-
-def _inhibit_upgrade(missing_flags):
- title = 'Current x86-64 microarchitecture is unsupported in RHEL9'
- summary = ('RHEL9 has a higher CPU requirement than older versions, it now requires a CPU '
- 'compatible with x86-64-v2 instruction set or higher.\n\n'
- 'Missings flags detected are: {}\n'.format(', '.join(missing_flags)))
-
- reporting.create_report([
- reporting.Title(title),
- reporting.Summary(summary),
- reporting.ExternalLink(title='Building Red Hat Enterprise Linux 9 for the x86-64-v2 microarchitecture level',
- url='https://red.ht/rhel-9-intel-microarchitectures'),
- reporting.Severity(reporting.Severity.HIGH),
- reporting.Groups([reporting.Groups.INHIBITOR]),
- reporting.Groups([reporting.Groups.SANITY]),
- reporting.Remediation(hint=('If case of using virtualization, virtualization platforms often allow '
- 'configuring a minimum denominator CPU model for compatibility when migrating '
- 'between different CPU models. Ensure that minimum requirements are not below '
- 'that of RHEL9\n')),
- ])
-
-
-def process():
- """
- Check whether the processor matches the required microarchitecture.
- """
-
- if not matches_architecture(ARCH_X86_64):
- api.current_logger().info('Architecture not x86-64. Skipping microarchitecture test.')
- return
-
- cpuinfo = next(api.consume(CPUInfo))
-
- required_flags = X86_64_BASELINE_FLAGS + X86_64_V2_FLAGS
- missing_flags = [flag for flag in required_flags if flag not in cpuinfo.flags]
- api.current_logger().debug('Required flags missing: %s', missing_flags)
- if missing_flags:
- _inhibit_upgrade(missing_flags)
--
2.47.0

View File

@ -1,133 +0,0 @@
From d3ebc990ba65801fbed2aaf1dce8329698667d1c Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Wed, 28 Aug 2024 12:18:40 +0200
Subject: [PATCH 13/40] check_microarch: add rhel10 requirements
---
.../actors/checkmicroarchitecture/actor.py | 13 ++++++++++--
.../libraries/checkmicroarchitecture.py | 8 +++++--
.../tests/test_checkmicroarchitecture.py | 21 ++++++++++++++-----
3 files changed, 33 insertions(+), 9 deletions(-)
diff --git a/repos/system_upgrade/common/actors/checkmicroarchitecture/actor.py b/repos/system_upgrade/common/actors/checkmicroarchitecture/actor.py
index 98ffea80..bb342f2f 100644
--- a/repos/system_upgrade/common/actors/checkmicroarchitecture/actor.py
+++ b/repos/system_upgrade/common/actors/checkmicroarchitecture/actor.py
@@ -17,7 +17,8 @@ class CheckMicroarchitecture(Actor):
levels.
RHEL9 has a higher CPU requirement than older versions, it now requires a
- CPU compatible with ``x86-64-v2`` instruction set or higher.
+ CPU compatible with ``x86-64-v2`` instruction set or higher. Similarly,
+ RHEL10 requires at least ``x86-64-v3`` instruction set.
.. table:: Required CPU features by microarchitecure level with a
corresponding flag as shown by ``lscpu``.
@@ -43,7 +44,15 @@ class CheckMicroarchitecture(Actor):
| | SSE4_2 | sse4_2 |
| | SSSE3 | ssse3 |
+------------+-------------+--------------------+
- | ... | | |
+ | x86-64-v3 | AVX | avx |
+ | | AVX2 | avx2 |
+ | | BMI1 | bmi1 |
+ | | BMI2 | bmi2 |
+ | | F16C | f16c |
+ | | FMA | fma |
+ | | LZCNT | abm |
+ | | MOVBE | movbe |
+ | | OSXSAVE | xsave |
+------------+-------------+--------------------+
Note: To get the corresponding flag for the CPU feature consult the file
diff --git a/repos/system_upgrade/common/actors/checkmicroarchitecture/libraries/checkmicroarchitecture.py b/repos/system_upgrade/common/actors/checkmicroarchitecture/libraries/checkmicroarchitecture.py
index cc617203..94e85e3e 100644
--- a/repos/system_upgrade/common/actors/checkmicroarchitecture/libraries/checkmicroarchitecture.py
+++ b/repos/system_upgrade/common/actors/checkmicroarchitecture/libraries/checkmicroarchitecture.py
@@ -8,6 +8,7 @@ from leapp.models import CPUInfo
X86_64_BASELINE_FLAGS = ['cmov', 'cx8', 'fpu', 'fxsr', 'mmx', 'syscall', 'sse', 'sse2']
X86_64_V2_FLAGS = ['cx16', 'lahf_lm', 'popcnt', 'pni', 'sse4_1', 'sse4_2', 'ssse3']
+X86_64_V3_FLAGS = ['avx2', 'bmi1', 'bmi2', 'f16c', 'fma', 'abm', 'movbe', 'xsave']
MicroarchInfo = namedtuple('MicroarchInfo', ('required_flags', 'extra_report_fields', 'microarch_ver'))
@@ -16,7 +17,7 @@ def _inhibit_upgrade(missing_flags, target_rhel, microarch_ver, extra_report_fie
title = 'Current x86-64 microarchitecture is unsupported in {0}'.format(target_rhel)
summary = ('{0} has a higher CPU requirement than older versions, it now requires a CPU '
'compatible with {1} instruction set or higher.\n\n'
- 'Missings flags detected are: {2}\n'.format(target_rhel, microarch_ver, ', '.join(missing_flags)))
+ 'Missings flags detected are: {2}\n').format(target_rhel, microarch_ver, ', '.join(missing_flags))
report_fields = [
reporting.Title(title),
@@ -24,7 +25,7 @@ def _inhibit_upgrade(missing_flags, target_rhel, microarch_ver, extra_report_fie
reporting.Severity(reporting.Severity.HIGH),
reporting.Groups([reporting.Groups.INHIBITOR]),
reporting.Groups([reporting.Groups.SANITY]),
- reporting.Remediation(hint=('If case of using virtualization, virtualization platforms often allow '
+ reporting.Remediation(hint=('If a case of using virtualization, virtualization platforms often allow '
'configuring a minimum denominator CPU model for compatibility when migrating '
'between different CPU models. Ensure that minimum requirements are not below '
'that of {0}\n').format(target_rhel)),
@@ -56,6 +57,9 @@ def process():
'9': MicroarchInfo(microarch_ver='x86-64-v2',
required_flags=(X86_64_BASELINE_FLAGS + X86_64_V2_FLAGS),
extra_report_fields=[rhel9_microarch_article]),
+ '10': MicroarchInfo(microarch_ver='x86-64-v3',
+ required_flags=(X86_64_BASELINE_FLAGS + X86_64_V2_FLAGS + X86_64_V3_FLAGS),
+ extra_report_fields=[]),
}
microarch_info = rhel_major_to_microarch_reqs.get(get_target_major_version())
diff --git a/repos/system_upgrade/common/actors/checkmicroarchitecture/tests/test_checkmicroarchitecture.py b/repos/system_upgrade/common/actors/checkmicroarchitecture/tests/test_checkmicroarchitecture.py
index b0624f2b..eeca8be0 100644
--- a/repos/system_upgrade/common/actors/checkmicroarchitecture/tests/test_checkmicroarchitecture.py
+++ b/repos/system_upgrade/common/actors/checkmicroarchitecture/tests/test_checkmicroarchitecture.py
@@ -25,10 +25,15 @@ def test_not_x86_64_passes(monkeypatch, arch):
assert not reporting.create_report.called
+ENTIRE_V2_FLAG_SET = checkmicroarchitecture.X86_64_BASELINE_FLAGS + checkmicroarchitecture.X86_64_V2_FLAGS
+ENTIRE_V3_FLAG_SET = ENTIRE_V2_FLAG_SET + checkmicroarchitecture.X86_64_V3_FLAGS
+
+
@pytest.mark.parametrize(
('target_ver', 'cpu_flags'),
[
- ('9.0', checkmicroarchitecture.X86_64_BASELINE_FLAGS + checkmicroarchitecture.X86_64_V2_FLAGS)
+ ('9.0', ENTIRE_V2_FLAG_SET),
+ ('10.0', ENTIRE_V3_FLAG_SET)
]
)
def test_valid_microarchitecture(monkeypatch, target_ver, cpu_flags):
@@ -48,16 +53,22 @@ def test_valid_microarchitecture(monkeypatch, target_ver, cpu_flags):
assert not reporting.create_report.called
-@pytest.mark.parametrize('target_ver', ['9.0'])
-def test_invalid_microarchitecture(monkeypatch, target_ver):
+@pytest.mark.parametrize(
+ ('target_ver', 'cpu_flags'),
+ (
+ ('9.0', checkmicroarchitecture.X86_64_BASELINE_FLAGS),
+ ('10.0', ENTIRE_V2_FLAG_SET),
+ )
+)
+def test_invalid_microarchitecture(monkeypatch, target_ver, cpu_flags):
"""
Test report is generated on x86-64 architecture with invalid microarchitecture and the upgrade is inhibited
"""
-
+ cpu_info = CPUInfo(flags=cpu_flags)
monkeypatch.setattr(reporting, "create_report", create_report_mocked())
monkeypatch.setattr(api, 'current_logger', logger_mocked())
monkeypatch.setattr(api, 'current_actor',
- CurrentActorMocked(arch=ARCH_X86_64, msgs=[CPUInfo()], dst_ver=target_ver))
+ CurrentActorMocked(arch=ARCH_X86_64, msgs=[cpu_info], dst_ver=target_ver))
checkmicroarchitecture.process()
--
2.47.0

View File

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

View File

@ -1,44 +0,0 @@
From a14793892bafaad0802844cbb56be3be3220eb47 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Wed, 25 Sep 2024 17:29:02 +0200
Subject: [PATCH 14/40] Skip checking files under .../directory-hash/ dir
* The main reason for this change is to improve performance and
reduce flood of logs for the content that does not seem to be important
to check for the upgrade process.
The directory has been relatively recently added to ca-certificates
rpm on EL 9+ systems mostly to improve performance of OpenSSL and
the content does not seem to be important for the IPU process.
The high number of files takes too much time to evaluate and causes
flood of logs that are not important.
This is updated solution that we drop originally: 60f500e59bb92
---
.../targetuserspacecreator/libraries/userspacegen.py | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
index cd2d7d6e..d7698056 100644
--- a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
+++ b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
@@ -311,6 +311,16 @@ def _get_files_owned_by_rpms(context, dirpath, pkgs=None, recursive=False):
searchdir = context.full_path(dirpath)
if recursive:
for root, _, files in os.walk(searchdir):
+ if '/directory-hash/' in root:
+ # tl;dr; for the performance improvement
+ # The directory has been relatively recently added to ca-certificates
+ # rpm on EL 9+ systems and the content does not seem to be important
+ # for the IPU process. Also, it contains high number of files and
+ # their processing floods the output and slows down IPU.
+ # So skipping it entirely.
+ # This is updated solution that we drop originally: 60f500e59bb92
+ api.current_logger().debug('SKIP files in the {} directory: Not important for the IPU.'.format(root))
+ continue
for filename in files:
relpath = os.path.relpath(os.path.join(root, filename), searchdir)
file_list.append(relpath)
--
2.47.0

View File

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

View File

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

View File

@ -1,66 +0,0 @@
From cef2825778eb63f95e13cf48b1683bc98c32c21b Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Fri, 25 Oct 2024 16:33:38 +0200
Subject: [PATCH 15/40] lib(overlay): cap the max size of disk images
On systems with large disks (e.g. 16TB) with lots of free space, leapp
might attemt to create files larger than the max file size of the
underlying FS. Attempting to create such large files causes leapp
to crash. This patch caps the max image size to 1TB, based on empirical
evidence that more free space is not needed for the upgrade RPM
transaction.
Jira-ref: RHEL-57064
---
.../common/libraries/overlaygen.py | 28 +++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/repos/system_upgrade/common/libraries/overlaygen.py b/repos/system_upgrade/common/libraries/overlaygen.py
index c1ac9ad3..867e3559 100644
--- a/repos/system_upgrade/common/libraries/overlaygen.py
+++ b/repos/system_upgrade/common/libraries/overlaygen.py
@@ -68,6 +68,27 @@ or close to that size, stay always with this minimal protected size defined by
this constant.
"""
+_MAX_DISK_IMAGE_SIZE_MB = 2**20 # 1*TB
+"""
+Maximum size of the created (sparse) images.
+
+Defaults to 1TB. If a disk with capacity larger than _MAX_DISK_IMAGE_SIZE_MB
+is mounted on the system, the corresponding image used to store overlay
+modifications will be capped to _MAX_DISK_IMAGE_SIZE_MB.
+
+Engineering rationale:
+ This constant was introduced to prevent leapp from creating files that are
+ virtually larger than the maximum file size supported by the file system.
+ E.g. if the source system hosts /var/lib/leapp on EXT4, then we cannot
+ create a file larger than 16TB.
+ We create these "disk images" to be able to verify the system has enough
+ disk space to perform the RPM upgrade transaction. From our experience,
+ we are not aware of any system which could have installed so much content
+ by RPMs that we would need 1TB of the free space on a single FS. Therefore,
+ we consider this value as safe while preventing us from exceeding FS
+ limits.
+"""
+
MountPoints = namedtuple('MountPoints', ['fs_file', 'fs_vfstype'])
@@ -287,6 +308,13 @@ def _prepare_required_mounts(scratch_dir, mounts_dir, storage_info, scratch_rese
disk_size = _get_fspace(mountpoint, convert_to_mibs=True, coefficient=0.95)
if mountpoint == scratch_mp:
disk_size = scratch_disk_size
+
+ if disk_size > _MAX_DISK_IMAGE_SIZE_MB:
+ msg = ('Image for overlayfs corresponding to the disk mounted at %s would ideally have %d MB, '
+ 'but we truncate it to %d MB to avoid bumping to max file limits.')
+ api.current_logger().info(msg, mountpoint, disk_size, _MAX_DISK_IMAGE_SIZE_MB)
+ disk_size = _MAX_DISK_IMAGE_SIZE_MB
+
image = _create_mount_disk_image(disk_images_directory, mountpoint, disk_size)
result[mountpoint] = mounting.LoopMount(
source=image,
--
2.47.0

View File

@ -1,168 +0,0 @@
From ec078243771f8ef43853bd242175a612fe84f95b Mon Sep 17 00:00:00 2001
From: tomasfratrik <tomasfratrik8@gmail.com>
Date: Wed, 17 Jul 2024 12:12:50 +0200
Subject: [PATCH 16/40] Raise proper error when ModelViolationError occurs
This error occurs when repo file has invalid definition, specifically
when the 'name' entry of the config files is invalid. Also add tests.
Jira: RHEL-19249
---
.../systemfacts/libraries/systemfacts.py | 13 ++++++++-
.../systemfacts/tests/test_systemfacts.py | 24 ++++++++++++++++-
.../common/libraries/repofileutils.py | 17 +++++++++++-
.../libraries/tests/test_repofileutils.py | 27 +++++++++++++++++++
4 files changed, 78 insertions(+), 3 deletions(-)
diff --git a/repos/system_upgrade/common/actors/systemfacts/libraries/systemfacts.py b/repos/system_upgrade/common/actors/systemfacts/libraries/systemfacts.py
index d1eeb28c..f16cea1d 100644
--- a/repos/system_upgrade/common/actors/systemfacts/libraries/systemfacts.py
+++ b/repos/system_upgrade/common/actors/systemfacts/libraries/systemfacts.py
@@ -217,7 +217,18 @@ def get_sysctls_status():
def get_repositories_status():
""" Get a basic information about YUM repositories installed in the system """
- return RepositoriesFacts(repositories=repofileutils.get_parsed_repofiles())
+ try:
+ return RepositoriesFacts(repositories=repofileutils.get_parsed_repofiles())
+ except repofileutils.InvalidRepoDefinition as e:
+ raise StopActorExecutionError(
+ message=str(e),
+ details={
+ 'hint': 'For more directions on how to resolve the issue, see: {url}.'
+ .format(
+ url='https://access.redhat.com/solutions/6969001'
+ )
+ }
+ )
def get_selinux_status():
diff --git a/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts.py b/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts.py
index badf174c..5831b979 100644
--- a/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts.py
+++ b/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts.py
@@ -3,7 +3,16 @@ import pwd
import pytest
-from leapp.libraries.actor.systemfacts import _get_system_groups, _get_system_users, anyendswith, anyhasprefix, aslist
+from leapp.exceptions import StopActorExecutionError
+from leapp.libraries.actor.systemfacts import (
+ _get_system_groups,
+ _get_system_users,
+ anyendswith,
+ anyhasprefix,
+ aslist,
+ get_repositories_status
+)
+from leapp.libraries.common import repofileutils
from leapp.libraries.common.testutils import logger_mocked
from leapp.libraries.stdlib import api
from leapp.snactor.fixture import current_actor_libraries
@@ -116,3 +125,16 @@ def test_get_system_groups(monkeypatch, etc_group_names, skipped_group_names):
assert group_name not in api.current_logger().dbgmsg[0]
else:
assert not api.current_logger().dbgmsg
+
+
+def test_failed_parsed_repofiles(monkeypatch):
+ def _raise_invalidrepo_error():
+ raise repofileutils.InvalidRepoDefinition(msg='mocked error',
+ repofile='/etc/yum.repos.d/mock.repo',
+ repoid='mocked repoid')
+
+ monkeypatch.setattr(repofileutils, 'get_parsed_repofiles', _raise_invalidrepo_error)
+ monkeypatch.setattr(api, 'current_logger', logger_mocked())
+
+ with pytest.raises(StopActorExecutionError):
+ get_repositories_status()
diff --git a/repos/system_upgrade/common/libraries/repofileutils.py b/repos/system_upgrade/common/libraries/repofileutils.py
index a563be52..cab3c42b 100644
--- a/repos/system_upgrade/common/libraries/repofileutils.py
+++ b/repos/system_upgrade/common/libraries/repofileutils.py
@@ -11,6 +11,16 @@ except ImportError:
api.current_logger().warning('repofileutils.py: failed to import dnf')
+class InvalidRepoDefinition(Exception):
+ """Raised when a repository definition is invalid."""
+ def __init__(self, msg, repofile, repoid):
+ message = 'Invalid repository definition: {repoid} in: {repofile}: {msg}'.format(
+ repoid=repoid, repofile=repofile, msg=msg)
+ super(InvalidRepoDefinition, self).__init__(message)
+ self.repofile = repofile
+ self.repoid = repoid
+
+
def _parse_repository(repoid, repo_data):
def asbool(x):
return x == '1'
@@ -33,12 +43,17 @@ def parse_repofile(repofile):
:param repofile: Path to the repo file
:type repofile: str
:rtype: RepositoryFile
+ :raises InvalidRepoDefinition: If the repository definition is invalid,
+ this can for example occur if 'name' field in repository is missing or it is invalid.
"""
data = []
with open(repofile, mode='r') as fp:
cp = utils.parse_config(fp, strict=False)
for repoid in cp.sections():
- data.append(_parse_repository(repoid, dict(cp.items(repoid))))
+ try:
+ data.append(_parse_repository(repoid, dict(cp.items(repoid))))
+ except fields.ModelViolationError as e:
+ raise InvalidRepoDefinition(e, repofile=repofile, repoid=repoid)
return RepositoryFile(file=repofile, data=data)
diff --git a/repos/system_upgrade/common/libraries/tests/test_repofileutils.py b/repos/system_upgrade/common/libraries/tests/test_repofileutils.py
index 51cc1c11..42c7e49e 100644
--- a/repos/system_upgrade/common/libraries/tests/test_repofileutils.py
+++ b/repos/system_upgrade/common/libraries/tests/test_repofileutils.py
@@ -1,7 +1,10 @@
import json
import os
+import pytest
+
from leapp.libraries.common import repofileutils
+from leapp.models.fields import ModelViolationError
CUR_DIR = os.path.dirname(os.path.abspath(__file__))
@@ -12,6 +15,30 @@ def test_invert_dict():
assert inv_dict == {'a': [1], 'b': [1, 2]}
+@pytest.mark.parametrize(
+ ('repoid', 'data'),
+ (
+ ('missing-name', {'baseurl': 'http://example.com', 'enabled': '1', 'gpgcheck': '1'}),
+ (None, {'name': 'name', 'baseurl': 'http://example.com', 'enabled': '1', 'gpgcheck': '1'}),
+ ('name-none', {'name': None, 'baseurl': 'http://example.com', 'enabled': '1', 'gpgcheck': '1'}),
+ ('baseurl-true', {'name': 'valid', 'baseurl': True, 'enabled': '1', 'gpgcheck': '1'}),
+ )
+)
+def test__parse_repository_missing_name(repoid, data):
+ with pytest.raises(ModelViolationError):
+ repofileutils._parse_repository(repoid, data)
+
+
+def test_parse_repofile_error(monkeypatch):
+ def _parse_repository_mocked(*args, **kwargs):
+ raise ModelViolationError('')
+
+ monkeypatch.setattr(repofileutils, '_parse_repository', _parse_repository_mocked)
+
+ with pytest.raises(repofileutils.InvalidRepoDefinition):
+ repofileutils.parse_repofile(os.path.join(CUR_DIR, 'sample_repos.txt'))
+
+
def test_parse_repofile():
repofile = repofileutils.parse_repofile(os.path.join(CUR_DIR, 'sample_repos.txt'))
--
2.47.0

View File

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

View File

@ -1,56 +0,0 @@
From f84c6f808a821d3ccd09a4a8278cef9c09984a28 Mon Sep 17 00:00:00 2001
From: Daniel Zatovic <daniel.zatovic@gmail.com>
Date: Wed, 3 Apr 2024 23:25:06 +0200
Subject: [PATCH 17/40] InhibitWhenLuks: simplify the logic
---
.../common/actors/inhibitwhenluks/actor.py | 35 +++++++------------
1 file changed, 13 insertions(+), 22 deletions(-)
diff --git a/repos/system_upgrade/common/actors/inhibitwhenluks/actor.py b/repos/system_upgrade/common/actors/inhibitwhenluks/actor.py
index d3ff2d2e..40b845b0 100644
--- a/repos/system_upgrade/common/actors/inhibitwhenluks/actor.py
+++ b/repos/system_upgrade/common/actors/inhibitwhenluks/actor.py
@@ -24,26 +24,17 @@ class InhibitWhenLuks(Actor):
ceph_info = next(self.consume(CephInfo))
if ceph_info:
ceph_vol = ceph_info.encrypted_volumes[:]
- for storage_info in self.consume(StorageInfo):
- for blk in storage_info.lsblk:
- if blk.tp == 'crypt' and blk.name not in ceph_vol:
- create_report([
- reporting.Title('LUKS encrypted partition detected'),
- reporting.Summary('Upgrading system with encrypted partitions is not supported'),
- reporting.Severity(reporting.Severity.HIGH),
- reporting.Groups([reporting.Groups.BOOT, reporting.Groups.ENCRYPTION]),
- reporting.Groups([reporting.Groups.INHIBITOR]),
- ])
- break
except StopIteration:
- for storage_info in self.consume(StorageInfo):
- for blk in storage_info.lsblk:
- if blk.tp == 'crypt':
- create_report([
- reporting.Title('LUKS encrypted partition detected'),
- reporting.Summary('Upgrading system with encrypted partitions is not supported'),
- reporting.Severity(reporting.Severity.HIGH),
- reporting.Groups([reporting.Groups.BOOT, reporting.Groups.ENCRYPTION]),
- reporting.Groups([reporting.Groups.INHIBITOR]),
- ])
- break
+ pass
+
+ for storage_info in self.consume(StorageInfo):
+ for blk in storage_info.lsblk:
+ if blk.tp == 'crypt' and blk.name not in ceph_vol:
+ create_report([
+ reporting.Title('LUKS encrypted partition detected'),
+ reporting.Summary('Upgrading system with encrypted partitions is not supported'),
+ reporting.Severity(reporting.Severity.HIGH),
+ reporting.Groups([reporting.Groups.BOOT, reporting.Groups.ENCRYPTION]),
+ reporting.Groups([reporting.Groups.INHIBITOR]),
+ ])
+ break
--
2.47.0

View File

@ -0,0 +1,407 @@
From 4432e62f02af820d040f45d7fc59296cf734bdc5 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Sat, 29 Mar 2025 22:00:38 +0100
Subject: [PATCH 17/37] cleanup(ipupaths): remove IPUPaths message
Drop the already deprecated IPUPaths message that was used to inform
actors about supported upgrade paths. Instead, the functionality has
been assumed by IPUConfig.
Jira-ref: RHEL-80550
---
.../common/actors/checktargetversion/actor.py | 3 +-
.../libraries/checktargetversion.py | 15 +--
.../tests/test_checktargetversion.py | 27 +++---
.../actors/scandefinedipupaths/actor.py | 31 ------
.../libraries/scandefinedipupaths.py | 43 --------
.../tests/files/upgrade_paths.json | 22 -----
.../tests/test_scandefinedipupaths.py | 97 -------------------
.../system_upgrade/common/models/ipupaths.py | 43 --------
8 files changed, 17 insertions(+), 264 deletions(-)
delete mode 100644 repos/system_upgrade/common/actors/scandefinedipupaths/actor.py
delete mode 100644 repos/system_upgrade/common/actors/scandefinedipupaths/libraries/scandefinedipupaths.py
delete mode 100644 repos/system_upgrade/common/actors/scandefinedipupaths/tests/files/upgrade_paths.json
delete mode 100644 repos/system_upgrade/common/actors/scandefinedipupaths/tests/test_scandefinedipupaths.py
delete mode 100644 repos/system_upgrade/common/models/ipupaths.py
diff --git a/repos/system_upgrade/common/actors/checktargetversion/actor.py b/repos/system_upgrade/common/actors/checktargetversion/actor.py
index 291ce3da..31375bfc 100644
--- a/repos/system_upgrade/common/actors/checktargetversion/actor.py
+++ b/repos/system_upgrade/common/actors/checktargetversion/actor.py
@@ -1,6 +1,5 @@
from leapp.actors import Actor
from leapp.libraries.actor import checktargetversion
-from leapp.models import IPUPaths
from leapp.reporting import Report
from leapp.tags import ChecksPhaseTag, IPUWorkflowTag
@@ -14,7 +13,7 @@ class CheckTargetVersion(Actor):
"""
name = 'check_target_version'
- consumes = (IPUPaths,)
+ consumes = ()
produces = (Report,)
tags = (ChecksPhaseTag, IPUWorkflowTag)
diff --git a/repos/system_upgrade/common/actors/checktargetversion/libraries/checktargetversion.py b/repos/system_upgrade/common/actors/checktargetversion/libraries/checktargetversion.py
index 0df1ece2..2369ae11 100644
--- a/repos/system_upgrade/common/actors/checktargetversion/libraries/checktargetversion.py
+++ b/repos/system_upgrade/common/actors/checktargetversion/libraries/checktargetversion.py
@@ -1,22 +1,15 @@
from leapp import reporting
-from leapp.exceptions import StopActorExecutionError
from leapp.libraries.common.config import get_env, version
from leapp.libraries.stdlib import api
-from leapp.models import IPUPaths
-from leapp.utils.deprecation import suppress_deprecation
FMT_LIST_SEPARATOR = '\n - '
-@suppress_deprecation(IPUPaths)
def get_supported_target_versions():
- ipu_paths = next(api.consume(IPUPaths), None)
src_version = version.get_source_version()
- if not ipu_paths:
- # NOTE: missing unit-tests. Unexpected situation and the solution
- # is possibly temporary
- raise StopActorExecutionError('Missing the IPUPaths message. Cannot determine defined upgrade paths.')
- for ipu_path in ipu_paths.data:
+ supported_paths = api.current_actor().configuration.supported_upgrade_paths
+
+ for ipu_path in supported_paths:
if ipu_path.source_version == src_version:
return ipu_path.target_versions
@@ -28,7 +21,7 @@ def get_supported_target_versions():
.format(src_version)
)
maj_version = version.get_source_major_version()
- for ipu_path in ipu_paths.data:
+ for ipu_path in supported_paths:
if ipu_path.source_version == maj_version:
return ipu_path.target_versions
diff --git a/repos/system_upgrade/common/actors/checktargetversion/tests/test_checktargetversion.py b/repos/system_upgrade/common/actors/checktargetversion/tests/test_checktargetversion.py
index 07391e7a..6927af23 100644
--- a/repos/system_upgrade/common/actors/checktargetversion/tests/test_checktargetversion.py
+++ b/repos/system_upgrade/common/actors/checktargetversion/tests/test_checktargetversion.py
@@ -4,36 +4,33 @@ import pytest
from leapp import reporting
from leapp.libraries.actor import checktargetversion
+from leapp.libraries.common.config import architecture
from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked, logger_mocked
from leapp.libraries.stdlib import api
-from leapp.models import IPUPath, IPUPaths
+from leapp.models import IPUSourceToPossibleTargets
from leapp.utils.deprecation import suppress_deprecation
from leapp.utils.report import is_inhibitor
-# It must be in a function so we can suppress the deprecation warning in tests.
-@suppress_deprecation(IPUPaths)
-def _get_upgrade_paths_data():
- return IPUPaths(data=[
- IPUPath(source_version='7.9', target_versions=['8.10']),
- IPUPath(source_version='8.10', target_versions=['9.4', '9.5', '9.6']),
- IPUPath(source_version='9.6', target_versions=['10.0']),
- IPUPath(source_version='7', target_versions=['8.10']),
- IPUPath(source_version='8', target_versions=['9.4', '9.5', '9.6']),
- IPUPath(source_version='9', target_versions=['10.0'])
- ])
-
-
@pytest.fixture
def setup_monkeypatch(monkeypatch):
"""Fixture to set up common monkeypatches."""
def _setup(source_version, target_version, leapp_unsupported='0'):
+ suppoted_upgrade_paths = [
+ IPUSourceToPossibleTargets(source_version='7.9', target_versions=['8.10']),
+ IPUSourceToPossibleTargets(source_version='8.10', target_versions=['9.4', '9.5', '9.6']),
+ IPUSourceToPossibleTargets(source_version='9.6', target_versions=['10.0']),
+ IPUSourceToPossibleTargets(source_version='7', target_versions=['8.10']),
+ IPUSourceToPossibleTargets(source_version='8', target_versions=['9.4', '9.5', '9.6']),
+ IPUSourceToPossibleTargets(source_version='9', target_versions=['10.0'])
+ ]
+
curr_actor_mocked = CurrentActorMocked(
src_ver=source_version,
dst_ver=target_version,
envars={'LEAPP_UNSUPPORTED': leapp_unsupported},
- msgs=[_get_upgrade_paths_data()]
+ supported_upgrade_paths=suppoted_upgrade_paths
)
monkeypatch.setattr(api, 'current_actor', curr_actor_mocked)
monkeypatch.setattr(api, 'current_logger', logger_mocked())
diff --git a/repos/system_upgrade/common/actors/scandefinedipupaths/actor.py b/repos/system_upgrade/common/actors/scandefinedipupaths/actor.py
deleted file mode 100644
index a84c85f2..00000000
--- a/repos/system_upgrade/common/actors/scandefinedipupaths/actor.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from leapp.actors import Actor
-from leapp.libraries.actor import scandefinedipupaths
-from leapp.models import IPUPaths
-from leapp.tags import FactsPhaseTag, IPUWorkflowTag
-
-
-class ScanDefinedIPUPaths(Actor):
- """
- Load defined IPU paths for the current major source system version
- and defined upgrade flavour.
-
- The upgrade paths are defined inside `files/upgrade_paths.json`.
- Based on the defined upgrade flavour (default, saphana, ..) loads particular
- definitions and filter out all upgrade paths from other system major versions.
- I.e. for RHEL 8.10 system with the default upgrade flavour, load all upgrade
- paths from any RHEL 8 system defined under the 'default' flavour.
-
- The code is mostly taken from the CLI command_utils. The duplicate solution
- is not so problematic now as it will be unified next time.
-
- Note the deprecation suppression is expected here as this is considered as
- temporary solution now.
- """
-
- name = 'scan_defined_ipu_paths'
- consumes = ()
- produces = (IPUPaths,)
- tags = (IPUWorkflowTag, FactsPhaseTag)
-
- def process(self):
- scandefinedipupaths.process()
diff --git a/repos/system_upgrade/common/actors/scandefinedipupaths/libraries/scandefinedipupaths.py b/repos/system_upgrade/common/actors/scandefinedipupaths/libraries/scandefinedipupaths.py
deleted file mode 100644
index 1e39f2c8..00000000
--- a/repos/system_upgrade/common/actors/scandefinedipupaths/libraries/scandefinedipupaths.py
+++ /dev/null
@@ -1,43 +0,0 @@
-import json
-
-from leapp.libraries.common.config.version import get_source_major_version
-from leapp.libraries.stdlib import api
-from leapp.models import IPUPath, IPUPaths
-from leapp.utils.deprecation import suppress_deprecation
-
-
-def load_ipu_paths_for_flavour(flavour, _filename='upgrade_paths.json'):
- """
- Load defined IPU paths from the upgrade_paths.json file for the specified
- flavour.
-
- Note the file is required to be always present, so skipping any test
- for the missing file. Crash hard and terribly if the file is missing
- or the content is invalid.
-
- We expect the flavour to be always good as it is under our control
- (already sanitized in IPUConfig), but return empty dict and log it if missing.
- """
- with open(api.get_common_file_path(_filename)) as fp:
- data = json.loads(fp.read())
- if flavour not in data:
- api.current_logger().warning(
- 'Cannot discover any upgrade paths for flavour: {}'
- .format(flavour)
- )
- return data.get(flavour, {})
-
-
-def get_filtered_ipu_paths(ipu_paths, src_major_version):
- result = []
- for src_version, tgt_versions in ipu_paths.items():
- if src_version.split('.')[0] == src_major_version:
- result.append(IPUPath(source_version=src_version, target_versions=tgt_versions))
- return result
-
-
-@suppress_deprecation(IPUPaths)
-def process():
- flavour = api.current_actor().configuration.flavour
- ipu_paths = load_ipu_paths_for_flavour(flavour)
- api.produce(IPUPaths(data=get_filtered_ipu_paths(ipu_paths, get_source_major_version())))
diff --git a/repos/system_upgrade/common/actors/scandefinedipupaths/tests/files/upgrade_paths.json b/repos/system_upgrade/common/actors/scandefinedipupaths/tests/files/upgrade_paths.json
deleted file mode 100644
index b6107376..00000000
--- a/repos/system_upgrade/common/actors/scandefinedipupaths/tests/files/upgrade_paths.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "rhel": {
- "default": {
- "8.10": ["9.4", "9.5", "9.6"],
- "8.4": ["9.2"],
- "9.6": ["10.0"],
- "8": ["9.4", "9.5", "9.6"],
- "9": ["10.0"]
- },
- "saphana": {
- "8.10": ["9.6", "9.4"],
- "8": ["9.6", "9.4"],
- "9.6": ["10.0"],
- "9": ["10.0"]
- }
- },
- "centos": {
- "default": {
- "8": ["9"]
- }
- }
-}
diff --git a/repos/system_upgrade/common/actors/scandefinedipupaths/tests/test_scandefinedipupaths.py b/repos/system_upgrade/common/actors/scandefinedipupaths/tests/test_scandefinedipupaths.py
deleted file mode 100644
index 9ffc9829..00000000
--- a/repos/system_upgrade/common/actors/scandefinedipupaths/tests/test_scandefinedipupaths.py
+++ /dev/null
@@ -1,97 +0,0 @@
-import json
-import os
-
-import pytest
-
-from leapp.libraries.actor import scandefinedipupaths
-from leapp.libraries.common.testutils import CurrentActorMocked, produce_mocked
-from leapp.models import IPUPath, IPUPaths
-from leapp.utils.deprecation import suppress_deprecation
-
-CUR_DIR = os.path.dirname(os.path.abspath(__file__))
-
-
-class CurrentActorMockedModified(CurrentActorMocked):
- def get_common_file_path(self, fname):
- fpath = os.path.join(CUR_DIR, 'files', fname)
- assert os.path.exists(fpath)
- if os.path.exists(fpath):
- return fpath
- return None
-
-
-@pytest.mark.parametrize(('flavour', 'expected_result'), (
- ('nonsense', {}),
- (
- 'default',
- {
- '8.10': ['9.4', '9.5', '9.6'],
- '8.4': ['9.2'],
- '9.6': ['10.0'],
- '8': ['9.4', '9.5', '9.6'],
- '9': ['10.0']
- }
- ),
- (
- 'saphana',
- {
- '8.10': ['9.6', '9.4'],
- '8': ['9.6', '9.4'],
- '9.6': ['10.0'],
- '9': ['10.0']
- }
- ),
-))
-def test_load_ipu_paths_for_flavour(monkeypatch, flavour, expected_result):
- monkeypatch.setattr(scandefinedipupaths.api, 'current_actor', CurrentActorMockedModified())
-
- result = scandefinedipupaths.load_ipu_paths_for_flavour(flavour=flavour)
- assert result == expected_result
-
-
-_DATA_IPU_PATHS = {
- '8.10': ['9.4', '9.5', '9.6'],
- '8.4': ['9.2'],
- '9.6': ['10.0'],
- '8': ['9.4', '9.5', '9.6'],
- '80.0': ['81.0']
-}
-
-
-@suppress_deprecation(IPUPaths)
-@pytest.mark.parametrize(('maj_version', 'expected_result'), (
- ('7', []),
- (
- '8',
- [
- IPUPath(source_version='8.10', target_versions=['9.4', '9.5', '9.6']),
- IPUPath(source_version='8.4', target_versions=['9.2']),
- IPUPath(source_version='8', target_versions=['9.4', '9.5', '9.6']),
- ]
- ),
- (
- '80',
- [
- IPUPath(source_version='80.0', target_versions=['81.0']),
- ]
- ),
-
-
-))
-def test_get_filtered_ipu_paths(monkeypatch, maj_version, expected_result):
- result = scandefinedipupaths.get_filtered_ipu_paths(_DATA_IPU_PATHS, maj_version)
- result = sorted(result, key=lambda x: x.source_version)
- assert result == sorted(expected_result, key=lambda x: x.source_version)
-
-
-def test_scan_defined_ipu_paths(monkeypatch):
- # let's try one 'full' happy run
- monkeypatch.setattr(scandefinedipupaths.api, 'current_actor', CurrentActorMockedModified(src_ver='9.6'))
- monkeypatch.setattr(scandefinedipupaths.api, 'produce', produce_mocked())
- scandefinedipupaths.process()
-
- assert scandefinedipupaths.api.produce.called == 1
- msg = scandefinedipupaths.api.produce.model_instances[0]
- assert isinstance(msg, IPUPaths)
- assert len(msg.data) == 2
- assert {i.source_version for i in msg.data} == {'9', '9.6'}
diff --git a/repos/system_upgrade/common/models/ipupaths.py b/repos/system_upgrade/common/models/ipupaths.py
deleted file mode 100644
index 5469f25e..00000000
--- a/repos/system_upgrade/common/models/ipupaths.py
+++ /dev/null
@@ -1,43 +0,0 @@
-from leapp.models import fields, Model
-from leapp.topics import SystemInfoTopic
-from leapp.utils.deprecation import deprecated
-
-
-class IPUPath(Model):
- """
- Represent upgrade paths from a source system version.
-
- This model is not supposed to be produced nor consumed directly by any actor.
- See `IPUPaths` instead.
- """
- topic = SystemInfoTopic
-
- source_version = fields.String()
- """Version of a particular source system."""
-
- target_versions = fields.List(fields.String())
- """List of defined target system versions for the `source_version` system."""
-
-
-@deprecated(
- since="2025-02-01",
- message="This model is temporary and not assumed to be used in any actors."
-)
-class IPUPaths(Model):
- """
- Defined Upgrade paths from the source system major version and used upgrade flavour.
-
- In example for the RHEL 8.10 system with the 'default' upgrade flavour it will
- contain information about all defined upgrade paths from any RHEL 8 system
- for the 'default' flavour (other flavour can be e.g. 'saphana' for systems
- with SAP HANA installed.
-
- Note this model is marked as deprecated now as it is considered as a temporary
- solution. It can be removed in any future release!
- """
- topic = SystemInfoTopic
-
- data = fields.List(fields.Model(IPUPath))
- """
- List of defined (filtered) upgrade paths.
- """
--
2.49.0

View File

@ -1,271 +0,0 @@
From 03fc6743b8916f23f6a213e3f0fc3020ee141b96 Mon Sep 17 00:00:00 2001
From: Daniel Zatovic <daniel.zatovic@gmail.com>
Date: Wed, 3 Apr 2024 23:42:45 +0200
Subject: [PATCH 18/40] StorageScanner: Add parent device name to lsblk
Modify the StorageInfo model to include path and name of the parent
device. Use StorageScanner to collect this information.
Morover fix lsblk test, there should be a full device path in "lsblk
-pbnr" output (just names were used in the original test).
---
.../tests/test_inhibitwhenluks.py | 12 +--
.../libraries/storagescanner.py | 29 +++++--
.../tests/unit_test_storagescanner.py | 78 +++++++++++++++----
.../common/models/storageinfo.py | 2 +
.../tests/unit_test_vdoconversionscanner.py | 4 +-
5 files changed, 95 insertions(+), 30 deletions(-)
diff --git a/repos/system_upgrade/common/actors/inhibitwhenluks/tests/test_inhibitwhenluks.py b/repos/system_upgrade/common/actors/inhibitwhenluks/tests/test_inhibitwhenluks.py
index fee50f9d..405a3429 100644
--- a/repos/system_upgrade/common/actors/inhibitwhenluks/tests/test_inhibitwhenluks.py
+++ b/repos/system_upgrade/common/actors/inhibitwhenluks/tests/test_inhibitwhenluks.py
@@ -5,8 +5,8 @@ from leapp.utils.report import is_inhibitor
def test_actor_with_luks(current_actor_context):
- with_luks = [LsblkEntry(name='luks-132', kname='kname1', maj_min='253:0', rm='0',
- size='10G', bsize=10*(1 << 39), ro='0', tp='crypt', mountpoint='')]
+ with_luks = [LsblkEntry(name='luks-132', kname='kname1', maj_min='253:0', rm='0', size='10G', bsize=10*(1 << 39),
+ ro='0', tp='crypt', mountpoint='', parent_name='', parent_path='')]
current_actor_context.feed(StorageInfo(lsblk=with_luks))
current_actor_context.run()
@@ -16,8 +16,8 @@ def test_actor_with_luks(current_actor_context):
def test_actor_with_luks_ceph_only(current_actor_context):
- with_luks = [LsblkEntry(name='luks-132', kname='kname1', maj_min='253:0', rm='0',
- size='10G', bsize=10*(1 << 39), ro='0', tp='crypt', mountpoint='')]
+ with_luks = [LsblkEntry(name='luks-132', kname='kname1', maj_min='253:0', rm='0', size='10G', bsize=10*(1 << 39),
+ ro='0', tp='crypt', mountpoint='', parent_name='', parent_path='')]
ceph_volume = ['luks-132']
current_actor_context.feed(StorageInfo(lsblk=with_luks))
current_actor_context.feed(CephInfo(encrypted_volumes=ceph_volume))
@@ -26,8 +26,8 @@ def test_actor_with_luks_ceph_only(current_actor_context):
def test_actor_without_luks(current_actor_context):
- without_luks = [LsblkEntry(name='sda1', kname='sda1', maj_min='8:0', rm='0',
- size='10G', bsize=10*(1 << 39), ro='0', tp='part', mountpoint='/boot')]
+ without_luks = [LsblkEntry(name='sda1', kname='sda1', maj_min='8:0', rm='0', size='10G', bsize=10*(1 << 39),
+ ro='0', tp='part', mountpoint='/boot', parent_name='', parent_path='')]
current_actor_context.feed(StorageInfo(lsblk=without_luks))
current_actor_context.run()
diff --git a/repos/system_upgrade/common/actors/storagescanner/libraries/storagescanner.py b/repos/system_upgrade/common/actors/storagescanner/libraries/storagescanner.py
index f15f0d87..cad6bd32 100644
--- a/repos/system_upgrade/common/actors/storagescanner/libraries/storagescanner.py
+++ b/repos/system_upgrade/common/actors/storagescanner/libraries/storagescanner.py
@@ -164,18 +164,31 @@ def _get_mount_info(path):
)
+def _get_lsblk_info_for_devpath(dev_path):
+ lsblk_cmd = ['lsblk', '-nr', '--output', 'NAME,KNAME,SIZE', dev_path]
+ lsblk_info_for_devpath = next(_get_cmd_output(lsblk_cmd, ' ', 3), None)
+
+ return lsblk_info_for_devpath
+
+
@aslist
def _get_lsblk_info():
""" Collect storage info from lsblk command """
- cmd = ['lsblk', '-pbnr', '--output', 'NAME,MAJ:MIN,RM,SIZE,RO,TYPE,MOUNTPOINT']
- for entry in _get_cmd_output(cmd, ' ', 7):
- dev_path, maj_min, rm, bsize, ro, tp, mountpoint = entry
- lsblk_cmd = ['lsblk', '-nr', '--output', 'NAME,KNAME,SIZE', dev_path]
- lsblk_info_for_devpath = next(_get_cmd_output(lsblk_cmd, ' ', 3), None)
+ cmd = ['lsblk', '-pbnr', '--output', 'NAME,MAJ:MIN,RM,SIZE,RO,TYPE,MOUNTPOINT,PKNAME']
+ for entry in _get_cmd_output(cmd, ' ', 8):
+ dev_path, maj_min, rm, bsize, ro, tp, mountpoint, parent_path = entry
+
+ lsblk_info_for_devpath = _get_lsblk_info_for_devpath(dev_path)
if not lsblk_info_for_devpath:
return
-
name, kname, size = lsblk_info_for_devpath
+
+ parent_name = ""
+ if parent_path:
+ parent_info = _get_lsblk_info_for_devpath(parent_path)
+ if parent_info:
+ parent_name, _, _ = parent_info
+
yield LsblkEntry(
name=name,
kname=kname,
@@ -185,7 +198,9 @@ def _get_lsblk_info():
bsize=int(bsize),
ro=ro,
tp=tp,
- mountpoint=mountpoint)
+ mountpoint=mountpoint,
+ parent_name=parent_name,
+ parent_path=parent_path)
@aslist
diff --git a/repos/system_upgrade/common/actors/storagescanner/tests/unit_test_storagescanner.py b/repos/system_upgrade/common/actors/storagescanner/tests/unit_test_storagescanner.py
index 4dc11ea4..456e40ec 100644
--- a/repos/system_upgrade/common/actors/storagescanner/tests/unit_test_storagescanner.py
+++ b/repos/system_upgrade/common/actors/storagescanner/tests/unit_test_storagescanner.py
@@ -255,13 +255,18 @@ def test_get_lsblk_info(monkeypatch):
bytes_per_gb = 1 << 30
def get_cmd_output_mocked(cmd, delim, expected_len):
- if cmd == ['lsblk', '-pbnr', '--output', 'NAME,MAJ:MIN,RM,SIZE,RO,TYPE,MOUNTPOINT']:
+ if cmd == ['lsblk', '-pbnr', '--output', 'NAME,MAJ:MIN,RM,SIZE,RO,TYPE,MOUNTPOINT,PKNAME']:
output_lines_split_on_whitespace = [
- ['vda', '252:0', '0', str(40 * bytes_per_gb), '0', 'disk', ''],
- ['vda1', '252:1', '0', str(1 * bytes_per_gb), '0', 'part', '/boot'],
- ['vda2', '252:2', '0', str(39 * bytes_per_gb), '0', 'part', ''],
- ['rhel_ibm--p8--kvm--03--guest--02-root', '253:0', '0', str(38 * bytes_per_gb), '0', 'lvm', '/'],
- ['rhel_ibm--p8--kvm--03--guest--02-swap', '253:1', '0', str(1 * bytes_per_gb), '0', 'lvm', '[SWAP]']
+ ['/dev/vda', '252:0', '0', str(40 * bytes_per_gb), '0', 'disk', '', ''],
+ ['/dev/vda1', '252:1', '0', str(1 * bytes_per_gb), '0', 'part', '/boot', ''],
+ ['/dev/vda2', '252:2', '0', str(39 * bytes_per_gb), '0', 'part', '', ''],
+ ['/dev/mapper/rhel_ibm--p8--kvm--03--guest--02-root', '253:0', '0', str(38 * bytes_per_gb), '0', 'lvm',
+ '/', ''],
+ ['/dev/mapper/rhel_ibm--p8--kvm--03--guest--02-swap', '253:1', '0', str(1 * bytes_per_gb), '0', 'lvm',
+ '[SWAP]', ''],
+ ['/dev/mapper/luks-01b60fff-a2a8-4c03-893f-056bfc3f06f6', '254:0', '0', str(38 * bytes_per_gb), '0',
+ 'crypt', '', '/dev/nvme0n1p1'],
+ ['/dev/nvme0n1p1', '259:1', '0', str(39 * bytes_per_gb), '0', 'part', '', '/dev/nvme0n1'],
]
for output_line_parts in output_lines_split_on_whitespace:
yield output_line_parts
@@ -269,11 +274,17 @@ def test_get_lsblk_info(monkeypatch):
# We cannot have the output in a list, since the command is called per device. Therefore, we have to map
# each device path to its output.
output_lines_split_on_whitespace_per_device = {
- 'vda': ['vda', 'vda', '40G'],
- 'vda1': ['vda1', 'vda1', '1G'],
- 'vda2': ['vda2', 'vda2', '39G'],
- 'rhel_ibm--p8--kvm--03--guest--02-root': ['rhel_ibm--p8--kvm--03--guest--02-root', 'kname1', '38G'],
- 'rhel_ibm--p8--kvm--03--guest--02-swap': ['rhel_ibm--p8--kvm--03--guest--02-swap', 'kname2', '1G']
+ '/dev/vda': ['vda', 'vda', '40G'],
+ '/dev/vda1': ['vda1', 'vda1', '1G'],
+ '/dev/vda2': ['vda2', 'vda2', '39G'],
+ '/dev/mapper/rhel_ibm--p8--kvm--03--guest--02-root':
+ ['rhel_ibm--p8--kvm--03--guest--02-root', 'kname1', '38G'],
+ '/dev/mapper/rhel_ibm--p8--kvm--03--guest--02-swap':
+ ['rhel_ibm--p8--kvm--03--guest--02-swap', 'kname2', '1G'],
+ '/dev/mapper/luks-01b60fff-a2a8-4c03-893f-056bfc3f06f6':
+ ['luks-01b60fff-a2a8-4c03-893f-056bfc3f06f6', 'dm-0', '38G'],
+ '/dev/nvme0n1p1': ['nvme0n1p1', 'nvme0n1p1', '39G'],
+ '/dev/nvme0n1': ['nvme0n1', 'nvme0n1', '40G'],
}
dev_path = cmd[4]
if dev_path not in output_lines_split_on_whitespace_per_device:
@@ -294,7 +305,9 @@ def test_get_lsblk_info(monkeypatch):
bsize=40 * bytes_per_gb,
ro='0',
tp='disk',
- mountpoint=''),
+ mountpoint='',
+ parent_name='',
+ parent_path=''),
LsblkEntry(
name='vda1',
kname='vda1',
@@ -304,7 +317,9 @@ def test_get_lsblk_info(monkeypatch):
bsize=1 * bytes_per_gb,
ro='0',
tp='part',
- mountpoint='/boot'),
+ mountpoint='/boot',
+ parent_name='',
+ parent_path=''),
LsblkEntry(
name='vda2',
kname='vda2',
@@ -314,7 +329,9 @@ def test_get_lsblk_info(monkeypatch):
bsize=39 * bytes_per_gb,
ro='0',
tp='part',
- mountpoint=''),
+ mountpoint='',
+ parent_name='',
+ parent_path=''),
LsblkEntry(
name='rhel_ibm--p8--kvm--03--guest--02-root',
kname='kname1',
@@ -324,7 +341,9 @@ def test_get_lsblk_info(monkeypatch):
bsize=38 * bytes_per_gb,
ro='0',
tp='lvm',
- mountpoint='/'),
+ mountpoint='/',
+ parent_name='',
+ parent_path=''),
LsblkEntry(
name='rhel_ibm--p8--kvm--03--guest--02-swap',
kname='kname2',
@@ -334,7 +353,34 @@ def test_get_lsblk_info(monkeypatch):
bsize=1 * bytes_per_gb,
ro='0',
tp='lvm',
- mountpoint='[SWAP]')]
+ mountpoint='[SWAP]',
+ parent_name='',
+ parent_path=''),
+ LsblkEntry(
+ name='luks-01b60fff-a2a8-4c03-893f-056bfc3f06f6',
+ kname='dm-0',
+ maj_min='254:0',
+ rm='0',
+ size='38G',
+ bsize=38 * bytes_per_gb,
+ ro='0',
+ tp='crypt',
+ mountpoint='',
+ parent_name='nvme0n1p1',
+ parent_path='/dev/nvme0n1p1'),
+ LsblkEntry(
+ name='nvme0n1p1',
+ kname='nvme0n1p1',
+ maj_min='259:1',
+ rm='0',
+ size='39G',
+ bsize=39 * bytes_per_gb,
+ ro='0',
+ tp='part',
+ mountpoint='',
+ parent_name='nvme0n1',
+ parent_path='/dev/nvme0n1'),
+ ]
actual = storagescanner._get_lsblk_info()
assert expected == actual
diff --git a/repos/system_upgrade/common/models/storageinfo.py b/repos/system_upgrade/common/models/storageinfo.py
index 5bb9caac..71e7459d 100644
--- a/repos/system_upgrade/common/models/storageinfo.py
+++ b/repos/system_upgrade/common/models/storageinfo.py
@@ -43,6 +43,8 @@ class LsblkEntry(Model):
ro = fields.String()
tp = fields.String()
mountpoint = fields.String()
+ parent_name = fields.String()
+ parent_path = fields.String()
class PvsEntry(Model):
diff --git a/repos/system_upgrade/el8toel9/actors/vdoconversionscanner/tests/unit_test_vdoconversionscanner.py b/repos/system_upgrade/el8toel9/actors/vdoconversionscanner/tests/unit_test_vdoconversionscanner.py
index 0745c91d..4d6ef0dc 100644
--- a/repos/system_upgrade/el8toel9/actors/vdoconversionscanner/tests/unit_test_vdoconversionscanner.py
+++ b/repos/system_upgrade/el8toel9/actors/vdoconversionscanner/tests/unit_test_vdoconversionscanner.py
@@ -26,7 +26,9 @@ def _lsblk_entry(prefix, number, types, size='128G', bsize=2 ** 37):
bsize=bsize,
ro='0',
tp=types[random.randint(0, len(types) - 1)],
- mountpoint='')
+ mountpoint='',
+ parent_name='',
+ parent_path='')
@aslist
--
2.47.0

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@ -1,455 +0,0 @@
From ad241f701b39a81d132105f1a301f2f5546f498a Mon Sep 17 00:00:00 2001
From: Daniel Zatovic <daniel.zatovic@gmail.com>
Date: Tue, 6 Aug 2024 17:26:58 +0200
Subject: [PATCH 20/40] InhibitWhenLuks: allow upgrades for LUKS2 bound to
Clevis TPM2 token
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
So far, upgrades with encrypted drives were not supported. Encrypted
drives require interactively typing unlock passphrases, which is not
suitable for automatic upgrades using Leapp. We add a feature, where
systems with all drives configured with automatic unlock method can be
upgraded.
Currently, we only support drives configured with Clevis/TPM2 token,
because networking is not configured during Leapp upgrade (excluding
NBDE).
We consume LuksDumps message to decide whether the upgrade process
should be inhibited. If there is at least one LUKS2 device without
Clevis TPM2 binding, we inhibit the upgrade because we cannot tell if
the device is not a part of a more complex storage stack and the failure
to unlock the device migt cause boot problem.
Co-authored-by: Petr Stodůlka <pstodulk@redhat.com>
---
.../common/actors/inhibitwhenluks/actor.py | 38 ++--
.../libraries/inhibitwhenluks.py | 164 +++++++++++++++++
.../tests/test_inhibitwhenluks.py | 169 ++++++++++++++++--
3 files changed, 329 insertions(+), 42 deletions(-)
create mode 100644 repos/system_upgrade/common/actors/inhibitwhenluks/libraries/inhibitwhenluks.py
diff --git a/repos/system_upgrade/common/actors/inhibitwhenluks/actor.py b/repos/system_upgrade/common/actors/inhibitwhenluks/actor.py
index 40b845b0..65607167 100644
--- a/repos/system_upgrade/common/actors/inhibitwhenluks/actor.py
+++ b/repos/system_upgrade/common/actors/inhibitwhenluks/actor.py
@@ -1,40 +1,24 @@
-from leapp import reporting
from leapp.actors import Actor
-from leapp.models import CephInfo, StorageInfo
-from leapp.reporting import create_report, Report
+from leapp.libraries.actor.inhibitwhenluks import check_invalid_luks_devices
+from leapp.models import CephInfo, LuksDumps, StorageInfo, TargetUserSpaceUpgradeTasks, UpgradeInitramfsTasks
+from leapp.reporting import Report
from leapp.tags import ChecksPhaseTag, IPUWorkflowTag
class InhibitWhenLuks(Actor):
"""
- Check if any encrypted partitions is in use. If yes, inhibit the upgrade process.
+ Check if any encrypted partitions are in use and whether they are supported for the upgrade.
- Upgrading system with encrypted partition is not supported.
+ Upgrading EL7 system with encrypted partition is not supported (but ceph OSDs).
+ For EL8+ it's ok if the discovered used encrypted storage has LUKS2 format
+ and it's bounded to clevis-tpm2 token (so it can be automatically unlocked
+ during the process).
"""
name = 'check_luks_and_inhibit'
- consumes = (StorageInfo, CephInfo)
- produces = (Report,)
+ consumes = (CephInfo, LuksDumps, StorageInfo)
+ produces = (Report, TargetUserSpaceUpgradeTasks, UpgradeInitramfsTasks)
tags = (ChecksPhaseTag, IPUWorkflowTag)
def process(self):
- # If encrypted Ceph volumes present, check if there are more encrypted disk in lsblk than Ceph vol
- ceph_vol = []
- try:
- ceph_info = next(self.consume(CephInfo))
- if ceph_info:
- ceph_vol = ceph_info.encrypted_volumes[:]
- except StopIteration:
- pass
-
- for storage_info in self.consume(StorageInfo):
- for blk in storage_info.lsblk:
- if blk.tp == 'crypt' and blk.name not in ceph_vol:
- create_report([
- reporting.Title('LUKS encrypted partition detected'),
- reporting.Summary('Upgrading system with encrypted partitions is not supported'),
- reporting.Severity(reporting.Severity.HIGH),
- reporting.Groups([reporting.Groups.BOOT, reporting.Groups.ENCRYPTION]),
- reporting.Groups([reporting.Groups.INHIBITOR]),
- ])
- break
+ check_invalid_luks_devices()
diff --git a/repos/system_upgrade/common/actors/inhibitwhenluks/libraries/inhibitwhenluks.py b/repos/system_upgrade/common/actors/inhibitwhenluks/libraries/inhibitwhenluks.py
new file mode 100644
index 00000000..57a94e9d
--- /dev/null
+++ b/repos/system_upgrade/common/actors/inhibitwhenluks/libraries/inhibitwhenluks.py
@@ -0,0 +1,164 @@
+from leapp import reporting
+from leapp.libraries.common.config.version import get_source_major_version
+from leapp.libraries.stdlib import api
+from leapp.models import (
+ CephInfo,
+ DracutModule,
+ LuksDumps,
+ StorageInfo,
+ TargetUserSpaceUpgradeTasks,
+ UpgradeInitramfsTasks
+)
+from leapp.reporting import create_report
+
+# https://red.ht/clevis-tpm2-luks-auto-unlock-rhel8
+# https://red.ht/clevis-tpm2-luks-auto-unlock-rhel9
+# https://red.ht/convert-to-luks2-rhel8
+# https://red.ht/convert-to-luks2-rhel9
+CLEVIS_DOC_URL_FMT = 'https://red.ht/clevis-tpm2-luks-auto-unlock-rhel{}'
+LUKS2_CONVERT_DOC_URL_FMT = 'https://red.ht/convert-to-luks2-rhel{}'
+
+FMT_LIST_SEPARATOR = '\n - '
+
+
+def _formatted_list_output(input_list, sep=FMT_LIST_SEPARATOR):
+ return ['{}{}'.format(sep, item) for item in input_list]
+
+
+def _at_least_one_tpm_token(luks_dump):
+ return any([token.token_type == "clevis-tpm2" for token in luks_dump.tokens])
+
+
+def _get_ceph_volumes():
+ ceph_info = next(api.consume(CephInfo), None)
+ return ceph_info.encrypted_volumes[:] if ceph_info else []
+
+
+def apply_obsoleted_check_ipu_7_8():
+ ceph_vol = _get_ceph_volumes()
+ for storage_info in api.consume(StorageInfo):
+ for blk in storage_info.lsblk:
+ if blk.tp == 'crypt' and blk.name not in ceph_vol:
+ create_report([
+ reporting.Title('LUKS encrypted partition detected'),
+ reporting.Summary('Upgrading system with encrypted partitions is not supported'),
+ reporting.Severity(reporting.Severity.HIGH),
+ reporting.Groups([reporting.Groups.BOOT, reporting.Groups.ENCRYPTION]),
+ reporting.Groups([reporting.Groups.INHIBITOR]),
+ ])
+ break
+
+
+def report_inhibitor(luks1_partitions, no_tpm2_partitions):
+ source_major_version = get_source_major_version()
+ clevis_doc_url = CLEVIS_DOC_URL_FMT.format(source_major_version)
+ luks2_convert_doc_url = LUKS2_CONVERT_DOC_URL_FMT.format(source_major_version)
+ summary = (
+ 'We have detected LUKS encrypted volumes that do not meet current'
+ ' criteria to be able to proceed the in-place upgrade process.'
+ ' Right now the upgrade process requires for encrypted storage to be'
+ ' in LUKS2 format configured with Clevis TPM 2.0.'
+ )
+
+ report_hints = []
+
+ if luks1_partitions:
+
+ summary += (
+ '\n\nSince RHEL 8 the default format for LUKS encryption is LUKS2.'
+ ' Despite the old LUKS1 format is still supported on RHEL systems'
+ ' it has some limitations in comparison to LUKS2.'
+ ' Only the LUKS2 format is supported for upgrades.'
+ ' The following LUKS1 partitions have been discovered on your system:{}'
+ .format(''.join(_formatted_list_output(luks1_partitions)))
+ )
+ report_hints.append(reporting.Remediation(
+ hint=(
+ 'Convert your LUKS1 encrypted devices to LUKS2 and bind it to TPM2 using clevis.'
+ ' If this is not possible in your case consider clean installation'
+ ' of the target RHEL system instead.'
+ )
+ ))
+ report_hints.append(reporting.ExternalLink(
+ url=luks2_convert_doc_url,
+ title='LUKS versions in RHEL: Conversion'
+ ))
+
+ if no_tpm2_partitions:
+ summary += (
+ '\n\nCurrently we require the process to be non-interactive and'
+ ' offline. For this reason we require automatic unlock of'
+ ' encrypted devices during the upgrade process.'
+ ' Currently we support automatic unlocking during the upgrade only'
+ ' for volumes bound to Clevis TPM2 token.'
+ ' The following LUKS2 devices without Clevis TPM2 token '
+ ' have been discovered on your system: {}'
+ .format(''.join(_formatted_list_output(no_tpm2_partitions)))
+ )
+
+ report_hints.append(reporting.Remediation(
+ hint=(
+ 'Add Clevis TPM2 binding to LUKS devices.'
+ ' If some LUKS devices use still the old LUKS1 format, convert'
+ ' them to LUKS2 prior to binding.'
+ )
+ ))
+ report_hints.append(reporting.ExternalLink(
+ url=clevis_doc_url,
+ title='Configuring manual enrollment of LUKS-encrypted volumes by using a TPM 2.0 policy'
+ )
+ )
+ create_report([
+ reporting.Title('Detected LUKS devices unsuitable for in-place upgrade.'),
+ reporting.Summary(summary),
+ reporting.Severity(reporting.Severity.HIGH),
+ reporting.Groups([reporting.Groups.BOOT, reporting.Groups.ENCRYPTION]),
+ reporting.Groups([reporting.Groups.INHIBITOR]),
+ ] + report_hints)
+
+
+def check_invalid_luks_devices():
+ if get_source_major_version() == '7':
+ # NOTE: keeping unchanged behaviour for IPU 7 -> 8
+ apply_obsoleted_check_ipu_7_8()
+ return
+
+ luks_dumps = next(api.consume(LuksDumps), None)
+ if not luks_dumps:
+ api.current_logger().debug('No LUKS volumes detected. Skipping.')
+ return
+
+ luks1_partitions = []
+ no_tpm2_partitions = []
+ ceph_vol = _get_ceph_volumes()
+ for luks_dump in luks_dumps.dumps:
+ # if the device is managed by ceph, don't inhibit
+ if luks_dump.device_name in ceph_vol:
+ api.current_logger().debug('Skipping LUKS CEPH volume: {}'.format(luks_dump.device_name))
+ continue
+
+ if luks_dump.version == 1:
+ luks1_partitions.append(luks_dump.device_name)
+ elif luks_dump.version == 2 and not _at_least_one_tpm_token(luks_dump):
+ no_tpm2_partitions.append(luks_dump.device_name)
+
+ if luks1_partitions or no_tpm2_partitions:
+ report_inhibitor(luks1_partitions, no_tpm2_partitions)
+ else:
+ required_crypt_rpms = [
+ 'clevis',
+ 'clevis-dracut',
+ 'clevis-systemd',
+ 'clevis-udisks2',
+ 'clevis-luks',
+ 'cryptsetup',
+ 'tpm2-tss',
+ 'tpm2-tools',
+ 'tpm2-abrmd'
+ ]
+ api.produce(TargetUserSpaceUpgradeTasks(install_rpms=required_crypt_rpms))
+ api.produce(UpgradeInitramfsTasks(include_dracut_modules=[
+ DracutModule(name='clevis'),
+ DracutModule(name='clevis-pin-tpm2')
+ ])
+ )
diff --git a/repos/system_upgrade/common/actors/inhibitwhenluks/tests/test_inhibitwhenluks.py b/repos/system_upgrade/common/actors/inhibitwhenluks/tests/test_inhibitwhenluks.py
index 405a3429..d559b54c 100644
--- a/repos/system_upgrade/common/actors/inhibitwhenluks/tests/test_inhibitwhenluks.py
+++ b/repos/system_upgrade/common/actors/inhibitwhenluks/tests/test_inhibitwhenluks.py
@@ -1,34 +1,173 @@
-from leapp.models import CephInfo, LsblkEntry, StorageInfo
+"""
+Unit tests for inhibitwhenluks actor
+
+Skip isort as it's kind of broken when mixing grid import and one line imports
+
+isort:skip_file
+"""
+
+from leapp.libraries.common.config import version
+from leapp.models import (
+ CephInfo,
+ LsblkEntry,
+ LuksDump,
+ LuksDumps,
+ LuksToken,
+ StorageInfo,
+ TargetUserSpaceUpgradeTasks,
+ UpgradeInitramfsTasks
+)
from leapp.reporting import Report
from leapp.snactor.fixture import current_actor_context
from leapp.utils.report import is_inhibitor
+_REPORT_TITLE_UNSUITABLE = 'Detected LUKS devices unsuitable for in-place upgrade.'
-def test_actor_with_luks(current_actor_context):
- with_luks = [LsblkEntry(name='luks-132', kname='kname1', maj_min='253:0', rm='0', size='10G', bsize=10*(1 << 39),
- ro='0', tp='crypt', mountpoint='', parent_name='', parent_path='')]
- current_actor_context.feed(StorageInfo(lsblk=with_luks))
+def test_actor_with_luks1_notpm(monkeypatch, current_actor_context):
+ monkeypatch.setattr(version, 'get_source_major_version', lambda: '8')
+ luks_dump = LuksDump(
+ version=1,
+ uuid='dd09e6d4-b595-4f1c-80b8-fd47540e6464',
+ device_path='/dev/sda',
+ device_name='sda')
+ current_actor_context.feed(LuksDumps(dumps=[luks_dump]))
+ current_actor_context.feed(CephInfo(encrypted_volumes=[]))
current_actor_context.run()
assert current_actor_context.consume(Report)
report_fields = current_actor_context.consume(Report)[0].report
assert is_inhibitor(report_fields)
+ assert not current_actor_context.consume(TargetUserSpaceUpgradeTasks)
+ assert not current_actor_context.consume(UpgradeInitramfsTasks)
+ assert report_fields['title'] == _REPORT_TITLE_UNSUITABLE
+ assert 'LUKS1 partitions have been discovered' in report_fields['summary']
+ assert luks_dump.device_name in report_fields['summary']
-def test_actor_with_luks_ceph_only(current_actor_context):
- with_luks = [LsblkEntry(name='luks-132', kname='kname1', maj_min='253:0', rm='0', size='10G', bsize=10*(1 << 39),
- ro='0', tp='crypt', mountpoint='', parent_name='', parent_path='')]
- ceph_volume = ['luks-132']
- current_actor_context.feed(StorageInfo(lsblk=with_luks))
- current_actor_context.feed(CephInfo(encrypted_volumes=ceph_volume))
+
+def test_actor_with_luks2_notpm(monkeypatch, current_actor_context):
+ monkeypatch.setattr(version, 'get_source_major_version', lambda: '8')
+ luks_dump = LuksDump(
+ version=2,
+ uuid='27b57c75-9adf-4744-ab04-9eb99726a301',
+ device_path='/dev/sda',
+ device_name='sda')
+ current_actor_context.feed(LuksDumps(dumps=[luks_dump]))
+ current_actor_context.feed(CephInfo(encrypted_volumes=[]))
+ current_actor_context.run()
+ assert current_actor_context.consume(Report)
+ report_fields = current_actor_context.consume(Report)[0].report
+ assert is_inhibitor(report_fields)
+ assert not current_actor_context.consume(TargetUserSpaceUpgradeTasks)
+ assert not current_actor_context.consume(UpgradeInitramfsTasks)
+
+ assert report_fields['title'] == _REPORT_TITLE_UNSUITABLE
+ assert 'LUKS2 devices without Clevis TPM2 token' in report_fields['summary']
+ assert luks_dump.device_name in report_fields['summary']
+
+
+def test_actor_with_luks2_invalid_token(monkeypatch, current_actor_context):
+ monkeypatch.setattr(version, 'get_source_major_version', lambda: '8')
+ luks_dump = LuksDump(
+ version=2,
+ uuid='dc1dbe37-6644-4094-9839-8fc5dcbec0c6',
+ device_path='/dev/sda',
+ device_name='sda',
+ tokens=[LuksToken(token_id=0, keyslot=1, token_type='clevis')])
+ current_actor_context.feed(LuksDumps(dumps=[luks_dump]))
+ current_actor_context.feed(CephInfo(encrypted_volumes=[]))
+ current_actor_context.run()
+ assert current_actor_context.consume(Report)
+ report_fields = current_actor_context.consume(Report)[0].report
+ assert is_inhibitor(report_fields)
+
+ assert report_fields['title'] == _REPORT_TITLE_UNSUITABLE
+ assert 'LUKS2 devices without Clevis TPM2 token' in report_fields['summary']
+ assert luks_dump.device_name in report_fields['summary']
+ assert not current_actor_context.consume(TargetUserSpaceUpgradeTasks)
+ assert not current_actor_context.consume(UpgradeInitramfsTasks)
+
+
+def test_actor_with_luks2_clevis_tpm_token(monkeypatch, current_actor_context):
+ monkeypatch.setattr(version, 'get_source_major_version', lambda: '8')
+ luks_dump = LuksDump(
+ version=2,
+ uuid='83050bd9-61c6-4ff0-846f-bfd3ac9bfc67',
+ device_path='/dev/sda',
+ device_name='sda',
+ tokens=[LuksToken(token_id=0, keyslot=1, token_type='clevis-tpm2')])
+ current_actor_context.feed(LuksDumps(dumps=[luks_dump]))
+ current_actor_context.feed(CephInfo(encrypted_volumes=[]))
current_actor_context.run()
assert not current_actor_context.consume(Report)
+ upgrade_tasks = current_actor_context.consume(TargetUserSpaceUpgradeTasks)
+ assert len(upgrade_tasks) == 1
+ assert set(upgrade_tasks[0].install_rpms) == set([
+ 'clevis',
+ 'clevis-dracut',
+ 'clevis-systemd',
+ 'clevis-udisks2',
+ 'clevis-luks',
+ 'cryptsetup',
+ 'tpm2-tss',
+ 'tpm2-tools',
+ 'tpm2-abrmd'
+ ])
+ assert current_actor_context.consume(UpgradeInitramfsTasks)
-def test_actor_without_luks(current_actor_context):
- without_luks = [LsblkEntry(name='sda1', kname='sda1', maj_min='8:0', rm='0', size='10G', bsize=10*(1 << 39),
- ro='0', tp='part', mountpoint='/boot', parent_name='', parent_path='')]
- current_actor_context.feed(StorageInfo(lsblk=without_luks))
+def test_actor_with_luks2_ceph(monkeypatch, current_actor_context):
+ monkeypatch.setattr(version, 'get_source_major_version', lambda: '8')
+ ceph_volume = ['sda']
+ current_actor_context.feed(CephInfo(encrypted_volumes=ceph_volume))
+ luks_dump = LuksDump(
+ version=2,
+ uuid='0edb8c11-1a04-4abd-a12d-93433ee7b8d8',
+ device_path='/dev/sda',
+ device_name='sda',
+ tokens=[LuksToken(token_id=0, keyslot=1, token_type='clevis')])
+ current_actor_context.feed(LuksDumps(dumps=[luks_dump]))
current_actor_context.run()
assert not current_actor_context.consume(Report)
+
+ # make sure we don't needlessly include clevis packages, when there is no clevis token
+ assert not current_actor_context.consume(TargetUserSpaceUpgradeTasks)
+
+
+LSBLK_ENTRY = LsblkEntry(
+ name="luks-whatever",
+ kname="dm-0",
+ maj_min="252:1",
+ rm="0",
+ size="1G",
+ bsize=1073741824,
+ ro="0",
+ tp="crypt",
+ mountpoint="/",
+ parent_name="",
+ parent_path=""
+)
+
+
+def test_inhibitor_on_el7(monkeypatch, current_actor_context):
+ # NOTE(pstodulk): consider it good enough as el7 stuff is going to be removed
+ # soon.
+ monkeypatch.setattr(version, 'get_source_major_version', lambda: '7')
+
+ luks_dump = LuksDump(
+ version=2,
+ uuid='83050bd9-61c6-4ff0-846f-bfd3ac9bfc67',
+ device_path='/dev/sda',
+ device_name='sda',
+ tokens=[LuksToken(token_id=0, keyslot=1, token_type='clevis-tpm2')])
+ current_actor_context.feed(LuksDumps(dumps=[luks_dump]))
+ current_actor_context.feed(CephInfo(encrypted_volumes=[]))
+
+ current_actor_context.feed(StorageInfo(lsblk=[LSBLK_ENTRY]))
+ current_actor_context.run()
+ assert current_actor_context.consume(Report)
+
+ report_fields = current_actor_context.consume(Report)[0].report
+ assert is_inhibitor(report_fields)
+ assert report_fields['title'] == 'LUKS encrypted partition detected'
--
2.47.0

View File

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

View File

@ -1,57 +0,0 @@
From 8e5fe75e4ee76eb62eb51001c28f1f1443f0a563 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Fri, 18 Oct 2024 07:13:42 +0200
Subject: [PATCH 21/40] Rename inhibitwhenluks actor to checkluks
The actor nowadays does more then just inhibiting the upgrade when
LUKS is detected. Let's rename it to respect current behaviour.
---
.../common/actors/{inhibitwhenluks => checkluks}/actor.py | 6 +++---
.../inhibitwhenluks.py => checkluks/libraries/checkluks.py} | 0
.../tests/test_checkluks.py} | 0
3 files changed, 3 insertions(+), 3 deletions(-)
rename repos/system_upgrade/common/actors/{inhibitwhenluks => checkluks}/actor.py (85%)
rename repos/system_upgrade/common/actors/{inhibitwhenluks/libraries/inhibitwhenluks.py => checkluks/libraries/checkluks.py} (100%)
rename repos/system_upgrade/common/actors/{inhibitwhenluks/tests/test_inhibitwhenluks.py => checkluks/tests/test_checkluks.py} (100%)
diff --git a/repos/system_upgrade/common/actors/inhibitwhenluks/actor.py b/repos/system_upgrade/common/actors/checkluks/actor.py
similarity index 85%
rename from repos/system_upgrade/common/actors/inhibitwhenluks/actor.py
rename to repos/system_upgrade/common/actors/checkluks/actor.py
index 65607167..607fd040 100644
--- a/repos/system_upgrade/common/actors/inhibitwhenluks/actor.py
+++ b/repos/system_upgrade/common/actors/checkluks/actor.py
@@ -1,11 +1,11 @@
from leapp.actors import Actor
-from leapp.libraries.actor.inhibitwhenluks import check_invalid_luks_devices
+from leapp.libraries.actor.checkluks import check_invalid_luks_devices
from leapp.models import CephInfo, LuksDumps, StorageInfo, TargetUserSpaceUpgradeTasks, UpgradeInitramfsTasks
from leapp.reporting import Report
from leapp.tags import ChecksPhaseTag, IPUWorkflowTag
-class InhibitWhenLuks(Actor):
+class CheckLuks(Actor):
"""
Check if any encrypted partitions are in use and whether they are supported for the upgrade.
@@ -15,7 +15,7 @@ class InhibitWhenLuks(Actor):
during the process).
"""
- name = 'check_luks_and_inhibit'
+ name = 'check_luks'
consumes = (CephInfo, LuksDumps, StorageInfo)
produces = (Report, TargetUserSpaceUpgradeTasks, UpgradeInitramfsTasks)
tags = (ChecksPhaseTag, IPUWorkflowTag)
diff --git a/repos/system_upgrade/common/actors/inhibitwhenluks/libraries/inhibitwhenluks.py b/repos/system_upgrade/common/actors/checkluks/libraries/checkluks.py
similarity index 100%
rename from repos/system_upgrade/common/actors/inhibitwhenluks/libraries/inhibitwhenluks.py
rename to repos/system_upgrade/common/actors/checkluks/libraries/checkluks.py
diff --git a/repos/system_upgrade/common/actors/inhibitwhenluks/tests/test_inhibitwhenluks.py b/repos/system_upgrade/common/actors/checkluks/tests/test_checkluks.py
similarity index 100%
rename from repos/system_upgrade/common/actors/inhibitwhenluks/tests/test_inhibitwhenluks.py
rename to repos/system_upgrade/common/actors/checkluks/tests/test_checkluks.py
--
2.47.0

View File

@ -1,172 +0,0 @@
From 5e6d176ab685f2e85ac1aea9533b04d46f25e9b7 Mon Sep 17 00:00:00 2001
From: tomasfratrik <tomasfratrik8@gmail.com>
Date: Tue, 18 Jun 2024 10:22:35 +0200
Subject: [PATCH 22/40] Fix IPU being blocked by resource limitations
First resource limit is maximum number of open file descriptors limit,
second one being limit for maximum writable file size. Plus add unit
tests.
Resolves: RHEL-26459 and RHEL-16881
---
commands/command_utils.py | 38 ++++++++++++++++++
commands/preupgrade/__init__.py | 2 +
commands/tests/test_upgrade_paths.py | 60 ++++++++++++++++++++++++++++
commands/upgrade/__init__.py | 3 ++
4 files changed, 103 insertions(+)
diff --git a/commands/command_utils.py b/commands/command_utils.py
index 4f6f99eb..2810a542 100644
--- a/commands/command_utils.py
+++ b/commands/command_utils.py
@@ -1,6 +1,7 @@
import json
import os
import re
+import resource
from leapp.exceptions import CommandError
from leapp.utils import path
@@ -140,3 +141,40 @@ def vet_upgrade_path(args):
flavor=flavor,
choices=','.join(supported_target_versions)))
return (target_release, flavor)
+
+
+def set_resource_limits():
+ """
+ Set resource limits for the maximum number of open file descriptors and the maximum writable file size.
+
+ :raises: `CommandError` if the resource limits cannot be set
+ """
+
+ def set_resource_limit(resource_type, soft, hard):
+ rtype_string = (
+ 'open file descriptors' if resource_type == resource.RLIMIT_NOFILE
+ else 'writable file size' if resource_type == resource.RLIMIT_FSIZE
+ else 'unknown resource'
+ )
+ try:
+ resource.setrlimit(resource_type, (soft, hard))
+ except ValueError as err:
+ raise CommandError(
+ 'Failure occurred while attempting to set soft limit higher than the hard limit. '
+ 'Resource type: {}, error: {}'.format(rtype_string, err)
+ )
+ except OSError as err:
+ raise CommandError(
+ 'Failed to set resource limit. Resource type: {}, error: {}'.format(rtype_string, err)
+ )
+
+ soft_nofile, _ = resource.getrlimit(resource.RLIMIT_NOFILE)
+ soft_fsize, _ = resource.getrlimit(resource.RLIMIT_FSIZE)
+ nofile_limit = 1024*16
+ fsize_limit = resource.RLIM_INFINITY
+
+ if soft_nofile < nofile_limit:
+ set_resource_limit(resource.RLIMIT_NOFILE, nofile_limit, nofile_limit)
+
+ if soft_fsize != fsize_limit:
+ set_resource_limit(resource.RLIMIT_FSIZE, fsize_limit, fsize_limit)
diff --git a/commands/preupgrade/__init__.py b/commands/preupgrade/__init__.py
index 5a89069f..a9fa40e0 100644
--- a/commands/preupgrade/__init__.py
+++ b/commands/preupgrade/__init__.py
@@ -59,6 +59,8 @@ def preupgrade(args, breadcrumbs):
except LeappError as exc:
raise CommandError(exc.message)
+ command_utils.set_resource_limits()
+
workflow = repositories.lookup_workflow('IPUWorkflow')()
util.warn_if_unsupported(configuration)
util.process_whitelist_experimental(repositories, workflow, configuration, logger)
diff --git a/commands/tests/test_upgrade_paths.py b/commands/tests/test_upgrade_paths.py
index 53f081a5..f1312f66 100644
--- a/commands/tests/test_upgrade_paths.py
+++ b/commands/tests/test_upgrade_paths.py
@@ -1,3 +1,5 @@
+import resource
+
import mock
import pytest
@@ -50,3 +52,61 @@ def test_vet_upgrade_path(mock_open, monkeypatch):
monkeypatch.setenv('LEAPP_DEVEL_TARGET_RELEASE', '9.0')
args = mock.Mock(target='1.2')
assert command_utils.vet_upgrade_path(args) == ('9.0', 'default')
+
+
+def _mock_getrlimit_factory(nofile_limits=(1024, 4096), fsize_limits=(1024, 4096)):
+ """
+ Factory function to create a mock `getrlimit` function with configurable return values.
+ The default param values are lower than the expected values.
+
+ :param nofile_limits: Tuple representing (soft, hard) limits for `RLIMIT_NOFILE`
+ :param fsize_limits: Tuple representing (soft, hard) limits for `RLIMIT_FSIZE`
+ :return: A mock `getrlimit` function
+ """
+ def mock_getrlimit(resource_type):
+ if resource_type == resource.RLIMIT_NOFILE:
+ return nofile_limits
+ if resource_type == resource.RLIMIT_FSIZE:
+ return fsize_limits
+ return (0, 0)
+
+ return mock_getrlimit
+
+
+@pytest.mark.parametrize("nofile_limits, fsize_limits, expected_calls", [
+ # Case where both limits need to be increased
+ ((1024, 4096), (1024, 4096), [
+ (resource.RLIMIT_NOFILE, (1024*16, 1024*16)),
+ (resource.RLIMIT_FSIZE, (resource.RLIM_INFINITY, resource.RLIM_INFINITY))
+ ]),
+ # Case where neither limit needs to be changed
+ ((1024*16, 1024*16), (resource.RLIM_INFINITY, resource.RLIM_INFINITY), [])
+])
+def test_set_resource_limits_increase(monkeypatch, nofile_limits, fsize_limits, expected_calls):
+ setrlimit_called = []
+
+ def mock_setrlimit(resource_type, limits):
+ setrlimit_called.append((resource_type, limits))
+
+ monkeypatch.setattr(resource, "getrlimit", _mock_getrlimit_factory(nofile_limits, fsize_limits))
+ monkeypatch.setattr(resource, "setrlimit", mock_setrlimit)
+
+ command_utils.set_resource_limits()
+
+ assert setrlimit_called == expected_calls
+
+
+@pytest.mark.parametrize("errortype, expected_message", [
+ (OSError, "Failed to set resource limit"),
+ (ValueError, "Failure occurred while attempting to set soft limit higher than the hard limit")
+])
+def test_set_resource_limits_exceptions(monkeypatch, errortype, expected_message):
+ monkeypatch.setattr(resource, "getrlimit", _mock_getrlimit_factory())
+
+ def mock_setrlimit(*args, **kwargs):
+ raise errortype("mocked error")
+
+ monkeypatch.setattr(resource, "setrlimit", mock_setrlimit)
+
+ with pytest.raises(CommandError, match=expected_message):
+ command_utils.set_resource_limits()
diff --git a/commands/upgrade/__init__.py b/commands/upgrade/__init__.py
index 1e15b59c..c7487fde 100644
--- a/commands/upgrade/__init__.py
+++ b/commands/upgrade/__init__.py
@@ -89,6 +89,9 @@ def upgrade(args, breadcrumbs):
repositories = util.load_repositories()
except LeappError as exc:
raise CommandError(exc.message)
+
+ command_utils.set_resource_limits()
+
workflow = repositories.lookup_workflow('IPUWorkflow')(auto_reboot=args.reboot)
util.process_whitelist_experimental(repositories, workflow, configuration, logger)
util.warn_if_unsupported(configuration)
--
2.47.0

View File

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

View File

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

View File

@ -1,675 +0,0 @@
From e1bdf2c02dd193cdd7a2da95e2a3cfa5e6e1e8b3 Mon Sep 17 00:00:00 2001
From: mhecko <mhecko@redhat.com>
Date: Mon, 29 Apr 2024 11:16:46 +0200
Subject: [PATCH 23/40] feature: add possibility to use net.naming-scheme
Leapp writes .link files to prevent interfaces being renamed
after booting to post-upgrade system. This patch adds a less
error-prone approach that uses net.naming-scheme kernel param.
The naming-scheme tells udev what hardware properties to use
when composing a device name. Moreover, possible values of this
parameter are coarse-grained "profiles", that tell udev to
behave as if it did on RHEL8.0.
The functionality is enabled by setting LEAPP_USE_NET_NAMING_SCHEME
environmental variable to 1. If the feature is enabled, the .link
file generation is disabled. A kernel parameter `net.naming-scheme=`
is added to the upgrade boot entry and the post-upgrade entry.
The value of the parameter will be `rhel-<source_major>.0`. Note
that the minor source version is *not used*. Using also source major
version instead of 0 causes the device names to change slightly,
so we use 0. Moreover, an extra RPM named `rhel-net-naming-sysattrs`
is installed to the target system and target userspace container.
The RPM provides definitions of the "profiles" for net.naming-scheme.
The feature is available only for 8>9 and higher. Attempting to
upgrade 7>8 with LEAPP_USE_NET_NAMING_SCHEME=1 will ignore
the value of LEAPP_USE_NET_NAMING_SCHEME.
Add a possibility to use the net.naming-scheme cmdline argument
to make immutable network interface names during the upgrade.
The feature can be used only for 8>9 upgrades and higher.
To enable the feature, use LEAPP_USE_NET_NAMING_SCHEME=1.
Jira-ref: RHEL-23473
---
.../actors/addupgradebootentry/actor.py | 10 +-
.../libraries/addupgradebootentry.py | 78 ++++++++++-----
.../tests/unit_test_addupgradebootentry.py | 47 ++++-----
.../actors/kernelcmdlineconfig/actor.py | 16 +++-
.../libraries/kernelcmdlineconfig.py | 12 ++-
.../libraries/persistentnetnamesconfig.py | 5 +-
.../common/models/kernelcmdlineargs.py | 21 ++++
.../actors/emit_net_naming_scheme/actor.py | 28 ++++++
.../libraries/emit_net_naming.py | 63 ++++++++++++
.../tests/test_emit_net_naming_scheme.py | 95 +++++++++++++++++++
10 files changed, 318 insertions(+), 57 deletions(-)
create mode 100644 repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/actor.py
create mode 100644 repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/libraries/emit_net_naming.py
create mode 100644 repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/tests/test_emit_net_naming_scheme.py
diff --git a/repos/system_upgrade/common/actors/addupgradebootentry/actor.py b/repos/system_upgrade/common/actors/addupgradebootentry/actor.py
index f400ebf8..e4ecf39e 100644
--- a/repos/system_upgrade/common/actors/addupgradebootentry/actor.py
+++ b/repos/system_upgrade/common/actors/addupgradebootentry/actor.py
@@ -8,11 +8,13 @@ from leapp.models import (
FirmwareFacts,
GrubConfigError,
KernelCmdline,
+ LateTargetKernelCmdlineArgTasks,
LiveImagePreparationInfo,
LiveModeArtifacts,
LiveModeConfig,
TargetKernelCmdlineArgTasks,
- TransactionDryRun
+ TransactionDryRun,
+ UpgradeKernelCmdlineArgTasks
)
from leapp.tags import InterimPreparationPhaseTag, IPUWorkflowTag
@@ -33,9 +35,11 @@ class AddUpgradeBootEntry(Actor):
LiveModeArtifacts,
LiveModeConfig,
KernelCmdline,
- TransactionDryRun
+ TransactionDryRun,
+ TargetKernelCmdlineArgTasks,
+ UpgradeKernelCmdlineArgTasks
)
- produces = (TargetKernelCmdlineArgTasks,)
+ produces = (LateTargetKernelCmdlineArgTasks,)
tags = (IPUWorkflowTag, InterimPreparationPhaseTag)
def process(self):
diff --git a/repos/system_upgrade/common/actors/addupgradebootentry/libraries/addupgradebootentry.py b/repos/system_upgrade/common/actors/addupgradebootentry/libraries/addupgradebootentry.py
index 553ffc35..b236e39b 100644
--- a/repos/system_upgrade/common/actors/addupgradebootentry/libraries/addupgradebootentry.py
+++ b/repos/system_upgrade/common/actors/addupgradebootentry/libraries/addupgradebootentry.py
@@ -9,14 +9,16 @@ from leapp.models import (
BootContent,
KernelCmdline,
KernelCmdlineArg,
+ LateTargetKernelCmdlineArgTasks,
LiveImagePreparationInfo,
LiveModeArtifacts,
LiveModeConfig,
- TargetKernelCmdlineArgTasks
+ TargetKernelCmdlineArgTasks,
+ UpgradeKernelCmdlineArgTasks
)
-def collect_boot_args(livemode_enabled):
+def collect_upgrade_kernel_args(livemode_enabled):
args = {
'enforcing': '0',
'rd.plymouth': '0',
@@ -34,7 +36,10 @@ def collect_boot_args(livemode_enabled):
livemode_args = construct_cmdline_args_for_livemode()
args.update(livemode_args)
- return args
+ upgrade_kernel_args = collect_set_of_kernel_args_from_msgs(UpgradeKernelCmdlineArgTasks, 'to_add')
+ args.update(upgrade_kernel_args)
+
+ return set(args.items())
def collect_undesired_args(livemode_enabled):
@@ -43,11 +48,11 @@ def collect_undesired_args(livemode_enabled):
args = dict(zip(('ro', 'rhgb', 'quiet'), itertools.repeat(None)))
args['rd.lvm.lv'] = _get_rdlvm_arg_values()
- return args
+ return set(args.items())
-def format_grubby_args_from_args_dict(args_dict):
- """ Format the given args dictionary in a form required by grubby's --args. """
+def format_grubby_args_from_args_set(args_dict):
+ """ Format the given args set in a form required by grubby's --args. """
def fmt_single_arg(arg_pair):
key, value = arg_pair
@@ -65,7 +70,7 @@ def format_grubby_args_from_args_dict(args_dict):
else:
yield (key, value) # Just a single (key, value) pair
- arg_sequence = itertools.chain(*(flatten_arguments(arg_pair) for arg_pair in args_dict.items()))
+ arg_sequence = itertools.chain(*(flatten_arguments(arg_pair) for arg_pair in args_dict))
# Sorting should be fine as only values can be None, but we cannot have a (key, None) and (key, value) in
# the dictionary at the same time.
@@ -78,7 +83,7 @@ def format_grubby_args_from_args_dict(args_dict):
def figure_out_commands_needed_to_add_entry(kernel_path, initramfs_path, args_to_add, args_to_remove):
boot_entry_modification_commands = []
- args_to_add_str = format_grubby_args_from_args_dict(args_to_add)
+ args_to_add_str = format_grubby_args_from_args_set(args_to_add)
create_entry_cmd = [
'/usr/sbin/grubby',
@@ -93,7 +98,7 @@ def figure_out_commands_needed_to_add_entry(kernel_path, initramfs_path, args_to
# We need to update root= param separately, since we cannot do it during --add-kernel with --copy-default.
# This is likely a bug in grubby.
- root_param_value = args_to_add.get('root', None)
+ root_param_value = dict(args_to_add).get('root', None)
if root_param_value:
enforce_root_param_for_the_entry_cmd = [
'/usr/sbin/grubby',
@@ -103,7 +108,7 @@ def figure_out_commands_needed_to_add_entry(kernel_path, initramfs_path, args_to
boot_entry_modification_commands.append(enforce_root_param_for_the_entry_cmd)
if args_to_remove:
- args_to_remove_str = format_grubby_args_from_args_dict(args_to_remove)
+ args_to_remove_str = format_grubby_args_from_args_set(args_to_remove)
remove_undesired_args_cmd = [
'/usr/sbin/grubby',
'--update-kernel', kernel_path,
@@ -113,18 +118,55 @@ def figure_out_commands_needed_to_add_entry(kernel_path, initramfs_path, args_to
return boot_entry_modification_commands
+def collect_set_of_kernel_args_from_msgs(msg_type, arg_list_field_name):
+ cmdline_modification_msgs = api.consume(msg_type)
+ lists_of_args_to_add = (getattr(msg, arg_list_field_name, []) for msg in cmdline_modification_msgs)
+ args = itertools.chain(*lists_of_args_to_add)
+ return set((arg.key, arg.value) for arg in args)
+
+
+def emit_removal_of_args_meant_only_for_upgrade_kernel(added_upgrade_kernel_args):
+ """
+ Emit message requesting removal of upgrade kernel args that should not be on the target kernel.
+
+ Target kernel args are created by copying the args of the booted (upgrade) kernel. Therefore,
+ we need to explicitly modify the target kernel cmdline, removing what should not have been copied.
+ """
+ target_args_to_add = collect_set_of_kernel_args_from_msgs(TargetKernelCmdlineArgTasks, 'to_add')
+ actual_kernel_args = collect_set_of_kernel_args_from_msgs(KernelCmdline, 'parameters')
+
+ # actual_kernel_args should not be changed during upgrade, unless explicitly removed by
+ # TargetKernelCmdlineArgTasks.to_remove, but that is handled by some other upgrade component. We just want
+ # to make sure we remove what was not on the source system and that we don't overwrite args to be added to target.
+ args_not_present_on_target_kernel = added_upgrade_kernel_args - actual_kernel_args - target_args_to_add
+
+ # We remove only what we've added and what will not be already removed by someone else.
+ args_to_remove = [KernelCmdlineArg(key=arg[0], value=arg[1]) for arg in args_not_present_on_target_kernel]
+
+ if args_to_remove:
+ msg = ('Following upgrade kernel args were added, but they should not be present '
+ 'on target cmdline: `%s`, requesting removal.')
+ api.current_logger().info(msg, args_not_present_on_target_kernel)
+ args_sorted = sorted(args_to_remove, key=lambda arg: arg.key)
+ api.produce(LateTargetKernelCmdlineArgTasks(to_remove=args_sorted))
+
+
def add_boot_entry(configs=None):
kernel_dst_path, initram_dst_path = get_boot_file_paths()
+
_remove_old_upgrade_boot_entry(kernel_dst_path, configs=configs)
livemode_enabled = next(api.consume(LiveImagePreparationInfo), None) is not None
- cmdline_args = collect_boot_args(livemode_enabled)
+ # We have to keep the desired and unwanted args separate and modify cmline in two separate grubby calls. Merging
+ # these sets and trying to execute only a single command would leave the unwanted cmdline args present if they
+ # are present on the original system.
+ added_cmdline_args = collect_upgrade_kernel_args(livemode_enabled)
undesired_cmdline_args = collect_undesired_args(livemode_enabled)
commands_to_run = figure_out_commands_needed_to_add_entry(kernel_dst_path,
initram_dst_path,
- args_to_add=cmdline_args,
+ args_to_add=added_cmdline_args,
args_to_remove=undesired_cmdline_args)
def run_commands_adding_entry(extra_command_suffix=None):
@@ -146,16 +188,8 @@ def add_boot_entry(configs=None):
# See https://bugzilla.redhat.com/show_bug.cgi?id=1764306
run(['/usr/sbin/zipl'])
- if 'debug' in cmdline_args:
- # The kernelopts for target kernel are generated based on the cmdline used in the upgrade initramfs,
- # therefore, if we enabled debug above, and the original system did not have the debug kernelopt, we
- # need to explicitly remove it from the target os boot entry.
- # NOTE(mhecko): This will also unconditionally remove debug kernelopt if the source system used it.
- api.produce(TargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='debug')]))
-
- # NOTE(mmatuska): This will remove the option even if the source system had it set.
- # However enforcing=0 shouldn't be set persistently anyway.
- api.produce(TargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='enforcing', value='0')]))
+ effective_upgrade_kernel_args = added_cmdline_args - undesired_cmdline_args
+ emit_removal_of_args_meant_only_for_upgrade_kernel(effective_upgrade_kernel_args)
except CalledProcessError as e:
raise StopActorExecutionError(
diff --git a/repos/system_upgrade/common/actors/addupgradebootentry/tests/unit_test_addupgradebootentry.py b/repos/system_upgrade/common/actors/addupgradebootentry/tests/unit_test_addupgradebootentry.py
index c4f5232b..2f58ba9e 100644
--- a/repos/system_upgrade/common/actors/addupgradebootentry/tests/unit_test_addupgradebootentry.py
+++ b/repos/system_upgrade/common/actors/addupgradebootentry/tests/unit_test_addupgradebootentry.py
@@ -12,6 +12,7 @@ from leapp.models import (
BootContent,
KernelCmdline,
KernelCmdlineArg,
+ LateTargetKernelCmdlineArgTasks,
LiveModeArtifacts,
LiveModeConfig,
TargetKernelCmdlineArgTasks
@@ -82,8 +83,10 @@ def test_add_boot_entry(monkeypatch, run_args, arch):
assert addupgradebootentry.run.args[0] == run_args.args_remove
assert addupgradebootentry.run.args[1] == run_args.args_add
assert api.produce.model_instances == [
- TargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='debug')]),
- TargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='enforcing', value='0')])
+ LateTargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='debug'),
+ KernelCmdlineArg(key='enforcing', value='0'),
+ KernelCmdlineArg(key='plymouth.enable', value='0'),
+ KernelCmdlineArg(key='rd.plymouth', value='0')])
]
if run_args.args_zipl:
@@ -103,16 +106,16 @@ def test_debug_kernelopt_removal_task_production(monkeypatch, is_leapp_invoked_w
CurrentActorMocked(envars={'LEAPP_DEBUG': str(int(is_leapp_invoked_with_debug))}))
addupgradebootentry.add_boot_entry()
+ assert len(api.produce.model_instances) == 1
- expected_produced_messages = []
- if is_leapp_invoked_with_debug:
- expected_produced_messages = [TargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='debug')])]
-
- expected_produced_messages.append(
- TargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='enforcing', value='0')])
- )
+ produced_msg = api.produce.model_instances[0]
+ assert isinstance(produced_msg, LateTargetKernelCmdlineArgTasks)
- assert api.produce.model_instances == expected_produced_messages
+ debug_kernel_cmline_arg = KernelCmdlineArg(key='debug')
+ if is_leapp_invoked_with_debug:
+ assert debug_kernel_cmline_arg in produced_msg.to_remove
+ else:
+ assert debug_kernel_cmline_arg not in produced_msg.to_remove
def test_add_boot_entry_configs(monkeypatch):
@@ -132,8 +135,10 @@ def test_add_boot_entry_configs(monkeypatch):
assert addupgradebootentry.run.args[2] == run_args_add + ['-c', CONFIGS[0]]
assert addupgradebootentry.run.args[3] == run_args_add + ['-c', CONFIGS[1]]
assert api.produce.model_instances == [
- TargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='debug')]),
- TargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='enforcing', value='0')]),
+ LateTargetKernelCmdlineArgTasks(to_remove=[KernelCmdlineArg(key='debug'),
+ KernelCmdlineArg(key='enforcing', value='0'),
+ KernelCmdlineArg(key='plymouth.enable', value='0'),
+ KernelCmdlineArg(key='rd.plymouth', value='0')])
]
@@ -183,7 +188,7 @@ def test_fix_grub_config_error(monkeypatch, error_type, test_file_name):
(False, False),
)
)
-def test_collect_boot_args(monkeypatch, is_debug_enabled, network_enablement_type):
+def test_collect_upgrade_kernel_args(monkeypatch, is_debug_enabled, network_enablement_type):
env_vars = {'LEAPP_DEBUG': str(int(is_debug_enabled))}
if network_enablement_type:
env_vars['LEAPP_DEVEL_INITRAM_NETWORK'] = network_enablement_type
@@ -192,7 +197,8 @@ def test_collect_boot_args(monkeypatch, is_debug_enabled, network_enablement_typ
monkeypatch.setattr(addupgradebootentry, 'construct_cmdline_args_for_livemode',
lambda *args: {'livemodearg': 'value'})
- args = addupgradebootentry.collect_boot_args(livemode_enabled=True)
+ arg_set = addupgradebootentry.collect_upgrade_kernel_args(livemode_enabled=True)
+ args = dict(arg_set)
assert args['enforcing'] == '0'
assert args['rd.plymouth'] == '0'
@@ -320,16 +326,3 @@ def test_get_device_uuid(monkeypatch):
uuid = addupgradebootentry._get_device_uuid(path)
assert uuid == 'MY_UUID1'
-
-
-@pytest.mark.parametrize(
- ('args', 'expected_result'),
- (
- ([('argA', 'val'), ('argB', 'valB'), ('argC', None), ], 'argA=val argB=valB argC'),
- ([('argA', ('val1', 'val2'))], 'argA=val1 argA=val2')
- )
-)
-def test_format_grubby_args_from_args_dict(args, expected_result):
- actual_result = addupgradebootentry.format_grubby_args_from_args_dict(dict(args))
-
- assert actual_result == expected_result
diff --git a/repos/system_upgrade/common/actors/kernelcmdlineconfig/actor.py b/repos/system_upgrade/common/actors/kernelcmdlineconfig/actor.py
index 3585a14e..6d5f39dd 100644
--- a/repos/system_upgrade/common/actors/kernelcmdlineconfig/actor.py
+++ b/repos/system_upgrade/common/actors/kernelcmdlineconfig/actor.py
@@ -3,7 +3,13 @@ import os
from leapp.actors import Actor
from leapp.exceptions import StopActorExecutionError
from leapp.libraries.actor import kernelcmdlineconfig
-from leapp.models import FirmwareFacts, InstalledTargetKernelInfo, KernelCmdlineArg, TargetKernelCmdlineArgTasks
+from leapp.models import (
+ FirmwareFacts,
+ InstalledTargetKernelInfo,
+ KernelCmdlineArg,
+ LateTargetKernelCmdlineArgTasks,
+ TargetKernelCmdlineArgTasks
+)
from leapp.reporting import Report
from leapp.tags import FinalizationPhaseTag, IPUWorkflowTag
@@ -14,7 +20,13 @@ class KernelCmdlineConfig(Actor):
"""
name = 'kernelcmdlineconfig'
- consumes = (KernelCmdlineArg, InstalledTargetKernelInfo, FirmwareFacts, TargetKernelCmdlineArgTasks)
+ consumes = (
+ KernelCmdlineArg,
+ InstalledTargetKernelInfo,
+ FirmwareFacts,
+ LateTargetKernelCmdlineArgTasks,
+ TargetKernelCmdlineArgTasks
+ )
produces = (Report,)
tags = (FinalizationPhaseTag, IPUWorkflowTag)
diff --git a/repos/system_upgrade/common/actors/kernelcmdlineconfig/libraries/kernelcmdlineconfig.py b/repos/system_upgrade/common/actors/kernelcmdlineconfig/libraries/kernelcmdlineconfig.py
index 19c50f3c..98b8b95b 100644
--- a/repos/system_upgrade/common/actors/kernelcmdlineconfig/libraries/kernelcmdlineconfig.py
+++ b/repos/system_upgrade/common/actors/kernelcmdlineconfig/libraries/kernelcmdlineconfig.py
@@ -1,3 +1,4 @@
+import itertools
import re
from leapp import reporting
@@ -5,7 +6,12 @@ from leapp.exceptions import StopActorExecutionError
from leapp.libraries import stdlib
from leapp.libraries.common.config import architecture, version
from leapp.libraries.stdlib import api
-from leapp.models import InstalledTargetKernelInfo, KernelCmdlineArg, TargetKernelCmdlineArgTasks
+from leapp.models import (
+ InstalledTargetKernelInfo,
+ KernelCmdlineArg,
+ LateTargetKernelCmdlineArgTasks,
+ TargetKernelCmdlineArgTasks
+)
KERNEL_CMDLINE_FILE = "/etc/kernel/cmdline"
@@ -71,7 +77,9 @@ def retrieve_arguments_to_modify():
kernelargs_msgs_to_add = list(api.consume(KernelCmdlineArg))
kernelargs_msgs_to_remove = []
- for target_kernel_arg_task in api.consume(TargetKernelCmdlineArgTasks):
+ modification_msgs = itertools.chain(api.consume(TargetKernelCmdlineArgTasks),
+ api.consume(LateTargetKernelCmdlineArgTasks))
+ for target_kernel_arg_task in modification_msgs:
kernelargs_msgs_to_add.extend(target_kernel_arg_task.to_add)
kernelargs_msgs_to_remove.extend(target_kernel_arg_task.to_remove)
diff --git a/repos/system_upgrade/common/actors/persistentnetnamesconfig/libraries/persistentnetnamesconfig.py b/repos/system_upgrade/common/actors/persistentnetnamesconfig/libraries/persistentnetnamesconfig.py
index dc5196ea..2f12742a 100644
--- a/repos/system_upgrade/common/actors/persistentnetnamesconfig/libraries/persistentnetnamesconfig.py
+++ b/repos/system_upgrade/common/actors/persistentnetnamesconfig/libraries/persistentnetnamesconfig.py
@@ -2,7 +2,7 @@ import errno
import os
import re
-from leapp.libraries.common.config import get_env
+from leapp.libraries.common.config import get_env, version
from leapp.libraries.stdlib import api
from leapp.models import (
InitrdIncludes,
@@ -39,6 +39,9 @@ def generate_link_file(interface):
@suppress_deprecation(InitrdIncludes)
def process():
+ if get_env('LEAPP_USE_NET_NAMING_SCHEMES', '0') == '1' and version.get_target_major_version() != '8':
+ api.current_logger().info('Skipping generation of .link files renaming NICs as LEAPP_USE_NET_NAMING_SCHEMES=1')
+ return
if get_env('LEAPP_NO_NETWORK_RENAMING', '0') == '1':
api.current_logger().info(
diff --git a/repos/system_upgrade/common/models/kernelcmdlineargs.py b/repos/system_upgrade/common/models/kernelcmdlineargs.py
index e3568a0a..fafd2853 100644
--- a/repos/system_upgrade/common/models/kernelcmdlineargs.py
+++ b/repos/system_upgrade/common/models/kernelcmdlineargs.py
@@ -24,6 +24,27 @@ class TargetKernelCmdlineArgTasks(Model):
to_remove = fields.List(fields.Model(KernelCmdlineArg), default=[])
+class LateTargetKernelCmdlineArgTasks(Model):
+ """
+ Desired modifications of the target kernel args produced later in the upgrade process.
+
+ Defined to prevent loops in the actor dependency graph.
+ """
+ topic = SystemInfoTopic
+
+ to_add = fields.List(fields.Model(KernelCmdlineArg), default=[])
+ to_remove = fields.List(fields.Model(KernelCmdlineArg), default=[])
+
+
+class UpgradeKernelCmdlineArgTasks(Model):
+ """
+ Modifications of the upgrade kernel cmdline.
+ """
+ topic = SystemInfoTopic
+
+ to_add = fields.List(fields.Model(KernelCmdlineArg), default=[])
+
+
class KernelCmdline(Model):
"""
Kernel command line parameters the system was booted with
diff --git a/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/actor.py b/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/actor.py
new file mode 100644
index 00000000..769fe20b
--- /dev/null
+++ b/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/actor.py
@@ -0,0 +1,28 @@
+from leapp.actors import Actor
+from leapp.libraries.actor import emit_net_naming as emit_net_naming_lib
+from leapp.models import (
+ KernelCmdline,
+ RpmTransactionTasks,
+ TargetKernelCmdlineArgTasks,
+ TargetUserSpaceUpgradeTasks,
+ UpgradeKernelCmdlineArgTasks
+)
+from leapp.tags import ChecksPhaseTag, IPUWorkflowTag
+
+
+class EmitNetNamingScheme(Actor):
+ """
+ Emit necessary modifications of the upgrade environment and target command line to use net.naming-scheme.
+ """
+ name = 'emit_net_naming_scheme'
+ consumes = (KernelCmdline,)
+ produces = (
+ RpmTransactionTasks,
+ TargetKernelCmdlineArgTasks,
+ TargetUserSpaceUpgradeTasks,
+ UpgradeKernelCmdlineArgTasks,
+ )
+ tags = (ChecksPhaseTag, IPUWorkflowTag)
+
+ def process(self):
+ emit_net_naming_lib.emit_msgs_to_use_net_naming_schemes()
diff --git a/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/libraries/emit_net_naming.py b/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/libraries/emit_net_naming.py
new file mode 100644
index 00000000..65abdd4d
--- /dev/null
+++ b/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/libraries/emit_net_naming.py
@@ -0,0 +1,63 @@
+from leapp.exceptions import StopActorExecutionError
+from leapp.libraries.common.config import get_env, version
+from leapp.libraries.stdlib import api
+from leapp.models import (
+ KernelCmdline,
+ KernelCmdlineArg,
+ RpmTransactionTasks,
+ TargetKernelCmdlineArgTasks,
+ TargetUserSpaceUpgradeTasks,
+ UpgradeKernelCmdlineArgTasks
+)
+
+NET_NAMING_SYSATTRS_RPM_NAME = 'rhel-net-naming-sysattrs'
+
+
+def is_net_scheme_compatible_with_current_cmdline():
+ kernel_cmdline = next(api.consume(KernelCmdline), None)
+ if not kernel_cmdline:
+ # Super unlikely
+ raise StopActorExecutionError('Did not receive any KernelCmdline messages.')
+
+ allows_predictable_names = True
+ already_has_a_net_naming_scheme = False
+ for param in kernel_cmdline.parameters:
+ if param.key == 'net.ifnames':
+ if param.value == '0':
+ allows_predictable_names = False
+ elif param.value == '1':
+ allows_predictable_names = True
+ if param.key == 'net.naming-scheme':
+ # We assume that the kernel cmdline does not contain invalid entries, namely,
+ # that the net.naming-scheme refers to a valid scheme.
+ already_has_a_net_naming_scheme = True
+
+ is_compatible = allows_predictable_names and not already_has_a_net_naming_scheme
+
+ msg = ('Should net.naming-scheme be added to kernel cmdline: %s. '
+ 'Reason: allows_predictable_names=%s, already_has_a_net_naming_scheme=%s')
+ api.current_logger().info(msg, 'yes' if is_compatible else 'no',
+ allows_predictable_names,
+ already_has_a_net_naming_scheme)
+
+ return is_compatible
+
+
+def emit_msgs_to_use_net_naming_schemes():
+ if get_env('LEAPP_USE_NET_NAMING_SCHEMES', '0') != '1' and version.get_target_major_version() != '8':
+ return
+
+ # The package should be installed regardless of whether we will modify the cmdline -
+ # if the cmdline already contains net.naming-scheme, then the package will be useful
+ # in both, the upgrade environment and on the target system.
+ pkgs_to_install = [NET_NAMING_SYSATTRS_RPM_NAME]
+ api.produce(TargetUserSpaceUpgradeTasks(install_rpms=pkgs_to_install))
+ api.produce(RpmTransactionTasks(to_install=pkgs_to_install))
+
+ if not is_net_scheme_compatible_with_current_cmdline():
+ return
+
+ naming_scheme = 'rhel-{0}.0'.format(version.get_source_major_version())
+ cmdline_args = [KernelCmdlineArg(key='net.naming-scheme', value=naming_scheme)]
+ api.produce(UpgradeKernelCmdlineArgTasks(to_add=cmdline_args))
+ api.produce(TargetKernelCmdlineArgTasks(to_add=cmdline_args))
diff --git a/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/tests/test_emit_net_naming_scheme.py b/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/tests/test_emit_net_naming_scheme.py
new file mode 100644
index 00000000..7a5eeba5
--- /dev/null
+++ b/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/tests/test_emit_net_naming_scheme.py
@@ -0,0 +1,95 @@
+import pytest
+
+from leapp.libraries.actor import emit_net_naming as emit_net_naming_lib
+from leapp.libraries.common.testutils import CurrentActorMocked, produce_mocked
+from leapp.libraries.stdlib import api
+from leapp.models import (
+ KernelCmdline,
+ KernelCmdlineArg,
+ RpmTransactionTasks,
+ TargetKernelCmdlineArgTasks,
+ TargetUserSpaceUpgradeTasks,
+ UpgradeKernelCmdlineArgTasks
+)
+
+
+@pytest.mark.parametrize(
+ ('kernel_args', 'should_be_compatible'),
+ [
+ ([KernelCmdlineArg(key='net.naming-scheme', value='rhel-8.10')], False),
+ ([KernelCmdlineArg(key='net.ifnames', value='1')], True),
+ ([KernelCmdlineArg(key='net.ifnames', value='0')], False),
+ (
+ [
+ KernelCmdlineArg(key='net.naming-scheme', value='rhel-8.10'),
+ KernelCmdlineArg(key='net.ifname', value='0'),
+ KernelCmdlineArg(key='root', value='/dev/vda1')
+ ],
+ False
+ ),
+ ([KernelCmdlineArg(key='root', value='/dev/vda1')], True),
+ ]
+)
+def test_is_net_scheme_compatible_with_current_cmdline(monkeypatch, kernel_args, should_be_compatible):
+ kernel_cmdline = KernelCmdline(parameters=kernel_args)
+
+ def mocked_consume(msg_type):
+ yield {KernelCmdline: kernel_cmdline}[msg_type]
+
+ monkeypatch.setattr(api, 'consume', mocked_consume)
+
+ assert emit_net_naming_lib.is_net_scheme_compatible_with_current_cmdline() == should_be_compatible, \
+ [(arg.key, arg.value) for arg in kernel_cmdline.parameters]
+
+
+@pytest.mark.parametrize(
+ ('is_net_scheme_enabled', 'is_current_cmdline_compatible'),
+ [
+ (True, True),
+ (True, False),
+ (False, True)
+ ]
+)
+def test_emit_msgs_to_use_net_naming_schemes(monkeypatch, is_net_scheme_enabled, is_current_cmdline_compatible):
+ envvar_value = '1' if is_net_scheme_enabled else '0'
+
+ mocked_actor = CurrentActorMocked(src_ver='8.10',
+ dst_ver='9.5',
+ envars={'LEAPP_USE_NET_NAMING_SCHEMES': envvar_value})
+ monkeypatch.setattr(api, 'current_actor', mocked_actor)
+
+ monkeypatch.setattr(api, 'produce', produce_mocked())
+ monkeypatch.setattr(emit_net_naming_lib,
+ 'is_net_scheme_compatible_with_current_cmdline',
+ lambda: is_current_cmdline_compatible)
+
+ emit_net_naming_lib.emit_msgs_to_use_net_naming_schemes()
+
+ def ensure_one_msg_of_type_produced(produced_messages, msg_type):
+ msgs = (msg for msg in produced_messages if isinstance(msg, msg_type))
+ msg = next(msgs)
+ assert not next(msgs, None), 'More than one message of type {type} produced'.format(type=type)
+ return msg
+
+ produced_messages = api.produce.model_instances
+ if is_net_scheme_enabled:
+ userspace_tasks = ensure_one_msg_of_type_produced(produced_messages, TargetUserSpaceUpgradeTasks)
+ assert userspace_tasks.install_rpms == [emit_net_naming_lib.NET_NAMING_SYSATTRS_RPM_NAME]
+
+ rpm_tasks = ensure_one_msg_of_type_produced(produced_messages, RpmTransactionTasks)
+ assert rpm_tasks.to_install == [emit_net_naming_lib.NET_NAMING_SYSATTRS_RPM_NAME]
+ else:
+ assert not api.produce.called
+ return
+
+ upgrade_cmdline_mods = (msg for msg in produced_messages if isinstance(msg, UpgradeKernelCmdlineArgTasks))
+ target_cmdline_mods = (msg for msg in produced_messages if isinstance(msg, TargetKernelCmdlineArgTasks))
+
+ if is_current_cmdline_compatible:
+ # We should emit cmdline modifications - both UpgradeKernelCmdlineArgTasks and TargetKernelCmdlineArgTasks
+ # should be produced
+ assert next(upgrade_cmdline_mods, None)
+ assert next(target_cmdline_mods, None)
+ else:
+ assert not next(upgrade_cmdline_mods, None)
+ assert not next(target_cmdline_mods, None)
--
2.47.0

File diff suppressed because it is too large Load Diff

View File

@ -1,26 +0,0 @@
From b4b535454b74c05682ecf0d3059decbd2c9530e0 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Wed, 6 Nov 2024 22:23:37 +0100
Subject: [PATCH 24/40] prevent the feature for being used outside 8>9
---
.../libraries/persistentnetnamesconfig.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/repos/system_upgrade/common/actors/persistentnetnamesconfig/libraries/persistentnetnamesconfig.py b/repos/system_upgrade/common/actors/persistentnetnamesconfig/libraries/persistentnetnamesconfig.py
index 2f12742a..b2c7f5ff 100644
--- a/repos/system_upgrade/common/actors/persistentnetnamesconfig/libraries/persistentnetnamesconfig.py
+++ b/repos/system_upgrade/common/actors/persistentnetnamesconfig/libraries/persistentnetnamesconfig.py
@@ -39,7 +39,8 @@ def generate_link_file(interface):
@suppress_deprecation(InitrdIncludes)
def process():
- if get_env('LEAPP_USE_NET_NAMING_SCHEMES', '0') == '1' and version.get_target_major_version() != '8':
+ if get_env('LEAPP_USE_NET_NAMING_SCHEMES', '0') == '1' and version.get_target_major_version() == '9':
+ # We can use this only for 8>9, for now
api.current_logger().info('Skipping generation of .link files renaming NICs as LEAPP_USE_NET_NAMING_SCHEMES=1')
return
--
2.47.0

View File

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

View File

@ -1,28 +0,0 @@
From e43a8922e06d72212e8e2a8b51747c668147182c Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Wed, 6 Nov 2024 22:26:01 +0100
Subject: [PATCH 25/40] fix condition on when net naming is emitted
---
.../emit_net_naming_scheme/libraries/emit_net_naming.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/libraries/emit_net_naming.py b/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/libraries/emit_net_naming.py
index 65abdd4d..726bb459 100644
--- a/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/libraries/emit_net_naming.py
+++ b/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/libraries/emit_net_naming.py
@@ -44,7 +44,10 @@ def is_net_scheme_compatible_with_current_cmdline():
def emit_msgs_to_use_net_naming_schemes():
- if get_env('LEAPP_USE_NET_NAMING_SCHEMES', '0') != '1' and version.get_target_major_version() != '8':
+ is_env_var_set = get_env('LEAPP_USE_NET_NAMING_SCHEMES', '0') == '1'
+ is_upgrade_8to9 = version.get_target_major_version() == '9'
+ is_net_naming_enabled_and_permitted = is_env_var_set and is_upgrade_8to9
+ if not is_net_naming_enabled_and_permitted:
return
# The package should be installed regardless of whether we will modify the cmdline -
--
2.47.0

View File

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

View File

@ -1,56 +0,0 @@
From 0bf07d1546ccdc6d4a9e6f4936a98b4d6ca27789 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Tue, 12 Nov 2024 09:10:50 +0100
Subject: [PATCH 26/40] scangrubdevpartitionlayout: Skip warning msgs
The fdisk output can contain warning msgs when a partition is not
aligned on physical sector boundary, like:
Partition 4 does not start on physical sector boundary.
We know that in case of MBR the line we expect to parse always
starts with canonical path. So let's skip all lines which does
not start with '/'.
jira: https://issues.redhat.com/browse/RHEL-50947
---
.../libraries/scan_layout.py | 10 ++++++++++
.../tests/test_scan_partition_layout.py | 3 +++
2 files changed, 13 insertions(+)
diff --git a/repos/system_upgrade/el7toel8/actors/scangrubdevpartitionlayout/libraries/scan_layout.py b/repos/system_upgrade/el7toel8/actors/scangrubdevpartitionlayout/libraries/scan_layout.py
index 83d02656..7f4a2a59 100644
--- a/repos/system_upgrade/el7toel8/actors/scangrubdevpartitionlayout/libraries/scan_layout.py
+++ b/repos/system_upgrade/el7toel8/actors/scangrubdevpartitionlayout/libraries/scan_layout.py
@@ -68,6 +68,16 @@ def get_partition_layout(device):
partitions = []
for partition_line in table_iter:
+ if not partition_line.startswith('/'):
+ # the output can contain warning msg when a partition is not aligned
+ # on physical sector boundary, like:
+ # ~~~
+ # Partition 4 does not start on physical sector boundary.
+ # ~~~
+ # We know that in case of MBR the line we expect to parse always
+ # starts with canonical path. So let's use this condition.
+ # See https://issues.redhat.com/browse/RHEL-50947
+ continue
# Fields: Device Boot Start End Sectors Size Id Type
# The line looks like: `/dev/vda1 * 2048 2099199 2097152 1G 83 Linux`
part_info = split_on_space_segments(partition_line)
diff --git a/repos/system_upgrade/el7toel8/actors/scangrubdevpartitionlayout/tests/test_scan_partition_layout.py b/repos/system_upgrade/el7toel8/actors/scangrubdevpartitionlayout/tests/test_scan_partition_layout.py
index 743ca71f..9c32e16f 100644
--- a/repos/system_upgrade/el7toel8/actors/scangrubdevpartitionlayout/tests/test_scan_partition_layout.py
+++ b/repos/system_upgrade/el7toel8/actors/scangrubdevpartitionlayout/tests/test_scan_partition_layout.py
@@ -49,6 +49,9 @@ def test_get_partition_layout(monkeypatch, devices, fs):
part_line = '{0} * {1} 2099199 1048576 83 {2}'.format(part.name, part.start_offset, fs)
fdisk_output.append(part_line)
+ # add a problematic warning msg to test:
+ # https://issues.redhat.com/browse/RHEL-50947
+ fdisk_output.append('Partition 3 does not start on physical sector boundary.')
device_to_fdisk_output[device.name] = fdisk_output
def mocked_run(cmd, *args, **kwargs):
--
2.47.0

View File

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

View File

@ -1,115 +0,0 @@
From 866a4b9f163c3aec31736ac0ce25f564fe016cb4 Mon Sep 17 00:00:00 2001
From: Jarek Prokop <jprokop@redhat.com>
Date: Tue, 5 Nov 2024 10:15:28 +0100
Subject: [PATCH 28/40] Add el9toel10 actor to handle symlink -> directory with
ruby IRB.
The `/usr/share/ruby/irb` path is a symlink in RHEL 9,
but a regular directory in RHEL 10.
This puts us back in line with RHEL 8 and Fedora in terms of the
path's file type regarding the rubygem-irb package.
Since this was not handled on RPM level, handle it as actor again.
This was copied and adjusted from same-named el8->el9 actor.
We do not care about the validity or target of the symlink, we just
remove it to allow DNF create the correct directory on upgrade.
Without this workaround, the upgrade will fail in transaction test with
reports of file conflicts on the directory path.
Users should not expect to ever retain anything in this directory.
---
.../actors/registerrubyirbadjustment/actor.py | 31 +++++++++++++++++++
.../test_register_ruby_irb_adjustments.py | 11 +++++++
.../el9toel10/tools/handlerubyirbsymlink | 22 +++++++++++++
3 files changed, 64 insertions(+)
create mode 100644 repos/system_upgrade/el9toel10/actors/registerrubyirbadjustment/actor.py
create mode 100644 repos/system_upgrade/el9toel10/actors/registerrubyirbadjustment/tests/test_register_ruby_irb_adjustments.py
create mode 100755 repos/system_upgrade/el9toel10/tools/handlerubyirbsymlink
diff --git a/repos/system_upgrade/el9toel10/actors/registerrubyirbadjustment/actor.py b/repos/system_upgrade/el9toel10/actors/registerrubyirbadjustment/actor.py
new file mode 100644
index 00000000..4fbec7ff
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/registerrubyirbadjustment/actor.py
@@ -0,0 +1,31 @@
+from leapp.actors import Actor
+from leapp.models import DNFWorkaround
+from leapp.tags import FactsPhaseTag, IPUWorkflowTag
+
+
+class RegisterRubyIRBAdjustment(Actor):
+ """
+ Register a workaround to allow rubygem-irb's symlink -> directory conversion.
+
+ The /usr/share/ruby/irb has been moved from a symlink to a directory
+ in RHEL 10 and this conversion was not handled on the RPM level.
+ This leads to DNF reporting package file conflicts when a major upgrade
+ is attempted and rubygem-irb is installed.
+
+ Register "handlerubyirbsymlink" script that removes the symlink prior
+ to DNF upgrade and allows it to create the expected directory in place of
+ the removed symlink.
+ """
+
+ name = 'register_ruby_irb_adjustment'
+ consumes = ()
+ produces = (DNFWorkaround,)
+ tags = (IPUWorkflowTag, FactsPhaseTag)
+
+ def process(self):
+ self.produce(
+ DNFWorkaround(
+ display_name='IRB directory fix',
+ script_path=self.get_tool_path('handlerubyirbsymlink'),
+ )
+ )
diff --git a/repos/system_upgrade/el9toel10/actors/registerrubyirbadjustment/tests/test_register_ruby_irb_adjustments.py b/repos/system_upgrade/el9toel10/actors/registerrubyirbadjustment/tests/test_register_ruby_irb_adjustments.py
new file mode 100644
index 00000000..fc341646
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/actors/registerrubyirbadjustment/tests/test_register_ruby_irb_adjustments.py
@@ -0,0 +1,11 @@
+import os.path
+
+from leapp.models import DNFWorkaround
+
+
+def test_register_ruby_irb_adjustments(current_actor_context):
+ current_actor_context.run()
+ assert len(current_actor_context.consume(DNFWorkaround)) == 1
+ assert current_actor_context.consume(DNFWorkaround)[0].display_name == 'IRB directory fix'
+ assert os.path.basename(current_actor_context.consume(DNFWorkaround)[0].script_path) == 'handlerubyirbsymlink'
+ assert os.path.exists(current_actor_context.consume(DNFWorkaround)[0].script_path)
diff --git a/repos/system_upgrade/el9toel10/tools/handlerubyirbsymlink b/repos/system_upgrade/el9toel10/tools/handlerubyirbsymlink
new file mode 100755
index 00000000..e9ac40fe
--- /dev/null
+++ b/repos/system_upgrade/el9toel10/tools/handlerubyirbsymlink
@@ -0,0 +1,22 @@
+#!/usr/bin/bash -e
+
+# just in case of hidden files.. not sure why would someone do that, it's more
+# like forgotten cache file possibility, but rather do that..
+shopt -s dotglob
+
+handle_dir() {
+ # Check that $1 is a symlink then unlink it so that RPM
+ # can freely create the directory.
+ if [ ! -L "$1" ]; then
+ return
+ fi
+
+ # There is no configuration or anything that the user should ever customize
+ # and expect to retain.
+ unlink "$1"
+
+ return 0
+}
+
+
+handle_dir /usr/share/ruby/irb
--
2.47.0

View File

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

View File

@ -1,40 +0,0 @@
From 81a3297516fbbd120b0fb870de36f1a1b290dd21 Mon Sep 17 00:00:00 2001
From: Jarek Prokop <jprokop@redhat.com>
Date: Wed, 6 Nov 2024 15:21:14 +0100
Subject: [PATCH 29/40] Expand on the actor docstring for the el8->el9
rubygem-irb symlink fix.
In RHEL 10, the directory is a regular directory again.
The 2 actors are separate over creating a common solution for both.
Expand in the docstring on the reason for the el8->el9 actor to
differentiate them apart.
---
.../actors/registerrubyirbadjustment/actor.py | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/repos/system_upgrade/el8toel9/actors/registerrubyirbadjustment/actor.py b/repos/system_upgrade/el8toel9/actors/registerrubyirbadjustment/actor.py
index ac4d1e6f..a33d8831 100644
--- a/repos/system_upgrade/el8toel9/actors/registerrubyirbadjustment/actor.py
+++ b/repos/system_upgrade/el8toel9/actors/registerrubyirbadjustment/actor.py
@@ -5,7 +5,16 @@ from leapp.tags import FactsPhaseTag, IPUWorkflowTag
class RegisterRubyIRBAdjustment(Actor):
"""
- Registers a workaround which will adjust the Ruby IRB directories during the upgrade.
+ Register a workaround to allow rubygem-irb's directory -> symlink conversion.
+
+ The /usr/share/ruby/irb has been moved from a directory to a symlink
+ in RHEL 9 and this conversion was not handled on RPM level.
+ This leads to DNF reporting package file conflicts when a major upgrade
+ is attempted and rubygem-irb (or ruby-irb) is installed.
+
+ Register "handlerubyirbsymlink" script that removes the directory prior
+ to DNF upgrade and allows it to create the expected symlink in place of
+ the removed directory.
"""
name = 'register_ruby_irb_adjustment'
--
2.47.0

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -1,56 +0,0 @@
From 89afbe8cb41f874f32acddc1e1696132f3531677 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Fri, 8 Nov 2024 17:40:01 +0100
Subject: [PATCH 31/40] Packaging: Require leapp-framework 6.x + update leapp
deps
The leapp actors configuration feature is present since
leapp-framework 6.0. Update the dependencies to ensure the correct
version of the framework is installed on the system.
Also, leapp requirements have been updated - requiring python3-PyYAML
as it requires YAML parser, bumping leapp-framework-dependencies to 6.
Address the change in leapp-deps metapackage to satisfy leapp
dependencies during the upgrade process.
---
packaging/leapp-repository.spec | 2 +-
packaging/other_specs/leapp-el7toel8-deps.spec | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/packaging/leapp-repository.spec b/packaging/leapp-repository.spec
index 0d63ba02..570d0df2 100644
--- a/packaging/leapp-repository.spec
+++ b/packaging/leapp-repository.spec
@@ -120,7 +120,7 @@ Requires: leapp-repository-dependencies = %{leapp_repo_deps}
# IMPORTANT: this is capability provided by the leapp framework rpm.
# Check that 'version' instead of the real framework rpm version.
-Requires: leapp-framework >= 5.0, leapp-framework < 6
+Requires: leapp-framework >= 6.0, leapp-framework < 7
# Since we provide sub-commands for the leapp utility, we expect the leapp
# tool to be installed as well.
diff --git a/packaging/other_specs/leapp-el7toel8-deps.spec b/packaging/other_specs/leapp-el7toel8-deps.spec
index d9e94faa..2c662a37 100644
--- a/packaging/other_specs/leapp-el7toel8-deps.spec
+++ b/packaging/other_specs/leapp-el7toel8-deps.spec
@@ -14,7 +14,7 @@
%define leapp_repo_deps 10
-%define leapp_framework_deps 5
+%define leapp_framework_deps 6
# NOTE: the Version contains the %{rhel} macro just for the convenience to
# have always upgrade path between newer and older deps packages. So for
@@ -112,6 +112,7 @@ Requires: python3
Requires: python3-six
Requires: python3-setuptools
Requires: python3-requests
+Requires: python3-PyYAML
%description -n %{ldname}
--
2.47.0

View File

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

View File

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

View File

@ -1,48 +0,0 @@
From 36b93e4a2504f72e5a371a75a23e7cd2c695b84b Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Sun, 6 Oct 2024 21:01:13 +0200
Subject: [PATCH 32/40] spec: create /etc/leapp/actor_conf.d
Add additional build steps to the specfile that create the actor
configuration directory. The directory is owned by the package, so
it gets removed when the user uninstalls leapp.
Also prepared some comment lines for future when we will want to
include some configuration files as part of the rpm.
---
etc/leapp/actor_conf.d/.gitkeep | 0
packaging/leapp-repository.spec | 7 +++++++
2 files changed, 7 insertions(+)
create mode 100644 etc/leapp/actor_conf.d/.gitkeep
diff --git a/etc/leapp/actor_conf.d/.gitkeep b/etc/leapp/actor_conf.d/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/packaging/leapp-repository.spec b/packaging/leapp-repository.spec
index 570d0df2..828355bf 100644
--- a/packaging/leapp-repository.spec
+++ b/packaging/leapp-repository.spec
@@ -250,6 +250,11 @@ install -m 0755 -d %{buildroot}%{_sysconfdir}/leapp/files/
install -m 0644 etc/leapp/transaction/* %{buildroot}%{_sysconfdir}/leapp/transaction
install -m 0644 etc/leapp/files/* %{buildroot}%{_sysconfdir}/leapp/files
+# Actor configuration dir
+install -m 0755 -d %{buildroot}%{_sysconfdir}/leapp/actor_conf.d/
+# uncomment to install existing configs
+#install -m 0644 etc/leapp/actor_conf.d/* %%{buildroot}%%{_sysconfdir}/leapp/actor_conf.d
+
# install CLI commands for the leapp utility on the expected path
install -m 0755 -d %{buildroot}%{leapp_python_sitelib}/leapp/cli/
cp -r commands %{buildroot}%{leapp_python_sitelib}/leapp/cli/
@@ -295,6 +300,8 @@ done;
%dir %{custom_repositorydir}
%dir %{leapp_python_sitelib}/leapp/cli/commands
%config %{_sysconfdir}/leapp/files/*
+# uncomment to package installed configs
+#%%config %%{_sysconfdir}/leapp/actor_conf.d/*
%{_sysconfdir}/leapp/repos.d/*
%{_sysconfdir}/leapp/transaction/*
%{repositorydir}/*
--
2.47.0

View File

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

View File

@ -1,31 +0,0 @@
From 87db66c863104fea824a4406732cbe233ffee412 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Wed, 13 Nov 2024 15:05:50 +0100
Subject: [PATCH 33/40] spec: drop .gitkeep files from the RPM
We have several .gitkeep files in the repo as we want to have some
directories present in git however these directories are empty
otherwise. This is common hack to achieve this, but we do not want
to have these files really in the resulting RPMs. So we just remove
them.
---
packaging/leapp-repository.spec | 3 +++
1 file changed, 3 insertions(+)
diff --git a/packaging/leapp-repository.spec b/packaging/leapp-repository.spec
index 828355bf..2bb52505 100644
--- a/packaging/leapp-repository.spec
+++ b/packaging/leapp-repository.spec
@@ -272,6 +272,9 @@ 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
+# .gitkeep file is used to have a directory in the repo. but we do not want these
+# files in the resulting RPM
+find %{buildroot} -name .gitkeep -delete
for DIRECTORY in $(find %{buildroot}%{repositorydir}/ -mindepth 1 -maxdepth 1 -type d);
do
--
2.47.0

View File

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

View File

@ -1,95 +0,0 @@
From 140a0bbb689814041fa6a03ee2b703e70a20f2f2 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Sun, 10 Nov 2024 13:54:20 +0100
Subject: [PATCH 34/40] cli: load actor configuration
Load actor configuration when running `leapp upgrade` or `leapp
preupgrade`. The configuration is loaded, saved to leapp's DB,
and remains available to all actors via framework's global variable.
---
commands/command_utils.py | 32 +++++++++++++++++++++++++++++++-
commands/preupgrade/__init__.py | 3 +++
commands/upgrade/__init__.py | 3 +++
3 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/commands/command_utils.py b/commands/command_utils.py
index 2810a542..190f5f03 100644
--- a/commands/command_utils.py
+++ b/commands/command_utils.py
@@ -1,10 +1,12 @@
+import hashlib
import json
import os
import re
import resource
+from leapp.actors import config as actor_config
from leapp.exceptions import CommandError
-from leapp.utils import path
+from leapp.utils import audit, path
HANA_BASE_PATH = '/hana/shared'
HANA_SAPCONTROL_PATH_X86_64 = 'exe/linuxx86_64/hdb/sapcontrol'
@@ -178,3 +180,31 @@ def set_resource_limits():
if soft_fsize != fsize_limit:
set_resource_limit(resource.RLIMIT_FSIZE, fsize_limit, fsize_limit)
+
+
+def load_actor_configs_and_store_it_in_db(context, repositories, framework_cfg):
+ """
+ Load actor configuration so that actor's can access it and store it into leapp db.
+
+ :param context: Current execution context
+ :param repositories: Discovered repositories
+ :param framework_cfg: Leapp's configuration
+ """
+ # Read the Actor Config and validate it against the schemas saved in the
+ # configuration.
+
+ actor_config_schemas = tuple(actor.config_schemas for actor in repositories.actors)
+ actor_config_schemas = actor_config.normalize_schemas(actor_config_schemas)
+ actor_config_path = framework_cfg.get('actor_config', 'path')
+
+ # Note: actor_config.load() stores the loaded actor config into a global
+ # variable which can then be accessed by functions in that file. Is this
+ # the right way to store that information?
+ actor_cfg = actor_config.load(actor_config_path, actor_config_schemas)
+
+ # Dump the collected configuration, checksum it and store it inside the DB
+ config_text = json.dumps(actor_cfg)
+ config_text_hash = hashlib.sha256(config_text.encode('utf-8')).hexdigest()
+ config_data = audit.ActorConfigData(config=config_text, hash_id=config_text_hash)
+ db_config = audit.ActorConfig(config=config_data, context=context)
+ db_config.store()
diff --git a/commands/preupgrade/__init__.py b/commands/preupgrade/__init__.py
index a9fa40e0..631eca6b 100644
--- a/commands/preupgrade/__init__.py
+++ b/commands/preupgrade/__init__.py
@@ -62,6 +62,9 @@ def preupgrade(args, breadcrumbs):
command_utils.set_resource_limits()
workflow = repositories.lookup_workflow('IPUWorkflow')()
+
+ command_utils.load_actor_configs_and_store_it_in_db(context, repositories, cfg)
+
util.warn_if_unsupported(configuration)
util.process_whitelist_experimental(repositories, workflow, configuration, logger)
with beautify_actor_exception():
diff --git a/commands/upgrade/__init__.py b/commands/upgrade/__init__.py
index c7487fde..3dedd438 100644
--- a/commands/upgrade/__init__.py
+++ b/commands/upgrade/__init__.py
@@ -93,6 +93,9 @@ def upgrade(args, breadcrumbs):
command_utils.set_resource_limits()
workflow = repositories.lookup_workflow('IPUWorkflow')(auto_reboot=args.reboot)
+
+ command_utils.load_actor_configs_and_store_it_in_db(context, repositories, cfg)
+
util.process_whitelist_experimental(repositories, workflow, configuration, logger)
util.warn_if_unsupported(configuration)
with beautify_actor_exception():
--
2.47.0

View File

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

View File

@ -1,157 +0,0 @@
From f3d38325fb525bca427a2b00e2bfb73b9297c36a Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Sun, 10 Nov 2024 14:35:26 +0100
Subject: [PATCH 35/40] configs(common): introduce RHUI configuration
Introduce a common configuration definition for RHUI related decisions.
The configuration has an atomic nature - if the user wants to overwrite
leapp's decisions, he/she must overwrite all of them. Essentially, all
fields of the RHUI_SETUPS cloud map entry can be configured. Almost no
non-empty defaults are provided, as no reasonable defaults can be given.
This is due to all setup parameters are different from provider to
provider. Therefore, default values are empty values, so that it can
later be detected by an actor whether all fields of the RHUI config
has been filled.
Jira ref: RHEL-56251
---
repos/system_upgrade/common/configs/rhui.py | 127 ++++++++++++++++++++
1 file changed, 127 insertions(+)
create mode 100644 repos/system_upgrade/common/configs/rhui.py
diff --git a/repos/system_upgrade/common/configs/rhui.py b/repos/system_upgrade/common/configs/rhui.py
new file mode 100644
index 00000000..ade9bab9
--- /dev/null
+++ b/repos/system_upgrade/common/configs/rhui.py
@@ -0,0 +1,127 @@
+"""
+Configuration keys for RHUI.
+
+In case of RHUI in private regions it usual that publicly known RHUI data
+is not valid. In such cases it's possible to provide the correct expected
+RHUI data to correct the in-place upgrade process.
+"""
+
+from leapp.actors.config import Config
+from leapp.models import fields
+
+RHUI_CONFIG_SECTION = 'rhui'
+
+
+# @Note(mhecko): We use to distinguish config instantiated from default values that we should ignore
+# # Maybe we could make all config values None and detect it that way, but then we cannot
+# # give the user an example how the config should look like.
+class RhuiUseConfig(Config):
+ section = RHUI_CONFIG_SECTION
+ name = "use_config"
+ type_ = fields.Boolean()
+ default = False
+ description = """
+ Use values provided in the configuration file to override leapp's decisions.
+ """
+
+
+class RhuiSourcePkgs(Config):
+ section = RHUI_CONFIG_SECTION
+ name = "source_clients"
+ type_ = fields.List(fields.String())
+ default = []
+ description = """
+ The name of the source RHUI client RPMs (to be removed from the system).
+ """
+
+
+class RhuiTargetPkgs(Config):
+ section = RHUI_CONFIG_SECTION
+ name = "target_clients"
+ type_ = fields.List(fields.String())
+ default = []
+ description = """
+ The name of the target RHUI client RPM (to be installed on the system).
+ """
+
+
+class RhuiCloudProvider(Config):
+ section = RHUI_CONFIG_SECTION
+ name = "cloud_provider"
+ type_ = fields.String()
+ default = ""
+ description = """
+ Cloud provider name that should be used internally by leapp.
+
+ Leapp recognizes the following cloud providers:
+ - azure
+ - aws
+ - google
+
+ Cloud provider information is used for triggering some provider-specific modifications. The value also
+ influences how leapp determines target repositories to enable.
+ """
+
+
+# @Note(mhecko): We likely don't need this. We need the variant primarily to grab files from a correct directory
+# in leapp-rhui-<provider> folders.
+class RhuiCloudVariant(Config):
+ section = RHUI_CONFIG_SECTION
+ name = "image_variant"
+ type_ = fields.String()
+ default = "ordinary"
+ description = """
+ RHEL variant of the source system - is the source system SAP-specific image?
+
+ Leapp recognizes the following cloud providers:
+ - ordinary # The source system has not been deployed from a RHEL with SAP image
+ - sap # RHEL SAP images
+ - sap-apps # RHEL SAP Apps images (Azure only)
+ - sap-ha # RHEL HA Apps images (HA only)
+
+ Cloud provider information is used for triggering some provider-specific modifications. The value also
+ influences how leapp determines target repositories to enable.
+
+ Default:
+ "ordinary"
+ """
+
+
+class RhuiUpgradeFiles(Config):
+ section = RHUI_CONFIG_SECTION
+ name = "upgrade_files"
+ type_ = fields.StringMap(fields.String())
+ default = dict()
+ description = """
+ A mapping from source file paths to the destination where should they be
+ placed in the upgrade container.
+
+ Typically, these files should be provided by leapp-rhui-<PROVIDER> packages.
+
+ These files are needed to facilitate access to target repositories. Typical examples are: repofile(s),
+ certificates and keys.
+ """
+
+
+class RhuiTargetRepositoriesToUse(Config):
+ section = RHUI_CONFIG_SECTION
+ name = "rhui_target_repositories_to_use"
+ type_ = fields.List(fields.String())
+ description = """
+ List of target repositories enabled during the upgrade. Similar to executing leapp with --enablerepo.
+
+ The repositories to be enabled need to be either in the repofiles listed in the `upgrade_files` field,
+ or in repofiles present on the source system.
+ """
+ default = list()
+
+
+all_rhui_cfg = (
+ RhuiTargetPkgs,
+ RhuiUpgradeFiles,
+ RhuiTargetRepositoriesToUse,
+ RhuiCloudProvider,
+ RhuiCloudVariant,
+ RhuiSourcePkgs,
+ RhuiUseConfig
+)
--
2.47.0

View File

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

View File

@ -1,457 +0,0 @@
From a03e8e5d10c1d6f3cdae216fafa0d7f0d0896494 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Sun, 10 Nov 2024 14:36:07 +0100
Subject: [PATCH 36/40] check_rhui: read RHUI configuration
Extend the check_rhui actor to read user-provided RHUI configuration.
If the provided configuration values say that the user wants to
overrwrite leapp's decisions, then the patch checks whether all values
are provided. If so, corresponding RHUIInfo message is produced. The
only implemented safe-guards are those that prevent the user from
accidentaly specifying a non-existing file to be copied into the
scrach container during us preparing to download target userspace
content. If the user provides only some of the configuration values
the upgrade is terminated early with an error, providing quick feedback
about misconfiguration. The patch has been designed to allow development
of upgrades on previously unknown clouds (clouds without an entry in
RHUI_SETUPS).
Jira ref: RHEL-56251
---
.../common/actors/cloud/checkrhui/actor.py | 4 +
.../cloud/checkrhui/libraries/checkrhui.py | 102 +++++++++-
.../tests/component_test_checkrhui.py | 178 ++++++++++++++++--
3 files changed, 265 insertions(+), 19 deletions(-)
diff --git a/repos/system_upgrade/common/actors/cloud/checkrhui/actor.py b/repos/system_upgrade/common/actors/cloud/checkrhui/actor.py
index 593e73e5..933ffcb3 100644
--- a/repos/system_upgrade/common/actors/cloud/checkrhui/actor.py
+++ b/repos/system_upgrade/common/actors/cloud/checkrhui/actor.py
@@ -1,4 +1,5 @@
from leapp.actors import Actor
+from leapp.configs.common.rhui import all_rhui_cfg
from leapp.libraries.actor import checkrhui as checkrhui_lib
from leapp.models import (
CopyFile,
@@ -8,6 +9,7 @@ from leapp.models import (
RequiredTargetUserspacePackages,
RHUIInfo,
RpmTransactionTasks,
+ TargetRepositories,
TargetUserSpacePreupgradeTasks
)
from leapp.reporting import Report
@@ -21,6 +23,7 @@ class CheckRHUI(Actor):
"""
name = 'checkrhui'
+ config_schemas = all_rhui_cfg
consumes = (InstalledRPM,)
produces = (
KernelCmdlineArg,
@@ -28,6 +31,7 @@ class CheckRHUI(Actor):
RequiredTargetUserspacePackages,
Report, DNFPluginTask,
RpmTransactionTasks,
+ TargetRepositories,
TargetUserSpacePreupgradeTasks,
CopyFile,
)
diff --git a/repos/system_upgrade/common/actors/cloud/checkrhui/libraries/checkrhui.py b/repos/system_upgrade/common/actors/cloud/checkrhui/libraries/checkrhui.py
index 3b217917..64e36e08 100644
--- a/repos/system_upgrade/common/actors/cloud/checkrhui/libraries/checkrhui.py
+++ b/repos/system_upgrade/common/actors/cloud/checkrhui/libraries/checkrhui.py
@@ -2,17 +2,29 @@ import itertools
import os
from collections import namedtuple
+import leapp.configs.common.rhui as rhui_config_lib
from leapp import reporting
+from leapp.configs.common.rhui import ( # Import all config fields so we are not using their name attributes directly
+ RhuiCloudProvider,
+ RhuiCloudVariant,
+ RhuiSourcePkgs,
+ RhuiTargetPkgs,
+ RhuiTargetRepositoriesToUse,
+ RhuiUpgradeFiles,
+ RhuiUseConfig
+)
from leapp.exceptions import StopActorExecutionError
from leapp.libraries.common import rhsm, rhui
from leapp.libraries.common.config import version
from leapp.libraries.stdlib import api
from leapp.models import (
CopyFile,
+ CustomTargetRepository,
DNFPluginTask,
InstalledRPM,
RHUIInfo,
RpmTransactionTasks,
+ TargetRepositories,
TargetRHUIPostInstallTasks,
TargetRHUIPreInstallTasks,
TargetRHUISetupInfo,
@@ -291,11 +303,11 @@ def produce_rhui_info_to_setup_target(rhui_family, source_setup_desc, target_set
api.produce(rhui_info)
-def produce_rpms_to_install_into_target(source_setup, target_setup):
- to_install = sorted(target_setup.clients - source_setup.clients)
- to_remove = sorted(source_setup.clients - target_setup.clients)
+def produce_rpms_to_install_into_target(source_clients, target_clients):
+ to_install = sorted(target_clients - source_clients)
+ to_remove = sorted(source_clients - target_clients)
- api.produce(TargetUserSpacePreupgradeTasks(install_rpms=sorted(target_setup.clients)))
+ api.produce(TargetUserSpacePreupgradeTasks(install_rpms=sorted(target_clients)))
if to_install or to_remove:
api.produce(RpmTransactionTasks(to_install=to_install, to_remove=to_remove))
@@ -316,7 +328,85 @@ def inform_about_upgrade_with_rhui_without_no_rhsm():
return False
+def emit_rhui_setup_tasks_based_on_config(rhui_config_dict):
+ config_upgrade_files = rhui_config_dict[RhuiUpgradeFiles.name]
+
+ nonexisting_files_to_copy = []
+ for source_path in config_upgrade_files:
+ if not os.path.exists(source_path):
+ nonexisting_files_to_copy.append(source_path)
+
+ if nonexisting_files_to_copy:
+ details_lines = ['The following files were not found:']
+ # Use .format and put backticks around paths so that weird unicode spaces will be easily seen
+ details_lines.extend(' - `{0}`'.format(path) for path in nonexisting_files_to_copy)
+ details = '\n'.join(details_lines)
+
+ reason = 'RHUI config lists nonexisting files in its `{0}` field.'.format(RhuiUpgradeFiles.name)
+ raise StopActorExecutionError(reason, details={'details': details})
+
+ files_to_copy_into_overlay = [CopyFile(src=key, dst=value) for key, value in config_upgrade_files.items()]
+ preinstall_tasks = TargetRHUIPreInstallTasks(files_to_copy_into_overlay=files_to_copy_into_overlay)
+
+ target_client_setup_info = TargetRHUISetupInfo(
+ preinstall_tasks=preinstall_tasks,
+ postinstall_tasks=TargetRHUIPostInstallTasks(),
+ bootstrap_target_client=False, # We don't need to install the client into overlay - user provided all files
+ )
+
+ rhui_info = RHUIInfo(
+ provider=rhui_config_dict[RhuiCloudProvider.name],
+ variant=rhui_config_dict[RhuiCloudVariant.name],
+ src_client_pkg_names=rhui_config_dict[RhuiSourcePkgs.name],
+ target_client_pkg_names=rhui_config_dict[RhuiTargetPkgs.name],
+ target_client_setup_info=target_client_setup_info
+ )
+ api.produce(rhui_info)
+
+
+def request_configured_repos_to_be_enabled(rhui_config):
+ config_repos_to_enable = rhui_config[RhuiTargetRepositoriesToUse.name]
+ custom_repos = [CustomTargetRepository(repoid=repoid) for repoid in config_repos_to_enable]
+ if custom_repos:
+ target_repos = TargetRepositories(custom_repos=custom_repos, rhel_repos=[])
+ api.produce(target_repos)
+
+
+def stop_with_err_if_config_missing_fields(config):
+ required_fields = [
+ RhuiTargetRepositoriesToUse,
+ RhuiCloudProvider,
+ # RhuiCloudVariant, <- this is not required
+ RhuiSourcePkgs,
+ RhuiTargetPkgs,
+ RhuiUpgradeFiles,
+ ]
+
+ missing_fields = tuple(field for field in required_fields if not config[field.name])
+ if missing_fields:
+ field_names = (field.name for field in missing_fields)
+ missing_fields_str = ', '.join(field_names)
+ details = 'The following required RHUI config fields are missing or they are set to an empty value: {}'
+ details = details.format(missing_fields_str)
+ raise StopActorExecutionError('Provided RHUI config is missing values for required fields.',
+ details={'details': details})
+
+
def process():
+ rhui_config = api.current_actor().config[rhui_config_lib.RHUI_CONFIG_SECTION]
+
+ if rhui_config[RhuiUseConfig.name]:
+ api.current_logger().info('Skipping RHUI upgrade auto-configuration - using provided config instead.')
+ stop_with_err_if_config_missing_fields(rhui_config)
+ emit_rhui_setup_tasks_based_on_config(rhui_config)
+
+ src_clients = set(rhui_config[RhuiSourcePkgs.name])
+ target_clients = set(rhui_config[RhuiTargetPkgs.name])
+ produce_rpms_to_install_into_target(src_clients, target_clients)
+
+ request_configured_repos_to_be_enabled(rhui_config)
+ return
+
installed_rpm = itertools.chain(*[installed_rpm_msg.items for installed_rpm_msg in api.consume(InstalledRPM)])
installed_pkgs = {rpm.name for rpm in installed_rpm}
@@ -342,7 +432,9 @@ def process():
# Instruction on how to access the target content
produce_rhui_info_to_setup_target(src_rhui_setup.family, src_rhui_setup.description, target_setup_desc)
- produce_rpms_to_install_into_target(src_rhui_setup.description, target_setup_desc)
+ source_clients = src_rhui_setup.description.clients
+ target_clients = target_setup_desc.clients
+ produce_rpms_to_install_into_target(source_clients, target_clients)
if src_rhui_setup.family.provider == rhui.RHUIProvider.AWS:
# We have to disable Amazon-id plugin in the initramdisk phase as there is no network
diff --git a/repos/system_upgrade/common/actors/cloud/checkrhui/tests/component_test_checkrhui.py b/repos/system_upgrade/common/actors/cloud/checkrhui/tests/component_test_checkrhui.py
index 27e70eea..3ac9c1b8 100644
--- a/repos/system_upgrade/common/actors/cloud/checkrhui/tests/component_test_checkrhui.py
+++ b/repos/system_upgrade/common/actors/cloud/checkrhui/tests/component_test_checkrhui.py
@@ -1,30 +1,43 @@
-from collections import namedtuple
+import itertools
+import os
+from collections import defaultdict
from enum import Enum
import pytest
from leapp import reporting
+from leapp.configs.common.rhui import (
+ all_rhui_cfg,
+ RhuiCloudProvider,
+ RhuiCloudVariant,
+ RhuiSourcePkgs,
+ RhuiTargetPkgs,
+ RhuiTargetRepositoriesToUse,
+ RhuiUpgradeFiles,
+ RhuiUseConfig
+)
from leapp.exceptions import StopActorExecutionError
from leapp.libraries.actor import checkrhui as checkrhui_lib
from leapp.libraries.common import rhsm, rhui
-from leapp.libraries.common.config import mock_configs, version
from leapp.libraries.common.rhui import mk_rhui_setup, RHUIFamily
-from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked, produce_mocked
+from leapp.libraries.common.testutils import (
+ _make_default_config,
+ create_report_mocked,
+ CurrentActorMocked,
+ produce_mocked
+)
from leapp.libraries.stdlib import api
from leapp.models import (
- CopyFile,
InstalledRPM,
- RequiredTargetUserspacePackages,
RHUIInfo,
RPM,
RpmTransactionTasks,
+ TargetRepositories,
TargetRHUIPostInstallTasks,
TargetRHUIPreInstallTasks,
TargetRHUISetupInfo,
TargetUserSpacePreupgradeTasks
)
-from leapp.reporting import Report
-from leapp.snactor.fixture import current_actor_context
RH_PACKAGER = 'Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla>'
@@ -95,7 +108,8 @@ def mk_cloud_map(variants):
]
)
def test_determine_rhui_src_variant(monkeypatch, extra_pkgs, rhui_setups, expected_result):
- monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(src_ver='7.9'))
+ actor = CurrentActorMocked(src_ver='7.9', config=_make_default_config(all_rhui_cfg))
+ monkeypatch.setattr(api, 'current_actor', actor)
installed_pkgs = {'zip', 'zsh', 'bash', 'grubby'}.union(set(extra_pkgs))
if expected_result and not isinstance(expected_result, RHUIFamily): # An exception
@@ -167,7 +181,8 @@ def test_google_specific_customization(provider, should_mutate):
)
def test_aws_specific_customization(monkeypatch, rhui_family, target_major, should_mutate):
dst_ver = '{major}.0'.format(major=target_major)
- monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(dst_ver=dst_ver))
+ actor = CurrentActorMocked(dst_ver=dst_ver, config=_make_default_config(all_rhui_cfg))
+ monkeypatch.setattr(api, 'current_actor', actor)
setup_info = mk_setup_info()
checkrhui_lib.customize_rhui_setup_for_aws(rhui_family, setup_info)
@@ -215,12 +230,12 @@ def produce_rhui_info_to_setup_target(monkeypatch):
def test_produce_rpms_to_install_into_target(monkeypatch):
- source_rhui_setup = mk_rhui_setup(clients={'src_pkg'}, leapp_pkg='leapp_pkg')
- target_rhui_setup = mk_rhui_setup(clients={'target_pkg'}, leapp_pkg='leapp_pkg')
+ source_clients = {'src_pkg'}
+ target_clients = {'target_pkg'}
monkeypatch.setattr(api, 'produce', produce_mocked())
- checkrhui_lib.produce_rpms_to_install_into_target(source_rhui_setup, target_rhui_setup)
+ checkrhui_lib.produce_rpms_to_install_into_target(source_clients, target_clients)
assert len(api.produce.model_instances) == 2
userspace_tasks, target_rpm_tasks = api.produce.model_instances[0], api.produce.model_instances[1]
@@ -276,7 +291,8 @@ def test_process(monkeypatch, extra_installed_pkgs, skip_rhsm, expected_action):
installed_rpms = InstalledRPM(items=installed_pkgs)
monkeypatch.setattr(api, 'produce', produce_mocked())
- monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(src_ver='7.9', msgs=[installed_rpms]))
+ actor = CurrentActorMocked(src_ver='7.9', msgs=[installed_rpms], config=_make_default_config(all_rhui_cfg))
+ monkeypatch.setattr(api, 'current_actor', actor)
monkeypatch.setattr(reporting, 'create_report', create_report_mocked())
monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: skip_rhsm)
monkeypatch.setattr(rhui, 'RHUI_SETUPS', known_setups)
@@ -315,7 +331,8 @@ def test_unknown_target_rhui_setup(monkeypatch, is_target_setup_known):
installed_rpms = InstalledRPM(items=installed_pkgs)
monkeypatch.setattr(api, 'produce', produce_mocked())
- monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(src_ver='7.9', msgs=[installed_rpms]))
+ actor = CurrentActorMocked(src_ver='7.9', msgs=[installed_rpms], config=_make_default_config(all_rhui_cfg))
+ monkeypatch.setattr(api, 'current_actor', actor)
monkeypatch.setattr(reporting, 'create_report', create_report_mocked())
monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: True)
monkeypatch.setattr(rhui, 'RHUI_SETUPS', known_setups)
@@ -374,3 +391,136 @@ def test_select_chronologically_closest(monkeypatch, setups, desired_minor, expe
setup = setups[0]
assert setup == expected_setup
+
+
+def test_config_overwrites_everything(monkeypatch):
+ rhui_config = {
+ RhuiUseConfig.name: True,
+ RhuiSourcePkgs.name: ['client_source'],
+ RhuiTargetPkgs.name: ['client_target'],
+ RhuiCloudProvider.name: 'aws',
+ RhuiUpgradeFiles.name: {
+ '/root/file.repo': '/etc/yum.repos.d/'
+ },
+ RhuiTargetRepositoriesToUse.name: [
+ 'repoid_to_use'
+ ]
+ }
+ all_config = {'rhui': rhui_config}
+
+ actor = CurrentActorMocked(config=all_config)
+ monkeypatch.setattr(api, 'current_actor', actor)
+
+ function_calls = defaultdict(int)
+
+ def mk_function_probe(fn_name):
+ def probe(*args, **kwargs):
+ function_calls[fn_name] += 1
+ return probe
+
+ monkeypatch.setattr(checkrhui_lib,
+ 'emit_rhui_setup_tasks_based_on_config',
+ mk_function_probe('emit_rhui_setup_tasks_based_on_config'))
+ monkeypatch.setattr(checkrhui_lib,
+ 'stop_with_err_if_config_missing_fields',
+ mk_function_probe('stop_with_err_if_config_missing_fields'))
+ monkeypatch.setattr(checkrhui_lib,
+ 'produce_rpms_to_install_into_target',
+ mk_function_probe('produce_rpms_to_install_into_target'))
+ monkeypatch.setattr(checkrhui_lib,
+ 'request_configured_repos_to_be_enabled',
+ mk_function_probe('request_configured_repos_to_be_enabled'))
+
+ checkrhui_lib.process()
+
+ expected_function_calls = {
+ 'emit_rhui_setup_tasks_based_on_config': 1,
+ 'stop_with_err_if_config_missing_fields': 1,
+ 'produce_rpms_to_install_into_target': 1,
+ 'request_configured_repos_to_be_enabled': 1,
+ }
+
+ assert function_calls == expected_function_calls
+
+
+def test_request_configured_repos_to_be_enabled(monkeypatch):
+ monkeypatch.setattr(api, 'produce', produce_mocked())
+
+ rhui_config = {
+ RhuiUseConfig.name: True,
+ RhuiSourcePkgs.name: ['client_source'],
+ RhuiTargetPkgs.name: ['client_target'],
+ RhuiCloudProvider.name: 'aws',
+ RhuiUpgradeFiles.name: {
+ '/root/file.repo': '/etc/yum.repos.d/'
+ },
+ RhuiTargetRepositoriesToUse.name: [
+ 'repoid1',
+ 'repoid2',
+ 'repoid3',
+ ]
+ }
+
+ checkrhui_lib.request_configured_repos_to_be_enabled(rhui_config)
+
+ assert api.produce.called
+ assert len(api.produce.model_instances) == 1
+
+ target_repos = api.produce.model_instances[0]
+ assert isinstance(target_repos, TargetRepositories)
+ assert not target_repos.rhel_repos
+
+ custom_repoids = sorted(custom_repo_model.repoid for custom_repo_model in target_repos.custom_repos)
+ assert custom_repoids == ['repoid1', 'repoid2', 'repoid3']
+
+
+@pytest.mark.parametrize(
+ ('upgrade_files', 'existing_files'),
+ (
+ (['/root/a', '/root/b'], ['/root/a', '/root/b']),
+ (['/root/a', '/root/b'], ['/root/b']),
+ (['/root/a', '/root/b'], []),
+ )
+)
+def test_missing_files_in_config(monkeypatch, upgrade_files, existing_files):
+ upgrade_files_map = dict((source_path, '/tmp/dummy') for source_path in upgrade_files)
+
+ rhui_config = {
+ RhuiUseConfig.name: True,
+ RhuiSourcePkgs.name: ['client_source'],
+ RhuiTargetPkgs.name: ['client_target'],
+ RhuiCloudProvider.name: 'aws',
+ RhuiCloudVariant.name: 'ordinary',
+ RhuiUpgradeFiles.name: upgrade_files_map,
+ RhuiTargetRepositoriesToUse.name: [
+ 'repoid_to_use'
+ ]
+ }
+
+ monkeypatch.setattr(os.path, 'exists', lambda path: path in existing_files)
+ monkeypatch.setattr(api, 'produce', produce_mocked())
+
+ should_error = (len(upgrade_files) != len(existing_files))
+ if should_error:
+ with pytest.raises(StopActorExecutionError):
+ checkrhui_lib.emit_rhui_setup_tasks_based_on_config(rhui_config)
+ else:
+ checkrhui_lib.emit_rhui_setup_tasks_based_on_config(rhui_config)
+ assert api.produce.called
+ assert len(api.produce.model_instances) == 1
+
+ rhui_info = api.produce.model_instances[0]
+ assert isinstance(rhui_info, RHUIInfo)
+ assert rhui_info.provider == 'aws'
+ assert rhui_info.variant == 'ordinary'
+ assert rhui_info.src_client_pkg_names == ['client_source']
+ assert rhui_info.target_client_pkg_names == ['client_target']
+
+ setup_info = rhui_info.target_client_setup_info
+ assert not setup_info.bootstrap_target_client
+
+ _copies_to_perform = setup_info.preinstall_tasks.files_to_copy_into_overlay
+ copies_to_perform = sorted((copy.src, copy.dst) for copy in _copies_to_perform)
+ expected_copies = sorted(zip(upgrade_files, itertools.repeat('/tmp/dummy')))
+
+ assert copies_to_perform == expected_copies
--
2.47.0

File diff suppressed because it is too large Load Diff

View File

@ -1,53 +0,0 @@
From a206a7f02c68f50ab50c9f547669d3a4178c4bd2 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Wed, 16 Oct 2024 17:38:36 +0200
Subject: [PATCH 37/40] testutils: add support for configs
Extend the CurrentActorMocked class to accept a `config` value,
allowing developers to mock actors that rely on configuration.
A library function `_make_default_config` is also introduced,
allowing to instantiate default configs from config schemas.
---
repos/system_upgrade/common/libraries/testutils.py | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/repos/system_upgrade/common/libraries/testutils.py b/repos/system_upgrade/common/libraries/testutils.py
index c538af1a..afeb360a 100644
--- a/repos/system_upgrade/common/libraries/testutils.py
+++ b/repos/system_upgrade/common/libraries/testutils.py
@@ -4,6 +4,7 @@ import os
from collections import namedtuple
from leapp import reporting
+from leapp.actors.config import _normalize_config, normalize_schemas
from leapp.libraries.common.config import architecture
from leapp.models import EnvVar
from leapp.utils.deprecation import deprecated
@@ -67,9 +68,15 @@ class logger_mocked(object):
return self
+def _make_default_config(actor_config_schema):
+ """ Make a config dict populated with default values. """
+ merged_schema = normalize_schemas((actor_config_schema, ))
+ return _normalize_config({}, merged_schema) # Will fill default values during normalization
+
+
class CurrentActorMocked(object): # pylint:disable=R0904
def __init__(self, arch=architecture.ARCH_X86_64, envars=None, kernel='3.10.0-957.43.1.el7.x86_64',
- release_id='rhel', src_ver='7.8', dst_ver='8.1', msgs=None, flavour='default'):
+ release_id='rhel', src_ver='7.8', dst_ver='8.1', msgs=None, flavour='default', config=None):
envarsList = [EnvVar(name=k, value=v) for k, v in envars.items()] if envars else []
version = namedtuple('Version', ['source', 'target'])(src_ver, dst_ver)
release = namedtuple('OS_release', ['release_id', 'version_id'])(release_id, src_ver)
@@ -82,6 +89,7 @@ class CurrentActorMocked(object): # pylint:disable=R0904
'configuration', ['architecture', 'kernel', 'leapp_env_vars', 'os_release', 'version', 'flavour']
)(arch, kernel, envarsList, release, version, flavour)
self._msgs = msgs or []
+ self.config = {} if config is None else config
def __call__(self):
return self
--
2.47.0

View File

@ -0,0 +1,91 @@
From 397975d6b63ff70755ea41b8ec8fc413966218e4 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Fri, 30 May 2025 14:13:35 +0200
Subject: [PATCH 38/43] Makefile: Non-zero exit code on failed tests in
container
Previously all exit codes from execution of tests inside
container have been ignored and make command ended with zero always.
Also drop testing of el7toel8 repository for Python 3.6 on RHEL 8.
The test started to fail for unknown reason (changes in pytest or
another nonstandard python module?). As we are in the middle of
dropping all el7toel8 and python2 related content, let's just drop
it. Keeping the full removal of Py2 and el7toel8 content on separate
PR.
---
Makefile | 29 ++++++++++++++++-------------
1 file changed, 16 insertions(+), 13 deletions(-)
diff --git a/Makefile b/Makefile
index ceb013ab..6769b2f3 100644
--- a/Makefile
+++ b/Makefile
@@ -164,9 +164,9 @@ help:
@echo " PR=7 SUFFIX='my_additional_suffix' make <target>"
@echo " MR=6 COPR_CONFIG='path/to/the/config/copr/file' make <target>"
@echo " ACTOR=<actor> TEST_LIBS=y make test"
- @echo " BUILD_CONTAINER=el7 make build_container"
+ @echo " BUILD_CONTAINER=rhel8 make build_container"
@echo " TEST_CONTAINER=f34 make test_container"
- @echo " CONTAINER_TOOL=docker TEST_CONTAINER=rhel7 make test_container_no_lint"
+ @echo " CONTAINER_TOOL=docker TEST_CONTAINER=rhel8 make test_container_no_lint"
@echo ""
clean:
@@ -459,30 +459,33 @@ test_container:
$(_CONTAINER_TOOL) ps -q -f name=$$_CONT_NAME && { $(_CONTAINER_TOOL) kill $$_CONT_NAME; $(_CONTAINER_TOOL) rm $$_CONT_NAME; }; \
$(_CONTAINER_TOOL) run -di --name $$_CONT_NAME -v "$$PWD":/repo:Z -e PYTHON_VENV=$$_VENV $$TEST_IMAGE && \
$(_CONTAINER_TOOL) exec $$_CONT_NAME rsync -aur --delete --exclude "tut*" /repo/ /repocopy && \
+ export res=0; \
case $$_VENV in \
python2.7) \
- TEST_CONT_IPU=el7toel8 $(MAKE) _test_container_ipu; \
+ TEST_CONT_IPU=el7toel8 $(MAKE) _test_container_ipu || res=1; \
;;\
python3.6) \
- TEST_CONT_IPU=el7toel8 $(MAKE) _test_container_ipu; \
- TEST_CONT_IPU=el8toel9 $(MAKE) _test_container_ipu; \
+ echo "INFO: Skipping testing of el7toel8 repository. Obsoleted"; \
+ TEST_CONT_IPU=el8toel9 $(MAKE) _test_container_ipu || res=1; \
;; \
python3.9) \
- TEST_CONT_IPU=el8toel9 $(MAKE) _test_container_ipu; \
- TEST_CONT_IPU=el9toel10 $(MAKE) _test_container_ipu; \
+ TEST_CONT_IPU=el8toel9 $(MAKE) _test_container_ipu || res=1; \
+ TEST_CONT_IPU=el9toel10 $(MAKE) _test_container_ipu || res=1; \
;; \
python3.12) \
- TEST_CONT_IPU=el9toel10 $(MAKE) _test_container_ipu; \
+ TEST_CONT_IPU=el9toel10 $(MAKE) _test_container_ipu || res=1; \
;; \
*) \
- TEST_CONT_IPU=el8toel9 $(MAKE) _test_container_ipu; \
- ;;\
+ TEST_CONT_IPU=el8toel9 $(MAKE) _test_container_ipu || res=1; \
+ ;; \
esac; \
$(_CONTAINER_TOOL) kill $$_CONT_NAME; \
- $(_CONTAINER_TOOL) rm $$_CONT_NAME
+ $(_CONTAINER_TOOL) rm $$_CONT_NAME; \
+ [ $$res -ne 0 ] && echo "TIP: If you do not see an error in the end of logs, scroll up. Multiple tests could be executed." ; \
+ exit $$res
test_container_all:
- @for container in "f34" "rhel7" "rhel8"; do \
+ @for container in "f34" "rhel7" "rhel8" "rhel9"; do \
TEST_CONTAINER=$$container $(MAKE) test_container || exit 1; \
done
@@ -490,7 +493,7 @@ test_container_no_lint:
@_TEST_CONT_TARGET="test_no_lint" $(MAKE) test_container
test_container_all_no_lint:
- @for container in "f34" "rhel7" "rhel8"; do \
+ @for container in "f34" "rhel7" "rhel8" "rhel9"; do \
TEST_CONTAINER=$$container $(MAKE) test_container_no_lint || exit 1; \
done
--
2.49.0

View File

@ -1,70 +0,0 @@
From 0147bc268607e5931ebca95e3253087ec71a3c66 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Sun, 20 Oct 2024 16:08:49 +0200
Subject: [PATCH 38/40] userspacegen(rhui): remove repofiles only if now owned
by an RPM
We copy files into the target userspace when setting up target
repository content. If this file is named equally as some of the
files installed by the target RHUI client installed during early
phases of target userspace setup process, we would delete it in
cleanup. Therefore, if we copy a repofile named /etc/yum.repos.d/X.repo
and the target client also owns a file /etc/yum.repos.d/X.repo, we
would remove it, making the container loose access to target content.
This patch prevents us from blindly deleting files, keeping files that
are owned by some RPM (usually that would be the target RHUI client).
---
.../libraries/userspacegen.py | 30 ++++++++++++++-----
1 file changed, 22 insertions(+), 8 deletions(-)
diff --git a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
index d7698056..12736ab7 100644
--- a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
+++ b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py
@@ -1120,6 +1120,27 @@ def _get_target_userspace():
return constants.TARGET_USERSPACE.format(get_target_major_version())
+def _remove_injected_repofiles_from_our_rhui_packages(target_userspace_ctx, rhui_setup_info):
+ target_userspace_path = _get_target_userspace()
+ for copy in rhui_setup_info.preinstall_tasks.files_to_copy_into_overlay:
+ dst_in_container = get_copy_location_from_copy_in_task(target_userspace_path, copy)
+ dst_in_container = dst_in_container.strip('/')
+ dst_in_host = os.path.join(target_userspace_path, dst_in_container)
+
+ if os.path.isfile(dst_in_host) and dst_in_host.endswith('.repo'):
+ # The repofile might have been replaced by a new one provided by the RHUI client if names collide
+ # Performance: Do the query here and not earlier, because we would be running rpm needlessly
+ try:
+ path_with_root = '/' + dst_in_container
+ target_userspace_ctx.call(['rpm', '-q', '--whatprovides', path_with_root])
+ api.current_logger().debug('Repofile {0} kept as it is owned by some RPM.'.format(dst_in_host))
+ except CalledProcessError:
+ # rpm exists with 1 if the file is not owned by any RPM. We might be catching all kinds of other
+ # problems here, but still better than always removing repofiles.
+ api.current_logger().debug('Removing repofile - not owned by any RPM: {0}'.format(dst_in_host))
+ os.remove(dst_in_host)
+
+
def _create_target_userspace(context, indata, packages, files, target_repoids):
"""Create the target userspace."""
target_path = _get_target_userspace()
@@ -1139,14 +1160,7 @@ def _create_target_userspace(context, indata, packages, files, target_repoids):
)
setup_info = indata.rhui_info.target_client_setup_info
if not setup_info.bootstrap_target_client:
- target_userspace_path = _get_target_userspace()
- for copy in setup_info.preinstall_tasks.files_to_copy_into_overlay:
- dst_in_container = get_copy_location_from_copy_in_task(target_userspace_path, copy)
- dst_in_container = dst_in_container.strip('/')
- dst_in_host = os.path.join(target_userspace_path, dst_in_container)
- if os.path.isfile(dst_in_host) and dst_in_host.endswith('.repo'):
- api.current_logger().debug('Removing repofile: {0}'.format(dst_in_host))
- os.remove(dst_in_host)
+ _remove_injected_repofiles_from_our_rhui_packages(context, setup_info)
# and do not forget to set the rhsm into the container mode again
with mounting.NspawnActions(_get_target_userspace()) as target_context:
--
2.47.0

View File

@ -0,0 +1,82 @@
From 4e87908b2e17d87b69bcec29ba1e9b777439a0fe Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Fri, 30 May 2025 15:02:53 +0200
Subject: [PATCH 39/43] CI: Unit-tests: Rename tasks & tests executions
Previous name have been very long, repeating, and it has been
problem to read the whole informatino about what tests are performed
as the description has been shortened in WebUI, e.g.:
Unit Tests / Run unit tests in containers (Run python linters for el8toel9 and common repositories on p...
Let's change the name so it's shortened and easier read what test
has been actually performed. Also, no need to mention that tests are
running in container anymore, as we are not running unit-tests outside
of the container in upstream. Example of new style names:
Unit Tests / Run: Linters (python:3.9; repos:el9toel10,common) (pull_request)
Unit Tests / Run: Unit Tests (python:3.9; repos:el9toel10,common) (pull_request)
---
.github/workflows/unit-tests.yml | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml
index 37748396..ed82e0e5 100644
--- a/.github/workflows/unit-tests.yml
+++ b/.github/workflows/unit-tests.yml
@@ -9,43 +9,43 @@ on:
jobs:
test:
- name: Run unit tests in containers
+ name: 'Run: ${{ matrix.scenarios.name }}'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
scenarios:
# 9to10
- - name: Run unit tests for el9toel10 and common repositories on python 3.12
+ - name: 'Unit tests (python:3.12; repos:el9toel10,common)'
python: python3.12
repos: 'el9toel10,common'
container: ubi9
- - name: Run python linters for el9toel10 and common repositories on python 3.12
+ - name: 'Linters (python:3.12; repos:el9toel10,common)'
python: python3.12
repos: 'el9toel10,common'
container: ubi9-lint
- - name: Run unit tests for el9toel10 and common repositories on python 3.9
+ - name: 'Unit tests (python:3.9; repos:el9toel10,common)'
python: python3.9
repos: 'el9toel10,common'
container: ubi9
- - name: Run python linters for el9toel10 and common repositories on python 3.9
+ - name: 'Linters (python:3.9; repos:el9toel10,common)'
python: python3.9
repos: 'el9toel10,common'
container: ubi9-lint
# 8to9
- - name: Run unit tests for el8toel9 and common repositories on python 3.9
+ - name: 'Unit tests (python:3.9; repos:el8toel9,common)'
python: python3.9
repos: 'el8toel9,common'
container: ubi9
- - name: Run python linters for el8toel9 and common repositories on python 3.9
+ - name: 'Linters (python:3.9; repos:el8toel9,common)'
python: python3.9
repos: 'el8toel9,common'
container: ubi9-lint
- - name: Run unit tests for el8toel9 and common repositories on python 3.6
+ - name: 'Unit tests (python:3.6; repos:el8toel9,common)'
python: python3.6
repos: 'el8toel9,common'
container: ubi8
- - name: Run python linters for el8toel9 and common repositories on python 3.6
+ - name: 'Linters (python:3.6; repos:el8toel9,common)'
python: python3.6
repos: 'el8toel9,common'
container: ubi8-lint
--
2.49.0

View File

@ -1,857 +0,0 @@
From c2f2895bb570a75eb2aaa7b84a2bcd9dcd537b0e Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Thu, 14 Nov 2024 14:24:15 +0100
Subject: [PATCH 39/40] Enable IPU for EL 9.6 (and drop EL 8.8/9.2)
* Add product certificates for RHEL 9.6
* Introduce upgrade path 8.10 -> 9.6
* Drop IPUs related to EL 8.8 and 9.2
* This will not be supported in this release.
* Keeping for now still IPU 8.10 -> 9.5 as it is a fresh release
so it has a value for us to run tests there. We will drop it
later during this lifecycle (CTC-2?).
* Drop EL 8.8 from the list of supported versions
* Update tests in packit
* Note that tests for 9.6 could be failing for a while until
composes are created.
jira: RHEL-67621
---
.packit.yaml | 257 +++++-------------
.../common/files/prod-certs/9.6/279.pem | 37 +++
.../common/files/prod-certs/9.6/362.pem | 37 +++
.../common/files/prod-certs/9.6/363.pem | 37 +++
.../common/files/prod-certs/9.6/419.pem | 36 +++
.../common/files/prod-certs/9.6/433.pem | 37 +++
.../common/files/prod-certs/9.6/479.pem | 36 +++
.../common/files/prod-certs/9.6/486.pem | 37 +++
.../common/files/prod-certs/9.6/72.pem | 36 +++
.../common/files/upgrade_paths.json | 18 +-
.../common/libraries/config/version.py | 2 +-
11 files changed, 363 insertions(+), 207 deletions(-)
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.6/279.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.6/362.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.6/363.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.6/419.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.6/433.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.6/479.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.6/486.pem
create mode 100644 repos/system_upgrade/common/files/prod-certs/9.6/72.pem
diff --git a/.packit.yaml b/.packit.yaml
index fbfd0eea..48c3cbbb 100644
--- a/.packit.yaml
+++ b/.packit.yaml
@@ -145,104 +145,6 @@ jobs:
# ######################### Individual tests ########################### #
# ###################################################################### #
-# Tests: 7.9 -> 8.8
-- &sanity-79to88-aws
- <<: *sanity-abstract-7to8-aws
- trigger: pull_request
- identifier: sanity-7.9to8.8-aws
- tf_extra_params:
- test:
- tmt:
- plan_filter: 'tag:7to8 & tag:upgrade_happy_path & enabled:true'
- environments:
- - tmt:
- context:
- distro: "rhel-7.9"
- distro_target: "rhel-8.8"
- settings:
- provisioning:
- post_install_script: "#!/bin/sh\nsudo sed -i s/.*ssh-rsa/ssh-rsa/ /root/.ssh/authorized_keys"
- tags:
- BusinessUnit: sst_upgrades@leapp_upstream_test
- env:
- SOURCE_RELEASE: "7.9"
- TARGET_RELEASE: "8.8"
- RHUI: "aws"
- LEAPPDATA_BRANCH: "upstream"
- LEAPP_NO_RHSM: "1"
- USE_CUSTOM_REPOS: rhui
-
-- &sanity-79to88
- <<: *sanity-abstract-7to8
- trigger: pull_request
- identifier: sanity-7.9to8.8
- tf_extra_params:
- test:
- tmt:
- plan_filter: 'tag:7to8 & tag:sanity & enabled:true'
- environments:
- - tmt:
- context:
- distro: "rhel-7.9"
- distro_target: "rhel-8.8"
- settings:
- provisioning:
- tags:
- BusinessUnit: sst_upgrades@leapp_upstream_test
- env:
- SOURCE_RELEASE: "7.9"
- TARGET_RELEASE: "8.8"
-
-- &beaker-minimal-79to88
- <<: *beaker-minimal-7to8-abstract-ondemand
- trigger: pull_request
- labels:
- - beaker-minimal
- - beaker-minimal-7.9to8.8
- - 7.9to8.8
- identifier: sanity-7.9to8.8-beaker-minimal-ondemand
- tf_extra_params:
- test:
- tmt:
- plan_filter: 'tag:7to8 & tag:partitioning & enabled:true'
- environments:
- - tmt:
- context:
- distro: "rhel-7.9"
- distro_target: "rhel-8.8"
- settings:
- provisioning:
- tags:
- BusinessUnit: sst_upgrades@leapp_upstream_test
- env:
- SOURCE_RELEASE: "7.9"
- TARGET_RELEASE: "8.8"
-
-- &kernel-rt-79to88
- <<: *kernel-rt-abstract-7to8-ondemand
- trigger: pull_request
- labels:
- - kernel-rt
- - kernel-rt-7.9to8.8
- - 7.9to8.8
- identifier: sanity-7.9to8.8-kernel-rt-ondemand
- tf_extra_params:
- test:
- tmt:
- plan_filter: 'tag:7to8 & tag:kernel-rt & enabled:true'
- environments:
- - tmt:
- context:
- distro: "rhel-7.9"
- distro_target: "rhel-8.8"
- settings:
- provisioning:
- tags:
- BusinessUnit: sst_upgrades@leapp_upstream_test
- env:
- SOURCE_RELEASE: "7.9"
- TARGET_RELEASE: "8.8"
-
# Tests: 7.9 -> 8.10
- &sanity-79to810
<<: *sanity-abstract-7to8
@@ -397,14 +299,11 @@ jobs:
# ######################### Individual tests ########################### #
# ###################################################################### #
-# Tests: 8.8 -> 9.2
-- &sanity-88to92
+# Tests: 8.10 -> 9.4
+- &sanity-810to94
<<: *sanity-abstract-8to9
trigger: pull_request
- targets:
- epel-8-x86_64:
- distros: [RHEL-8.8.0-Nightly]
- identifier: sanity-8.8to9.2
+ identifier: sanity-8.10to9.4
tf_extra_params:
test:
tmt:
@@ -412,108 +311,74 @@ jobs:
environments:
- tmt:
context:
- distro: "rhel-8.8"
- distro_target: "rhel-9.2"
- settings:
- provisioning:
- tags:
- BusinessUnit: sst_upgrades@leapp_upstream_test
- env:
- SOURCE_RELEASE: "8.8"
- TARGET_RELEASE: "9.2"
- RHSM_REPOS_EUS: "eus"
-
-- &sanity-88to92-aws
- <<: *sanity-abstract-8to9-aws
- trigger: pull_request
- targets:
- epel-8-x86_64:
- distros: [RHEL-8.8-rhui]
- identifier: sanity-8.8to9.2-aws
- tf_extra_params:
- test:
- tmt:
- plan_filter: 'tag:8to9 & tag:rhui-tier[0] & enabled:true'
- environments:
- - tmt:
- context:
- distro: "rhel-8.8"
- distro_target: "rhel-9.2"
+ distro: "rhel-8.10"
+ distro_target: "rhel-9.4"
settings:
provisioning:
- post_install_script: "#!/bin/sh\nsudo sed -i s/.*ssh-rsa/ssh-rsa/ /root/.ssh/authorized_keys"
tags:
BusinessUnit: sst_upgrades@leapp_upstream_test
env:
- SOURCE_RELEASE: "8.8"
- TARGET_RELEASE: "9.2"
- RHUI_HYPERSCALER: aws
+ SOURCE_RELEASE: "8.10"
+ TARGET_RELEASE: "9.4"
-- &beaker-minimal-88to92
+# On-demand minimal beaker tests
+- &beaker-minimal-810to94
<<: *beaker-minimal-8to9-abstract-ondemand
trigger: pull_request
labels:
- beaker-minimal
- - beaker-minimal-8.8to9.2
- - 8.8to9.2
- targets:
- epel-8-x86_64:
- distros: [RHEL-8.8.0-Nightly]
- identifier: sanity-8.8to9.2-beaker-minimal-ondemand
+ - beaker-minimal-8.10to9.4
+ - 8.10to9.4
+ identifier: sanity-8.10to9.4-beaker-minimal-ondemand
tf_extra_params:
test:
tmt:
- plan_filter: 'tag:8to9 &tag:partitioning & enabled:true'
+ plan_filter: 'tag:8to9 & tag:partitioning & enabled:true'
environments:
- tmt:
context:
- distro: "rhel-8.8"
- distro_target: "rhel-9.2"
+ distro: "rhel-8.10"
+ distro_target: "rhel-9.4"
settings:
provisioning:
- post_install_script: "#!/bin/sh\nsudo sed -i s/.*ssh-rsa/ssh-rsa/ /root/.ssh/authorized_keys"
tags:
BusinessUnit: sst_upgrades@leapp_upstream_test
env:
- SOURCE_RELEASE: "8.8"
- TARGET_RELEASE: "9.2"
- RHSM_REPOS_EUS: "eus"
+ SOURCE_RELEASE: "8.10"
+ TARGET_RELEASE: "9.4"
-- &kernel-rt-88to92
+# On-demand kernel-rt tests
+- &kernel-rt-810to94
<<: *kernel-rt-abstract-8to9-ondemand
trigger: pull_request
labels:
- kernel-rt
- - kernel-rt-8.8to9.2
- - 8.8to9.2
- identifier: sanity-8.8to9.2-kernel-rt-ondemand
- targets:
- epel-8-x86_64:
- distros: [RHEL-8.8.0-Nightly]
+ - kernel-rt-8.10to9.4
+ - 8.10to9.4
+ identifier: sanity-8.10to9.4-kernel-rt-ondemand
tf_extra_params:
test:
tmt:
- plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true'
+ plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true'
environments:
- tmt:
context:
- distro: "rhel-8.8"
- distro_target: "rhel-9.2"
+ distro: "rhel-8.10"
+ distro_target: "rhel-9.4"
settings:
provisioning:
tags:
BusinessUnit: sst_upgrades@leapp_upstream_test
env:
- SOURCE_RELEASE: "8.8"
- TARGET_RELEASE: "9.2"
- RHSM_REPOS_EUS: "eus"
+ SOURCE_RELEASE: "8.10"
+ TARGET_RELEASE: "9.4"
-# Tests: 8.10 -> 9.4
-- &sanity-810to94
+# Tests: 8.10 -> 9.5
+- &sanity-810to95
<<: *sanity-abstract-8to9
trigger: pull_request
- identifier: sanity-8.10to9.4
+ identifier: sanity-8.10to9.5
tf_extra_params:
test:
tmt:
@@ -522,24 +387,24 @@ jobs:
- tmt:
context:
distro: "rhel-8.10"
- distro_target: "rhel-9.4"
+ distro_target: "rhel-9.5"
settings:
provisioning:
tags:
BusinessUnit: sst_upgrades@leapp_upstream_test
env:
SOURCE_RELEASE: "8.10"
- TARGET_RELEASE: "9.4"
+ TARGET_RELEASE: "9.5"
# On-demand minimal beaker tests
-- &beaker-minimal-810to94
+- &beaker-minimal-810to95
<<: *beaker-minimal-8to9-abstract-ondemand
trigger: pull_request
labels:
- beaker-minimal
- - beaker-minimal-8.10to9.4
- - 8.10to9.4
- identifier: sanity-8.10to9.4-beaker-minimal-ondemand
+ - beaker-minimal-8.10to9.5
+ - 8.10to9.5
+ identifier: sanity-8.10to9.5-beaker-minimal-ondemand
tf_extra_params:
test:
tmt:
@@ -548,24 +413,24 @@ jobs:
- tmt:
context:
distro: "rhel-8.10"
- distro_target: "rhel-9.4"
+ distro_target: "rhel-9.5"
settings:
provisioning:
tags:
BusinessUnit: sst_upgrades@leapp_upstream_test
env:
SOURCE_RELEASE: "8.10"
- TARGET_RELEASE: "9.4"
+ TARGET_RELEASE: "9.5"
# On-demand kernel-rt tests
-- &kernel-rt-810to94
+- &kernel-rt-810to95
<<: *kernel-rt-abstract-8to9-ondemand
trigger: pull_request
labels:
- kernel-rt
- - kernel-rt-8.10to9.4
- - 8.10to9.4
- identifier: sanity-8.10to9.4-kernel-rt-ondemand
+ - kernel-rt-8.10to9.5
+ - 8.10to9.5
+ identifier: sanity-8.10to9.5-kernel-rt-ondemand
tf_extra_params:
test:
tmt:
@@ -574,21 +439,21 @@ jobs:
- tmt:
context:
distro: "rhel-8.10"
- distro_target: "rhel-9.4"
+ distro_target: "rhel-9.5"
settings:
provisioning:
tags:
BusinessUnit: sst_upgrades@leapp_upstream_test
env:
SOURCE_RELEASE: "8.10"
- TARGET_RELEASE: "9.4"
+ TARGET_RELEASE: "9.5"
-# Tests: 8.10 -> 9.5
-- &sanity-810to95
+# Tests: 8.10 -> 9.6
+- &sanity-810to96
<<: *sanity-abstract-8to9
trigger: pull_request
- identifier: sanity-8.10to9.5
+ identifier: sanity-8.10to9.6
tf_extra_params:
test:
tmt:
@@ -597,24 +462,24 @@ jobs:
- tmt:
context:
distro: "rhel-8.10"
- distro_target: "rhel-9.5"
+ distro_target: "rhel-9.6"
settings:
provisioning:
tags:
BusinessUnit: sst_upgrades@leapp_upstream_test
env:
SOURCE_RELEASE: "8.10"
- TARGET_RELEASE: "9.5"
+ TARGET_RELEASE: "9.6"
# On-demand minimal beaker tests
-- &beaker-minimal-810to95
+- &beaker-minimal-810to96
<<: *beaker-minimal-8to9-abstract-ondemand
trigger: pull_request
labels:
- beaker-minimal
- - beaker-minimal-8.10to9.5
- - 8.10to9.5
- identifier: sanity-8.10to9.5-beaker-minimal-ondemand
+ - beaker-minimal-8.10to9.6
+ - 8.10to9.6
+ identifier: sanity-8.10to9.6-beaker-minimal-ondemand
tf_extra_params:
test:
tmt:
@@ -623,24 +488,24 @@ jobs:
- tmt:
context:
distro: "rhel-8.10"
- distro_target: "rhel-9.5"
+ distro_target: "rhel-9.6"
settings:
provisioning:
tags:
BusinessUnit: sst_upgrades@leapp_upstream_test
env:
SOURCE_RELEASE: "8.10"
- TARGET_RELEASE: "9.5"
+ TARGET_RELEASE: "9.6"
# On-demand kernel-rt tests
-- &kernel-rt-810to95
+- &kernel-rt-810to96
<<: *kernel-rt-abstract-8to9-ondemand
trigger: pull_request
labels:
- kernel-rt
- - kernel-rt-8.10to9.5
- - 8.10to9.5
- identifier: sanity-8.10to9.5-kernel-rt-ondemand
+ - kernel-rt-8.10to9.6
+ - 8.10to9.6
+ identifier: sanity-8.10to9.6-kernel-rt-ondemand
tf_extra_params:
test:
tmt:
@@ -649,11 +514,11 @@ jobs:
- tmt:
context:
distro: "rhel-8.10"
- distro_target: "rhel-9.5"
+ distro_target: "rhel-9.6"
settings:
provisioning:
tags:
BusinessUnit: sst_upgrades@leapp_upstream_test
env:
SOURCE_RELEASE: "8.10"
- TARGET_RELEASE: "9.5"
+ TARGET_RELEASE: "9.6"
diff --git a/repos/system_upgrade/common/files/prod-certs/9.6/279.pem b/repos/system_upgrade/common/files/prod-certs/9.6/279.pem
new file mode 100644
index 00000000..a9ef267b
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.6/279.pem
@@ -0,0 +1,37 @@
+-----BEGIN CERTIFICATE-----
+MIIGZTCCBE2gAwIBAgIJALDxRLt/tVEiMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI0MDgxMjE5MDIwNVoXDTQ0MDgx
+MjE5MDIwNVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs1MzUwNTA4
+OC05ZTk5LTQyODItYmE4OS1mMjhhNjAwZWNhZWFdMIICIjANBgkqhkiG9w0BAQEF
+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
+AwEAAaOB7jCB6zAJBgNVHRMEAjAAMEMGDCsGAQQBkggJAYIXAQQzDDFSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIFBvd2VyLCBsaXR0bGUgZW5kaWFuMBUGDCsG
+AQQBkggJAYIXAgQFDAM5LjYwGQYMKwYBBAGSCAkBghcDBAkMB3BwYzY0bGUwJwYM
+KwYBBAGSCAkBghcEBBcMFXJoZWwtOSxyaGVsLTktcHBjNjRsZTAdBgNVHQ4EFgQU
+YeogtTV8r2dkOv9rCOYQeNDNH5UwHwYDVR0jBBgwFoAUlv27HEBA/0CErbIfCybB
+w2pv1nwwDQYJKoZIhvcNAQELBQADggIBACRmyYbMhmuV+w4E+Hlonlt0mooB6EF6
+h/xknuBRw/saSL+7sLfbItaxWH5euxDc/5XvII2t0Jjl+GDnAjI75xrTuN3gT88Z
+9wd1kvDVqt46GI6VKVH1SujJoJpGenfhTVwenATZwdq260RgYgM3Zv1d3I4Lu/GY
+65T//j0/8tBmgqMc6BRvIrDa1wtVUbEwH3b/jwZoeitps1hKIH9yKZV79HZ7WVdb
+otDtsAk7VKZGRjGdvYsfWZrjmyyyc5wX2AemzpnhSm1kkGvOAjSMsJ0QcrSu/5vj
+AAK64J1tDA93WKsAqDnK7tUOx6qwICllbgVmKWl/02JH8ELs/sJnsWBEigfdZmTh
+/3Q8DPNni7scYkJ5Vs0tL8pke29C1bgAYjoBiQgf/ffNunTOWgdkdFHbd9I3+aLh
+pO7qqkndEkl85xkQJrZWO35NvPD4NAwnsDrIP0oJg5mYNTB11C5SlHhllT/Iu374
+8afWtoHaB50vsqM2dtvh/UsCyGynWYc93TLsU6a4gBl19D7VAx0fiOwdD+CyweUp
+xcos6MIIuFAFUIVpD+/3w499Lw9m5dcfApl6HCyQgAoafXCJjM/aXsSsSWr2d9TF
+c6S/uA2egh4fUv8zYnlZKUvCTu8kn4Lv439wW0xyIEB/sD/gXk9e8H9KkUuKDExx
+yTSjzqnPM82N
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.6/362.pem b/repos/system_upgrade/common/files/prod-certs/9.6/362.pem
new file mode 100644
index 00000000..d7c1a6be
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.6/362.pem
@@ -0,0 +1,37 @@
+-----BEGIN CERTIFICATE-----
+MIIGdDCCBFygAwIBAgIJALDxRLt/tVE4MA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI0MDgxMjE5MDIyNFoXDTQ0MDgx
+MjE5MDIyNFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs2MjBmNzkx
+MC0xNDk5LTRmMzAtYTk3NS1hYWFiOGQyMWE1NmNdMIICIjANBgkqhkiG9w0BAQEF
+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
+AwEAAaOB/TCB+jAJBgNVHRMEAjAAMEgGDCsGAQQBkggJAYJqAQQ4DDZSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIFBvd2VyLCBsaXR0bGUgZW5kaWFuIEJldGEw
+GgYMKwYBBAGSCAkBgmoCBAoMCDkuNiBCZXRhMBkGDCsGAQQBkggJAYJqAwQJDAdw
+cGM2NGxlMCwGDCsGAQQBkggJAYJqBAQcDBpyaGVsLTkscmhlbC05LWJldGEtcHBj
+NjRsZTAdBgNVHQ4EFgQUYeogtTV8r2dkOv9rCOYQeNDNH5UwHwYDVR0jBBgwFoAU
+lv27HEBA/0CErbIfCybBw2pv1nwwDQYJKoZIhvcNAQELBQADggIBADzaMxiligMU
+vVUxGdlKgceVXcZR6TC/nACDxyRFm7JGKYC0Ncxum2RWQ10mMD1HM1xa0NVz3BLO
+a+VrZ3MGTpKuWQgN0TKIzjykxxfJMip8AVYx6UvQ4SxxZWFIVPuC0XYfYc2pOV5A
+OcO63O+R7QVvLpZ3q7tX3uAXCfWWvJkoJ+MzKCl3lEmeKAcaikcums+aOd/JwTSo
+bt5ExLgC4J1cvevH+IBCUbmN1r+xrkHNiNWjys0MIo1JsPmi1A1kDeORXPN4xXvH
+x69z9SuHrUd2iFXpMfezqZsmiaa/FP6UOKwpDyEqZGE+/aT/RBza9BeYX74vDpFI
+h0vMtx3lHE+PGh7a6kfXV2GL4IP7w5MbdZQIJ/ZS4oT/zG3E2wRnGD4+oQ3Bm/TV
+Or0IHnafxXYXgsQ6bsMsZN7BRZ8VfaEdM3IVRqVyPVWzo0kYkHZcnVQpabmCWPjc
+NUwMJDni3LfjxKreHLDQBEkwX4XoZnSq/xMHO6ppe0sZ2XgAOsw/B92ekTTEdoKZ
+dEQBkqv2FRUbMoILnNVWJp4yGMOPcTl7hrlcJjKRvKs1hKWkQKN6g4YDHCglkVfH
+ltDGkolsUYFvoygoi8VCCDfz7whn6pXmzlpk1VkzE+V1R88Tf5ygrSNWETOZMU/B
+5P07jdNriEBCZaCPq7T8odOt1cKZpVdg
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.6/363.pem b/repos/system_upgrade/common/files/prod-certs/9.6/363.pem
new file mode 100644
index 00000000..f75b478d
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.6/363.pem
@@ -0,0 +1,37 @@
+-----BEGIN CERTIFICATE-----
+MIIGZjCCBE6gAwIBAgIJALDxRLt/tVE3MA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI0MDgxMjE5MDIyNFoXDTQ0MDgx
+MjE5MDIyNFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs1MDE5NmU1
+ZC1lNDgzLTQwNDAtYjcwYS03NDg5NDliZTRjZmFdMIICIjANBgkqhkiG9w0BAQEF
+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
+AwEAAaOB7zCB7DAJBgNVHRMEAjAAMDoGDCsGAQQBkggJAYJrAQQqDChSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIEFSTSA2NCBCZXRhMBoGDCsGAQQBkggJAYJr
+AgQKDAg5LjYgQmV0YTAZBgwrBgEEAZIICQGCawMECQwHYWFyY2g2NDAsBgwrBgEE
+AZIICQGCawQEHAwacmhlbC05LHJoZWwtOS1iZXRhLWFhcmNoNjQwHQYDVR0OBBYE
+FGHqILU1fK9nZDr/awjmEHjQzR+VMB8GA1UdIwQYMBaAFJb9uxxAQP9AhK2yHwsm
+wcNqb9Z8MA0GCSqGSIb3DQEBCwUAA4ICAQBiaXwTsDt1Kz79ZJ3TnNDuX3IntXuS
+DxIGAhpgJ+ynaSULh8xL6pq5L6EtYnVzpO6T+j2ADbJlLkIRV0fMD6MMZo4YQtHH
+NofoNgJoYI4uXcCKYS2vIUw+0Br7qx8BPTb5jP+VRl9LU8W299nYOTp+vY7GQ0Ny
+hT66G+FJfo5CqHZpMTGgJbpjoP3DMpXZcARBnjQ0LhvjvcalGmPP4//tcPNwft6r
+ei8fxBvpmCXDS9/vXwiEf6jEidqq1Q6bCdL20Y1ZPY13oUEYFqrf8PhexlV1yoD4
+F4gEbVHPQ4yvH3D6xIAFE4959+H+dgMfXqn9gkUvnTMdyfzcUYGLTAib3zb4eW/J
+anzwfBAcssBzjU1v/txWMRlZI1GJFNtboAixnRksj1epE848J3bjtiw3R/Z5grFn
+dieJwjfM4AEDrpRmA5tDnv5z73k1djJbacL7fTIyTuSnDbjH2J5PtCAvWTLYq/kP
+h8E3sJ9zXP2nJMBRgQiZJY98bPKLT63ngRScI+CZs1fLvaoCq0o+qkcfnDEja3aH
+TQYXHVZblA4TYnD8Vh8gKwCt8+1WF5C9BGcMmKvozuuIaIJgT21V+DLzfTESpZz7
+lcPKk/3dBFtFGOdA4SQ4o/dxItJ0Eay1SlOI9xL9KgTNqv6ftA+9kxZ0MSPwO7eG
+b5Am4gNTK734uQ==
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.6/419.pem b/repos/system_upgrade/common/files/prod-certs/9.6/419.pem
new file mode 100644
index 00000000..e2d3ee5b
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.6/419.pem
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIGVzCCBD+gAwIBAgIJALDxRLt/tVEhMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI0MDgxMjE5MDIwNVoXDTQ0MDgx
+MjE5MDIwNVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFtkN2E2ZDhi
+Mi0yZjMzLTRhYzMtYmM5Ni1mMjU5MTNmZTQxNWNdMIICIjANBgkqhkiG9w0BAQEF
+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
+AwEAAaOB4DCB3TAJBgNVHRMEAjAAMDUGDCsGAQQBkggJAYMjAQQlDCNSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIEFSTSA2NDAVBgwrBgEEAZIICQGDIwIEBQwD
+OS42MBkGDCsGAQQBkggJAYMjAwQJDAdhYXJjaDY0MCcGDCsGAQQBkggJAYMjBAQX
+DBVyaGVsLTkscmhlbC05LWFhcmNoNjQwHQYDVR0OBBYEFGHqILU1fK9nZDr/awjm
+EHjQzR+VMB8GA1UdIwQYMBaAFJb9uxxAQP9AhK2yHwsmwcNqb9Z8MA0GCSqGSIb3
+DQEBCwUAA4ICAQCJqWcTJezGVGxsNvFkbsrvbHhJBuBMeDZZuOLaXaQVyfNwYRS2
+2k/oUhhQQMfiDiaLkz7yz0Zw5clC/K5G6Sg9+nWDA57lsZuNV5CnSBYOJf2jY2fK
+ue/1M75Y4fJAKtBxpvkFaIaKyMQ/0VC67OFYtbBZEOuwIpQh9aPFHnrh2WnpcUvJ
+B93O0fsRjHK30E7jF8ncNmhevMLvVlxH0JjfbvcU3dGG964K41tFiozshvnAGFce
+kFzxVVYQL3ZKycqonwFr3BbzgKwx5EXUFBg/ax694aijeeVA6yuQXWJvV42IjUeW
+vn+dvRrHh2fv4MXuyc+oljbXaEZE7m9gtWBtUEBHqWoQz6rQ25uZylnK+SDWE5bt
+xM+1qGUSf90VvyFO3fu1qeVVr0LbnMAgO9YnJjLRQax0mgj3tZTRvM72W4hfBy36
+ndYnJE2le5xYWVl1Hd29dil70cokj5hN8nQI9eStfcOvs9Vw2ngIL/H3+QTRS/NO
+l7MHQXbriLAaHavED6B50dEfw8pQXybEju4Rs+nDgm5hdE7FjbVflVQejSjyHIMd
+AQnwrDSMPRezCJFHQeB0t7oaHpAHECc2zBpvcvy7qCN2Z08h6jdzfrp15UDkHEcy
+Qa9dtYRUthI3pjGGu7WTPwX9y0veot3EZRnEzeIprIsHcMKfmkMg4HRJ3A==
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.6/433.pem b/repos/system_upgrade/common/files/prod-certs/9.6/433.pem
new file mode 100644
index 00000000..ac588c1c
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.6/433.pem
@@ -0,0 +1,37 @@
+-----BEGIN CERTIFICATE-----
+MIIGaTCCBFGgAwIBAgIJALDxRLt/tVE5MA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI0MDgxMjE5MDIyNFoXDTQ0MDgx
+MjE5MDIyNFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs4NzcwNzQ4
+MS02MGEwLTQwYTUtYWVhMi0xNjNmODUyMzI3ZTFdMIICIjANBgkqhkiG9w0BAQEF
+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
+AwEAAaOB8jCB7zAJBgNVHRMEAjAAMEEGDCsGAQQBkggJAYMxAQQxDC9SZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIElCTSB6IFN5c3RlbXMgQmV0YTAaBgwrBgEE
+AZIICQGDMQIECgwIOS42IEJldGEwFwYMKwYBBAGSCAkBgzEDBAcMBXMzOTB4MCoG
+DCsGAQQBkggJAYMxBAQaDBhyaGVsLTkscmhlbC05LWJldGEtczM5MHgwHQYDVR0O
+BBYEFGHqILU1fK9nZDr/awjmEHjQzR+VMB8GA1UdIwQYMBaAFJb9uxxAQP9AhK2y
+HwsmwcNqb9Z8MA0GCSqGSIb3DQEBCwUAA4ICAQC57eNKMpTQuIEEoYXkhD0oYkgD
+RzDFyqKZgyK0IdOy6t0d9GcMY/nI/uYQltUC+HWBUJWYkHc84xjfP3ITfuHWP8KP
+3qdXLPwTDcNVUGtLgXIfEz4FEM4OVwfM2X0jIcLfkDmZzffWjHgBpAUfZM6fBvXl
+soPJ+s4/vIUFNbVtcJh9iw4glt/GFBOX/bNPV9kniAAYuyabW43X7GxfREJY18Db
++Fv7c+z2eM4fQFpLkSEZwsNN68G4OHDC7tWsYtCRocipWGs6lN5MBNXC0q90ds5O
+kOLRfHKOLFqbZnBNdgSOlsf+ENH3exUhoDvZE0gnAVALABVv6PCtsHn2rPLonsrB
+l9ZKqCVVDpQMDXmZC79XKB0nVrNQ7qYorCVnYqnTAkuvw4BuXpKASaSCDSRWLQN0
+H89phUM64VnyPD5pBTw+YJURDm8cwD5e6HaXhKzG1ca9PWL+RVxedB4Rl2VG00fE
+QUBbHZktH+H1P3MtqALB7IUav4IuBgdF27W55GExCgshRuyV6/VHmYiD+L52XxCH
+71mdWTp6JR1/hMYKPLhc5/ESBoMpqMXa4UWIOtMWiafWaDS4Cib+uyIIzCgqW8ee
+t+yQtCs7MUUd6t87XP7/TTQJe6e0JsyDnME9br0E4g57Y8cXjOILGg/ihqBFOGt1
+vhbX7w/YRjVpwJhi9w==
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.6/479.pem b/repos/system_upgrade/common/files/prod-certs/9.6/479.pem
new file mode 100644
index 00000000..c2bac3ee
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.6/479.pem
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIGVTCCBD2gAwIBAgIJALDxRLt/tVEkMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI0MDgxMjE5MDIwNVoXDTQ0MDgx
+MjE5MDIwNVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFtjZWRlZTRi
+My0xOGFhLTQwMzMtYjE3OS01OTkwMjk2OGFkZjhdMIICIjANBgkqhkiG9w0BAQEF
+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
+AwEAAaOB3jCB2zAJBgNVHRMEAjAAMDUGDCsGAQQBkggJAYNfAQQlDCNSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIHg4Nl82NDAVBgwrBgEEAZIICQGDXwIEBQwD
+OS42MBgGDCsGAQQBkggJAYNfAwQIDAZ4ODZfNjQwJgYMKwYBBAGSCAkBg18EBBYM
+FHJoZWwtOSxyaGVsLTkteDg2XzY0MB0GA1UdDgQWBBRh6iC1NXyvZ2Q6/2sI5hB4
+0M0flTAfBgNVHSMEGDAWgBSW/bscQED/QIStsh8LJsHDam/WfDANBgkqhkiG9w0B
+AQsFAAOCAgEADoQWjROe9jPuYIB5cW7URXgDPVK3cpGnlKxEINdXT+dL7N2qNijy
+BcV0+SCHmswZ+F7OTozyGzGbJCrSHZrvF2lp2L8YddvkIFsWqrPkseU/0/oog5Qf
+ULA5WzV12u0Ra/DWinhUq6NZWLAt/FvJ7+WHPdJ7B0WsiA751l7crvfKfen93Xzb
+0eakHrotcPi9YH/Jez8xjs4Wc3ra/7CbLqpsHuWzgzwJabiuLaf5PK95VVedzQIx
+lT+N6JydFIkXkofQJwTptPTh9lDbZDe33/dg5zX3l9CAQK7JYZKYoUzLirM2LO7s
+TGejW1mKGB+O23bQBGRkLoD4kbY17UMCFcKD7mZSO6laoOBOk8NYUxTDjT4e3cUB
+dHw5YVrj+BSHzgOGpc1KrmuBiOWZrZf4iaFuz4Kr88tL6TT6IH5UmfP3fuvvMyXs
+OWqTAfr/CPeJjLhjmbEagkS0kpgkyXodY8sq2Ph5vpn0o1QYNfy6KRtD/m6YaF7G
+SDkWEY5li338SROIFV6X8lKEzHMfQZzhqQWoJWQlFuAdByKrxz8x1RJZTkIT82h6
+uM/GO3v5xT5UXXa2x1X0JtS9rPGdnmAKQLJJz07s+2WCRqCFuBxJsV+aWCRLsab4
+jpo1NG0RH0KorjvBBMLx8bVSbl4YFJdOcomlRVrsC2iMUwl+PH5Ah4g=
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.6/486.pem b/repos/system_upgrade/common/files/prod-certs/9.6/486.pem
new file mode 100644
index 00000000..e130d5dc
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.6/486.pem
@@ -0,0 +1,37 @@
+-----BEGIN CERTIFICATE-----
+MIIGZDCCBEygAwIBAgIJALDxRLt/tVE6MA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI0MDgxMjE5MDIyNFoXDTQ0MDgx
+MjE5MDIyNFowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFsyMTM1ODk1
+Yi1mMDRiLTRlNjUtOWYzMC04MmRlYmQ0Njc0NjNdMIICIjANBgkqhkiG9w0BAQEF
+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
+AwEAAaOB7TCB6jAJBgNVHRMEAjAAMDoGDCsGAQQBkggJAYNmAQQqDChSZWQgSGF0
+IEVudGVycHJpc2UgTGludXggZm9yIHg4Nl82NCBCZXRhMBoGDCsGAQQBkggJAYNm
+AgQKDAg5LjYgQmV0YTAYBgwrBgEEAZIICQGDZgMECAwGeDg2XzY0MCsGDCsGAQQB
+kggJAYNmBAQbDBlyaGVsLTkscmhlbC05LWJldGEteDg2XzY0MB0GA1UdDgQWBBRh
+6iC1NXyvZ2Q6/2sI5hB40M0flTAfBgNVHSMEGDAWgBSW/bscQED/QIStsh8LJsHD
+am/WfDANBgkqhkiG9w0BAQsFAAOCAgEAHhaEBX5fhB2zweFT0SuLB3OB11aE3Tjy
+q0dNxm8t3d5glgtratmAkPD+6Ct0gkdoGJ8GcBsFVzzM2ig236YOy8dCPVWBzLtd
+Oni5DpjSqnMX6yq4PuSViF1w+9pCKPJqzQK/u/F0njkwdu0mAwc1fkiCR0B6oB7s
+m1rHhuyC4PkAj5RYQ6+M4MpGfce0HSpUCzlnAlHYgjvmT3qCUvlEYLPg4/Z+wihZ
+1xdhhhoLNi43IdfmFQlTSNZqTwLB780qzHzi+UYgWg7wflTn8m1LAOlad5HWJFnE
+y6JnX+c+vfzvxFBSZABKJsZY/YKIAV14g42XL8zhIpJHtdYnUaveo1M90UAvSECP
+RAnPUIKWM1VYKfa2PpEC2/157KOQ4y7BUrAUlqs1qh8FoGCZYHMRmgYqHoycIvw+
+gs1gH77O9EyOMMjwyQqBUnzylJfhjkEgINDIGbPEiQpI33TBniw5yMRZ74XWOoi3
+rOIiaYxHBDpJ25LwbZsJOQUPmIKBTOpLK9N4IK7UvA7O8HCEEJz2+VLVf2svaoU1
+fd7MUYh9aCjEocKRQknxScJLVBXcFRy0I+tfVQwkcLqWCOrp3qpNmYwhC+C0vYtR
+/LZ58vf60+m+mKUmEJWF6X7QGFZptsc0ERme6sE1E41iNAIq3BsBMU/hQIVP50k4
+T3KefQomWk4=
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/prod-certs/9.6/72.pem b/repos/system_upgrade/common/files/prod-certs/9.6/72.pem
new file mode 100644
index 00000000..35927fbc
--- /dev/null
+++ b/repos/system_upgrade/common/files/prod-certs/9.6/72.pem
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIGVjCCBD6gAwIBAgIJALDxRLt/tVEjMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD
+VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI
+YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk
+IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ
+ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI0MDgxMjE5MDIwNVoXDTQ0MDgx
+MjE5MDIwNVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs0ZDhmOTky
+Yy04NDBjLTQ4MzYtODVkOS0zYWI5YjA1ZjViY2FdMIICIjANBgkqhkiG9w0BAQEF
+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
+AwEAAaOB3zCB3DAJBgNVHRMEAjAAMDsGCysGAQQBkggJAUgBBCwMKlJlZCBIYXQg
+RW50ZXJwcmlzZSBMaW51eCBmb3IgSUJNIHogU3lzdGVtczAUBgsrBgEEAZIICQFI
+AgQFDAM5LjYwFgYLKwYBBAGSCAkBSAMEBwwFczM5MHgwJAYLKwYBBAGSCAkBSAQE
+FQwTcmhlbC05LHJoZWwtOS1zMzkweDAdBgNVHQ4EFgQUYeogtTV8r2dkOv9rCOYQ
+eNDNH5UwHwYDVR0jBBgwFoAUlv27HEBA/0CErbIfCybBw2pv1nwwDQYJKoZIhvcN
+AQELBQADggIBANOzzfUKjlJsgJWUryjKfzPYISkCZXauHqBcST4N1HP1GA8tmMXi
+bgh14+l7ZO8EloFvEGANsX2ffMfauuJx2NV6ks07NHWuM7W9kghDe5ZccrJCz88E
+1zdvyWae5oSvTwfnvR/b63duOhs88u7NCQN2+n+pmJA0dPWbGTaIp3n4kJg8YKnd
+O8Nct2doNS+1rrLpRmVKQy/E7fAXQzt1Bxqs2hORqbgffiSE9a+4akitY97GXRBm
+nOO2DkyEW0xPtdy3zDvL7o7b1B0gdMOwqEolgGuDFsrfD+7ofpwOWjS+83gF6hMP
+5YVD3sugu6xzCx6y7Yl/BfX4qvvT4YHtYob5rQA/t7JY4u4ryadkUxQLMEccMsyS
+pKZQ8KFC5ZNJVK/ievkcBCsBlulbRftVJGF3TA2Hl2aBuMhGdUR5y/Q89WHUzeV6
+U6AVzyEsvIJguswvKvFAyHwNuViCfFCkjNkJolvd/g03OSy1A7piQaU20QyltWmx
+FILCR/DBUbCWIzKTfkLr93TbV2b1AH9uRW1SAGrftuevVXrNemWIwq1x/VgjDm3o
+nk637pnEfZZzX8T2gO5z5yjlP0PR4s7hKkmp3TmAeG9015pFxPnD3AMI261srQ+c
+KZBdIc5UseQo/4KvRKZ1CzxPh0WjJCzc/C/TKzIlEdELq/rnKGuqHKB9
+-----END CERTIFICATE-----
diff --git a/repos/system_upgrade/common/files/upgrade_paths.json b/repos/system_upgrade/common/files/upgrade_paths.json
index 5399f148..cc9dcdb5 100644
--- a/repos/system_upgrade/common/files/upgrade_paths.json
+++ b/repos/system_upgrade/common/files/upgrade_paths.json
@@ -1,19 +1,17 @@
{
"default": {
- "7.9": ["8.8", "8.10"],
- "8.8": ["9.2"],
- "8.10": ["9.4", "9.5"],
+ "7.9": ["8.10"],
+ "8.10": ["9.4", "9.5", "9.6"],
"9.6": ["10.0"],
- "7": ["8.8", "8.10"],
- "8": ["9.2", "9.4", "9.5"],
+ "7": ["8.10"],
+ "8": ["9.4", "9.5", "9.6"],
"9": ["10.0"]
},
"saphana": {
- "7.9": ["8.10", "8.8"],
- "7": ["8.10", "8.8"],
- "8.8": ["9.2"],
- "8.10": ["9.4"],
- "8": ["9.4", "9.2"],
+ "7.9": ["8.10"],
+ "7": ["8.10"],
+ "8.10": ["9.6", "9.4"],
+ "8": ["9.6", "9.4"],
"9.6": ["10.0"],
"9": ["10.0"]
}
diff --git a/repos/system_upgrade/common/libraries/config/version.py b/repos/system_upgrade/common/libraries/config/version.py
index 152d9112..d710a647 100644
--- a/repos/system_upgrade/common/libraries/config/version.py
+++ b/repos/system_upgrade/common/libraries/config/version.py
@@ -18,7 +18,7 @@ OP_MAP = {
_SUPPORTED_VERSIONS = {
# Note: 'rhel-alt' is detected when on 'rhel' with kernel 4.x
'7': {'rhel': ['7.9'], 'rhel-alt': [], 'rhel-saphana': ['7.9']},
- '8': {'rhel': ['8.8', '8.10'], 'rhel-saphana': ['8.8', '8.10']},
+ '8': {'rhel': ['8.10'], 'rhel-saphana': ['8.10']},
'9': {'rhel': ['9.4', '9.5', '9.6'], 'rhel-saphana': ['9.4', '9.6']},
}
--
2.47.0

View File

@ -0,0 +1,166 @@
From 2646484407bef15688fb4838c2f61d06f2098f81 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Wed, 30 Apr 2025 12:54:22 +0200
Subject: [PATCH 40/43] Fix parsing of the kernel cmdline
Original parsing has been splitting string tokens by "=" without a
limit, means that e.g.
root=UUID=some-id
has been split to
(root, UUID, some-id)
and and stored just "root" and "UUID" strings in the parsed msg,
instead of "root" and "UUID=some-id".
So split the key=value just based on the first occurence of "="
instead.
JIRA: RHELMISC-12490
Co-Authored-By: Karolina Kula <kkula@redhat.com>
---
.../common/actors/scankernelcmdline/actor.py | 16 ++---
.../libraries/scankernelcmdline.py | 23 +++++++
.../tests/test_scankernelcmdline.py | 67 +++++++++++++++++++
3 files changed, 94 insertions(+), 12 deletions(-)
create mode 100644 repos/system_upgrade/common/actors/scankernelcmdline/libraries/scankernelcmdline.py
create mode 100644 repos/system_upgrade/common/actors/scankernelcmdline/tests/test_scankernelcmdline.py
diff --git a/repos/system_upgrade/common/actors/scankernelcmdline/actor.py b/repos/system_upgrade/common/actors/scankernelcmdline/actor.py
index 9f8fef30..2f1a5ae2 100644
--- a/repos/system_upgrade/common/actors/scankernelcmdline/actor.py
+++ b/repos/system_upgrade/common/actors/scankernelcmdline/actor.py
@@ -1,12 +1,12 @@
from leapp.actors import Actor
-from leapp.libraries.stdlib import run
-from leapp.models import KernelCmdline, KernelCmdlineArg
+from leapp.libraries.actor import scankernelcmdline
+from leapp.models import KernelCmdline
from leapp.tags import FactsPhaseTag, IPUWorkflowTag
class ScanKernelCmdline(Actor):
"""
- No documentation has been provided for the scan_kernel_cmdline actor.
+ Scan the kernel command line of the booted system.
"""
name = 'scan_kernel_cmdline'
@@ -15,12 +15,4 @@ class ScanKernelCmdline(Actor):
tags = (FactsPhaseTag, IPUWorkflowTag)
def process(self):
- cmdline = run(['cat', '/proc/cmdline'])['stdout'].strip()
- parameters = []
- for parameter in cmdline.split(' '):
- if '=' in parameter:
- kv = parameter.split('=')
- parameters.append(KernelCmdlineArg(key=kv[0], value=kv[1]))
- else:
- parameters.append(KernelCmdlineArg(key=parameter))
- self.produce(KernelCmdline(parameters=parameters))
+ scankernelcmdline.parse_cmdline_input()
diff --git a/repos/system_upgrade/common/actors/scankernelcmdline/libraries/scankernelcmdline.py b/repos/system_upgrade/common/actors/scankernelcmdline/libraries/scankernelcmdline.py
new file mode 100644
index 00000000..9cffa70e
--- /dev/null
+++ b/repos/system_upgrade/common/actors/scankernelcmdline/libraries/scankernelcmdline.py
@@ -0,0 +1,23 @@
+from leapp.libraries.stdlib import api, CalledProcessError, run
+from leapp.models import KernelCmdline, KernelCmdlineArg
+
+
+def get_cmdline_input():
+ try:
+ cmdline_input = run(['cat', '/proc/cmdline'])['stdout'].strip()
+ return cmdline_input
+ except (OSError, CalledProcessError):
+ api.current_logger().debug('Executing `cat /proc/cmdline` failed', exc_info=True)
+ return ''
+
+
+def parse_cmdline_input():
+ cmdline = get_cmdline_input()
+ parameters = []
+ for parameter in cmdline.split(' '):
+ if '=' in parameter:
+ kv = parameter.split('=', 1)
+ parameters.append(KernelCmdlineArg(key=kv[0], value=kv[1]))
+ else:
+ parameters.append(KernelCmdlineArg(key=parameter))
+ api.produce(KernelCmdline(parameters=parameters))
diff --git a/repos/system_upgrade/common/actors/scankernelcmdline/tests/test_scankernelcmdline.py b/repos/system_upgrade/common/actors/scankernelcmdline/tests/test_scankernelcmdline.py
new file mode 100644
index 00000000..ff79054f
--- /dev/null
+++ b/repos/system_upgrade/common/actors/scankernelcmdline/tests/test_scankernelcmdline.py
@@ -0,0 +1,67 @@
+import pytest
+
+from leapp.libraries.actor import scankernelcmdline
+from leapp.libraries.common.testutils import CurrentActorMocked, produce_mocked
+from leapp.libraries.stdlib import api, CalledProcessError
+from leapp.models import KernelCmdline, KernelCmdlineArg
+
+
+def mock_cmd_output():
+ expected_cmd_output = (
+ 'BOOT_IMAGE=(hd0,msdos1)/vmlinuz-xxx root=UUID=some_uid ro console=tty0'
+ ' console=ttyS0,115200 rd_NO_PLYMOUTH biosdevname=0 net.ifnames=0 crashkernel=auto'
+ )
+ return expected_cmd_output
+
+
+def test_cmdline_output(monkeypatch):
+
+ monkeypatch.setattr(scankernelcmdline, 'get_cmdline_input', mock_cmd_output)
+ current_actor = CurrentActorMocked(src_ver='8.10', dst_ver='9.6')
+ monkeypatch.setattr(api, 'current_actor', current_actor)
+ monkeypatch.setattr(api, 'produce', produce_mocked())
+
+ scankernelcmdline.parse_cmdline_input()
+
+ expected_params = [KernelCmdlineArg(key=k, value=v) for k, v in [
+ ('BOOT_IMAGE', '(hd0,msdos1)/vmlinuz-xxx'),
+ ('root', 'UUID=some_uid'),
+ ('ro', None),
+ ('console', 'tty0'),
+ ('console', 'ttyS0,115200'),
+ ('rd_NO_PLYMOUTH', None),
+ ('biosdevname', '0'),
+ ('net.ifnames', '0'),
+ ('crashkernel', 'auto')]]
+
+ expected_output_msg = KernelCmdline(parameters=expected_params)
+ assert api.produce.model_instances
+ assert expected_output_msg == api.produce.model_instances[0]
+
+
+def test_cmdline_content(monkeypatch):
+
+ def run_mocked(cmd, **kwargs):
+ assert cmd == ['cat', '/proc/cmdline']
+ output = mock_cmd_output()
+ return {'stdout': output}
+
+ monkeypatch.setattr(scankernelcmdline, 'run', run_mocked)
+ cmd_output = scankernelcmdline.get_cmdline_input()
+ expected_cmd_output = mock_cmd_output()
+
+ assert cmd_output == expected_cmd_output
+
+
+@pytest.mark.parametrize('is_os_error', [True, False])
+def test_cmdline_run_failed(monkeypatch, is_os_error):
+
+ def run_mocked_error(cmd, **kwargs):
+ assert cmd == ['cat', '/proc/cmdline']
+ if is_os_error:
+ raise OSError('OSError raised')
+ raise CalledProcessError("CalledProcessError raised", cmd, "result")
+
+ monkeypatch.setattr(scankernelcmdline, 'run', run_mocked_error)
+ cmd_output = scankernelcmdline.get_cmdline_input()
+ assert cmd_output == ''
--
2.49.0

View File

@ -1,29 +0,0 @@
From f50e3474a619ed338c2514933303320d986e6ffe Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Thu, 14 Nov 2024 16:26:55 +0100
Subject: [PATCH 40/40] spec: drop the /etc/leapp/actor_confid.d dir
The directory should be provided by the framework. leapp-repository
should provide only a content inside if any present.
---
packaging/leapp-repository.spec | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/packaging/leapp-repository.spec b/packaging/leapp-repository.spec
index 2bb52505..6676d907 100644
--- a/packaging/leapp-repository.spec
+++ b/packaging/leapp-repository.spec
@@ -250,9 +250,7 @@ install -m 0755 -d %{buildroot}%{_sysconfdir}/leapp/files/
install -m 0644 etc/leapp/transaction/* %{buildroot}%{_sysconfdir}/leapp/transaction
install -m 0644 etc/leapp/files/* %{buildroot}%{_sysconfdir}/leapp/files
-# Actor configuration dir
-install -m 0755 -d %{buildroot}%{_sysconfdir}/leapp/actor_conf.d/
-# uncomment to install existing configs
+# uncomment to install existing configs if any exists
#install -m 0644 etc/leapp/actor_conf.d/* %%{buildroot}%%{_sysconfdir}/leapp/actor_conf.d
# install CLI commands for the leapp utility on the expected path
--
2.47.0

View File

@ -1,25 +0,0 @@
From 9c07443b0148139b511bcd52ecac294c86a15826 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Wed, 16 Oct 2024 09:17:17 +0000
Subject: [PATCH 41/53] chore(deps): update dependency ubuntu to v24
---
.github/workflows/reuse-copr-build.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/reuse-copr-build.yml b/.github/workflows/reuse-copr-build.yml
index 3cf06254..c6702e1a 100644
--- a/.github/workflows/reuse-copr-build.yml
+++ b/.github/workflows/reuse-copr-build.yml
@@ -16,7 +16,7 @@ jobs:
reusable_workflow_copr_build_job:
# This job only runs for '/rerun' pull request comments by owner, member, or collaborator of the repo/organization.
name: Build copr builds for tft tests
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
outputs:
artifacts: ${{ steps.gen_artifacts.outputs.artifacts }}
if: |
--
2.47.1

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,74 +0,0 @@
From 3c3421a0f155fe3bdfaee74c5345e86874684a09 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Tue, 19 Nov 2024 10:56:50 +0100
Subject: [PATCH 42/53] feat(net-naming-scheme): enable by default
This commit enables the use of net.naming-scheme for 8>9 upgrades by
default. The previously used environmental variablel
LEAPP_USE_NET_NAMING_SCHEMES is replaced with
LEAPP_DISABLE_NET_NAMING_SCHEMES with inverse semantics.
---
.../libraries/persistentnetnamesconfig.py | 11 ++++++++---
.../libraries/emit_net_naming.py | 4 ++--
.../tests/test_emit_net_naming_scheme.py | 4 ++--
3 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/repos/system_upgrade/common/actors/persistentnetnamesconfig/libraries/persistentnetnamesconfig.py b/repos/system_upgrade/common/actors/persistentnetnamesconfig/libraries/persistentnetnamesconfig.py
index b2c7f5ff..c90d13f2 100644
--- a/repos/system_upgrade/common/actors/persistentnetnamesconfig/libraries/persistentnetnamesconfig.py
+++ b/repos/system_upgrade/common/actors/persistentnetnamesconfig/libraries/persistentnetnamesconfig.py
@@ -39,9 +39,14 @@ def generate_link_file(interface):
@suppress_deprecation(InitrdIncludes)
def process():
- if get_env('LEAPP_USE_NET_NAMING_SCHEMES', '0') == '1' and version.get_target_major_version() == '9':
- # We can use this only for 8>9, for now
- api.current_logger().info('Skipping generation of .link files renaming NICs as LEAPP_USE_NET_NAMING_SCHEMES=1')
+ are_net_schemes_enabled = get_env('LEAPP_DISABLE_NET_NAMING_SCHEMES', '0') != '1'
+ is_upgrade_8to9 = version.get_target_major_version() == '9'
+
+ if are_net_schemes_enabled and is_upgrade_8to9:
+ # For 8>9 we are using net.naming_scheme kernel arg by default - do not generate link files
+ msg = ('Skipping generation of .link files renaming NICs as net.naming-scheme '
+ '{LEAPP_DISABLE_NET_NAMING_SCHEMES != 1} is enabled and upgrade is 8>9')
+ api.current_logger().info(msg)
return
if get_env('LEAPP_NO_NETWORK_RENAMING', '0') == '1':
diff --git a/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/libraries/emit_net_naming.py b/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/libraries/emit_net_naming.py
index 726bb459..bab62a56 100644
--- a/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/libraries/emit_net_naming.py
+++ b/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/libraries/emit_net_naming.py
@@ -44,9 +44,9 @@ def is_net_scheme_compatible_with_current_cmdline():
def emit_msgs_to_use_net_naming_schemes():
- is_env_var_set = get_env('LEAPP_USE_NET_NAMING_SCHEMES', '0') == '1'
+ is_feature_enabled = get_env('LEAPP_DISABLE_NET_NAMING_SCHEMES', '0') != '1'
is_upgrade_8to9 = version.get_target_major_version() == '9'
- is_net_naming_enabled_and_permitted = is_env_var_set and is_upgrade_8to9
+ is_net_naming_enabled_and_permitted = is_feature_enabled and is_upgrade_8to9
if not is_net_naming_enabled_and_permitted:
return
diff --git a/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/tests/test_emit_net_naming_scheme.py b/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/tests/test_emit_net_naming_scheme.py
index 7a5eeba5..acf72241 100644
--- a/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/tests/test_emit_net_naming_scheme.py
+++ b/repos/system_upgrade/el8toel9/actors/emit_net_naming_scheme/tests/test_emit_net_naming_scheme.py
@@ -51,11 +51,11 @@ def test_is_net_scheme_compatible_with_current_cmdline(monkeypatch, kernel_args,
]
)
def test_emit_msgs_to_use_net_naming_schemes(monkeypatch, is_net_scheme_enabled, is_current_cmdline_compatible):
- envvar_value = '1' if is_net_scheme_enabled else '0'
+ envvar_value = '0' if is_net_scheme_enabled else '1'
mocked_actor = CurrentActorMocked(src_ver='8.10',
dst_ver='9.5',
- envars={'LEAPP_USE_NET_NAMING_SCHEMES': envvar_value})
+ envars={'LEAPP_DISABLE_NET_NAMING_SCHEMES': envvar_value})
monkeypatch.setattr(api, 'current_actor', mocked_actor)
monkeypatch.setattr(api, 'produce', produce_mocked())
--
2.47.1

View File

@ -1,48 +0,0 @@
From 1a0183b1a43e42891199efed9bd0891a24224142 Mon Sep 17 00:00:00 2001
From: David Kubek <dkubek@redhat.com>
Date: Wed, 8 Jan 2025 12:05:57 +0100
Subject: [PATCH 43/53] Fix unreadable output in upgrade log
This commit resolves an issue where unwanted escape sequences (e.g.,
ANSI codes) appear in the output of certain commands like `dnf` during
upgrades.
The issue arises because, starting with version 242, `systemd-nspawn`
introduced new pseudo-TTY capabilities (see the `Input/Output Options`
section in `systemd-nspawn(1)`). As a result, commands run within
container may include these escape sequences.
To address this, pseudo-TTY support is explicitly disabled in
`systemd-nspawn` for upgrades on RHEL9 and later.
JIRA: RHEL-69829
---
repos/system_upgrade/common/libraries/mounting.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/repos/system_upgrade/common/libraries/mounting.py b/repos/system_upgrade/common/libraries/mounting.py
index a546e9d0..2eb19d31 100644
--- a/repos/system_upgrade/common/libraries/mounting.py
+++ b/repos/system_upgrade/common/libraries/mounting.py
@@ -5,7 +5,7 @@ import shutil
from collections import namedtuple
from leapp.libraries.common.config import get_all_envs
-from leapp.libraries.common.config.version import get_source_major_version
+from leapp.libraries.common.config.version import get_source_major_version, matches_source_version
from leapp.libraries.stdlib import api, CalledProcessError, run
# Using ALWAYS_BIND will crash the upgrade process if the file does not exist.
@@ -88,6 +88,9 @@ class IsolationType(object):
# in such a case, just add line into the previous solution..
# TODO: the same about --capability=all
final_cmd += ['--keep-unit', '--capability=all']
+ if matches_source_version('>= 9.0'):
+ # Disable pseudo-TTY in container
+ final_cmd += ['--pipe']
return final_cmd + ['-D', self.target] + binds + setenvs + cmd
class CHROOT(_Implementation):
--
2.47.1

View File

@ -0,0 +1,28 @@
From 6c205281850c28068edc7fc5ab453c65398b7054 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Fri, 30 May 2025 18:28:25 +0200
Subject: [PATCH 43/43] unit-tests: suppress deprecation warning for
is_rhel_alt()
The deprecation warning is not wanted in unit-tests. Supress it.
Signed-off-by: Petr Stodulka <pstodulk@redhat.com>
---
.../system_upgrade/common/libraries/config/tests/test_version.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/repos/system_upgrade/common/libraries/config/tests/test_version.py b/repos/system_upgrade/common/libraries/config/tests/test_version.py
index 420571c0..d51f8098 100644
--- a/repos/system_upgrade/common/libraries/config/tests/test_version.py
+++ b/repos/system_upgrade/common/libraries/config/tests/test_version.py
@@ -108,6 +108,7 @@ def test_matches_target_version(monkeypatch, result, version_list):
(False, '4.14.0-100.8.2.el8.x86_64', 'rhel', '8.1'),
(False, '4.14.0-100.8.2.el9.x86_64', 'rhel', '9.1'),
])
+@suppress_deprecation(version.is_rhel_alt)
def test_is_rhel_alt(monkeypatch, result, kernel, release_id, src_ver):
monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(src_ver=src_ver, kernel=kernel,
release_id=release_id))
--
2.49.0

View File

@ -0,0 +1,267 @@
From c7ea9fc29989a37071bf6355828328910b6b5e1d Mon Sep 17 00:00:00 2001
From: Daniel Diblik <ddiblik@redhat.com>
Date: Tue, 17 Jun 2025 15:21:15 +0200
Subject: [PATCH 44/66] Remove obsolete workflows
* tmt-tests.yml and reuse-copr-build.yml were replaced by the Packit
workflows ages ago
* removed the obsolete workflows
Signed-off-by: Daniel Diblik <ddiblik@redhat.com>
---
.github/workflows/reuse-copr-build.yml | 163 -------------------------
.github/workflows/tmt-tests.yml | 72 -----------
2 files changed, 235 deletions(-)
delete mode 100644 .github/workflows/reuse-copr-build.yml
delete mode 100644 .github/workflows/tmt-tests.yml
diff --git a/.github/workflows/reuse-copr-build.yml b/.github/workflows/reuse-copr-build.yml
deleted file mode 100644
index a772fb64..00000000
--- a/.github/workflows/reuse-copr-build.yml
+++ /dev/null
@@ -1,163 +0,0 @@
-name: reuse-copr-build@TF
-
-on:
- workflow_call:
- secrets:
- FEDORA_COPR_LOGIN:
- required: true
- FEDORA_COPR_TOKEN:
- required: true
- outputs:
- artifacts:
- description: "A string with test artifacts to install in tft test env"
- value: ${{ jobs.reusable_workflow_copr_build_job.outputs.artifacts }}
-
-jobs:
- reusable_workflow_copr_build_job:
- # This job only runs for '/rerun' pull request comments by owner, member, or collaborator of the repo/organization.
- name: Build copr builds for tft tests
- runs-on: ubuntu-24.04
- outputs:
- artifacts: ${{ steps.gen_artifacts.outputs.artifacts }}
- if: |
- github.event.issue.pull_request
- && startsWith(github.event.comment.body, '/rerun')
- && contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
- steps:
- - name: Update repository
- id: repo_update
- run: sudo apt-get update
-
- - name: Install necessary deps
- id: deps_install
- run: sudo apt-get install -y libkrb5-dev
-
- - name: Get pull request number
- id: pr_nr
- run: |
- PR_URL="${{ github.event.comment.issue_url }}"
- echo "::set-output name=pr_nr::${PR_URL##*/}"
-
- - name: Checkout
- # TODO: The correct way to checkout would be to use similar approach as in get_commit_by_timestamp function of
- # the github gluetool module (i.e. do not use HEAD but the last commit before comment).
- id: checkout
- uses: actions/checkout@v4
- with:
- ref: "refs/pull/${{ steps.pr_nr.outputs.pr_nr }}/head"
-
- - name: Get ref and sha
- id: ref_sha
- run: |
- echo "::set-output name=sha::$(git rev-parse --short HEAD)"
- echo "::set-output name=ref::refs/pull/${{ steps.pr_nr.outputs.pr_nr }}/head"
-
- - name: Trigger copr build
- id: copr_build
- env:
- COPR_CONFIG: "copr_fedora.conf"
- COPR_CHROOT: "epel-8-x86_64"
- COPR_REPO: "@oamg/leapp"
- run: |
- cat << EOF > $COPR_CONFIG
- [copr-cli]
- login = ${{ secrets.FEDORA_COPR_LOGIN }}
- username = oamgbot
- token = ${{ secrets.FEDORA_COPR_TOKEN }}
- copr_url = https://copr.fedorainfracloud.org
- # expiration date: 2030-07-04
- EOF
-
- pip install copr-cli
- PR=${{ steps.pr_nr.outputs.pr_nr }} COPR_CONFIG=$COPR_CONFIG COPR_REPO="$COPR_REPO" COPR_CHROOT=$COPR_CHROOT make copr_build | tee copr.log
-
- COPR_URL=$(grep -Po 'https://copr.fedorainfracloud.org/coprs/build/\d+' copr.log)
- echo "::set-output name=copr_url::${COPR_URL}"
- echo "::set-output name=copr_id::${COPR_URL##*/}"
-
- - name: Add comment with copr build url
- # TODO: Create comment when copr build fails.
- id: link_copr
- uses: actions/github-script@v7
- with:
- script: |
- github.issues.createComment({
- issue_number: context.issue.number,
- owner: context.repo.owner,
- repo: context.repo.repo,
- body: 'Copr build succeeded: ${{ steps.copr_build.outputs.copr_url }}'
- })
-
- - name: Get dependent leapp pr number from rerun comment
- uses: actions-ecosystem/action-regex-match@v2
- id: leapp_pr_regex_match
- with:
- text: ${{ github.event.comment.body }}
- regex: '^/(rerun|rerun-sst)\s+([0-9]+)\s*$'
-
- - name: If leapp_pr was specified in the comment - trigger copr build
- # TODO: XXX FIXME This should schedule copr build for leapp but for now it will be just setting an env var
- id: leapp_pr
- if: ${{ steps.leapp_pr_regex_match.outputs.match != '' }}
- run: |
- echo "::set-output name=leapp_pr::${{ steps.leapp_pr_regex_match.outputs.group2 }}"
-
- - name: Checkout leapp
- id: checkout_leapp
- if: ${{ steps.leapp_pr_regex_match.outputs.match != '' }}
- uses: actions/checkout@v4
- with:
- repository: "oamg/leapp"
- ref: "refs/pull/${{ steps.leapp_pr.outputs.leapp_pr }}/head"
-
- - name: Get ref and sha for leapp
- id: ref_sha_leapp
- if: ${{ steps.leapp_pr_regex_match.outputs.match != '' }}
- run: |
- echo "::set-output name=sha::$(git rev-parse --short HEAD)"
- echo "::set-output name=ref::refs/pull/${{ steps.leapp_pr.outputs.leapp_pr }}/head"
-
- - name: Trigger copr build for leapp
- id: copr_build_leapp
- if: ${{ steps.leapp_pr_regex_match.outputs.match != '' }}
- env:
- COPR_CONFIG: "copr_fedora.conf"
- COPR_CHROOT: "epel-8-x86_64"
- COPR_REPO: "@oamg/leapp"
- run: |
- cat << EOF > $COPR_CONFIG
- [copr-cli]
- login = ${{ secrets.FEDORA_COPR_LOGIN }}
- username = oamgbot
- token = ${{ secrets.FEDORA_COPR_TOKEN }}
- copr_url = https://copr.fedorainfracloud.org
- # expiration date: 2030-07-04
- EOF
-
- pip install copr-cli
- PR=${{ steps.leapp_pr.outputs.leapp_pr }} COPR_CONFIG=$COPR_CONFIG COPR_REPO="$COPR_REPO" COPR_CHROOT=$COPR_CHROOT make copr_build | tee copr.log
-
- COPR_URL=$(grep -Po 'https://copr.fedorainfracloud.org/coprs/build/\d+' copr.log)
- echo "::set-output name=copr_url::${COPR_URL}"
- echo "::set-output name=copr_id::${COPR_URL##*/}"
-
- - name: Add comment with copr build url for leapp
- # TODO: Create comment when copr build fails.
- id: link_copr_leapp
- if: ${{ steps.leapp_pr_regex_match.outputs.match != '' }}
- uses: actions/github-script@v7
- with:
- script: |
- github.issues.createComment({
- issue_number: context.issue.number,
- owner: context.repo.owner,
- repo: context.repo.repo,
- body: 'Copr build succeeded: ${{ steps.copr_build_leapp.outputs.copr_url }}'
- })
-
- - name: Generate artifacts output
- id: gen_artifacts
- env:
- ARTIFACTS: ${{ steps.leapp_pr_regex_match.outputs.match != '' && format('{0};{1}', steps.copr_build_leapp.outputs.copr_id, steps.copr_build.outputs.copr_id) || steps.copr_build.outputs.copr_id }}
- run: |
- echo "::set-output name=artifacts::${{ env.ARTIFACTS }}"
diff --git a/.github/workflows/tmt-tests.yml b/.github/workflows/tmt-tests.yml
deleted file mode 100644
index c9f76ef7..00000000
--- a/.github/workflows/tmt-tests.yml
+++ /dev/null
@@ -1,72 +0,0 @@
-name: tmt@TF
-
-on:
- issue_comment:
- types:
- - created
-
-jobs:
- call_workflow_copr_build:
- uses: ./.github/workflows/reuse-copr-build.yml
- secrets: inherit
-
- call_workflow_tests_86to90_integration:
- needs: call_workflow_copr_build
- uses: oamg/leapp/.github/workflows/reuse-tests-8to9.yml@main
- secrets: inherit
- with:
- copr_artifacts: ${{ needs.call_workflow_copr_build.outputs.artifacts }}
- tmt_plan_regex: "^(?!.*max_sst)(.*tier1)"
- variables: 'SOURCE_RELEASE=8.6;TARGET_RELEASE=9.0;TARGET_KERNEL=el9;RHSM_REPOS=rhel-8-for-x86_64-appstream-eus-rpms,rhel-8-for-x86_64-baseos-eus-rpms;LEAPPDATA_BRANCH=upstream'
- pull_request_status_name: "8.6to9.0"
- if: |
- github.event.issue.pull_request
- && ! startsWith(github.event.comment.body, '/rerun-sst')
- && contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
-
- call_workflow_tests_88to92_integration:
- needs: call_workflow_copr_build
- uses: oamg/leapp/.github/workflows/reuse-tests-8to9.yml@main
- secrets: inherit
- with:
- copr_artifacts: ${{ needs.call_workflow_copr_build.outputs.artifacts }}
- tmt_plan_regex: "^(?!.*max_sst)(.*tier1)"
- variables: 'SOURCE_RELEASE=8.8;TARGET_RELEASE=9.2;TARGET_KERNEL=el9;RHSM_REPOS=rhel-8-for-x86_64-appstream-rpms,rhel-8-for-x86_64-baseos-rpms;LEAPPDATA_BRANCH=upstream'
- compose: "RHEL-8.8.0-Nightly"
- pull_request_status_name: "8.8to9.2"
- tmt_context: "distro=rhel-8.8"
- if: |
- github.event.issue.pull_request
- && ! startsWith(github.event.comment.body, '/rerun-sst')
- && contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
-
- call_workflow_tests_86to90_sst:
- needs: call_workflow_copr_build
- uses: oamg/leapp/.github/workflows/reuse-tests-8to9.yml@main
- secrets: inherit
- with:
- copr_artifacts: ${{ needs.call_workflow_copr_build.outputs.artifacts }}
- tmt_plan_regex: "^(?!.*tier[2-3].*)(.*max_sst.*)"
- variables: 'SOURCE_RELEASE=8.6;TARGET_RELEASE=9.0;TARGET_KERNEL=el9;RHSM_REPOS=rhel-8-for-x86_64-appstream-eus-rpms,rhel-8-for-x86_64-baseos-eus-rpms;LEAPPDATA_BRANCH=upstream'
- pull_request_status_name: "8to9-sst"
- update_pull_request_status: 'false'
- if: |
- github.event.issue.pull_request
- && startsWith(github.event.comment.body, '/rerun-sst')
- && contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
-
- call_workflow_tests_86to90_aws:
- needs: call_workflow_copr_build
- uses: oamg/leapp/.github/workflows/reuse-tests-8to9.yml@main
- secrets: inherit
- with:
- copr_artifacts: ${{ needs.call_workflow_copr_build.outputs.artifacts }}
- tmt_plan_regex: "^(?!.*upgrade_plugin)(?!.*tier[2-3].*)(?!.*rhsm)(?!.*c2r)(?!.*sap)(?!.*7to8)(.*e2e)"
- compose: "RHEL-8.6-rhui"
- environment_settings: '{"provisioning": {"post_install_script": "#!/bin/sh\nsudo sed -i s/.*ssh-rsa/ssh-rsa/ /root/.ssh/authorized_keys"}}'
- pull_request_status_name: "8to9-aws-e2e"
- variables: 'SOURCE_RELEASE=8.6;TARGET_RELEASE=9.0;TARGET_KERNEL=el9;RHSM_REPOS=rhel-8-for-x86_64-appstream-eus-rpms,rhel-8-for-x86_64-baseos-eus-rpms;RHUI=aws;LEAPPDATA_BRANCH=upstream'
- if: |
- github.event.issue.pull_request
- && ! startsWith(github.event.comment.body, '/rerun-sst')
- && contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
--
2.50.1

View File

@ -1,53 +0,0 @@
From c92dbb41fc3d3c3c77ae33a723ad9f961b8b8215 Mon Sep 17 00:00:00 2001
From: dosas <dosas@users.noreply.github.com>
Date: Thu, 9 Jan 2025 14:58:54 +0100
Subject: [PATCH 44/53] Remove unmaintained .gitlab-ci.yml config file
---
.gitlab-ci.yml | 34 ----------------------------------
1 file changed, 34 deletions(-)
delete mode 100644 .gitlab-ci.yml
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
deleted file mode 100644
index 24e91dbb..00000000
--- a/.gitlab-ci.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-stages:
-- build-initrd
-- build-srpm
-# - build-rpms
-
-build_initrd:
- only:
- - master@leapp/leapp-actors-internal
- stage: build-initrd
- cache:
- key: "${CI_PIPELINE_ID}"
- paths:
- - sources/dracut/upgrade-boot-files.tgz
- script:
- - 'export BASEDIR="$PWD"'
- - helpers/docker/docker-run.sh
- image: docker-registry.engineering.redhat.com/leapp-builds/leapp-initrd-rhel8-build:latest
-
-build_srpm:
- only:
- - master@leapp/leapp-actors-internal
- stage: build-srpm
- dependencies:
- - build_initrd
- cache:
- key: "${CI_PIPELINE_ID}"
- paths:
- - sources/dracut/upgrade-boot-files.tgz
- script:
- - dnf install -y git-core make rpm-build copr-cli
- - export LEAPP_INITRD_SKIP=1
- - make srpm
- image: fedora:28
-
--
2.47.1

View File

@ -0,0 +1,24 @@
From 7c6bb64e550ccfefe4001e79fef44b7d69446c36 Mon Sep 17 00:00:00 2001
From: Michal Bocek <mbocek@redhat.com>
Date: Thu, 19 Jun 2025 12:46:50 +0200
Subject: [PATCH 45/66] README: IRC -> GitHub discussions
The Leapp team is not available on IRC anymore. We advise the public to
talk to us on GitHub instead.
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 5ec5f723..6b45b4b7 100644
--- a/README.md
+++ b/README.md
@@ -29,4 +29,4 @@ Then you may attach only the `leapp-logs.tgz` file.
Well gladly answer your questions and lead you to through any troubles with the
actor development.
-You can reach us at IRC: `#leapp` on Libera.Chat.
+You can reach us in the [discussions sections of our GitHub repository](https://github.com/oamg/leapp-repository/discussions).
--
2.50.1

View File

@ -1,55 +0,0 @@
From e10968202016575ed4431f67a09ab7a3aef8dfcc Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Wed, 18 Sep 2024 00:40:25 +0200
Subject: [PATCH 45/53] fix(pes_events_scanner): ensure output contains no
duplicates
RpmTransactionTasks messages have higher priority than instructions
based on PES data. Previously, if multiple such messages existed
with duplicate instructions, this could lead to the crash of
the actor - especially in case when an existing package has been
asked to be removed several times. Ensure the occurance of each
instruction is unique (list -> set).
jira: RHEL-50076
---
.../libraries/pes_events_scanner.py | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/repos/system_upgrade/common/actors/peseventsscanner/libraries/pes_events_scanner.py b/repos/system_upgrade/common/actors/peseventsscanner/libraries/pes_events_scanner.py
index f5cb2613..a798017f 100644
--- a/repos/system_upgrade/common/actors/peseventsscanner/libraries/pes_events_scanner.py
+++ b/repos/system_upgrade/common/actors/peseventsscanner/libraries/pes_events_scanner.py
@@ -78,19 +78,22 @@ def get_installed_pkgs():
def get_transaction_configuration():
"""
- Get pkgs to install, keep and remove from the user configuration files in /etc/leapp/transaction/.
+ Get pkgs to install, keep and remove from RpmTransactionTasks messages.
- These configuration files have higher priority than PES data.
- :return: RpmTransactionTasks model instance
+ Note these messages reflects inputs from various actors and configuration
+ files in /etc/leapp/transaction/. As these are explicit instruction, they
+ have higher priority than instructions from PES data.
+
+ :return: TransactionConfiguration
"""
- transaction_configuration = TransactionConfiguration(to_install=[], to_remove=[], to_keep=[])
+ transaction_configuration = TransactionConfiguration(to_install=set(), to_remove=set(), to_keep=set())
_Pkg = partial(Package, repository=None, modulestream=None)
for tasks in api.consume(RpmTransactionTasks):
- transaction_configuration.to_install.extend(_Pkg(name=pkg_name) for pkg_name in tasks.to_install)
- transaction_configuration.to_remove.extend(_Pkg(name=pkg_name) for pkg_name in tasks.to_remove)
- transaction_configuration.to_keep.extend(_Pkg(name=pkg_name) for pkg_name in tasks.to_keep)
+ transaction_configuration.to_install.update(_Pkg(name=pkg_name) for pkg_name in tasks.to_install)
+ transaction_configuration.to_remove.update(_Pkg(name=pkg_name) for pkg_name in tasks.to_remove)
+ transaction_configuration.to_keep.update(_Pkg(name=pkg_name) for pkg_name in tasks.to_keep)
return transaction_configuration
--
2.47.1

View File

@ -0,0 +1,538 @@
From 9966eb19daca97c18d798080c62af5638c1e0eab Mon Sep 17 00:00:00 2001
From: David Kubek <dkubek@redhat.com>
Date: Tue, 20 Aug 2024 12:57:42 +0200
Subject: [PATCH 46/66] Resolve boot issues in hybrid azure during upgrades
from RHEL 7 > 8 > 9.
This commit addresses the issue where the `/boot/grub2/grub.cfg` file is
overwritten during the upgrade process by an old RHEL7 configuration
leftover on the system, causing the system to fail to boot.
The problem occurs on hybrid Azure images, which support both UEFI and
Legacy systems and have both `grub-pc` and `grub-efi` packages installed.
It is caused by one of the scriplets in `grub-efi` which overwrites the old
configuration.
If old configuration is detected, this actor regenerates the grub
configuration using `grub2-mkconfig -o /boot/grub2/grub.cfg` after
installing rpms to ensure the correct boot configuration is in place.
The fix is applied specifically to Azure hybrid cloud systems.
JIRA: RHEL-38255
---
.../cloud/ensurevalidgrubcfghybrid/actor.py | 34 +++
.../libraries/ensurevalidgrubcfghybrid.py | 66 ++++++
.../tests/files/invalid_grub.cfg | 51 +++++
.../tests/files/valid_grub.cfg | 195 ++++++++++++++++++
.../tests/test_ensurevalidgrubcfghybrid.py | 124 +++++++++++
5 files changed, 470 insertions(+)
create mode 100644 repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/actor.py
create mode 100644 repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/libraries/ensurevalidgrubcfghybrid.py
create mode 100644 repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/tests/files/invalid_grub.cfg
create mode 100644 repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/tests/files/valid_grub.cfg
create mode 100644 repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/tests/test_ensurevalidgrubcfghybrid.py
diff --git a/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/actor.py b/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/actor.py
new file mode 100644
index 00000000..68de0433
--- /dev/null
+++ b/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/actor.py
@@ -0,0 +1,34 @@
+from leapp.actors import Actor
+from leapp.libraries.actor import ensurevalidgrubcfghybrid
+from leapp.models import HybridImage
+from leapp.tags import ApplicationsPhaseTag, IPUWorkflowTag
+
+
+class EnsureValidGrubcfgHybrid(Actor):
+ """
+ Resolve boot failures in Azure Gen1 VMs during upgrades from RHEL 7 to RHEL 8 to RHEL 9.
+
+ This actor addresses the issue where the `/boot/grub2/grub.cfg` file is
+ overwritten during the upgrade process by an old RHEL7 configuration
+ leftover on the system, causing the system to fail to boot.
+
+ The problem occurs on hybrid Azure images, which support both UEFI and
+ Legacy systems and have both `grub-pc` and `grub-efi` packages installed.
+ It is caused by one of the scriplets in `grub-efi` which overwrites the old
+ configuration.
+
+ If old configuration is detected, this actor regenerates the grub
+ configuration using `grub2-mkconfig -o /boot/grub2/grub.cfg` after
+ installing rpms to ensure the correct boot configuration is in place.
+
+ The fix is applied specifically to Azure hybrid cloud systems.
+
+ """
+
+ name = 'ensure_valid_grubcfg_hybrid'
+ consumes = (HybridImage,)
+ produces = ()
+ tags = (ApplicationsPhaseTag, IPUWorkflowTag)
+
+ def process(self):
+ ensurevalidgrubcfghybrid.process()
diff --git a/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/libraries/ensurevalidgrubcfghybrid.py b/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/libraries/ensurevalidgrubcfghybrid.py
new file mode 100644
index 00000000..127eccfc
--- /dev/null
+++ b/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/libraries/ensurevalidgrubcfghybrid.py
@@ -0,0 +1,66 @@
+import re
+
+from leapp.exceptions import StopActorExecutionError
+from leapp.libraries.common.config.architecture import ARCH_ACCEPTED
+from leapp.libraries.stdlib import api, CalledProcessError, run
+from leapp.models import HybridImage
+
+GRUB_CFG_PATH = '/boot/grub2/grub.cfg'
+
+MATCH_ARCH = r'({})'.format('|'.join(ARCH_ACCEPTED))
+MATCH_RHEL7_KERNEL_VERSION = r"\d+\.\d+\.\d+-\d+(\.\d+)*\.el7\.{}".format(MATCH_ARCH)
+MATCH_RHEL7_KERNEL_DEFINITION = r"vmlinuz-{}".format(MATCH_RHEL7_KERNEL_VERSION)
+
+
+def process():
+ if not _is_hybrid_image():
+ api.current_logger().info('System is not a hybrid image. Skipping.')
+ return
+
+ grubcfg = _read_grubcfg()
+ if _is_grubcfg_invalid(grubcfg):
+ _run_grub2_mkconfig()
+
+
+def _is_hybrid_image():
+ return next(api.consume(HybridImage), None) is not None
+
+
+def _read_grubcfg():
+ api.current_logger().debug('Reading {}:'.format(GRUB_CFG_PATH))
+ with open(GRUB_CFG_PATH, 'r') as fin:
+ grubcfg = fin.read()
+
+ api.current_logger().debug(grubcfg)
+ return grubcfg
+
+
+def _is_grubcfg_invalid(grubcfg):
+ return _contains_rhel7_kernel_definition(grubcfg)
+
+
+def _contains_rhel7_kernel_definition(grubcfg):
+ api.current_logger().debug("Looking for RHEL7 kernel version ...")
+
+ match = re.search(MATCH_RHEL7_KERNEL_DEFINITION, grubcfg)
+
+ api.current_logger().debug(
+ "Matched: {}".format(match.group() if match else "[NO MATCH]")
+ )
+
+ return match is not None
+
+
+def _run_grub2_mkconfig():
+ api.current_logger().info("Regenerating {}".format(GRUB_CFG_PATH))
+
+ try:
+ run([
+ 'grub2-mkconfig',
+ '-o',
+ GRUB_CFG_PATH
+ ])
+ except CalledProcessError as err:
+ msg = 'Could not regenerate {}: {}'.format(GRUB_CFG_PATH, str(err))
+ api.current_logger().error(msg)
+ raise StopActorExecutionError(msg)
diff --git a/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/tests/files/invalid_grub.cfg b/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/tests/files/invalid_grub.cfg
new file mode 100644
index 00000000..58f55c53
--- /dev/null
+++ b/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/tests/files/invalid_grub.cfg
@@ -0,0 +1,51 @@
+
+# Created by osbuild
+
+set timeout=10
+
+# load the grubenv file
+load_env
+
+# selection of the next boot entry
+if [ "${next_entry}" ] ; then
+ set default="${next_entry}"
+ set next_entry=
+ save_env next_entry
+ set boot_once=true
+else
+ set default="${saved_entry}"
+fi
+
+if [ "${prev_saved_entry}" ]; then
+ set saved_entry="${prev_saved_entry}"
+ save_env saved_entry
+ set prev_saved_entry=
+ save_env prev_saved_entry
+ set boot_once=true
+fi
+
+function savedefault {
+ if [ -z "${boot_once}" ]; then
+ saved_entry="${chosen}"
+ save_env saved_entry
+ fi
+}
+
+serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1
+terminal_input serial console
+terminal_output serial console
+
+menuentry 'Red Hat Enterprise Linux Server (3.10.0-1160.119.1.el7.x86_64) 7.9 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted --id 'gnulinux-3.10.0-1160.99.1.el7.x86_64-advanced-76a22bf4-f153-4541-b6c7-0332c0dfaeac' {
+ insmod all_video
+ set gfxpayload=keep
+ search --no-floppy --set=root --fs-uuid 61779359-8d11-49ba-bc9d-8d038ee4b108
+ linuxefi /vmlinuz-3.10.0-1160.119.1.el7.x86_64 root=UUID=d3c9a2bd-7ffb-4113-9b8f-234c13b18274 ro crashkernel=auto console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300 scsi_mod.use_blk_mq=y LANG=en_US.UTF-8
+ initrdefi /initramfs-3.10.0-1160.119.1.el7.x86_64.img
+}
+menuentry 'Red Hat Enterprise Linux (3.10.0-1160.99.1.el7.x86_64) 7.9 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted --id 'gnulinux-3.10.0-1160.99.1.el7.x86_64-advanced-76a22bf4-f153-4541-b6c7-0332c0dfaeac' {
+ insmod all_video
+ set gfxpayload=keep
+ search --no-floppy --set=root --fs-uuid 61779359-8d11-49ba-bc9d-8d038ee4b108
+ linuxefi /vmlinuz-3.10.0-1160.99.1.el7.x86_64 root=UUID=d3c9a2bd-7ffb-4113-9b8f-234c13b18274 ro crashkernel=auto console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300 scsi_mod.use_blk_mq=y
+ initrdefi /initramfs-3.10.0-1160.99.1.el7.x86_64.img
+}
diff --git a/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/tests/files/valid_grub.cfg b/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/tests/files/valid_grub.cfg
new file mode 100644
index 00000000..8192665e
--- /dev/null
+++ b/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/tests/files/valid_grub.cfg
@@ -0,0 +1,195 @@
+#
+# DO NOT EDIT THIS FILE
+#
+# It is automatically generated by grub2-mkconfig using templates
+# from /etc/grub.d and settings from /etc/default/grub
+#
+
+### BEGIN /etc/grub.d/00_header ###
+set pager=1
+
+if [ -f ${config_directory}/grubenv ]; then
+ load_env -f ${config_directory}/grubenv
+elif [ -s $prefix/grubenv ]; then
+ load_env
+fi
+if [ "${next_entry}" ] ; then
+ set default="${next_entry}"
+ set next_entry=
+ save_env next_entry
+ set boot_once=true
+else
+ set default="${saved_entry}"
+fi
+
+if [ x"${feature_menuentry_id}" = xy ]; then
+ menuentry_id_option="--id"
+else
+ menuentry_id_option=""
+fi
+
+export menuentry_id_option
+
+if [ "${prev_saved_entry}" ]; then
+ set saved_entry="${prev_saved_entry}"
+ save_env saved_entry
+ set prev_saved_entry=
+ save_env prev_saved_entry
+ set boot_once=true
+fi
+
+function savedefault {
+ if [ -z "${boot_once}" ]; then
+ saved_entry="${chosen}"
+ save_env saved_entry
+ fi
+}
+
+function load_video {
+ if [ x$feature_all_video_module = xy ]; then
+ insmod all_video
+ else
+ insmod efi_gop
+ insmod efi_uga
+ insmod ieee1275_fb
+ insmod vbe
+ insmod vga
+ insmod video_bochs
+ insmod video_cirrus
+ fi
+}
+
+serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1
+terminal_input serial console
+terminal_output serial console
+if [ x$feature_timeout_style = xy ] ; then
+ set timeout_style=countdown
+ set timeout=10
+# Fallback hidden-timeout code in case the timeout_style feature is
+# unavailable.
+elif sleep --interruptible 10 ; then
+ set timeout=0
+fi
+### END /etc/grub.d/00_header ###
+
+### BEGIN /etc/grub.d/00_tuned ###
+set tuned_params=""
+set tuned_initrd=""
+### END /etc/grub.d/00_tuned ###
+
+### BEGIN /etc/grub.d/01_users ###
+if [ -f ${prefix}/user.cfg ]; then
+ source ${prefix}/user.cfg
+ if [ -n "${GRUB2_PASSWORD}" ]; then
+ set superusers="root"
+ export superusers
+ password_pbkdf2 root ${GRUB2_PASSWORD}
+ fi
+fi
+### END /etc/grub.d/01_users ###
+
+### BEGIN /etc/grub.d/08_fallback_counting ###
+insmod increment
+# Check if boot_counter exists and boot_success=0 to activate this behaviour.
+if [ -n "${boot_counter}" -a "${boot_success}" = "0" ]; then
+ # if countdown has ended, choose to boot rollback deployment,
+ # i.e. default=1 on OSTree-based systems.
+ if [ "${boot_counter}" = "0" -o "${boot_counter}" = "-1" ]; then
+ set default=1
+ set boot_counter=-1
+ # otherwise decrement boot_counter
+ else
+ decrement boot_counter
+ fi
+ save_env boot_counter
+fi
+### END /etc/grub.d/08_fallback_counting ###
+
+### BEGIN /etc/grub.d/10_linux ###
+insmod part_gpt
+insmod xfs
+set root='hd0,gpt2'
+if [ x$feature_platform_search_hint = xy ]; then
+ search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 61779359-8d11-49ba-bc9d-8d038ee4b108
+else
+ search --no-floppy --fs-uuid --set=root 61779359-8d11-49ba-bc9d-8d038ee4b108
+fi
+insmod part_gpt
+insmod xfs
+set boot='hd0,gpt2'
+if [ x$feature_platform_search_hint = xy ]; then
+ search --no-floppy --fs-uuid --set=boot --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 61779359-8d11-49ba-bc9d-8d038ee4b108
+else
+ search --no-floppy --fs-uuid --set=boot 61779359-8d11-49ba-bc9d-8d038ee4b108
+fi
+
+# This section was generated by a script. Do not modify the generated file - all changes
+# will be lost the next time file is regenerated. Instead edit the BootLoaderSpec files.
+#
+# The blscfg command parses the BootLoaderSpec files stored in /boot/loader/entries and
+# populates the boot menu. Please refer to the Boot Loader Specification documentation
+# for the files format: https://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/.
+
+# The kernelopts variable should be defined in the grubenv file. But to ensure that menu
+# entries populated from BootLoaderSpec files that use this variable work correctly even
+# without a grubenv file, define a fallback kernelopts variable if this has not been set.
+#
+# The kernelopts variable in the grubenv file can be modified using the grubby tool or by
+# executing the grub2-mkconfig tool. For the latter, the values of the GRUB_CMDLINE_LINUX
+# and GRUB_CMDLINE_LINUX_DEFAULT options from /etc/default/grub file are used to set both
+# the kernelopts variable in the grubenv file and the fallback kernelopts variable.
+if [ -z "${kernelopts}" ]; then
+ set kernelopts="root=/dev/mapper/rootvg-rootlv ro ro crashkernel=auto console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300 scsi_mod.use_blk_mq=y "
+fi
+
+insmod blscfg
+blscfg
+### END /etc/grub.d/10_linux ###
+
+### BEGIN /etc/grub.d/10_reset_boot_success ###
+# Hiding the menu is ok if last boot was ok or if this is a first boot attempt to boot the entry
+if [ "${boot_success}" = "1" -o "${boot_indeterminate}" = "1" ]; then
+ set menu_hide_ok=1
+else
+ set menu_hide_ok=0
+fi
+# Reset boot_indeterminate after a successful boot
+if [ "${boot_success}" = "1" ] ; then
+ set boot_indeterminate=0
+# Avoid boot_indeterminate causing the menu to be hidden more then once
+elif [ "${boot_indeterminate}" = "1" ]; then
+ set boot_indeterminate=2
+fi
+# Reset boot_success for current boot
+set boot_success=0
+save_env boot_success boot_indeterminate
+### END /etc/grub.d/10_reset_boot_success ###
+
+### BEGIN /etc/grub.d/12_menu_auto_hide ###
+### END /etc/grub.d/12_menu_auto_hide ###
+
+### BEGIN /etc/grub.d/20_linux_xen ###
+### END /etc/grub.d/20_linux_xen ###
+
+### BEGIN /etc/grub.d/20_ppc_terminfo ###
+### END /etc/grub.d/20_ppc_terminfo ###
+
+### BEGIN /etc/grub.d/30_os-prober ###
+### END /etc/grub.d/30_os-prober ###
+
+### BEGIN /etc/grub.d/30_uefi-firmware ###
+### END /etc/grub.d/30_uefi-firmware ###
+
+### BEGIN /etc/grub.d/40_custom ###
+# This file provides an easy way to add custom menu entries. Simply type the
+# menu entries you want to add after this comment. Be careful not to change
+# the 'exec tail' line above.
+### END /etc/grub.d/40_custom ###
+
+### BEGIN /etc/grub.d/41_custom ###
+if [ -f ${config_directory}/custom.cfg ]; then
+ source ${config_directory}/custom.cfg
+elif [ -z "${config_directory}" -a -f $prefix/custom.cfg ]; then
+ source $prefix/custom.cfg;
+fi
+### END /etc/grub.d/41_custom ###
diff --git a/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/tests/test_ensurevalidgrubcfghybrid.py b/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/tests/test_ensurevalidgrubcfghybrid.py
new file mode 100644
index 00000000..c0fb0a0d
--- /dev/null
+++ b/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/tests/test_ensurevalidgrubcfghybrid.py
@@ -0,0 +1,124 @@
+import os
+
+import pytest
+
+from leapp.exceptions import StopActorExecutionError
+from leapp.libraries.actor import ensurevalidgrubcfghybrid
+from leapp.libraries.common.testutils import CurrentActorMocked, logger_mocked
+from leapp.libraries.stdlib import api, CalledProcessError
+from leapp.models import HybridImage
+
+CUR_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+def raise_call_error(args=None):
+ raise CalledProcessError(
+ message='A Leapp Command Error occurred.',
+ command=args,
+ result={'signal': None, 'exit_code': 1, 'pid': 0, 'stdout': 'fake', 'stderr': 'fake'}
+ )
+
+
+class run_mocked(object):
+ def __init__(self, raise_err=False):
+ self.called = 0
+ self.args = []
+ self.raise_err = raise_err
+
+ def __call__(self, *args):
+ self.called += 1
+ self.args.append(args)
+ if self.raise_err:
+ raise_call_error(args)
+
+
+def test_not_hybrid_image(monkeypatch):
+ """
+ Skip when system is not a hybrid.
+ """
+
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(msgs=[]))
+ monkeypatch.setattr(api, 'current_logger', logger_mocked())
+ monkeypatch.setattr(ensurevalidgrubcfghybrid, 'run', run_mocked(raise_err=False))
+
+ ensurevalidgrubcfghybrid.process()
+
+ assert api.current_logger.infomsg[0].startswith('System is not a hybrid image')
+ assert ensurevalidgrubcfghybrid.run.called == 0
+
+
+@pytest.mark.parametrize("is_invalid", [True, False])
+def test_is_grubcfg_valid(monkeypatch, is_invalid):
+
+ grubcfg_filename = ('invalid' if is_invalid else 'valid') + '_grub.cfg'
+ grubcfg_filepath = os.path.join(CUR_DIR, 'files', grubcfg_filename)
+ with open(grubcfg_filepath, 'r') as fin:
+ grubcfg = fin.read()
+
+ assert ensurevalidgrubcfghybrid._is_grubcfg_invalid(grubcfg) == is_invalid
+
+
+def test_valid_grubcfg(monkeypatch):
+ """
+ Test valid configuration does not trigger grub2-mkconfig
+ """
+
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(msgs=[HybridImage()]))
+ monkeypatch.setattr(api, 'current_logger', logger_mocked())
+ monkeypatch.setattr(ensurevalidgrubcfghybrid, 'run', run_mocked(raise_err=False))
+
+ grubcfg_filepath = os.path.join(CUR_DIR, 'files', 'valid_grub.cfg')
+ with open(grubcfg_filepath, 'r') as fin:
+ grubcfg = fin.read()
+
+ monkeypatch.setattr(ensurevalidgrubcfghybrid, '_read_grubcfg', lambda: grubcfg)
+
+ ensurevalidgrubcfghybrid.process()
+
+ assert ensurevalidgrubcfghybrid.run.called == 0
+
+
+def test_invalid_grubcfg(monkeypatch):
+ """
+ Test invalid configuration triggers grub2-mkconfig
+ """
+
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(msgs=[HybridImage()]))
+ monkeypatch.setattr(api, 'current_logger', logger_mocked())
+ monkeypatch.setattr(ensurevalidgrubcfghybrid, 'run', run_mocked(raise_err=False))
+
+ grubcfg_filepath = os.path.join(CUR_DIR, 'files', 'invalid_grub.cfg')
+ with open(grubcfg_filepath, 'r') as fin:
+ grubcfg = fin.read()
+
+ monkeypatch.setattr(ensurevalidgrubcfghybrid, '_read_grubcfg', lambda: grubcfg)
+
+ ensurevalidgrubcfghybrid.process()
+
+ assert ensurevalidgrubcfghybrid.run.called == 1
+ assert any(msg.startswith('Regenerating') for msg in api.current_logger.infomsg)
+
+
+def test_run_error(monkeypatch):
+ """
+ Test invalid configuration triggers grub2-mkconfig
+ """
+
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(msgs=[HybridImage()]))
+ monkeypatch.setattr(api, 'current_logger', logger_mocked())
+ monkeypatch.setattr(ensurevalidgrubcfghybrid, 'run', run_mocked(raise_err=True))
+
+ grubcfg_filepath = os.path.join(CUR_DIR, 'files', 'invalid_grub.cfg')
+ with open(grubcfg_filepath, 'r') as fin:
+ grubcfg = fin.read()
+
+ monkeypatch.setattr(ensurevalidgrubcfghybrid, '_read_grubcfg', lambda: grubcfg)
+
+ with pytest.raises(StopActorExecutionError):
+ ensurevalidgrubcfghybrid.process()
+
+ assert ensurevalidgrubcfghybrid.run.called == 1
+ assert any(
+ msg.startswith('Could not regenerate')
+ for msg in api.current_logger.err
+ )
--
2.50.1

View File

@ -1,247 +0,0 @@
From 49627082e79744d9b7831356f87c71e2e67add03 Mon Sep 17 00:00:00 2001
From: Michal Hecko <mhecko@redhat.com>
Date: Thu, 31 Oct 2024 18:13:49 +0100
Subject: [PATCH 46/53] fix(pes_event_scanner): respect user's trasaction
configuration
Previously, pes_events_scanner used transaction configuration to
only modify the way it initializes event application. As a consequence,
if a user specified to_remove=['pkg'], then the information would
not make it to pes_events_scanner's output. Similar situation would
arise with to_install/to_keep. This patch adds a post-processing to
explicitly add transaction configuration to the result of applying PES
events.
---
.../libraries/pes_events_scanner.py | 64 +++++++++++++--
.../tests/test_pes_event_scanner.py | 78 +++++++++++++++----
2 files changed, 120 insertions(+), 22 deletions(-)
diff --git a/repos/system_upgrade/common/actors/peseventsscanner/libraries/pes_events_scanner.py b/repos/system_upgrade/common/actors/peseventsscanner/libraries/pes_events_scanner.py
index a798017f..50336150 100644
--- a/repos/system_upgrade/common/actors/peseventsscanner/libraries/pes_events_scanner.py
+++ b/repos/system_upgrade/common/actors/peseventsscanner/libraries/pes_events_scanner.py
@@ -470,9 +470,8 @@ def replace_pesids_with_repoids_in_packages(packages, source_pkgs_repoids):
return packages_with_repoid.union(packages_without_pesid)
-def apply_transaction_configuration(source_pkgs):
+def apply_transaction_configuration(source_pkgs, transaction_configuration):
source_pkgs_with_conf_applied = set(source_pkgs)
- transaction_configuration = get_transaction_configuration()
source_pkgs_with_conf_applied = source_pkgs.union(transaction_configuration.to_install)
@@ -504,6 +503,50 @@ def remove_leapp_related_events(events):
return res
+def include_instructions_from_transaction_configuration(rpm_tasks, transaction_configuration, installed_pkgs):
+ """
+ Extend current rpm_tasks applying data from transaction_configuration
+
+ :param PESRpmTransactionTasks rpm_tasks: Currently calculated rpm tasks based on PES data.
+ :param TransactionConfiguration transaction_configuration: Tasked configured by user manually.
+ :param set(str) installed_pkgs: Set of distribution signed packages installed on the system.
+ :returns: updated tasks respecting configuration changes made by user
+ :rtype: PESRpmTransactionTasks
+ """
+ to_install_from_rpm_tasks = set() if not rpm_tasks else set(rpm_tasks.to_install)
+ to_remove_from_rpm_tasks = set() if not rpm_tasks else set(rpm_tasks.to_remove)
+ to_keep_from_rpm_tasks = set() if not rpm_tasks else set(rpm_tasks.to_keep)
+
+ # We don't want to try removing packages that are not installed - include only installed ones
+ installed_pkgs_requested_to_be_removed = transaction_configuration.to_remove.intersection(installed_pkgs)
+ pkgs_names_to_extend_to_remove_with = set(pkg.name for pkg in installed_pkgs_requested_to_be_removed)
+
+ # Add packages to 'to_install' only if they are not already requested to be installed by rpm_tasks
+ pkgs_names_requested_to_be_installed = set(pkg.name for pkg in transaction_configuration.to_install)
+ to_install_pkgs_names_missing_from_tasks = pkgs_names_requested_to_be_installed - to_install_from_rpm_tasks
+
+ pkg_names_user_wants_to_keep = {pkg.name for pkg in transaction_configuration.to_keep}
+
+ # Remove packages that were requested by rpm_tasks or by user, but exclude those that should be kept
+ new_to_remove_set = (to_remove_from_rpm_tasks | pkgs_names_to_extend_to_remove_with) - pkg_names_user_wants_to_keep
+ new_to_remove_list = sorted(new_to_remove_set)
+
+ new_to_install_list = sorted(to_install_from_rpm_tasks | to_install_pkgs_names_missing_from_tasks)
+ new_to_keep_list = sorted(to_keep_from_rpm_tasks | pkg_names_user_wants_to_keep)
+
+ if not any((new_to_remove_list, new_to_keep_list, new_to_install_list)): # Are all empty?
+ return rpm_tasks # We do not modify the original tasks
+
+ modules_to_enable = rpm_tasks.modules_to_enable if rpm_tasks else []
+ modules_to_reset = rpm_tasks.modules_to_reset if rpm_tasks else []
+
+ return PESRpmTransactionTasks(to_install=new_to_install_list,
+ to_remove=new_to_remove_list,
+ to_keep=new_to_keep_list,
+ modules_to_enable=modules_to_enable,
+ modules_to_reset=modules_to_reset)
+
+
def process():
# Retrieve data - installed_pkgs, transaction configuration, pes events
events = get_pes_events('/etc/leapp/files', 'pes-events.json')
@@ -511,24 +554,27 @@ def process():
return
releases = get_relevant_releases(events)
- source_pkgs = get_installed_pkgs()
- source_pkgs = apply_transaction_configuration(source_pkgs)
+ installed_pkgs = get_installed_pkgs()
+ transaction_configuration = get_transaction_configuration()
+ pkgs_to_begin_computation_with = apply_transaction_configuration(installed_pkgs, transaction_configuration)
# Keep track of what repoids have the source packages to be able to determine what are the PESIDs of the computed
# packages of the target system, so we can distinguish what needs to be repomapped
- repoids_of_source_pkgs = {pkg.repository for pkg in source_pkgs}
+ repoids_of_source_pkgs = {pkg.repository for pkg in pkgs_to_begin_computation_with}
events = remove_leapp_related_events(events)
events = remove_undesired_events(events, releases)
# Apply events - compute what packages should the target system have
- target_pkgs, pkgs_to_demodularize = compute_packages_on_target_system(source_pkgs, events, releases)
+ target_pkgs, pkgs_to_demodularize = compute_packages_on_target_system(pkgs_to_begin_computation_with,
+ events, releases)
# Packages coming out of the events have PESID as their repository, however, we need real repoid
target_pkgs = replace_pesids_with_repoids_in_packages(target_pkgs, repoids_of_source_pkgs)
# Apply the desired repository blacklisting
- blacklisted_repoids, target_pkgs = remove_new_packages_from_blacklisted_repos(source_pkgs, target_pkgs)
+ blacklisted_repoids, target_pkgs = remove_new_packages_from_blacklisted_repos(pkgs_to_begin_computation_with,
+ target_pkgs)
# Look at the target packages and determine what repositories to enable
target_repoids = sorted(set(p.repository for p in target_pkgs) - blacklisted_repoids - repoids_of_source_pkgs)
@@ -536,6 +582,8 @@ def process():
api.produce(repos_to_enable)
# Compare the packages on source system and the computed packages on target system and determine what to install
- rpm_tasks = compute_rpm_tasks_from_pkg_set_diff(source_pkgs, target_pkgs, pkgs_to_demodularize)
+ rpm_tasks = compute_rpm_tasks_from_pkg_set_diff(pkgs_to_begin_computation_with, target_pkgs, pkgs_to_demodularize)
+ rpm_tasks = include_instructions_from_transaction_configuration(rpm_tasks, transaction_configuration,
+ installed_pkgs)
if rpm_tasks:
api.produce(rpm_tasks)
diff --git a/repos/system_upgrade/common/actors/peseventsscanner/tests/test_pes_event_scanner.py b/repos/system_upgrade/common/actors/peseventsscanner/tests/test_pes_event_scanner.py
index 80ece770..9a499baa 100644
--- a/repos/system_upgrade/common/actors/peseventsscanner/tests/test_pes_event_scanner.py
+++ b/repos/system_upgrade/common/actors/peseventsscanner/tests/test_pes_event_scanner.py
@@ -9,9 +9,7 @@ from leapp.libraries.actor.pes_events_scanner import (
api,
compute_packages_on_target_system,
compute_rpm_tasks_from_pkg_set_diff,
- get_installed_pkgs,
Package,
- process,
reporting,
TransactionConfiguration
)
@@ -27,8 +25,8 @@ from leapp.models import (
RepositoriesSetupTasks,
RepositoryData,
RepositoryFile,
- RHUIInfo,
- RPM
+ RPM,
+ RpmTransactionTasks
)
@@ -286,17 +284,14 @@ def test_actor_performs(monkeypatch):
def test_transaction_configuration_has_effect(monkeypatch):
_Pkg = partial(Package, repository=None, modulestream=None)
- def mocked_transaction_conf():
- return TransactionConfiguration(
- to_install=[_Pkg('pkg-a'), _Pkg('pkg-b')],
- to_remove=[_Pkg('pkg-c'), _Pkg('pkg-d')],
- to_keep=[]
- )
-
- monkeypatch.setattr(pes_events_scanner, 'get_transaction_configuration', mocked_transaction_conf)
+ transaction_cfg = TransactionConfiguration(
+ to_install=[_Pkg('pkg-a'), _Pkg('pkg-b')],
+ to_remove=[_Pkg('pkg-c'), _Pkg('pkg-d')],
+ to_keep=[]
+ )
packages = {_Pkg('pkg-a'), _Pkg('pkg-c')}
- _result = pes_events_scanner.apply_transaction_configuration(packages)
+ _result = pes_events_scanner.apply_transaction_configuration(packages, transaction_cfg)
result = {(p.name, p.repository, p.modulestream) for p in _result}
expected = {('pkg-a', None, None), ('pkg-b', None, None)}
@@ -340,7 +335,7 @@ def test_blacklisted_repoid_is_not_produced(monkeypatch):
monkeypatch.setattr(pes_events_scanner, 'get_installed_pkgs', lambda: installed_pkgs)
monkeypatch.setattr(pes_events_scanner, 'get_pes_events', lambda folder, filename: events)
- monkeypatch.setattr(pes_events_scanner, 'apply_transaction_configuration', lambda pkgs: pkgs)
+ monkeypatch.setattr(pes_events_scanner, 'apply_transaction_configuration', lambda pkgs, transaction_cfg: pkgs)
monkeypatch.setattr(pes_events_scanner, 'get_blacklisted_repoids', lambda: {'blacklisted-rhel8'})
monkeypatch.setattr(pes_events_scanner, 'replace_pesids_with_repoids_in_packages',
lambda pkgs, src_pkgs_repoids: pkgs)
@@ -475,3 +470,58 @@ def test_remove_leapp_related_events(monkeypatch):
out_events = pes_events_scanner.remove_leapp_related_events(in_events)
assert out_events == expected_out_events
+
+
+def test_transaction_configuration_is_applied(monkeypatch):
+ installed_pkgs = {
+ Package(name='moved-in', repository='rhel7-base', modulestream=None),
+ Package(name='split-in', repository='rhel7-base', modulestream=None),
+ Package(name='pkg-not-in-events', repository='rhel7-base', modulestream=None),
+ }
+ monkeypatch.setattr(pes_events_scanner, 'get_installed_pkgs', lambda *args, **kwags: installed_pkgs)
+
+ Pkg = partial(Package, modulestream=None)
+ events = [
+ Event(1, Action.SPLIT,
+ {Pkg('split-in', 'rhel7-base')},
+ {Pkg('split-out0', 'rhel8-BaseOS'), Pkg('split-out1', 'rhel8-BaseOS')},
+ (7, 9), (8, 0), []),
+ Event(3, Action.MOVED,
+ {Pkg('moved-in', 'rhel7-base')}, {Pkg('moved-out', 'rhel8-BaseOS')},
+ (7, 9), (8, 0), []),
+ ]
+ monkeypatch.setattr(pes_events_scanner, 'get_pes_events', lambda *args, **kwargs: events)
+ monkeypatch.setattr(pes_events_scanner, 'remove_leapp_related_events', lambda events: events)
+ monkeypatch.setattr(pes_events_scanner, 'remove_undesired_events', lambda events, releases: events)
+ monkeypatch.setattr(pes_events_scanner, '_get_enabled_modules', lambda *args: [])
+ monkeypatch.setattr(pes_events_scanner, 'replace_pesids_with_repoids_in_packages',
+ lambda target_pkgs, repoids_of_source_pkgs: target_pkgs)
+ monkeypatch.setattr(pes_events_scanner,
+ 'remove_new_packages_from_blacklisted_repos',
+ lambda source_pkgs, target_pkgs: (set(), target_pkgs))
+
+ msgs = [
+ RpmTransactionTasks(to_remove=['pkg-not-in-events']),
+ RpmTransactionTasks(to_remove=['pkg-not-in-events', 'pkg-not-in-events']),
+ RpmTransactionTasks(to_install=['pkg-to-install']),
+ RpmTransactionTasks(to_keep=['keep-me']),
+ ]
+ mocked_actor = CurrentActorMocked(arch='x86_64', src_ver='7.9', dst_ver='8.8', msgs=msgs)
+ monkeypatch.setattr(api, 'current_actor', mocked_actor)
+
+ monkeypatch.setattr(api, 'produce', produce_mocked())
+
+ pes_events_scanner.process()
+
+ assert api.produce.called == 2
+
+ produced_rpm_transaction_tasks = [
+ msg for msg in api.produce.model_instances if isinstance(msg, PESRpmTransactionTasks)
+ ]
+
+ assert len(produced_rpm_transaction_tasks) == 1
+ rpm_transaction_tasks = produced_rpm_transaction_tasks[0]
+ # It is important to see 'pkg-not-in-events' in the list - if the user says remove pkg A, we really remove it
+ assert sorted(rpm_transaction_tasks.to_remove) == ['moved-in', 'pkg-not-in-events', 'split-in']
+ assert sorted(rpm_transaction_tasks.to_install) == ['moved-out', 'pkg-to-install', 'split-out0', 'split-out1']
+ assert sorted(rpm_transaction_tasks.to_keep) == ['keep-me']
--
2.47.1

View File

@ -1,36 +0,0 @@
From 75b8b96f8b7b6705fe52135dab32cc6c8d886db3 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Fri, 10 Jan 2025 15:16:05 +0100
Subject: [PATCH 47/53] IPU 9 -> 10: obsolete GPG key with SHA1 signature
When upgrading to RHEL 10, we have analogical problem as we had for
IPU 8 -> 9 due to GPG keys with SHA1 signatures. The SHA1 algorithm
is considered unsecure since RHEL 9 and all RPMs are required to be
signed by keys with SHA2 signatures. The RHEL 9 GPG (auxiliary) key
is unfortunately still signed with SHA1 and RHEL 10 tooling refuse
to use it for any operations.
To resolve this apply the same solution as we did in the past:
* obsolete original key
* install the target RHEL 10 GPG keys during the upgrade
jira: RHEL-71517
---
.../system_upgrade/common/files/distro/rhel/gpg-signatures.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/repos/system_upgrade/common/files/distro/rhel/gpg-signatures.json b/repos/system_upgrade/common/files/distro/rhel/gpg-signatures.json
index 8a5471a8..3cc67f82 100644
--- a/repos/system_upgrade/common/files/distro/rhel/gpg-signatures.json
+++ b/repos/system_upgrade/common/files/distro/rhel/gpg-signatures.json
@@ -14,6 +14,6 @@
"gpg-pubkey-db42a60e-37ea5438"
],
"9": ["gpg-pubkey-d4082792-5b32db75"],
- "10": []
+ "10": ["gpg-pubkey-fd431d51-4ae0493b"]
}
}
--
2.47.1

File diff suppressed because it is too large Load Diff

View File

@ -1,49 +0,0 @@
From d183370047ab5ef139825dfce7a1b4d6f987092f Mon Sep 17 00:00:00 2001
From: tomasfratrik <tomasfratrik8@gmail.com>
Date: Fri, 28 Jun 2024 14:27:41 +0200
Subject: [PATCH 48/53] Fix storage scanner parsing error
Fix storagescanner actor crash when parsing the output of,
e.g., 'pvs -a', which used ':' as a separator and caused errors.
The issue occurred because separator ':' is used to split the outputs of executed commands.
This commit resolves the problem by changing the separator to '|'.
Jira: RHEL-34570
---
.../actors/storagescanner/libraries/storagescanner.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/repos/system_upgrade/common/actors/storagescanner/libraries/storagescanner.py b/repos/system_upgrade/common/actors/storagescanner/libraries/storagescanner.py
index cad6bd32..cae38731 100644
--- a/repos/system_upgrade/common/actors/storagescanner/libraries/storagescanner.py
+++ b/repos/system_upgrade/common/actors/storagescanner/libraries/storagescanner.py
@@ -206,7 +206,7 @@ def _get_lsblk_info():
@aslist
def _get_pvs_info():
""" Collect storage info from pvs command """
- for entry in _get_cmd_output(['pvs', '--noheadings', '--separator', r':'], ':', 6):
+ for entry in _get_cmd_output(['pvs', '--noheadings', '--separator', r'|'], '|', 6):
pv, vg, fmt, attr, psize, pfree = entry
yield PvsEntry(
pv=pv,
@@ -220,7 +220,7 @@ def _get_pvs_info():
@aslist
def _get_vgs_info():
""" Collect storage info from vgs command """
- for entry in _get_cmd_output(['vgs', '--noheadings', '--separator', r':'], ':', 7):
+ for entry in _get_cmd_output(['vgs', '--noheadings', '--separator', r'|'], '|', 7):
vg, pv, lv, sn, attr, vsize, vfree = entry
yield VgsEntry(
vg=vg,
@@ -235,7 +235,7 @@ def _get_vgs_info():
@aslist
def _get_lvdisplay_info():
""" Collect storage info from lvdisplay command """
- for entry in _get_cmd_output(['lvdisplay', '-C', '--noheadings', '--separator', r':'], ':', 12):
+ for entry in _get_cmd_output(['lvdisplay', '-C', '--noheadings', '--separator', r'|'], '|', 12):
lv, vg, attr, lsize, pool, origin, data, meta, move, log, cpy_sync, convert = entry
yield LvdisplayEntry(
lv=lv,
--
2.47.1

View File

@ -0,0 +1,61 @@
From ba074a40e4297c90cbb8e5e522ec2a154fa2b9b0 Mon Sep 17 00:00:00 2001
From: Michal Bocek <mbocek@redhat.com>
Date: Tue, 1 Jul 2025 20:38:20 +0200
Subject: [PATCH 48/66] Point to leapp-repository contribution guidelines
Instead of the leapp framework contribution guidelines.
Also update the leapp-repository contribution guidelines to point to the
new place of the leapp framework Python coding guidelines (moved under
https://github.com/oamg/leapp/commit/123f2700dc0a354d4357ce325ff61fcb2f53e33b).
---
CONTRIBUTING.md | 2 +-
README.md | 6 +++---
docs/source/contrib-and-devel-guidelines.md | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d4cb2046..7315b693 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1 +1 @@
-See the [Contribution guidelines](https://leapp.readthedocs.io/en/latest/contributing.html)
+See the [contribution guidelines](https://leapp-repository.readthedocs.io/latest/contrib-and-devel-guidelines.html).
diff --git a/README.md b/README.md
index 6b45b4b7..43da589e 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-**Before doing anything, please read the upstream [documentation](https://leapp-repository.readthedocs.io/).**
+**Before doing anything, please read the [leapp-repository documentation](https://leapp-repository.readthedocs.io/).**
-Also, you could find useufl to read [Leapp framework documentation](https://leapp.readthedocs.io/).
+Also, you could find the [Leapp framework documentation](https://leapp.readthedocs.io/) useful to read.
---
@@ -17,7 +17,7 @@ Also, you could find useufl to read [Leapp framework documentation](https://leap
- *All files in /var/log/leapp*
- */var/lib/leapp/leapp.db*
- *journalctl*
- - If you want, you can optionally send anything else would you like to provide (e.g. storage info)
+ - If you want, you can optionally send any other relevant information (e.g. storage, network)
**For your convenience you can pack all logs with this command:**
diff --git a/docs/source/contrib-and-devel-guidelines.md b/docs/source/contrib-and-devel-guidelines.md
index 66bef9b1..f2edf8b7 100644
--- a/docs/source/contrib-and-devel-guidelines.md
+++ b/docs/source/contrib-and-devel-guidelines.md
@@ -1,7 +1,7 @@
# Contribution and development guidelines
## Code guidelines
-Your code should follow the [Python Coding Guidelines](https://leapp.readthedocs.io/en/latest/python-coding-guidelines.html) used for the leapp project. On top of these rules follow instructions
+Your code should follow the [Python Coding Guidelines](https://leapp.readthedocs.io/en/latest/contributing.html#follow-python-coding-guidelines) used for the leapp project. On top of these rules follow instructions
below.
### Retrieving information about the source system should be separated from its use
--
2.50.1

View File

@ -0,0 +1,46 @@
From be6d23241e6fbe0c42a4f6a2df48efd6f999ed71 Mon Sep 17 00:00:00 2001
From: karolinku <kkula@redhat.com>
Date: Thu, 3 Jul 2025 13:12:32 +0200
Subject: [PATCH 49/66] Read the DNF config by module.py library
The DNF configuration has not been loaded when trying to get
information about available module streams (library module.py).
This causes a traceback e.g. on systems which must access DNF
repositories via a proxy.
This patch introduces loading the DNF configuration before trying
to access remote resources.
Jira: RHEL-39095
---
.../common/actors/rpmscanner/libraries/rpmscanner.py | 2 ++
repos/system_upgrade/common/libraries/module.py | 1 +
2 files changed, 3 insertions(+)
diff --git a/repos/system_upgrade/common/actors/rpmscanner/libraries/rpmscanner.py b/repos/system_upgrade/common/actors/rpmscanner/libraries/rpmscanner.py
index dbe56191..74c4b101 100644
--- a/repos/system_upgrade/common/actors/rpmscanner/libraries/rpmscanner.py
+++ b/repos/system_upgrade/common/actors/rpmscanner/libraries/rpmscanner.py
@@ -25,6 +25,8 @@ except ImportError:
def _get_package_repository_data_yum():
yum_base = yum.YumBase()
+ # DNF configuration is not loaded here, since no impact for operations
+ # done by the actor is observed here
pkg_repos = {}
try:
diff --git a/repos/system_upgrade/common/libraries/module.py b/repos/system_upgrade/common/libraries/module.py
index 7d4e8aa4..db725e71 100644
--- a/repos/system_upgrade/common/libraries/module.py
+++ b/repos/system_upgrade/common/libraries/module.py
@@ -38,6 +38,7 @@ def _create_or_get_dnf_base(base=None):
conf.substitutions.update_from_etc('/')
base = dnf.Base(conf=conf)
+ base.conf.read()
base.init_plugins()
base.read_all_repos()
# configure plugins after the repositories are loaded
--
2.50.1

View File

@ -1,54 +0,0 @@
From a46f20841ef32b9de23553591dd7ae8ff5150eff Mon Sep 17 00:00:00 2001
From: "Bryn M. Reeves" <bmr@redhat.com>
Date: Tue, 14 Jan 2025 19:57:37 +0000
Subject: [PATCH 49/53] Use --sysinit when calling vgchange from mount_usr.sh
The mount_usr.sh script runs 'lvm vgchange': if there are logical
volumes present that require monitoring (snapshots, thin pools, RAID,
etc.) the command will attempt to launch dmeventd.
Since dmeventd is not installed in the dracut initramfs this produces a
warning and causes the lvm command to exit with non-zero exit status
even though the volume group has been activated and LV block devices are
available.
This in turn triggers the retry logic in mount_usr.sh: once the retries
are exhausted the script carries on and successfully initiates the
upgrade process.
The --sysinit switch is used by the LVM dracut modules for this reason.
From vgchange(8):
--sysinit
Indicates that vgchange/lvchange is being invoked from early
system initialisation scripts (e.g. rc.sysinit or an initrd),
before writable filesystems are available. As such, some
functionality needs to be disabled and this option acts as a
shortcut which selects an appropriate set of options. Currently,
this is equivalent to using --ignorelockingfailure,
--ignoremonitoring, --poll n, and setting env var
LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES. vgchange/lvchange skip
autoactivation, and defer to pvscan autoactivation.
Testing with this change I no longer see the long delay booting the
upgrade initramfs when snapshot LVs are present.
---
.../files/dracut/85sys-upgrade-redhat/mount_usr.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/mount_usr.sh b/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/mount_usr.sh
index 84f4857d..9366ac13 100755
--- a/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/mount_usr.sh
+++ b/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/mount_usr.sh
@@ -107,7 +107,7 @@ try_to_mount_usr() {
# In case we have the LVM command available try make it activate all partitions
if command -v lvm 2>/dev/null 1>/dev/null; then
- lvm vgchange -a y || {
+ lvm vgchange --sysinit -a y || {
warn "Detected problem when tried to activate LVM VG."
if [ "$_last_attempt" != "true" ]; then
# this is not last execution, retry
--
2.47.1

Some files were not shown because too many files have changed in this diff Show More