From 024e1a030d6844c630e548fe3e2fae4bb9ef84b8 Mon Sep 17 00:00:00 2001 From: Yuriy Kohut Date: Fri, 10 Oct 2025 14:16:21 +0300 Subject: [PATCH] Update Vendors patch against upstream 215f307eeb1362e420ac08f528f9f11d6c1c974d (0.23.0-1) The package version 0.23.0-1.elevate.3 --- SOURCES/leapp-repository-0.23.0-elevate.patch | 5838 ++++++++++++++++- SPECS/leapp-repository.spec | 5 +- 2 files changed, 5805 insertions(+), 38 deletions(-) diff --git a/SOURCES/leapp-repository-0.23.0-elevate.patch b/SOURCES/leapp-repository-0.23.0-elevate.patch index 666d54e..776480a 100644 --- a/SOURCES/leapp-repository-0.23.0-elevate.patch +++ b/SOURCES/leapp-repository-0.23.0-elevate.patch @@ -1,3 +1,95 @@ +diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml +index 3e595e32..4b07e4b3 100644 +--- a/.github/workflows/codespell.yml ++++ b/.github/workflows/codespell.yml +@@ -14,7 +14,7 @@ jobs: + runs-on: ubuntu-latest + + steps: +- - uses: actions/checkout@v4 ++ - uses: actions/checkout@v5 + - uses: codespell-project/actions-codespell@v2 + with: + ignore_words_list: ro,fo,couldn,repositor,zeor,bootup +diff --git a/.github/workflows/differential-shellcheck.yml b/.github/workflows/differential-shellcheck.yml +index e1bafb93..6c81713c 100644 +--- a/.github/workflows/differential-shellcheck.yml ++++ b/.github/workflows/differential-shellcheck.yml +@@ -19,7 +19,7 @@ jobs: + + steps: + - name: Repository checkout +- uses: actions/checkout@v4 ++ uses: actions/checkout@v5 + with: + fetch-depth: 0 + +diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml +index ed82e0e5..d1b8fb2a 100644 +--- a/.github/workflows/unit-tests.yml ++++ b/.github/workflows/unit-tests.yml +@@ -19,40 +19,40 @@ jobs: + - name: 'Unit tests (python:3.12; repos:el9toel10,common)' + python: python3.12 + repos: 'el9toel10,common' +- container: ubi9 ++ container: el9 + - name: 'Linters (python:3.12; repos:el9toel10,common)' + python: python3.12 + repos: 'el9toel10,common' +- container: ubi9-lint ++ container: el9-lint + - name: 'Unit tests (python:3.9; repos:el9toel10,common)' + python: python3.9 + repos: 'el9toel10,common' +- container: ubi9 ++ container: el9 + - name: 'Linters (python:3.9; repos:el9toel10,common)' + python: python3.9 + repos: 'el9toel10,common' +- container: ubi9-lint ++ container: el9-lint + # 8to9 + - name: 'Unit tests (python:3.9; repos:el8toel9,common)' + python: python3.9 + repos: 'el8toel9,common' +- container: ubi9 ++ container: el9 + - name: 'Linters (python:3.9; repos:el8toel9,common)' + python: python3.9 + repos: 'el8toel9,common' +- container: ubi9-lint ++ container: el9-lint + - name: 'Unit tests (python:3.6; repos:el8toel9,common)' + python: python3.6 + repos: 'el8toel9,common' +- container: ubi8 ++ container: el8 + - name: 'Linters (python:3.6; repos:el8toel9,common)' + python: python3.6 + repos: 'el8toel9,common' +- container: ubi8-lint ++ container: el8-lint + + steps: + - name: Checkout code +- uses: actions/checkout@v4 ++ uses: actions/checkout@v5 + with: + # 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. +@@ -63,4 +63,10 @@ jobs: + run: | + 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' ++ run: | ++ script -e -c /bin/bash -c \ ++ 'TERM=xterm \ ++ podman build -t leapp-tests -f utils/container-tests/ci/Containerfile.${{matrix.scenarios.container}} . && \ ++ PYTHON_VENV=${{matrix.scenarios.python}} \ ++ REPOSITORIES=${{matrix.scenarios.repos}} \ ++ podman run --rm -ti -v ${PWD}:/payload --env=PYTHON_VENV --env=REPOSITORIES leapp-tests' diff --git a/.gitignore b/.gitignore index 0bb92d3d..a04c7ded 100644 --- a/.gitignore @@ -10,6 +102,811 @@ index 0bb92d3d..a04c7ded 100644 # pycharm .idea +diff --git a/.packit.yaml b/.packit.yaml +index 607dff93..0c3f682a 100644 +--- a/.packit.yaml ++++ b/.packit.yaml +@@ -104,6 +104,8 @@ jobs: + # is the last RHEL 8 release and all new future tests will start from this + # one release. + ++# This job is never triggered - we define abstract anchor that are reused in jobs that 'inherit' ++# and have actionable triggers + - &sanity-abstract-8to9 + job: tests + trigger: ignore +@@ -116,6 +118,47 @@ jobs: + epel-8-x86_64: + distros: [RHEL-8.10.0-Nightly] + identifier: sanity-abstract-8to9 ++ tf_extra_params: ++ test: ++ tmt: ++ plan_filter: 'tag:8to9' ++ environments: ++ - &tmt-env-settings-810to94 ++ tmt: ++ context: &tmt-context-810to94 ++ distro: "rhel-8.10" ++ distro_target: "rhel-9.4" ++ settings: ++ provisioning: ++ tags: ++ BusinessUnit: sst_upgrades@leapp_upstream_test ++ - &tmt-env-settings-810to96 ++ tmt: ++ context: &tmt-context-810to96 ++ distro: "rhel-8.10" ++ distro_target: "rhel-9.6" ++ settings: ++ provisioning: ++ tags: ++ BusinessUnit: sst_upgrades@leapp_upstream_test ++ - &tmt-env-settings-810to97 ++ tmt: ++ context: &tmt-context-810to97 ++ distro: "rhel-8.10" ++ distro_target: "rhel-9.7" ++ settings: ++ provisioning: ++ tags: ++ BusinessUnit: sst_upgrades@leapp_upstream_test ++ - &tmt-env-settings-810to98 ++ tmt: ++ context: &tmt-context-810to98 ++ distro: "rhel-8.10" ++ distro_target: "rhel-9.8" ++ settings: ++ provisioning: ++ tags: ++ BusinessUnit: sst_upgrades@leapp_upstream_test + + - &sanity-abstract-8to9-aws + <<: *sanity-abstract-8to9 +@@ -147,7 +190,10 @@ jobs: + # ######################### Individual tests ########################### # + # ###################################################################### # + +-# Tests: 8.10 -> 9.4 ++# ###################################################################### # ++# ############################# 8.10 > 9.4 ############################# # ++# ###################################################################### # ++ + - &sanity-810to94 + <<: *sanity-abstract-8to9 + trigger: pull_request +@@ -155,17 +201,10 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:tier0 & enabled:true' ++ plan_filter: 'tag:8to9 & tag:tier0 & enabled:true & tag:-rhsm' + environments: +- - tmt: +- context: +- distro: "rhel-8.10" +- distro_target: "rhel-9.4" +- settings: +- provisioning: +- tags: +- BusinessUnit: sst_upgrades@leapp_upstream_test +- env: ++ - *tmt-env-settings-810to94 ++ env: &env-810to94 + SOURCE_RELEASE: "8.10" + TARGET_RELEASE: "9.4" + LEAPP_TARGET_PRODUCT_CHANNEL: "EUS" +@@ -182,20 +221,11 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:partitioning & enabled:true' ++ plan_filter: 'tag:8to9 & tag:partitioning & enabled:true & tag:-rhsm' + environments: +- - tmt: +- context: +- distro: "rhel-8.10" +- distro_target: "rhel-9.4" +- settings: +- provisioning: +- tags: +- BusinessUnit: sst_upgrades@leapp_upstream_test ++ - *tmt-env-settings-810to94 + env: +- SOURCE_RELEASE: "8.10" +- TARGET_RELEASE: "9.4" +- LEAPP_TARGET_PRODUCT_CHANNEL: "EUS" ++ <<: *env-810to94 + + # On-demand kernel-rt tests + - &kernel-rt-810to94 +@@ -209,22 +239,22 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true' ++ plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true & tag:-rhsm' + environments: + - tmt: +- context: +- distro: "rhel-8.10" +- distro_target: "rhel-9.4" ++ context: *tmt-context-810to94 + settings: + provisioning: + tags: + BusinessUnit: sst_upgrades@leapp_upstream_test + env: +- SOURCE_RELEASE: "8.10" +- TARGET_RELEASE: "9.4" +- LEAPP_TARGET_PRODUCT_CHANNEL: "EUS" ++ <<: *env-810to94 ++ ++ ++# ###################################################################### # ++# ############################# 8.10 > 9.6 ############################# # ++# ###################################################################### # + +-# Tests: 8.10 -> 9.6 + - &sanity-810to96 + <<: *sanity-abstract-8to9 + trigger: pull_request +@@ -232,17 +262,10 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:tier0 & enabled:true' ++ plan_filter: 'tag:8to9 & tag:tier0 & enabled:true & tag:-rhsm' + environments: +- - tmt: +- context: +- distro: "rhel-8.10" +- distro_target: "rhel-9.6" +- settings: +- provisioning: +- tags: +- BusinessUnit: sst_upgrades@leapp_upstream_test +- env: ++ - *tmt-env-settings-810to96 ++ env: &env-810to96 + SOURCE_RELEASE: "8.10" + TARGET_RELEASE: "9.6" + +@@ -258,19 +281,11 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:partitioning & enabled:true' ++ plan_filter: 'tag:8to9 & tag:partitioning & enabled:true & tag:-rhsm' + environments: +- - tmt: +- context: +- distro: "rhel-8.10" +- distro_target: "rhel-9.6" +- settings: +- provisioning: +- tags: +- BusinessUnit: sst_upgrades@leapp_upstream_test ++ - *tmt-env-settings-810to96 + env: +- SOURCE_RELEASE: "8.10" +- TARGET_RELEASE: "9.6" ++ <<: *env-810to96 + + # On-demand kernel-rt tests + - &kernel-rt-810to96 +@@ -284,21 +299,38 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true' ++ plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true & tag:-rhsm' ++ environments: ++ - *tmt-env-settings-810to96 ++ env: ++ <<: *env-810to96 ++ ++- &sanity-810to96-aws ++ <<: *sanity-abstract-8to9-aws ++ trigger: pull_request ++ targets: ++ epel-8-x86_64: ++ distros: [RHEL-8.10-rhui] ++ identifier: sanity-8.10to9.6-aws ++ tf_extra_params: ++ test: ++ tmt: ++ plan_filter: 'tag:8to9 & tag:rhui-aws-tier0 & enabled:true & tag:-rhsm' + environments: + - tmt: +- context: +- distro: "rhel-8.10" +- distro_target: "rhel-9.6" ++ context: *tmt-context-810to96 + settings: + provisioning: + tags: + BusinessUnit: sst_upgrades@leapp_upstream_test + env: +- SOURCE_RELEASE: "8.10" +- TARGET_RELEASE: "9.6" ++ <<: *env-810to96 ++ ++ ++# ###################################################################### # ++# ############################# 8.10 > 9.7 ############################# # ++# ###################################################################### # + +-# Tests: 8.10 -> 9.7 + - &sanity-810to97 + <<: *sanity-abstract-8to9 + trigger: pull_request +@@ -306,17 +338,10 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:tier0 & enabled:true' ++ plan_filter: 'tag:8to9 & tag:tier0 & enabled:true & tag:-rhsm' + environments: +- - tmt: +- context: +- distro: "rhel-8.10" +- distro_target: "rhel-9.7" +- settings: +- provisioning: +- tags: +- BusinessUnit: sst_upgrades@leapp_upstream_test +- env: ++ - *tmt-env-settings-810to97 ++ env: &env-810to97 + SOURCE_RELEASE: "8.10" + TARGET_RELEASE: "9.7" + +@@ -332,19 +357,11 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:partitioning & enabled:true' ++ plan_filter: 'tag:8to9 & tag:partitioning & enabled:true & tag:-rhsm' + environments: +- - tmt: +- context: +- distro: "rhel-8.10" +- distro_target: "rhel-9.7" +- settings: +- provisioning: +- tags: +- BusinessUnit: sst_upgrades@leapp_upstream_test ++ - *tmt-env-settings-810to97 + env: +- SOURCE_RELEASE: "8.10" +- TARGET_RELEASE: "9.7" ++ <<: *env-810to97 + + # On-demand kernel-rt tests + - &kernel-rt-810to97 +@@ -358,19 +375,65 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true' ++ plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true & tag:-rhsm' + environments: +- - tmt: +- context: +- distro: "rhel-8.10" +- distro_target: "rhel-9.7" +- settings: +- provisioning: +- tags: +- BusinessUnit: sst_upgrades@leapp_upstream_test ++ - *tmt-env-settings-810to97 + env: ++ <<: *env-810to97 ++ ++# ###################################################################### # ++# ############################# 8.10 > 9.8 ############################# # ++# ###################################################################### # ++ ++- &sanity-810to98 ++ <<: *sanity-abstract-8to9 ++ trigger: pull_request ++ identifier: sanity-8.10to9.8 ++ tf_extra_params: ++ test: ++ tmt: ++ plan_filter: 'tag:8to9 & tag:tier0 & enabled:true' ++ environments: ++ - *tmt-env-settings-810to98 ++ env: &env-810to98 + SOURCE_RELEASE: "8.10" +- TARGET_RELEASE: "9.7" ++ TARGET_RELEASE: "9.8" ++ ++# On-demand minimal beaker tests ++- &beaker-minimal-810to98 ++ <<: *beaker-minimal-8to9-abstract-ondemand ++ trigger: pull_request ++ labels: ++ - beaker-minimal ++ - beaker-minimal-8.10to9.8 ++ - 8.10to9.8 ++ identifier: sanity-8.10to9.8-beaker-minimal-ondemand ++ tf_extra_params: ++ test: ++ tmt: ++ plan_filter: 'tag:8to9 & tag:partitioning & enabled:true' ++ environments: ++ - *tmt-env-settings-810to98 ++ env: ++ <<: *env-810to98 ++ ++# On-demand kernel-rt tests ++- &kernel-rt-810to98 ++ <<: *kernel-rt-abstract-8to9-ondemand ++ trigger: pull_request ++ labels: ++ - kernel-rt ++ - kernel-rt-8.10to9.8 ++ - 8.10to9.8 ++ identifier: sanity-8.10to9.8-kernel-rt-ondemand ++ tf_extra_params: ++ test: ++ tmt: ++ plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true' ++ environments: ++ - *tmt-env-settings-810to98 ++ env: ++ <<: *env-810to98 + + # ###################################################################### # + # ############################## 9 TO 10 ################################ # +@@ -392,6 +455,38 @@ jobs: + epel-9-x86_64: + distros: [RHEL-9.6.0-Nightly] + identifier: sanity-abstract-9to10 ++ tf_extra_params: ++ test: ++ tmt: ++ plan_filter: 'tag:9to10' ++ environments: ++ - &tmt-env-settings-96to100 ++ tmt: ++ context: &tmt-context-96to100 ++ distro: "rhel-9.6" ++ distro_target: "rhel-10.0" ++ settings: ++ provisioning: ++ tags: ++ BusinessUnit: sst_upgrades@leapp_upstream_test ++ - &tmt-env-settings-97to101 ++ tmt: ++ context: &tmt-context-97to101 ++ distro: "rhel-9.7" ++ distro_target: "rhel-10.1" ++ settings: ++ provisioning: ++ tags: ++ BusinessUnit: sst_upgrades@leapp_upstream_test ++ - &tmt-env-settings-98to102 ++ tmt: ++ context: &tmt-context-98to102 ++ distro: "rhel-9.8" ++ distro_target: "rhel-10.2" ++ settings: ++ provisioning: ++ tags: ++ BusinessUnit: sst_upgrades@leapp_upstream_test + + - &sanity-abstract-9to10-aws + <<: *sanity-abstract-9to10 +@@ -423,7 +518,10 @@ jobs: + # ######################### Individual tests ########################### # + # ###################################################################### # + +-# Tests: 9.6 -> 10.0 ++# ###################################################################### # ++# ############################# 9.6 > 10.0 ############################# # ++# ###################################################################### # ++ + - &sanity-96to100 + <<: *sanity-abstract-9to10 + trigger: pull_request +@@ -434,17 +532,10 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:9to10 & tag:tier0 & enabled:true' ++ plan_filter: 'tag:9to10 & tag:tier0 & enabled:true & tag:-rhsm' + environments: +- - tmt: +- context: +- distro: "rhel-9.6" +- distro_target: "rhel-10.0" +- settings: +- provisioning: +- tags: +- BusinessUnit: sst_upgrades@leapp_upstream_test +- env: ++ - *tmt-env-settings-96to100 ++ env: &env-96to100 + SOURCE_RELEASE: "9.6" + TARGET_RELEASE: "10.0" + +@@ -463,19 +554,11 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:partitioning & enabled:true' ++ plan_filter: 'tag:8to9 & tag:partitioning & enabled:true & tag:-rhsm' + environments: +- - tmt: +- context: +- distro: "rhel-9.6" +- distro_target: "rhel-10.0" +- settings: +- provisioning: +- tags: +- BusinessUnit: sst_upgrades@leapp_upstream_test ++ - *tmt-env-settings-96to100 + env: +- SOURCE_RELEASE: "9.6" +- TARGET_RELEASE: "10.0" ++ <<: *env-96to100 + + # On-demand kernel-rt tests + - &kernel-rt-96to100 +@@ -489,21 +572,16 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true' ++ plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true & tag:-rhsm' + environments: +- - tmt: +- context: +- distro: "rhel-9.6" +- distro_target: "rhel-10.0" +- settings: +- provisioning: +- tags: +- BusinessUnit: sst_upgrades@leapp_upstream_test ++ - *tmt-env-settings-96to100 + env: +- SOURCE_RELEASE: "9.6" +- TARGET_RELEASE: "10.0" ++ <<: *env-96to100 ++ ++# ###################################################################### # ++# ############################# 9.7 > 10.1 ############################# # ++# ###################################################################### # + +-# Tests: 9.7 -> 10.1 + - &sanity-97to101 + <<: *sanity-abstract-9to10 + trigger: pull_request +@@ -514,17 +592,10 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:9to10 & tag:tier0 & enabled:true' ++ plan_filter: 'tag:9to10 & tag:tier0 & enabled:true & tag:-rhsm' + environments: +- - tmt: +- context: +- distro: "rhel-9.7" +- distro_target: "rhel-10.1" +- settings: +- provisioning: +- tags: +- BusinessUnit: sst_upgrades@leapp_upstream_test +- env: ++ - *tmt-env-settings-97to101 ++ env: &env-97to101 + SOURCE_RELEASE: "9.7" + TARGET_RELEASE: "10.1" + +@@ -543,19 +614,11 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:partitioning & enabled:true' ++ plan_filter: 'tag:8to9 & tag:partitioning & enabled:true & tag:-rhsm' + environments: +- - tmt: +- context: +- distro: "rhel-9.7" +- distro_target: "rhel-10.1" +- settings: +- provisioning: +- tags: +- BusinessUnit: sst_upgrades@leapp_upstream_test ++ - *tmt-env-settings-97to101 + env: +- SOURCE_RELEASE: "9.7" +- TARGET_RELEASE: "10.1" ++ <<: *env-97to101 + + # On-demand kernel-rt tests + - &kernel-rt-97to101 +@@ -572,16 +635,73 @@ jobs: + tf_extra_params: + test: + tmt: +- plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true' ++ plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true & tag:-rhsm' + environments: +- - tmt: +- context: +- distro: "rhel-9.7" +- distro_target: "rhel-10.1" +- settings: +- provisioning: +- tags: +- BusinessUnit: sst_upgrades@leapp_upstream_test ++ - *tmt-env-settings-97to101 + env: +- SOURCE_RELEASE: "9.7" +- TARGET_RELEASE: "10.1" ++ <<: *env-97to101 ++ ++ ++# ###################################################################### # ++# ############################# 9.8 > 10.2 ############################# # ++# ###################################################################### # ++ ++- &sanity-98to102 ++ <<: *sanity-abstract-9to10 ++ trigger: pull_request ++ identifier: sanity-9.8to10.2 ++ targets: ++ epel-9-x86_64: ++ distros: [RHEL-9.8.0-Nightly] ++ tf_extra_params: ++ test: ++ tmt: ++ plan_filter: 'tag:9to10 & tag:tier0 & enabled:true & tag:-rhsm' ++ environments: ++ - *tmt-env-settings-98to102 ++ env: &env-98to102 ++ SOURCE_RELEASE: "9.8" ++ TARGET_RELEASE: "10.2" ++ ++# On-demand minimal beaker tests ++- &beaker-minimal-98to102 ++ <<: *beaker-minimal-9to10-abstract-ondemand ++ trigger: pull_request ++ labels: ++ - beaker-minimal ++ - beaker-minimal-9.8to10.2 ++ - 9.8to10.2 ++ identifier: sanity-9.8to10.2-beaker-minimal-ondemand ++ targets: ++ epel-9-x86_64: ++ distros: [RHEL-9.8-Nightly] ++ tf_extra_params: ++ test: ++ tmt: ++ plan_filter: 'tag:8to9 & tag:partitioning & enabled:true & tag:-rhsm' ++ environments: ++ - *tmt-env-settings-98to102 ++ env: ++ <<: *env-98to102 ++ ++# On-demand kernel-rt tests ++- &kernel-rt-98to102 ++ <<: *kernel-rt-abstract-9to10-ondemand ++ trigger: pull_request ++ labels: ++ - kernel-rt ++ - kernel-rt-9.8to10.2 ++ - 9.8to10.2 ++ identifier: sanity-9.8to10.2-kernel-rt-ondemand ++ targets: ++ epel-9-x86_64: ++ distros: [RHEL-9.8-Nightly] ++ tf_extra_params: ++ test: ++ tmt: ++ plan_filter: 'tag:8to9 & tag:kernel-rt & enabled:true & tag:-rhsm' ++ environments: ++ - *tmt-env-settings-98to102 ++ env: ++ <<: *env-98to102 ++ +diff --git a/.pylintrc b/.pylintrc +index 5d75df40..a82f8818 100644 +--- a/.pylintrc ++++ b/.pylintrc +@@ -9,23 +9,19 @@ disable= + raising-bad-type, + redundant-keyword-arg, # it's one or the other, this one is not so bad at all + # "W" Warnings for stylistic problems or minor programming issues +- no-absolute-import, + arguments-differ, + cell-var-from-loop, + fixme, + lost-exception, +- no-init, + pointless-string-statement, + protected-access, + redefined-outer-name, +- relative-import, + undefined-loop-variable, + unsubscriptable-object, + unused-argument, + unused-import, + unspecified-encoding, + # "C" Coding convention violations +- bad-continuation, + missing-docstring, + wrong-import-order, + use-maxsplit-arg, +@@ -33,7 +29,6 @@ disable= + consider-using-enumerate, + # "R" Refactor recommendations + duplicate-code, +- no-self-use, + too-few-public-methods, + too-many-branches, + too-many-locals, +@@ -42,24 +37,12 @@ disable= + 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 ++ too-many-positional-arguments, + # 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) + unnecessary-pass, +- invalid-envvar-default, # pylint3 warnings envvar returns str/none by default +- bad-option-value, # python 2 doesn't have import-outside-toplevel, but in some case we need to import outside toplevel +- super-with-arguments, # required in python 2 + raise-missing-from, # no 'raise from' in python 2 +- use-a-generator, # cannot be modified because of Python2 support +- consider-using-with, # on bunch spaces we cannot change that... +- duplicate-string-formatting-argument, # TMP: will be fixed in close future + consider-using-f-string, # sorry, not gonna happen, still have to support py2 +- use-dict-literal, +- 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 ++ logging-format-interpolation + + [FORMAT] + # Maximum number of characters on a single line. +diff --git a/Makefile b/Makefile +index 81b16376..64115006 100644 +--- a/Makefile ++++ b/Makefile +@@ -51,7 +51,7 @@ _COPR_CONFIG=$${COPR_CONFIG:-~/.config/copr_rh_oamg.conf} + _CONTAINER_TOOL=$${CONTAINER_TOOL:-podman} + + # container to run tests in +-_TEST_CONTAINER=$${TEST_CONTAINER:-rhel8} ++_TEST_CONTAINER=$${TEST_CONTAINER:-el8} + + # In case just specific CHROOTs should be used for the COPR build, you can + # set the multiple CHROOTs separated by comma in the COPR_CHROOT envar, e.g. +@@ -129,7 +129,7 @@ help: + @echo " test lint source code and run tests" + @echo " test_no_lint run tests without linting the source code" + @echo " test_container run lint and tests in container" +- @echo " - default container is 'rhel8'" ++ @echo " - default container is 'el8'" + @echo " - can be changed by setting TEST_CONTAINER env" + @echo " test_container_all run lint and tests in all available containers" + @echo " test_container_no_lint run tests without linting in container, see test_container" +@@ -164,9 +164,9 @@ help: + @echo " PR=7 SUFFIX='my_additional_suffix' make " + @echo " MR=6 COPR_CONFIG='path/to/the/config/copr/file' make " + @echo " ACTOR= TEST_LIBS=y make test" +- @echo " BUILD_CONTAINER=rhel8 make build_container" +- @echo " TEST_CONTAINER=f34 make test_container" +- @echo " CONTAINER_TOOL=docker TEST_CONTAINER=rhel8 make test_container_no_lint" ++ @echo " BUILD_CONTAINER=el8 make build_container" ++ @echo " TEST_CONTAINER=f42 make test_container" ++ @echo " CONTAINER_TOOL=docker TEST_CONTAINER=el8 make test_container_no_lint" + @echo "" + + clean: +@@ -252,10 +252,10 @@ build_container: + echo "--- Build RPM ${PKGNAME}-${VERSION}-${RELEASE}.el$(DIST_VERSION).rpm in container ---"; + case "$(BUILD_CONTAINER)" in \ + el8) \ +- CONT_FILE="utils/container-builds/Containerfile.ubi8"; \ ++ CONT_FILE="utils/container-builds/Containerfile.el8"; \ + ;; \ + el9) \ +- CONT_FILE="utils/container-builds/Containerfile.ubi9"; \ ++ CONT_FILE="utils/container-builds/Containerfile.el9"; \ + ;; \ + "") \ + echo "BUILD_CONTAINER must be set"; \ +@@ -379,7 +379,6 @@ test_no_lint: + done; \ + $(_PYTHON_VENV) -m pytest $(REPORT_ARG) $(TEST_PATHS) $(LIBRARY_PATH) $(PYTEST_ARGS) + +- + test: lint test_no_lint + + # container images act like a cache so that dependencies can only be downloaded once +@@ -416,7 +415,7 @@ lint_container: + @_TEST_CONT_TARGET="lint" $(MAKE) test_container + + lint_container_all: +- @for container in "f34" "rhel8" "rhel9"; do \ ++ @for container in f42 el{8,9}; do \ + TEST_CONTAINER=$$container $(MAKE) lint_container || exit 1; \ + done + +@@ -426,20 +425,20 @@ lint_container_all: + # because e.g RHEL8 to RHEL9 IPU must work on python3.6 and python3.9. + test_container: + @case $(_TEST_CONTAINER) in \ +- f34) \ +- export CONT_FILE="utils/container-tests/Containerfile.f34"; \ +- export _VENV="python3.9"; \ ++ f42) \ ++ export CONT_FILE="utils/container-tests/Containerfile.f42"; \ ++ export _VENV="python3.13"; \ + ;; \ +- rhel8) \ +- export CONT_FILE="utils/container-tests/Containerfile.rhel8"; \ ++ el8) \ ++ export CONT_FILE="utils/container-tests/Containerfile.el8"; \ + export _VENV="python3.6"; \ + ;; \ +- rhel9) \ +- export CONT_FILE="utils/container-tests/Containerfile.rhel9"; \ ++ el9) \ ++ export CONT_FILE="utils/container-tests/Containerfile.el9"; \ + export _VENV="python3.9"; \ + ;; \ + *) \ +- echo "Error: Available containers are: f34, rhel8, rhel9"; exit 1; \ ++ echo "Error: Available containers are: f42, el8, el9"; exit 1; \ + ;; \ + esac; \ + export TEST_IMAGE="leapp-repo-tests-$(_TEST_CONTAINER)"; \ +@@ -448,7 +447,8 @@ test_container: + export _CONT_NAME="leapp-repo-tests-$(_TEST_CONTAINER)-cont"; \ + $(_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 && \ ++ $(_CONTAINER_TOOL) exec $$_CONT_NAME rsync -aur --delete --exclude 'tut/' --exclude 'docs/' --exclude '**/__pycache__/' --exclude 'packaging/' --exclude '.git/' /repo/ /repocopy && \ ++ $(_CONTAINER_TOOL) exec $$_CONT_NAME rsync -aur --delete --exclude '**/__pycache__/' /repo/commands/ /repocopy/tut/lib/$$_VENV/site-packages/leapp/cli/commands/ && \ + export res=0; \ + case $$_VENV in \ + python3.6) \ +@@ -471,7 +471,7 @@ test_container: + exit $$res + + test_container_all: +- @for container in "f34" "rhel8" "rhel9"; do \ ++ @for container in "f42" "el8" "el9"; do \ + TEST_CONTAINER=$$container $(MAKE) test_container || exit 1; \ + done + +@@ -479,14 +479,13 @@ test_container_no_lint: + @_TEST_CONT_TARGET="test_no_lint" $(MAKE) test_container + + test_container_all_no_lint: +- @for container in "f34" "rhel8" "rhel9"; do \ ++ @for container in f42 el{8,9}; do \ + TEST_CONTAINER=$$container $(MAKE) test_container_no_lint || exit 1; \ + done + + # clean all testing and building containers and their images + clean_containers: +- @for i in "leapp-repo-tests-f34" "leapp-repo-tests-rhel8" \ +- "leapp-repo-tests-rhel9" "leapp-repo-build-el8"; do \ ++ @for i in leapp-repo-tests-f42 leapp-repo-tests-el{8,9} leapp-repo-build-el{8,9}; do \ + $(_CONTAINER_TOOL) kill "$$i-cont" || :; \ + $(_CONTAINER_TOOL) rm "$$i-cont" || :; \ + $(_CONTAINER_TOOL) rmi "$$i" || :; \ diff --git a/ci/.gitignore b/ci/.gitignore new file mode 100644 index 00000000..e6f97f0f @@ -3421,6 +4318,104 @@ index 00000000..370758e6 + end + end +end +diff --git a/commands/preupgrade/__init__.py b/commands/preupgrade/__init__.py +index 6443bd8a..f24e779a 100644 +--- a/commands/preupgrade/__init__.py ++++ b/commands/preupgrade/__init__.py +@@ -26,7 +26,7 @@ from leapp.utils.output import beautify_actor_exception, report_errors, report_i + help='Use only custom repositories and skip actions with Red Hat Subscription Manager.' + ' This only has effect on Red Hat Enterprise Linux systems.' + ) +-@command_opt('no-insights-register', is_flag=True, help='Do not register into Red Hat Insights') ++@command_opt('no-insights-register', is_flag=True, help='Do not register into Red Hat Lightspeed') + @command_opt('no-rhsm-facts', is_flag=True, help='Do not store migration information using Red Hat ' + 'Subscription Manager. Automatically implied by --no-rhsm.') + @command_opt('enablerepo', action='append', metavar='', +diff --git a/commands/tests/test_upgrade_paths.py b/commands/tests/test_upgrade_paths.py +index 89b5eb71..9bdf5792 100644 +--- a/commands/tests/test_upgrade_paths.py ++++ b/commands/tests/test_upgrade_paths.py +@@ -42,6 +42,11 @@ def test_get_target_version(mock_open, monkeypatch): + }, + ) + def test_get_target_release(mock_open, monkeypatch): # do not remove mock_open ++ # Make it look like it's RHEL even on centos, because that's what the test ++ # assumes. ++ # Otherwise the test, when ran on Centos, fails because it works ++ # with MAJOR.MINOR version format while Centos uses MAJOR format. ++ monkeypatch.setattr(command_utils, 'get_distro_id', lambda: 'rhel') + monkeypatch.setattr(command_utils, 'get_os_release_version_id', lambda x: '8.6') + + # make sure env var LEAPP_DEVEL_TARGET_RELEASE takes precedence +diff --git a/commands/upgrade/__init__.py b/commands/upgrade/__init__.py +index 36be0719..c5900c0d 100644 +--- a/commands/upgrade/__init__.py ++++ b/commands/upgrade/__init__.py +@@ -32,7 +32,7 @@ from leapp.utils.output import beautify_actor_exception, report_errors, report_i + help='Use only custom repositories and skip actions with Red Hat Subscription Manager.' + ' This only has effect on Red Hat Enterprise Linux systems.' + ) +-@command_opt('no-insights-register', is_flag=True, help='Do not register into Red Hat Insights') ++@command_opt('no-insights-register', is_flag=True, help='Do not register into Red Hat Lightspeed') + @command_opt('no-rhsm-facts', is_flag=True, help='Do not store migration information using Red Hat ' + 'Subscription Manager. Automatically implied by --no-rhsm.') + @command_opt('enablerepo', action='append', metavar='', +diff --git a/commands/upgrade/breadcrumbs.py b/commands/upgrade/breadcrumbs.py +index 3a3dcde3..95a551c3 100644 +--- a/commands/upgrade/breadcrumbs.py ++++ b/commands/upgrade/breadcrumbs.py +@@ -36,7 +36,7 @@ def _flattened(d): + return dict(items) + + +-class _BreadCrumbs(object): ++class _BreadCrumbs: + def __init__(self, activity): + self._crumbs = { + 'activity': activity, +@@ -80,7 +80,8 @@ class _BreadCrumbs(object): + # even though it shouldn't though, just ignore it + pass + +- def _commit_rhsm_facts(self): ++ @staticmethod ++ def _commit_rhsm_facts(): + if runs_in_container(): + return + cmd = ['/usr/sbin/subscription-manager', 'facts', '--update'] +@@ -122,7 +123,8 @@ class _BreadCrumbs(object): + except OSError: + sys.stderr.write('WARNING: Could not write to /etc/migration-results\n') + +- def _get_packages(self): ++ @staticmethod ++ def _get_packages(): + cmd = ['/bin/bash', '-c', 'rpm -qa --queryformat="%{nevra} %{SIGPGP:pgpsig}\n" | grep -Ee "leapp|snactor"'] + res = _call(cmd, lambda x, y: None, lambda x, y: None) + if res.get('exit_code', None) == 0: +@@ -131,7 +133,8 @@ class _BreadCrumbs(object): + for t in [line.strip().split(' ', 1) for line in res['stdout'].split('\n') if line.strip()]] + return [] + +- def _verify_leapp_pkgs(self): ++ @staticmethod ++ def _verify_leapp_pkgs(): + if not os.environ.get('LEAPP_IPU_IN_PROGRESS'): + return [] + upg_path = os.environ.get('LEAPP_IPU_IN_PROGRESS').split('to') +diff --git a/docs/source/configuring-ipu/envars.md b/docs/source/configuring-ipu/envars.md +index a042ba4a..09634df2 100644 +--- a/docs/source/configuring-ipu/envars.md ++++ b/docs/source/configuring-ipu/envars.md +@@ -21,7 +21,7 @@ Overrides the automatically detected storage device with GRUB core (e.g. /dev/sd + Set to 1 to disable RPM GPG checks (same as yum/dnf –nogpgckeck option). It‘s equivalent to the --nogpgcheck leapp option. + + #### LEAPP_NO_INSIGHTS_REGISTER +-If set to `1`, Leapp does not register the system into Red Hat Insights automatically. It‘s equivalent to the --no-insights-register leapp option. ++If set to `1`, Leapp does not register the system into Red Hat Lightspeed automatically. It‘s equivalent to the --no-insights-register leapp option. + + #### LEAPP_NO_NETWORK_RENAMING + If set to `1`, the actor responsible to handle NICs names ends without doing anything. The actor usually creates UDEV rules to preserve original NICs in case they are changed. However, in some cases it‘s not wanted and it leads in malfunction network configuration (e.g. in case the bonding is configured on the system). It‘s expected that NICs have to be handled manually if needed. diff --git a/etc/leapp/transaction/to_reinstall b/etc/leapp/transaction/to_reinstall new file mode 100644 index 00000000..c6694a8e @@ -3444,9 +4439,27 @@ index b28ec57c..6882488a 100644 '--make-default', '--args', args_to_add_str 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 e5f632bc..3e8d8c7b 100644 +index e5f632bc..b2ced8ae 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 +@@ -24,7 +24,7 @@ from leapp.models import ( + CUR_DIR = os.path.dirname(os.path.abspath(__file__)) + + +-class run_mocked(object): ++class run_mocked: + def __init__(self): + self.args = [] + +@@ -32,7 +32,7 @@ class run_mocked(object): + self.args.append(args) + + +-class write_to_file_mocked(object): ++class write_to_file_mocked: + def __init__(self): + self.content = None + @@ -53,7 +53,7 @@ run_args_add = [ '/usr/sbin/grubby', '--add-kernel', '/abc', @@ -3456,6 +4469,210 @@ index e5f632bc..3e8d8c7b 100644 '--copy-default', '--make-default', '--args', +diff --git a/repos/system_upgrade/common/actors/adjustlocalrepos/tests/test_adjustlocalrepos.py b/repos/system_upgrade/common/actors/adjustlocalrepos/tests/test_adjustlocalrepos.py +index 41cff200..6abf4189 100644 +--- a/repos/system_upgrade/common/actors/adjustlocalrepos/tests/test_adjustlocalrepos.py ++++ b/repos/system_upgrade/common/actors/adjustlocalrepos/tests/test_adjustlocalrepos.py +@@ -83,7 +83,7 @@ def test_adjust_local_file_url(repo_file_line, expected_adjusted_repo_file_line) + assert adjusted_repo_file_line == expected_adjusted_repo_file_line + + +-class MockedFileDescriptor(object): ++class MockedFileDescriptor: + + def __init__(self, repo_file, expected_new_repo_file): + self.repo_file = repo_file +@@ -113,7 +113,7 @@ class MockedFileDescriptor(object): + assert expected_repo_file_contents == new_contents + + +-class MockedContext(object): ++class MockedContext: + + def __init__(self, repo_contents, expected_repo_contents): + self.repo_contents = repo_contents +diff --git a/repos/system_upgrade/common/actors/applytransactionworkarounds/tests/unit_test_applytransactionworkarounds.py b/repos/system_upgrade/common/actors/applytransactionworkarounds/tests/unit_test_applytransactionworkarounds.py +index 8fe33645..96b8094f 100644 +--- a/repos/system_upgrade/common/actors/applytransactionworkarounds/tests/unit_test_applytransactionworkarounds.py ++++ b/repos/system_upgrade/common/actors/applytransactionworkarounds/tests/unit_test_applytransactionworkarounds.py +@@ -7,7 +7,7 @@ from leapp.models import DNFWorkaround + + class ShowMessageCurrentActorMocked(CurrentActorMocked): + def __init__(self, *args, **kwargs): +- super(ShowMessageCurrentActorMocked, self).__init__(*args, **kwargs) ++ super().__init__(*args, **kwargs) + self._show_messages = [] + + @property +@@ -18,7 +18,7 @@ class ShowMessageCurrentActorMocked(CurrentActorMocked): + self._show_messages.append(message) + + +-class MockedNotIsolatedActions(object): ++class MockedNotIsolatedActions: + def __init__(self): + self.called = 0 + self.args = None +diff --git a/repos/system_upgrade/common/actors/biosdevname/tests/test_biosdevname.py b/repos/system_upgrade/common/actors/biosdevname/tests/test_biosdevname.py +index c60aa7a4..427eea54 100644 +--- a/repos/system_upgrade/common/actors/biosdevname/tests/test_biosdevname.py ++++ b/repos/system_upgrade/common/actors/biosdevname/tests/test_biosdevname.py +@@ -9,7 +9,7 @@ from leapp.libraries.stdlib import api + from leapp.models import Interface, PCIAddress + + +-class LoggerMocked(object): ++class LoggerMocked: + def __init__(self): + self.infomsg = None + +@@ -32,12 +32,12 @@ def test_biosdevname_enabled(monkeypatch): + assert not biosdevname.is_biosdevname_disabled() + + +-class pyudev_enum_mock(object): ++class pyudev_enum_mock: + def __init__(self, vendor): + self.vendor = vendor + + def match_sys_name(self, _): +- class dev(object): ++ class dev: + attributes = {'sys_vendor': self.vendor} + + return [dev()] +diff --git a/repos/system_upgrade/common/actors/cephvolumescan/libraries/cephvolumescan.py b/repos/system_upgrade/common/actors/cephvolumescan/libraries/cephvolumescan.py +index b2364104..a9bff005 100644 +--- a/repos/system_upgrade/common/actors/cephvolumescan/libraries/cephvolumescan.py ++++ b/repos/system_upgrade/common/actors/cephvolumescan/libraries/cephvolumescan.py +@@ -8,7 +8,7 @@ from leapp.libraries.stdlib import api, CalledProcessError, run + from leapp.models import InstalledRPM + + CEPH_CONF = "/etc/ceph/ceph.conf" +-CONTAINER = "ceph-osd" ++CONTAINER = "ceph-.*osd" + + + def select_osd_container(engine): +@@ -63,7 +63,8 @@ def encrypted_osds_list(): + output = get_ceph_lvm_list() + if output is not None: + try: +- result = [output[key][0]['lv_uuid'] for key in output if output[key][0]['tags']['ceph.encrypted']] ++ for key in output: ++ result.extend([element['lv_uuid'] for element in output[key] if element['tags']['ceph.encrypted']]) + except KeyError: + # TODO: possibly raise a report item with a medium risk factor + # TODO: possibly create list of problematic osds, extend the cephinfo +diff --git a/repos/system_upgrade/common/actors/cephvolumescan/tests/test_cephvolumescan.py b/repos/system_upgrade/common/actors/cephvolumescan/tests/test_cephvolumescan.py +index f3811c45..168b8fc2 100644 +--- a/repos/system_upgrade/common/actors/cephvolumescan/tests/test_cephvolumescan.py ++++ b/repos/system_upgrade/common/actors/cephvolumescan/tests/test_cephvolumescan.py +@@ -8,6 +8,8 @@ from leapp.reporting import Report + CONT_PS_COMMAND_OUTPUT = { + "stdout": + """CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ++ b5a3d8ef25b9 undercloud-0.ctlplane.redhat.local:8787/rh-osbs/rhceph:5 "-n osd.8 -f --set..." \ ++ 2 hours ago Up 2 hours ago ceph-bea1a933-0846-4aaa-8223-62cb8cb2873c-osd-8 + 50d96fe72019 registry.redhat.io/rhceph/rhceph-4-rhel8:latest "/opt/ceph-contain..." \ + 2 weeks ago Up 2 weeks ceph-osd-0 + f93c17b49c40 registry.redhat.io/rhceph/rhceph-4-rhel8:latest "/opt/ceph-contain..." \ +@@ -41,6 +43,32 @@ CEPH_VOLUME_OUTPUT = { + "type":"block", + "vg_name":"ceph-a696c40d-6b1d-448d-a40e-fadca22b64bc" + } ++ ], ++ "8":[ ++ { ++ "devices": [ ++ "/dev/nvme0n1" ++ ], ++ "lv_name": "osd-db-b04857a0-a2a2-40c3-a490-cbe1f892a76c", ++ "lv_uuid": "zcvGix-drzz-JwzP-6ktU-Od6W-N5jL-kxRFa3", ++ "tags":{ ++ "ceph.encrypted":"1" ++ }, ++ "type": "db", ++ "vg_name": "ceph-b78309b3-bd80-4399-87a3-ac647b216b63" ++ }, ++ { ++ "devices": [ ++ "/dev/sdb" ++ ], ++ "lv_name": "osd-block-477c303f-5eaf-4be8-b5cc-f6073eb345bf", ++ "lv_uuid": "Mz1dep-D715-Wxh1-zUuS-0cOA-mKXE-UxaEM3", ++ "tags":{ ++ "ceph.encrypted":"1" ++ }, ++ "type": "block", ++ "vg_name": "ceph-e3e0345b-8be1-40a7-955a-378ba967f954" ++ } + ] + }""" + } +@@ -51,7 +79,19 @@ CEPH_LVM_LIST = { + 'lv_uuid': 'Tyc0TH-RDxr-ebAF-9mWF-Kh5R-YnvJ-cEcGVn', + 'tags': {'ceph.encrypted': '1'}, + 'type': 'block', +- 'vg_name': 'ceph-a696c40d-6b1d-448d-a40e-fadca22b64bc'}] ++ 'vg_name': 'ceph-a696c40d-6b1d-448d-a40e-fadca22b64bc'}], ++ '8': [{'devices': ['/dev/nvme0n1'], ++ 'lv_name': 'osd-db-b04857a0-a2a2-40c3-a490-cbe1f892a76c', ++ 'lv_uuid': 'zcvGix-drzz-JwzP-6ktU-Od6W-N5jL-kxRFa3', ++ 'tags': {'ceph.encrypted': '1'}, ++ 'type': 'db', ++ 'vg_name': 'ceph-b78309b3-bd80-4399-87a3-ac647b216b63'}, ++ {'devices': ['/dev/sdb'], ++ 'lv_name': 'osd-block-477c303f-5eaf-4be8-b5cc-f6073eb345bf', ++ 'lv_uuid': 'Mz1dep-D715-Wxh1-zUuS-0cOA-mKXE-UxaEM3', ++ 'tags': {'ceph.encrypted': '1'}, ++ 'type': 'block', ++ 'vg_name': 'ceph-e3e0345b-8be1-40a7-955a-378ba967f954'}] + } + + +@@ -60,7 +100,7 @@ def test_select_osd_container(m_run): + + m_run.return_value = CONT_PS_COMMAND_OUTPUT + +- assert cephvolumescan.select_osd_container('docker') == "ceph-osd-0" ++ assert cephvolumescan.select_osd_container('docker') == "ceph-bea1a933-0846-4aaa-8223-62cb8cb2873c-osd-8" + + + @patch('leapp.libraries.actor.cephvolumescan.has_package') +@@ -82,4 +122,8 @@ def test_encrypted_osds_list(m_get_ceph_lvm_list, m_isfile): + m_get_ceph_lvm_list.return_value = CEPH_LVM_LIST + m_isfile.return_value = True + +- assert cephvolumescan.encrypted_osds_list() == ['Tyc0TH-RDxr-ebAF-9mWF-Kh5R-YnvJ-cEcGVn'] ++ assert cephvolumescan.encrypted_osds_list() == [ ++ 'Tyc0TH-RDxr-ebAF-9mWF-Kh5R-YnvJ-cEcGVn', ++ 'zcvGix-drzz-JwzP-6ktU-Od6W-N5jL-kxRFa3', ++ 'Mz1dep-D715-Wxh1-zUuS-0cOA-mKXE-UxaEM3' ++ ] +diff --git a/repos/system_upgrade/common/actors/checkbootavailspace/tests/unit_test_checkbootavailspace.py b/repos/system_upgrade/common/actors/checkbootavailspace/tests/unit_test_checkbootavailspace.py +index 094164c7..fbcd0820 100644 +--- a/repos/system_upgrade/common/actors/checkbootavailspace/tests/unit_test_checkbootavailspace.py ++++ b/repos/system_upgrade/common/actors/checkbootavailspace/tests/unit_test_checkbootavailspace.py +@@ -10,7 +10,7 @@ from leapp.libraries.common.testutils import create_report_mocked + from leapp.utils.report import is_inhibitor + + +-class fake_get_avail_bytes_on_boot(object): ++class fake_get_avail_bytes_on_boot: + def __init__(self, size): + self.size = size + +diff --git a/repos/system_upgrade/common/actors/checkconsumedassets/tests/test_asset_version_checking.py b/repos/system_upgrade/common/actors/checkconsumedassets/tests/test_asset_version_checking.py +index 9c324b44..f37dcea4 100644 +--- a/repos/system_upgrade/common/actors/checkconsumedassets/tests/test_asset_version_checking.py ++++ b/repos/system_upgrade/common/actors/checkconsumedassets/tests/test_asset_version_checking.py +@@ -44,4 +44,4 @@ def test_make_report_entries_with_unique_urls(): + docs_url_to_title_map = {'/path/to/asset1': ['asset1_title1', 'asset1_title2'], + '/path/to/asset2': ['asset2_title']} + report_urls = check_consumed_assets_lib.make_report_entries_with_unique_urls(docs_url_to_title_map) +- assert set([ru.value['url'] for ru in report_urls]) == {'/path/to/asset1', '/path/to/asset2'} ++ assert {ru.value['url'] for ru in report_urls} == {'/path/to/asset1', '/path/to/asset2'} diff --git a/repos/system_upgrade/common/actors/checkdnfpluginpath/actor.py b/repos/system_upgrade/common/actors/checkdnfpluginpath/actor.py new file mode 100644 index 00000000..34055886 @@ -3624,6 +4841,338 @@ index 00000000..52f5af9d + api.produce(ActiveVendorList(data=list(active_vendors))) + else: + self.log.info("No active vendors found, vendor list not generated") +diff --git a/repos/system_upgrade/common/actors/checkinsightsautoregister/actor.py b/repos/system_upgrade/common/actors/checkinsightsautoregister/actor.py +index 70b3b670..52108566 100644 +--- a/repos/system_upgrade/common/actors/checkinsightsautoregister/actor.py ++++ b/repos/system_upgrade/common/actors/checkinsightsautoregister/actor.py +@@ -7,7 +7,7 @@ from leapp.tags import ChecksPhaseTag, IPUWorkflowTag + + class CheckInsightsAutoregister(Actor): + """ +- Checks if system can be automatically registered into Red Hat Insights ++ Checks if system can be automatically registered into Red Hat Lightspeed + + The registration is skipped if NO_INSIGHTS_REGISTER=1 environment variable + is set, the --no-insights-register command line argument present. if the +diff --git a/repos/system_upgrade/common/actors/checkinsightsautoregister/libraries/checkinsightsautoregister.py b/repos/system_upgrade/common/actors/checkinsightsautoregister/libraries/checkinsightsautoregister.py +index 762f3c08..8e26485b 100644 +--- a/repos/system_upgrade/common/actors/checkinsightsautoregister/libraries/checkinsightsautoregister.py ++++ b/repos/system_upgrade/common/actors/checkinsightsautoregister/libraries/checkinsightsautoregister.py +@@ -24,9 +24,9 @@ def _ensure_package(package): + def _report_registration_info(installing_client): + pkg_msg = " The '{}' package required for the registration will be installed during the upgrade." + +- title = "Automatic registration into Red Hat Insights" ++ title = "Automatic registration into Red Hat Lightspeed" + summary = ( +- "After the upgrade, this system will be automatically registered into Red Hat Insights." ++ "After the upgrade, this system will be automatically registered into Red Hat Lightspeed." + "{}" + " To skip the automatic registration, use the '--no-insights-register' command line option or" + " set the LEAPP_NO_INSIGHTS_REGISTER environment variable." +@@ -38,6 +38,7 @@ def _report_registration_info(installing_client): + reporting.Summary(summary), + reporting.Severity(reporting.Severity.INFO), + reporting.Groups([reporting.Groups.SERVICES]), ++ reporting.Key('693963253195f418526f045b6d630a1f4c7a193d'), + ] + ) + +diff --git a/repos/system_upgrade/common/actors/checkluks/libraries/checkluks.py b/repos/system_upgrade/common/actors/checkluks/libraries/checkluks.py +index 57a94e9d..84e8e61f 100644 +--- a/repos/system_upgrade/common/actors/checkluks/libraries/checkluks.py ++++ b/repos/system_upgrade/common/actors/checkluks/libraries/checkluks.py +@@ -3,6 +3,7 @@ from leapp.libraries.common.config.version import get_source_major_version + from leapp.libraries.stdlib import api + from leapp.models import ( + CephInfo, ++ CopyFile, + DracutModule, + LuksDumps, + StorageInfo, +@@ -26,7 +27,7 @@ def _formatted_list_output(input_list, sep=FMT_LIST_SEPARATOR): + + + def _at_least_one_tpm_token(luks_dump): +- return any([token.token_type == "clevis-tpm2" for token in luks_dump.tokens]) ++ return any(token.token_type == "clevis-tpm2" for token in luks_dump.tokens) + + + def _get_ceph_volumes(): +@@ -156,8 +157,13 @@ def check_invalid_luks_devices(): + 'tpm2-tools', + 'tpm2-abrmd' + ] +- api.produce(TargetUserSpaceUpgradeTasks(install_rpms=required_crypt_rpms)) +- api.produce(UpgradeInitramfsTasks(include_dracut_modules=[ ++ api.produce(TargetUserSpaceUpgradeTasks( ++ copy_files=[CopyFile(src="/etc/crypttab")], ++ install_rpms=required_crypt_rpms) ++ ) ++ api.produce(UpgradeInitramfsTasks( ++ include_files=['/etc/crypttab'], ++ include_dracut_modules=[ + DracutModule(name='clevis'), + DracutModule(name='clevis-pin-tpm2') + ]) +diff --git a/repos/system_upgrade/common/actors/checkmemory/libraries/checkmemory.py b/repos/system_upgrade/common/actors/checkmemory/libraries/checkmemory.py +index 808c9662..040b404b 100644 +--- a/repos/system_upgrade/common/actors/checkmemory/libraries/checkmemory.py ++++ b/repos/system_upgrade/common/actors/checkmemory/libraries/checkmemory.py +@@ -34,8 +34,8 @@ def process(): + if minimum_req_error: + title = 'Minimum memory requirements for RHEL {} are not met'.format(version.get_target_major_version()) + summary = 'Memory detected: {} MiB, required: {} MiB'.format( +- int(minimum_req_error['detected'] / 1024), # noqa: W1619; pylint: disable=old-division +- int(minimum_req_error['minimal_req'] / 1024), # noqa: W1619; pylint: disable=old-division ++ int(minimum_req_error['detected'] / 1024), ++ int(minimum_req_error['minimal_req'] / 1024), + ) + reporting.create_report([ + reporting.Title(title), +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 1e43f403..8ec8d17f 100644 +--- a/repos/system_upgrade/common/actors/checksaphana/tests/test_checksaphana.py ++++ b/repos/system_upgrade/common/actors/checksaphana/tests/test_checksaphana.py +@@ -97,7 +97,7 @@ def _parse_manifest_data(manifest): + return result + + +-class MockSapHanaInstanceInfo(object): ++class MockSapHanaInstanceInfo: + def __init__(self, name, number, path, admin, manifest_data, running=True): + self.manifest = _parse_manifest_data(manifest_data) + self.name = name +@@ -118,7 +118,7 @@ def _gen_instance_info(name, manifest_data, index, running=True): + ) + + +-class MockSapHanaInfo(object): ++class MockSapHanaInfo: + def __init__(self, v1names, v2names, v2lownames, running=None): + self.installed = bool(v1names or v2names or v2lownames) + self.running = running if running is not None else self.installed +@@ -151,7 +151,7 @@ def _consume_mock_sap_hana_info(v1names=(), v2names=(), v2lownames=(), running=T + return _consume + + +-class MockSAPHanaVersionInstance(object): ++class MockSAPHanaVersionInstance: + def __init__(self, major, rev, patchlevel): + self.name = "TestName" + +@@ -284,7 +284,7 @@ def test_checksaphana_perform_check(monkeypatch): + # Expected 3 reports due to v1names + v2lownames + running + assert len(reports) == 3 + # Verifies that all expected title patterns are within the reports and not just coincidentally 3 +- assert all([any([pattern(report) for report in reports]) for pattern in EXPECTED_TITLE_PATTERNS.values()]) ++ assert all(any(pattern(report) for report in reports) for pattern in EXPECTED_TITLE_PATTERNS.values()) + + list_clear(reports) + monkeypatch.setattr(checksaphana.api, 'consume', _consume_mock_sap_hana_info( +@@ -294,4 +294,7 @@ def test_checksaphana_perform_check(monkeypatch): + # Expected 2 reports due to v1names + v2lownames + assert len(reports) == 2 + # Verifies that all expected title patterns are within the reports and not just coincidentally 2 +- assert all([any([EXPECTED_TITLE_PATTERNS[pattern](report) for report in reports]) for pattern in ['v1', 'low']]) ++ assert all( ++ any(EXPECTED_TITLE_PATTERNS[pattern](report) for report in reports) ++ for pattern in ['v1', 'low'] ++ ) +diff --git a/repos/system_upgrade/common/actors/checktargetrepos/actor.py b/repos/system_upgrade/common/actors/checktargetrepos/actor.py +index d61fb685..a5bdde10 100644 +--- a/repos/system_upgrade/common/actors/checktargetrepos/actor.py ++++ b/repos/system_upgrade/common/actors/checktargetrepos/actor.py +@@ -6,7 +6,9 @@ from leapp.tags import ChecksPhaseTag, IPUWorkflowTag + + class Checktargetrepos(Actor): + """ +- Check whether target yum repositories are specified. ++ Check whether target dnf repositories are specified on RHEL. ++ ++ NOTE: this actor does nothing on distros other than RHEL. + + RHSM | RHUI | ER | CTR | CTRF || result + -----+------+----+-----+------++------- +diff --git a/repos/system_upgrade/common/actors/checktargetrepos/libraries/checktargetrepos.py b/repos/system_upgrade/common/actors/checktargetrepos/libraries/checktargetrepos.py +index c286ed4f..ea21e1de 100644 +--- a/repos/system_upgrade/common/actors/checktargetrepos/libraries/checktargetrepos.py ++++ b/repos/system_upgrade/common/actors/checktargetrepos/libraries/checktargetrepos.py +@@ -2,12 +2,14 @@ from leapp import reporting + from leapp.libraries.common import config, rhsm + from leapp.libraries.common.config.version import get_target_major_version + from leapp.libraries.stdlib import api +-from leapp.models import CustomTargetRepositoryFile, RHUIInfo, TargetRepositories ++from leapp.models import CustomTargetRepositoryFile, RHELTargetRepository, RHUIInfo, TargetRepositories ++from leapp.utils.deprecation import suppress_deprecation + + # TODO: we need to provide this path in a shared library + CUSTOM_REPO_PATH = '/etc/leapp/files/leapp_upgrade_repositories.repo' + + ++@suppress_deprecation(RHELTargetRepository) # member of TargetRepositories + def _any_custom_repo_defined(): + for tr in api.consume(TargetRepositories): + if tr.custom_repos: +@@ -38,9 +40,10 @@ def process(): + + rhui_info = next(api.consume(RHUIInfo), None) + +- if not rhsm.skip_rhsm() or rhui_info: +- # getting RH repositories through RHSM or RHUI; resolved by seatbelts +- # implemented in other actors ++ if config.get_distro_id() != 'rhel' or (not rhsm.skip_rhsm() or rhui_info): ++ # RHEL: getting RH repositories through RHSM or RHUI; ++ # resolved by seatbelts in other actors ++ # other: distro repos provided by the distro directly, seatbelts elsewhere + return + + # rhsm skipped; take your seatbelts please +diff --git a/repos/system_upgrade/common/actors/checktargetrepos/tests/test_checktargetrepos.py b/repos/system_upgrade/common/actors/checktargetrepos/tests/test_checktargetrepos.py +index c1ca8cd1..dfe5d06a 100644 +--- a/repos/system_upgrade/common/actors/checktargetrepos/tests/test_checktargetrepos.py ++++ b/repos/system_upgrade/common/actors/checktargetrepos/tests/test_checktargetrepos.py +@@ -8,16 +8,15 @@ from leapp.libraries.stdlib import api + from leapp.models import ( + CustomTargetRepository, + CustomTargetRepositoryFile, +- EnvVar, +- Report, +- RepositoryData, ++ DistroTargetRepository, + RHELTargetRepository, + TargetRepositories + ) ++from leapp.utils.deprecation import suppress_deprecation + from leapp.utils.report import is_inhibitor + + +-class MockedConsume(object): ++class MockedConsume: + def __init__(self, *args): + self._msgs = [] + for arg in args: +@@ -32,11 +31,21 @@ class MockedConsume(object): + return iter([msg for msg in self._msgs if isinstance(msg, model)]) + + +-_RHEL_REPOS = [ +- RHELTargetRepository(repoid='repo1'), +- RHELTargetRepository(repoid='repo2'), +- RHELTargetRepository(repoid='repo3'), +- RHELTargetRepository(repoid='repo4'), ++@suppress_deprecation(RHELTargetRepository) ++def _test_rhel_repos(): ++ return [ ++ RHELTargetRepository(repoid='repo1'), ++ RHELTargetRepository(repoid='repo2'), ++ RHELTargetRepository(repoid='repo3'), ++ RHELTargetRepository(repoid='repo4'), ++ ] ++ ++ ++_DISTRO_REPOS = [ ++ DistroTargetRepository(repoid='repo1'), ++ DistroTargetRepository(repoid='repo2'), ++ DistroTargetRepository(repoid='repo3'), ++ DistroTargetRepository(repoid='repo4'), + ] + + _CUSTOM_REPOS = [ +@@ -46,16 +55,17 @@ _CUSTOM_REPOS = [ + CustomTargetRepository(repoid='repo4', name='repo4name', baseurl=None, enabled=True), + ] + +-_TARGET_REPOS_CUSTOM = TargetRepositories(rhel_repos=_RHEL_REPOS, custom_repos=_CUSTOM_REPOS) +-_TARGET_REPOS_NO_CUSTOM = TargetRepositories(rhel_repos=_RHEL_REPOS) ++_TARGET_REPOS_CUSTOM = TargetRepositories( ++ rhel_repos=_test_rhel_repos(), distro_repos=_DISTRO_REPOS, custom_repos=_CUSTOM_REPOS ++) ++_TARGET_REPOS_NO_CUSTOM = TargetRepositories(rhel_repos=_test_rhel_repos(), distro_repos=_DISTRO_REPOS) + _CUSTOM_TARGET_REPOFILE = CustomTargetRepositoryFile(file='/etc/leapp/files/leapp_upgrade_repositories.repo') + + + def test_checktargetrepos_rhsm(monkeypatch): + monkeypatch.setattr(reporting, 'create_report', create_report_mocked()) + monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: False) +- monkeypatch.setattr(api, 'consume', MockedConsume()) +- monkeypatch.setattr(checktargetrepos, 'get_target_major_version', lambda: '8') ++ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked()) + checktargetrepos.process() + assert reporting.create_report.called == 0 + +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 ea154173..5dcdd967 100644 +--- a/repos/system_upgrade/common/actors/cloud/checkrhui/libraries/checkrhui.py ++++ b/repos/system_upgrade/common/actors/cloud/checkrhui/libraries/checkrhui.py +@@ -22,6 +22,7 @@ from leapp.models import ( + CustomTargetRepository, + DNFPluginTask, + InstalledRPM, ++ RHELTargetRepository, + RHUIInfo, + RpmTransactionTasks, + TargetRepositories, +@@ -30,6 +31,7 @@ from leapp.models import ( + TargetRHUISetupInfo, + TargetUserSpacePreupgradeTasks + ) ++from leapp.utils.deprecation import suppress_deprecation + + MatchingSetup = namedtuple('MatchingSetup', ['family', 'description']) + +@@ -370,11 +372,12 @@ def emit_rhui_setup_tasks_based_on_config(rhui_config_dict): + api.produce(rhui_info) + + ++@suppress_deprecation(RHELTargetRepository) # member of TargetRepositories + 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=[]) ++ target_repos = TargetRepositories(custom_repos=custom_repos, rhel_repos=[], distro_repos=[]) + api.produce(target_repos) + + +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 3ac9c1b8..02ca352e 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 +@@ -468,6 +468,7 @@ def test_request_configured_repos_to_be_enabled(monkeypatch): + + target_repos = api.produce.model_instances[0] + assert isinstance(target_repos, TargetRepositories) ++ assert not target_repos.distro_repos + assert not target_repos.rhel_repos + + custom_repoids = sorted(custom_repo_model.repoid for custom_repo_model in target_repos.custom_repos) +diff --git a/repos/system_upgrade/common/actors/cloud/convertgrubenvtofile/tests/test_convertgrubenvtofile.py b/repos/system_upgrade/common/actors/cloud/convertgrubenvtofile/tests/test_convertgrubenvtofile.py +index c4534bd6..257060cc 100644 +--- a/repos/system_upgrade/common/actors/cloud/convertgrubenvtofile/tests/test_convertgrubenvtofile.py ++++ b/repos/system_upgrade/common/actors/cloud/convertgrubenvtofile/tests/test_convertgrubenvtofile.py +@@ -14,7 +14,7 @@ def raise_call_error(args=None): + ) + + +-class run_mocked(object): ++class run_mocked: + def __init__(self, raise_err=False): + self.called = 0 + self.args = [] +diff --git a/repos/system_upgrade/common/actors/cloud/scanhybridimage/tests/test_scanhybridimage.py b/repos/system_upgrade/common/actors/cloud/scanhybridimage/tests/test_scanhybridimage.py +index a0f6fd4c..660a1382 100644 +--- a/repos/system_upgrade/common/actors/cloud/scanhybridimage/tests/test_scanhybridimage.py ++++ b/repos/system_upgrade/common/actors/cloud/scanhybridimage/tests/test_scanhybridimage.py +@@ -36,7 +36,7 @@ def raise_call_error(args=None): + ) + + +-class run_mocked(object): ++class run_mocked: + def __init__(self, hypervisor='', raise_err=False): + self.hypervisor = hypervisor + self.called = 0 diff --git a/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh b/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh index 56a94b5d..46c5d9b6 100755 --- a/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh @@ -3844,6 +5393,19 @@ index 366b5cab..d2bf7313 100644 -After=basic.target sysroot.mount +After=basic.target sysroot.mount initrd-fs.target AllowIsolate=yes +diff --git a/repos/system_upgrade/common/actors/createresumeservice/tests/test_createresumeservice.py b/repos/system_upgrade/common/actors/createresumeservice/tests/test_createresumeservice.py +index 5302cdd2..c1cefc37 100644 +--- a/repos/system_upgrade/common/actors/createresumeservice/tests/test_createresumeservice.py ++++ b/repos/system_upgrade/common/actors/createresumeservice/tests/test_createresumeservice.py +@@ -6,7 +6,7 @@ import pytest + + @pytest.mark.skipif(os.getuid() != 0, reason='User is not a root') + @pytest.mark.skipif( +- distro.linux_distribution()[0] == 'Fedora', ++ distro.id() == 'fedora', + reason='default.target.wants does not exists on Fedora distro', + ) + def test_create_resume_service(current_actor_context): diff --git a/repos/system_upgrade/common/actors/distributionsignedrpmscanner/actor.py b/repos/system_upgrade/common/actors/distributionsignedrpmscanner/actor.py index 003f3fc5..9e7bbf4a 100644 --- a/repos/system_upgrade/common/actors/distributionsignedrpmscanner/actor.py @@ -4013,6 +5575,34 @@ index f42909f0..6383a56f 100644 + + if not has_grub_cfg: + run(['/sbin/grub2-mkconfig', '-o', grub_cfg_path]) +diff --git a/repos/system_upgrade/common/actors/enablerhsmtargetrepos/tests/test_enablerhsmtargetrepos.py b/repos/system_upgrade/common/actors/enablerhsmtargetrepos/tests/test_enablerhsmtargetrepos.py +index 12d53d26..dba38fff 100644 +--- a/repos/system_upgrade/common/actors/enablerhsmtargetrepos/tests/test_enablerhsmtargetrepos.py ++++ b/repos/system_upgrade/common/actors/enablerhsmtargetrepos/tests/test_enablerhsmtargetrepos.py +@@ -13,11 +13,12 @@ from leapp.models import EnvVar, UsedTargetRepositories, UsedTargetRepository + def not_isolated_actions(raise_err=False): + commands_called = [] + +- class MockNotIsolatedActions(object): ++ class MockNotIsolatedActions: + def __init__(self, base_dir=None): + pass + +- def call(self, cmd, **kwargs): ++ @staticmethod ++ def call(cmd, **kwargs): + commands_called.append((cmd, kwargs)) + if raise_err: + raise_call_error() +@@ -33,7 +34,7 @@ def raise_call_error(args=None): + ) + + +-class run_mocked(object): ++class run_mocked: + def __init__(self, raise_err=False): + self.called = 0 + self.args = [] diff --git a/repos/system_upgrade/common/actors/filterrpmtransactionevents/actor.py b/repos/system_upgrade/common/actors/filterrpmtransactionevents/actor.py index 582a5821..18f2c33f 100644 --- a/repos/system_upgrade/common/actors/filterrpmtransactionevents/actor.py @@ -4048,6 +5638,92 @@ index 582a5821..18f2c33f 100644 + to_reinstall=list(to_reinstall), modules_to_reset=list(modules_to_reset.values()), modules_to_enable=list(modules_to_enable.values()))) +diff --git a/repos/system_upgrade/common/actors/forcedefaultboottotargetkernelversion/tests/test_forcedefaultboot_forcedefaultboottotargetkernelversion.py b/repos/system_upgrade/common/actors/forcedefaultboottotargetkernelversion/tests/test_forcedefaultboot_forcedefaultboottotargetkernelversion.py +index b903df45..a39e29a7 100644 +--- a/repos/system_upgrade/common/actors/forcedefaultboottotargetkernelversion/tests/test_forcedefaultboot_forcedefaultboottotargetkernelversion.py ++++ b/repos/system_upgrade/common/actors/forcedefaultboottotargetkernelversion/tests/test_forcedefaultboot_forcedefaultboottotargetkernelversion.py +@@ -69,7 +69,7 @@ initrd=/boot/initramfs-{kernel_version}.img + ''' + + +-class MockedRun(object): ++class MockedRun: + def __init__(self, case): + self.case = case + self.called_setdefault = False +diff --git a/repos/system_upgrade/common/actors/ifcfgscanner/libraries/ifcfgscanner.py b/repos/system_upgrade/common/actors/ifcfgscanner/libraries/ifcfgscanner.py +index 683327b3..f0c8b847 100644 +--- a/repos/system_upgrade/common/actors/ifcfgscanner/libraries/ifcfgscanner.py ++++ b/repos/system_upgrade/common/actors/ifcfgscanner/libraries/ifcfgscanner.py +@@ -18,23 +18,22 @@ def process_ifcfg(filename, secrets=False): + return None + + properties = [] +- for line in open(filename).readlines(): +- try: +- (name, value) = line.split("#")[0].strip().split("=") ++ with open(filename) as f: ++ for line in f: ++ try: ++ (name, value) = line.split("#")[0].strip().split("=") ++ except ValueError: ++ # We're not interested in lines that are not ++ # simple assignments. Play it safe. ++ continue ++ + if secrets: + value = None +- except ValueError: +- # We're not interested in lines that are not +- # simple assignments. Play it safe. +- continue +- +- # Deal with simple quoting. We don't expand anything, nor do +- # multiline strings or anything of that sort. +- if value is not None and len(value) > 1 and value[0] == value[-1]: +- if value.startswith('"') or value.startswith("'"): ++ elif len(value) > 1 and value[0] in ('"', "'") and value[0] == value[-1]: ++ # Deal with simple quoting. We don't expand anything, nor do ++ # multiline strings or anything of that sort. + value = value[1:-1] +- +- properties.append(IfCfgProperty(name=name, value=value)) ++ properties.append(IfCfgProperty(name=name, value=value)) + return properties + + +diff --git a/repos/system_upgrade/common/actors/ifcfgscanner/tests/unit_test_ifcfgscanner.py b/repos/system_upgrade/common/actors/ifcfgscanner/tests/unit_test_ifcfgscanner.py +index d3b4846f..d996de84 100644 +--- a/repos/system_upgrade/common/actors/ifcfgscanner/tests/unit_test_ifcfgscanner.py ++++ b/repos/system_upgrade/common/actors/ifcfgscanner/tests/unit_test_ifcfgscanner.py +@@ -1,5 +1,6 @@ + import errno + import textwrap ++from io import StringIO + from os.path import basename + + import mock +@@ -63,8 +64,7 @@ def test_ifcfg1(monkeypatch): + KEY_TYPE=key + """) + +- mock_config = mock.mock_open(read_data=ifcfg_file) +- with mock.patch(_builtins_open, mock_config): ++ with mock.patch(_builtins_open, return_value=StringIO(ifcfg_file)): + monkeypatch.setattr(ifcfgscanner, "listdir", _listdir_ifcfg) + monkeypatch.setattr(ifcfgscanner.path, "exists", _exists_ifcfg) + monkeypatch.setattr(api, "produce", produce_mocked()) +@@ -110,8 +110,8 @@ def test_ifcfg_key(monkeypatch): + Report ifcfg secrets from keys- file. + """ + +- mock_config = mock.mock_open(read_data="KEY_PASSPHRASE1=Hell0") +- with mock.patch(_builtins_open, mock_config): ++ file_data = "KEY_PASSPHRASE1=Hell0" ++ with mock.patch(_builtins_open, side_effect=lambda *a, **k: StringIO(file_data)): + monkeypatch.setattr(ifcfgscanner, "listdir", _listdir_ifcfg) + monkeypatch.setattr(ifcfgscanner.path, "exists", _exists_keys) + monkeypatch.setattr(api, "produce", produce_mocked()) diff --git a/repos/system_upgrade/common/actors/initramfs/enable_lvm_autoactivation/actor.py b/repos/system_upgrade/common/actors/initramfs/enable_lvm_autoactivation/actor.py new file mode 100644 index 00000000..aba60645 @@ -4160,23 +5836,26 @@ index 00000000..c5150aea + assert api.produce.called == 0 diff --git a/repos/system_upgrade/common/actors/initramfs/mount_units_generator/actor.py b/repos/system_upgrade/common/actors/initramfs/mount_units_generator/actor.py new file mode 100644 -index 00000000..5fe25515 +index 00000000..dd667513 --- /dev/null +++ b/repos/system_upgrade/common/actors/initramfs/mount_units_generator/actor.py -@@ -0,0 +1,22 @@ +@@ -0,0 +1,25 @@ +from leapp.actors import Actor +from leapp.libraries.actor import mount_unit_generator as mount_unit_generator_lib -+from leapp.models import TargetUserSpaceInfo, UpgradeInitramfsTasks ++from leapp.models import LiveModeConfig, TargetUserSpaceInfo, UpgradeInitramfsTasks +from leapp.tags import InterimPreparationPhaseTag, IPUWorkflowTag + + +class MountUnitGenerator(Actor): + """ + Sets up storage initialization using systemd's mount units in the upgrade container. ++ ++ Note that this storage initialization is skipped when the LiveMode is enabled. + """ + + name = 'mount_unit_generator' + consumes = ( ++ LiveModeConfig, + TargetUserSpaceInfo, + ) + produces = ( @@ -4188,10 +5867,10 @@ index 00000000..5fe25515 + mount_unit_generator_lib.setup_storage_initialization() diff --git a/repos/system_upgrade/common/actors/initramfs/mount_units_generator/libraries/mount_unit_generator.py b/repos/system_upgrade/common/actors/initramfs/mount_units_generator/libraries/mount_unit_generator.py new file mode 100644 -index 00000000..e1060559 +index 00000000..943bddd4 --- /dev/null +++ b/repos/system_upgrade/common/actors/initramfs/mount_units_generator/libraries/mount_unit_generator.py -@@ -0,0 +1,307 @@ +@@ -0,0 +1,311 @@ +import os +import shutil +import tempfile @@ -4199,7 +5878,7 @@ index 00000000..e1060559 +from leapp.exceptions import StopActorExecutionError +from leapp.libraries.common import mounting +from leapp.libraries.stdlib import api, CalledProcessError, run -+from leapp.models import TargetUserSpaceInfo, UpgradeInitramfsTasks ++from leapp.models import LiveModeConfig, TargetUserSpaceInfo, UpgradeInitramfsTasks + + +def run_systemd_fstab_generator(output_directory): @@ -4489,8 +6168,12 @@ index 00000000..e1060559 + + +def setup_storage_initialization(): -+ userspace_info = next(api.consume(TargetUserSpaceInfo), None) ++ livemode_config = next(api.consume(LiveModeConfig), None) ++ if livemode_config and livemode_config.is_enabled: ++ api.current_logger().debug('Pre-generation of systemd fstab mount units skipped: The LiveMode is enabled.') ++ return + ++ userspace_info = next(api.consume(TargetUserSpaceInfo), None) + with mounting.NspawnActions(base_dir=userspace_info.path) as upgrade_container_ctx: + with tempfile.TemporaryDirectory(dir='/var/lib/leapp/', prefix='tmp_systemd_fstab_') as workspace_path: + run_systemd_fstab_generator(workspace_path) @@ -4501,7 +6184,7 @@ index 00000000..e1060559 + request_units_inclusion_in_initramfs(mount_unit_files) diff --git a/repos/system_upgrade/common/actors/initramfs/mount_units_generator/tests/test_mount_unit_generation.py b/repos/system_upgrade/common/actors/initramfs/mount_units_generator/tests/test_mount_unit_generation.py new file mode 100644 -index 00000000..b814f6ce +index 00000000..8849ada9 --- /dev/null +++ b/repos/system_upgrade/common/actors/initramfs/mount_units_generator/tests/test_mount_unit_generation.py @@ -0,0 +1,269 @@ @@ -4703,8 +6386,7 @@ index 00000000..b814f6ce + ('/source/dir', ['local-fs.target.requires'], ['unit1.mount', 'unit2.mount']), + ('/source/dir/local-fs.target.requires', [], ['unit1.mount', 'unit2.mount']), + ] -+ for i in tuples_to_yield: -+ yield i ++ yield from tuples_to_yield + + def mock_isdir(path): + return 'local-fs.target.requires' in path @@ -4757,7 +6439,8 @@ index 00000000..b814f6ce + def __init__(self): + self.base_dir = '/container' + -+ def full_path(self, path): ++ @staticmethod ++ def full_path(path): + return os.path.join('/container', path.lstrip('/')) + + mock_container = MockedContainerContext() @@ -4774,6 +6457,307 @@ index 00000000..b814f6ce + ] + assert sorted(files) == sorted(expected_files) + assert mount_unit_generator._delete_file.removal_called +diff --git a/repos/system_upgrade/common/actors/initramfs/targetinitramfsgenerator/tests/test_targetinitramfsgenerator.py b/repos/system_upgrade/common/actors/initramfs/targetinitramfsgenerator/tests/test_targetinitramfsgenerator.py +index b4c9dd89..4df9a485 100644 +--- a/repos/system_upgrade/common/actors/initramfs/targetinitramfsgenerator/tests/test_targetinitramfsgenerator.py ++++ b/repos/system_upgrade/common/actors/initramfs/targetinitramfsgenerator/tests/test_targetinitramfsgenerator.py +@@ -33,7 +33,7 @@ def raise_call_error(args=None): + }) + + +-class RunMocked(object): ++class RunMocked: + + def __init__(self, raise_err=False): + self.called = 0 +diff --git a/repos/system_upgrade/common/actors/initramfs/upgradeinitramfsgenerator/libraries/upgradeinitramfsgenerator.py b/repos/system_upgrade/common/actors/initramfs/upgradeinitramfsgenerator/libraries/upgradeinitramfsgenerator.py +index 02c3fd9d..f7e4a8af 100644 +--- a/repos/system_upgrade/common/actors/initramfs/upgradeinitramfsgenerator/libraries/upgradeinitramfsgenerator.py ++++ b/repos/system_upgrade/common/actors/initramfs/upgradeinitramfsgenerator/libraries/upgradeinitramfsgenerator.py +@@ -271,7 +271,7 @@ def _get_fspace(path, convert_to_mibs=False, coefficient=1): + coefficient = min(coefficient, 1) + fspace_bytes = int(stat.f_frsize * stat.f_bavail * coefficient) + if convert_to_mibs: +- return int(fspace_bytes / 1024 / 1024) # noqa: W1619; pylint: disable=old-division ++ return int(fspace_bytes / 1024 / 1024) + return fspace_bytes + + +@@ -436,6 +436,9 @@ def _generate_livemode_initramfs(context, userspace_initramfs_dest, target_kerne + '--lvmconf', '--mdadmconf', + '--kver', target_kernel_ver, '-f', userspace_initramfs_dest] + ++ # Add included files ++ cmd.extend(itertools.chain(*(('--install', file) for file in initramfs_includes.files))) ++ + # Add dracut modules + cmd.extend(itertools.chain(*(('--add', module) for module in dracut_modules))) + +diff --git a/repos/system_upgrade/common/actors/initramfs/upgradeinitramfsgenerator/tests/unit_test_upgradeinitramfsgenerator.py b/repos/system_upgrade/common/actors/initramfs/upgradeinitramfsgenerator/tests/unit_test_upgradeinitramfsgenerator.py +index 8408233e..b96bf79f 100644 +--- a/repos/system_upgrade/common/actors/initramfs/upgradeinitramfsgenerator/tests/unit_test_upgradeinitramfsgenerator.py ++++ b/repos/system_upgrade/common/actors/initramfs/upgradeinitramfsgenerator/tests/unit_test_upgradeinitramfsgenerator.py +@@ -82,7 +82,7 @@ def gen_UDM_list(data): + return [UpgradeDracutModule(name=i[0], module_path=i[1]) for i in data] + + +-class MockedContext(object): ++class MockedContext: + def __init__(self): + self.called_copy_from = [] + self.called_copytree_from = [] +@@ -174,7 +174,7 @@ def test_copy_boot_files(monkeypatch, arch): + assert actual_boot_content == bootc + + +-class MockedCopyArgs(object): ++class MockedCopyArgs: + def __init__(self): + self.args = None + +@@ -250,14 +250,14 @@ def test_prepare_userspace_for_initram(monkeypatch, adjust_cwd, input_msgs, pkgs + assert _sort_files(upgradeinitramfsgenerator._copy_files.args[1]) == _files + + +-class MockedGetFspace(object): ++class MockedGetFspace: + def __init__(self, space): + self.space = space + + def __call__(self, dummy_path, convert_to_mibs=False): + if not convert_to_mibs: + return self.space +- return int(self.space / 1024 / 1024) # noqa: W1619; pylint: disable=old-division ++ return int(self.space / 1024 / 1024) + + + @pytest.mark.parametrize('input_msgs,dracut_modules,kernel_modules', [ +diff --git a/repos/system_upgrade/common/actors/insightsautoregister/actor.py b/repos/system_upgrade/common/actors/insightsautoregister/actor.py +index a81b434c..56615390 100644 +--- a/repos/system_upgrade/common/actors/insightsautoregister/actor.py ++++ b/repos/system_upgrade/common/actors/insightsautoregister/actor.py +@@ -7,7 +7,7 @@ from leapp.tags import FirstBootPhaseTag, IPUWorkflowTag + + class InsightsAutoregister(Actor): + """ +- Automatically registers system into Red Hat Insights ++ Automatically registers system into Red Hat Lightspeed + + The registration is skipped if NO_INSIGHTS_REGISTER=1 environment variable + is set, the --no-insights-register command line argument present or the +diff --git a/repos/system_upgrade/common/actors/insightsautoregister/libraries/insightsautoregister.py b/repos/system_upgrade/common/actors/insightsautoregister/libraries/insightsautoregister.py +index 2134a8bb..bd113a1f 100644 +--- a/repos/system_upgrade/common/actors/insightsautoregister/libraries/insightsautoregister.py ++++ b/repos/system_upgrade/common/actors/insightsautoregister/libraries/insightsautoregister.py +@@ -6,18 +6,18 @@ from leapp.libraries.stdlib import api, CalledProcessError, run + def _insights_register(): + try: + run(['insights-client', '--register']) +- api.current_logger().info('Automatically registered into Red Hat Insights') ++ api.current_logger().info('Automatically registered into Red Hat Lightspeed') + except (CalledProcessError) as err: + # TODO(mmatuska) produce post-upgrade report? + api.current_logger().error( +- 'Automatic registration into Red Hat Insights failed: {}'.format(err) ++ 'Automatic registration into Red Hat Lightspeed failed: {}'.format(err) + ) + + + def process(): + if rhsm.skip_rhsm() or get_env('LEAPP_NO_INSIGHTS_REGISTER', '0') == '1': + api.current_logger().debug( +- 'Skipping registration into Insights due to --no-insights-register' ++ 'Skipping registration into Red Hat Lightspeed due to --no-insights-register' + ' or LEAPP_NO_INSIGHTS_REGISTER=1 set' + ) + return +diff --git a/repos/system_upgrade/common/actors/insightsautoregister/tests/test_insightsautoregister.py b/repos/system_upgrade/common/actors/insightsautoregister/tests/test_insightsautoregister.py +index 0a039455..d5e6ba20 100644 +--- a/repos/system_upgrade/common/actors/insightsautoregister/tests/test_insightsautoregister.py ++++ b/repos/system_upgrade/common/actors/insightsautoregister/tests/test_insightsautoregister.py +@@ -41,7 +41,7 @@ def test_insights_register_success_logged(monkeypatch): + + def run_mocked(cmd, **kwargs): + return { +- 'stdout': 'Successfully registered into Insights', ++ 'stdout': 'Successfully registered into Red Hat Lightspeed', + 'stderr': '', + 'exit_code': 0 + } +diff --git a/repos/system_upgrade/el8toel9/actors/kernel/checkkpatch/actor.py b/repos/system_upgrade/common/actors/kernel/checkkpatch/actor.py +similarity index 100% +rename from repos/system_upgrade/el8toel9/actors/kernel/checkkpatch/actor.py +rename to repos/system_upgrade/common/actors/kernel/checkkpatch/actor.py +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 e5759a7b..5b35bcd3 100644 +--- a/repos/system_upgrade/common/actors/kernelcmdlineconfig/tests/test_kernelcmdlineconfig.py ++++ b/repos/system_upgrade/common/actors/kernelcmdlineconfig/tests/test_kernelcmdlineconfig.py +@@ -15,7 +15,7 @@ from leapp.models import InstalledTargetKernelInfo, KernelCmdlineArg, TargetKern + + TARGET_KERNEL_NEVRA = 'kernel-core-1.2.3-4.x86_64.el8.x64_64' + +-# pylint: disable=E501 ++# pylint: disable=line-too-long + SAMPLE_KERNEL_ARGS = ('ro rootflags=subvol=root' + ' resume=/dev/mapper/luks-2c0df999-81ec-4a35-a1f9-b93afee8c6ad' + ' rd.luks.uuid=luks-90a6412f-c588-46ca-9118-5aca35943d25' +@@ -31,10 +31,10 @@ title="Fedora Linux (6.5.13-100.fc37.x86_64) 37 (Thirty Seven)" + id="a3018267cdd8451db7c77bb3e5b1403d-6.5.13-100.fc37.x86_64" + """ # noqa: E501 + SAMPLE_GRUBBY_INFO_OUTPUT = TEMPLATE_GRUBBY_INFO_OUTPUT.format(SAMPLE_KERNEL_ARGS, SAMPLE_KERNEL_ROOT) +-# pylint: enable=E501 ++# pylint: enable=line-too-long + + +-class MockedRun(object): ++class MockedRun: + def __init__(self, outputs=None): + """ + Mock stdlib.run(). +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 16ae0a09..e3ddce48 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 +@@ -68,7 +68,7 @@ def test_generate_live_image_if_enabled(monkeypatch, livemode_config, should_pro + actor_mock = CurrentActorMocked(msgs=messages) + monkeypatch.setattr(api, 'current_actor', actor_mock) + +- class NspawnMock(object): ++ class NspawnMock: + def __init__(self, *args, **kwargs): + pass + +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 26fd9d09..7d72204c 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 +@@ -5,7 +5,6 @@ from leapp.libraries.common.rpms import has_package + from leapp.libraries.stdlib import api + from leapp.models import InstalledRPM, LiveModeConfig + +-LIVEMODE_CONFIG_LOCATION = '/etc/leapp/files/devel-livemode.ini' + DEFAULT_SQUASHFS_PATH = '/var/lib/leapp/live-upgrade.img' + + +@@ -39,8 +38,7 @@ def scan_config_and_emit_message(): + if not should_scan_config(): + return + +- api.current_logger().info('Loading livemode config from %s', LIVEMODE_CONFIG_LOCATION) +- ++ api.current_logger().info('Loading the livemode configuration.') + config = api.current_actor().config[livemode_config_lib.LIVEMODE_CONFIG_SECTION] + + # Mapping from model field names to configuration fields - because we might have +diff --git a/repos/system_upgrade/common/actors/livemode/modify_userspace_for_livemode/tests/test_livemode_userspace_modifications.py b/repos/system_upgrade/common/actors/livemode/modify_userspace_for_livemode/tests/test_livemode_userspace_modifications.py +index 58046b61..e890f45a 100644 +--- a/repos/system_upgrade/common/actors/livemode/modify_userspace_for_livemode/tests/test_livemode_userspace_modifications.py ++++ b/repos/system_upgrade/common/actors/livemode/modify_userspace_for_livemode/tests/test_livemode_userspace_modifications.py +@@ -26,7 +26,7 @@ _LiveModeConfig = functools.partial(LiveModeConfig, squashfs_fullpath=' fallback_channel + # hardcoded always as ga? instead of list of channels.. + # it'd be possibly confusing naming now... +diff --git a/repos/system_upgrade/common/actors/setuptargetrepos/tests/test_setuptargetrepos.py b/repos/system_upgrade/common/actors/setuptargetrepos/tests/test_setuptargetrepos.py +index 1f898e8f..e4a30f7f 100644 +--- a/repos/system_upgrade/common/actors/setuptargetrepos/tests/test_setuptargetrepos.py ++++ b/repos/system_upgrade/common/actors/setuptargetrepos/tests/test_setuptargetrepos.py +@@ -198,11 +198,23 @@ def test_repos_mapping_for_distro(monkeypatch, distro_id): + setuptargetrepos.process() + assert api.produce.called + ++ distro_repos = api.produce.model_instances[0].distro_repos + rhel_repos = api.produce.model_instances[0].rhel_repos +- assert len(rhel_repos) == 3 + ++ assert len(distro_repos) == 3 ++ ++ produced_distro_repoids = {repo.repoid for repo in distro_repos} + produced_rhel_repoids = {repo.repoid for repo in rhel_repos} +- expected_rhel_repoids = {'{0}-8-for-x86_64-baseos-htb-rpms'.format(distro_id), +- '{0}-8-for-x86_64-appstream-htb-rpms'.format(distro_id), +- '{0}-8-for-x86_64-satellite-extras-rpms'.format(distro_id)} +- assert produced_rhel_repoids == expected_rhel_repoids ++ ++ expected_repoids = { ++ "{0}-8-for-x86_64-baseos-htb-rpms".format(distro_id), ++ "{0}-8-for-x86_64-appstream-htb-rpms".format(distro_id), ++ "{0}-8-for-x86_64-satellite-extras-rpms".format(distro_id), ++ } ++ ++ assert produced_distro_repoids == expected_repoids ++ if distro_id == 'rhel': ++ assert len(rhel_repos) == 3 ++ assert produced_rhel_repoids == expected_repoids ++ else: ++ assert len(rhel_repos) == 0 +diff --git a/repos/system_upgrade/common/actors/storagescanner/libraries/storagescanner.py b/repos/system_upgrade/common/actors/storagescanner/libraries/storagescanner.py +index cae38731..e2d869da 100644 +--- a/repos/system_upgrade/common/actors/storagescanner/libraries/storagescanner.py ++++ b/repos/system_upgrade/common/actors/storagescanner/libraries/storagescanner.py +@@ -35,7 +35,7 @@ def _is_file_readable(path): + def _get_cmd_output(cmd, delim, expected_len): + """ Verify if command exists and return output """ + if not any(os.access(os.path.join(path, cmd[0]), os.X_OK) for path in os.environ['PATH'].split(os.pathsep)): +- api.current_logger().warning("'%s': command not found" % cmd[0]) ++ api.current_logger().warning("'%s': command not found", cmd[0]) + return + + try: +@@ -45,7 +45,11 @@ def _get_cmd_output(cmd, delim, expected_len): + output = subprocess.check_output(cmd, env={'LVM_SUPPRESS_FD_WARNINGS': '1', 'PATH': os.environ['PATH']}) + + except subprocess.CalledProcessError as e: +- api.current_logger().debug("Command '%s' return non-zero exit status: %s" % (" ".join(cmd), e.returncode)) ++ api.current_logger().debug( ++ "Command '%s' returned non-zero exit status: %s", ++ " ".join(cmd), ++ e.returncode ++ ) + return + + if bytes is not str: +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 456e40ec..6879e52a 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 +@@ -268,8 +268,7 @@ def test_get_lsblk_info(monkeypatch): + '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 ++ yield from output_lines_split_on_whitespace + elif len(cmd) == 5 and cmd[:4] == ['lsblk', '-nr', '--output', 'NAME,KNAME,SIZE']: + # 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. +@@ -460,7 +459,7 @@ def test_get_lvdisplay_info(monkeypatch): + + def test_get_systemd_mount_info(monkeypatch): + +- class UdevDeviceMocked(object): ++ class UdevDeviceMocked: + def __init__(self, device_node, path, model, wwn, fs_type, label, uuid): + self.device_node = device_node + # Simulate udev device attributes that should be queried +@@ -482,7 +481,7 @@ def test_get_systemd_mount_info(monkeypatch): + + return self.device_attributes[attribute] + +- class UdevContextMocked(object): ++ class UdevContextMocked: + def __init__(self, mocked_devices): + self.mocked_devices = mocked_devices + +diff --git a/repos/system_upgrade/common/actors/systemd/checksystemdbrokensymlinks/tests/test_checksystemdbrokensymlinks.py b/repos/system_upgrade/common/actors/systemd/checksystemdbrokensymlinks/tests/test_checksystemdbrokensymlinks.py +index 2364f7a5..a4c0a657 100644 +--- a/repos/system_upgrade/common/actors/systemd/checksystemdbrokensymlinks/tests/test_checksystemdbrokensymlinks.py ++++ b/repos/system_upgrade/common/actors/systemd/checksystemdbrokensymlinks/tests/test_checksystemdbrokensymlinks.py +@@ -20,7 +20,7 @@ def test_report_broken_symlinks(monkeypatch): + checksystemdbrokensymlinks._report_broken_symlinks(symlinks) + + assert created_reports.called +- assert all([s in created_reports.report_fields['summary'] for s in symlinks]) ++ assert all(s in created_reports.report_fields['summary'] for s in symlinks) + + + def test_report_enabled_services_broken_symlinks(monkeypatch): +@@ -35,10 +35,10 @@ def test_report_enabled_services_broken_symlinks(monkeypatch): + checksystemdbrokensymlinks._report_enabled_services_broken_symlinks(symlinks) + + assert created_reports.called +- assert all([s in created_reports.report_fields['summary'] for s in symlinks]) ++ assert all(s in created_reports.report_fields['summary'] for s in symlinks) + + +-class ReportBrokenSymlinks(object): ++class ReportBrokenSymlinks: + def __init__(self): + self.symlinks = [] + +diff --git a/repos/system_upgrade/common/actors/systemd/repairsystemdsymlinks/tests/test_repairsystemdsymlinks.py b/repos/system_upgrade/common/actors/systemd/repairsystemdsymlinks/tests/test_repairsystemdsymlinks.py +index 2394df5e..5771fc6c 100644 +--- a/repos/system_upgrade/common/actors/systemd/repairsystemdsymlinks/tests/test_repairsystemdsymlinks.py ++++ b/repos/system_upgrade/common/actors/systemd/repairsystemdsymlinks/tests/test_repairsystemdsymlinks.py +@@ -10,7 +10,7 @@ from leapp.models import ( + ) + + +-class MockedSystemdCmd(object): ++class MockedSystemdCmd: + def __init__(self): + self.units = [] + +diff --git a/repos/system_upgrade/common/actors/systemd/scansystemdsource/tests/test_scansystemdsource.py b/repos/system_upgrade/common/actors/systemd/scansystemdsource/tests/test_scansystemdsource.py +index 7b95a2df..f92657d3 100644 +--- a/repos/system_upgrade/common/actors/systemd/scansystemdsource/tests/test_scansystemdsource.py ++++ b/repos/system_upgrade/common/actors/systemd/scansystemdsource/tests/test_scansystemdsource.py +@@ -73,7 +73,7 @@ _CALL_PROC_ERR = CalledProcessError( + ) + + +-class GetOrRaise(object): ++class GetOrRaise: + def __init__(self, value): + self.value = value + +diff --git a/repos/system_upgrade/common/actors/systemd/scansystemdtarget/tests/test_scansystemdtarget.py b/repos/system_upgrade/common/actors/systemd/scansystemdtarget/tests/test_scansystemdtarget.py +index 227ba61a..2e806e25 100644 +--- a/repos/system_upgrade/common/actors/systemd/scansystemdtarget/tests/test_scansystemdtarget.py ++++ b/repos/system_upgrade/common/actors/systemd/scansystemdtarget/tests/test_scansystemdtarget.py +@@ -73,7 +73,7 @@ _CALL_PROC_ERR = CalledProcessError( + ) + + +-class GetOrRaise(object): ++class GetOrRaise: + def __init__(self, value): + self.value = value + +diff --git a/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/tests/test_setsystemdservicesstate.py b/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/tests/test_setsystemdservicesstate.py +index fa17a94c..976da6da 100644 +--- a/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/tests/test_setsystemdservicesstate.py ++++ b/repos/system_upgrade/common/actors/systemd/setsystemdservicesstates/tests/test_setsystemdservicesstate.py +@@ -8,7 +8,7 @@ from leapp.libraries.stdlib import api, CalledProcessError + from leapp.models import SystemdServicesTasks + + +-class MockedSystemdCmd(object): ++class MockedSystemdCmd: + def __init__(self): + self.units = [] + +diff --git a/repos/system_upgrade/common/actors/systemd/transitionsystemdservicesstates/tests/test_transitionsystemdservicesstates.py b/repos/system_upgrade/common/actors/systemd/transitionsystemdservicesstates/tests/test_transitionsystemdservicesstates.py +index 6964a65b..488b37d4 100644 +--- a/repos/system_upgrade/common/actors/systemd/transitionsystemdservicesstates/tests/test_transitionsystemdservicesstates.py ++++ b/repos/system_upgrade/common/actors/systemd/transitionsystemdservicesstates/tests/test_transitionsystemdservicesstates.py +@@ -205,9 +205,7 @@ def test_report_kept_enabled(monkeypatch, tasks, expect_extended_summary): + assert created_reports.called + if expect_extended_summary: + assert extended_summary_str in created_reports.report_fields["summary"] +- assert all( +- [s in created_reports.report_fields["summary"] for s in tasks.to_enable] +- ) ++ all(s in created_reports.report_fields['summary'] for s in tasks.to_enable) + else: + assert extended_summary_str not in created_reports.report_fields["summary"] + +@@ -238,7 +236,7 @@ def test_report_newly_enabled(monkeypatch): + transitionsystemdservicesstates._report_newly_enabled(newly_enabled) + + assert created_reports.called +- assert all([s in created_reports.report_fields["summary"] for s in newly_enabled]) ++ assert all(s in created_reports.report_fields["summary"] for s in newly_enabled) + + + @pytest.mark.parametrize( diff --git a/repos/system_upgrade/common/actors/systemfacts/actor.py b/repos/system_upgrade/common/actors/systemfacts/actor.py index 59b12c87..85d4a09e 100644 --- a/repos/system_upgrade/common/actors/systemfacts/actor.py @@ -5746,11 +8514,93 @@ index 59b12c87..85d4a09e 100644 def process(self): self.produce(systemfacts.get_sysctls_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 5831b979..16405b15 100644 +--- a/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts.py ++++ b/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts.py +@@ -61,7 +61,7 @@ def test_aslist(current_actor_libraries): + ) + def test_get_system_users(monkeypatch, etc_passwd_names, etc_passwd_directory, skipped_user_names): + +- class MockedPwdEntry(object): ++ class MockedPwdEntry: + def __init__(self, pw_name, pw_uid, pw_gid, pw_dir): + self.pw_name = pw_name + self.pw_uid = pw_uid +@@ -99,7 +99,7 @@ def test_get_system_users(monkeypatch, etc_passwd_names, etc_passwd_directory, s + ) + def test_get_system_groups(monkeypatch, etc_group_names, skipped_group_names): + +- class MockedGrpEntry(object): ++ class MockedGrpEntry: + def __init__(self, gr_name, gr_gid, gr_mem): + self.gr_name = gr_name + self.gr_gid = gr_gid +diff --git a/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts_grub.py b/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts_grub.py +index 08552771..7fd774b5 100644 +--- a/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts_grub.py ++++ b/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts_grub.py +@@ -4,7 +4,7 @@ from leapp.libraries.actor import systemfacts + from leapp.models import DefaultGrub + + +-class RunMocked(object): ++class RunMocked: + def __init__(self, cmd_result): + self.called = 0 + self.cmd_result = cmd_result +diff --git a/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts_selinux.py b/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts_selinux.py +index b9e0c71d..d36900bd 100644 +--- a/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts_selinux.py ++++ b/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts_selinux.py +@@ -74,7 +74,7 @@ def test_selinux_disabled(monkeypatch): + assert SELinuxFacts(**expected_data) == get_selinux_status() + + +-class MockNoConfigFileOSError(object): ++class MockNoConfigFileOSError: + def __init__(self): + raise OSError + diff --git a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py -index 55877d05..0b7a5b3a 100644 +index 55877d05..399b836c 100644 --- a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py +++ b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py -@@ -152,9 +152,10 @@ def _import_gpg_keys(context, install_root_dir, target_major_version): +@@ -6,7 +6,7 @@ import shutil + from leapp import reporting + from leapp.exceptions import StopActorExecution, StopActorExecutionError + from leapp.libraries.actor import constants +-from leapp.libraries.common import dnfplugin, mounting, overlaygen, repofileutils, rhsm, utils ++from leapp.libraries.common import distro, dnfplugin, mounting, overlaygen, repofileutils, rhsm, utils + from leapp.libraries.common.config import get_distro_id, get_env, get_product_type + from leapp.libraries.common.config.version import get_target_major_version + from leapp.libraries.common.gpg import get_path_to_gpg_certs, is_nogpgcheck_set +@@ -17,6 +17,7 @@ from leapp.models import ( + CustomTargetRepositoryFile, + PkgManagerInfo, + RepositoriesFacts, ++ RHELTargetRepository, + RHSMInfo, + RHUIInfo, + StorageInfo, +@@ -57,6 +58,7 @@ from leapp.utils.deprecation import suppress_deprecation + PROD_CERTS_FOLDER = 'prod-certs' + PERSISTENT_PACKAGE_CACHE_DIR = '/var/lib/leapp/persistent_package_cache' + DEDICATED_LEAPP_PART_URL = 'https://access.redhat.com/solutions/7011704' ++FMT_LIST_SEPARATOR = '\n - ' + + + def _check_deprecated_rhsm_skip(): +@@ -77,7 +79,7 @@ class BrokenSymlinkError(Exception): + """Raised when we encounter a broken symlink where we weren't expecting it.""" + + +-class _InputData(object): ++class _InputData: + def __init__(self): + self._consume_data() + +@@ -152,9 +154,10 @@ def _import_gpg_keys(context, install_root_dir, target_major_version): # Import the RHEL X+1 GPG key to be able to verify the installation of initial packages try: # Import also any other keys provided by the customer in the same directory @@ -5764,7 +8614,7 @@ index 55877d05..0b7a5b3a 100644 except CalledProcessError as exc: raise StopActorExecutionError( message=( -@@ -641,6 +642,7 @@ def _prep_repository_access(context, target_userspace): +@@ -641,6 +644,7 @@ def _prep_repository_access(context, target_userspace): run(["chroot", target_userspace, "/bin/bash", "-c", "su - -c update-ca-trust"]) if not rhsm.skip_rhsm(): @@ -5772,6 +8622,495 @@ index 55877d05..0b7a5b3a 100644 run(['rm', '-rf', os.path.join(target_etc, 'rhsm')]) context.copytree_from('/etc/rhsm', os.path.join(target_etc, 'rhsm')) +@@ -777,7 +781,7 @@ def _inhibit_on_duplicate_repos(repofiles): + list_separator_fmt = '\n - ' + api.current_logger().warning( + 'The following repoids are defined multiple times:{0}{1}' +- .format(list_separator_fmt, list_separator_fmt.join(duplicates)) ++ .format(list_separator_fmt, list_separator_fmt.join(sorted(duplicates))) + ) + + reporting.create_report([ +@@ -785,7 +789,7 @@ def _inhibit_on_duplicate_repos(repofiles): + reporting.Summary( + 'The following repositories are defined multiple times inside the' + ' "upgrade" container:{0}{1}' +- .format(list_separator_fmt, list_separator_fmt.join(duplicates)) ++ .format(list_separator_fmt, list_separator_fmt.join(sorted(duplicates))) + ), + reporting.Severity(reporting.Severity.MEDIUM), + reporting.Groups([reporting.Groups.REPOSITORY]), +@@ -814,21 +818,19 @@ def _get_all_available_repoids(context): + return set(repoids) + + +-def _get_rhsm_available_repoids(context): +- target_major_version = get_target_major_version() ++def _inhibit_if_no_base_repos(distro_repoids): + # FIXME: check that required repo IDs (baseos, appstream) + # + or check that all required RHEL repo IDs are available. +- if rhsm.skip_rhsm(): +- return set() +- # Get the RHSM repos available in the target RHEL container +- # TODO: very similar thing should happens for all other repofiles in container +- # +- repoids = rhsm.get_available_repo_ids(context) ++ ++ target_major_version = get_target_major_version() + # NOTE(ivasilev) For the moment at least AppStream and BaseOS repos are required. While we are still + # contemplating on what can be a generic solution to checking this, let's introduce a minimal check for + # at-least-one-appstream and at-least-one-baseos among present repoids +- if not repoids or all("baseos" not in ri for ri in repoids) or all("appstream" not in ri for ri in repoids): ++ no_baseos = all("baseos" not in ri for ri in distro_repoids) ++ no_appstream = all("appstream" not in ri for ri in distro_repoids) ++ if no_baseos or no_appstream: + reporting.create_report([ ++ # TODO: Make the report distro agnostic + reporting.Title('Cannot find required basic RHEL target repositories.'), + reporting.Summary( + 'This can happen when a repository ID was entered incorrectly either while using the --enablerepo' +@@ -860,21 +862,6 @@ def _get_rhsm_available_repoids(context): + title='Preparing for the upgrade') + ]) + raise StopActorExecution() +- return set(repoids) +- +- +-def _get_rhui_available_repoids(context, cloud_repo): +- repofiles = repofileutils.get_parsed_repofiles(context) +- +- # TODO: same refactoring as Issue #486? +- _inhibit_on_duplicate_repos(repofiles) +- repoids = [] +- for rfile in repofiles: +- if rfile.file == cloud_repo and rfile.data: +- repoids = [repo.repoid for repo in rfile.data] +- repoids.sort() +- break +- return set(repoids) + + + def get_copy_location_from_copy_in_task(context_basepath, copy_task): +@@ -885,88 +872,109 @@ def get_copy_location_from_copy_in_task(context_basepath, copy_task): + return copy_task.dst + + +-def _get_rh_available_repoids(context, indata): ++def _get_rhui_available_repoids(context, rhui_info): + """ +- RH repositories are provided either by RHSM or are stored in the expected repo file provided by +- RHUI special packages (every cloud provider has itw own rpm). ++ Get repoids provided by the RHUI target clients ++ ++ :rtype: set[str] + """ ++ # If we are upgrading a RHUI system, check what repositories are provided by the (already installed) target clients ++ setup_info = rhui_info.target_client_setup_info ++ target_content_access_files = set() ++ if setup_info.bootstrap_target_client: ++ target_content_access_files = _query_rpm_for_pkg_files(context, rhui_info.target_client_pkg_names) + +- rh_repoids = _get_rhsm_available_repoids(context) ++ def is_repofile(path): ++ return os.path.dirname(path) == '/etc/yum.repos.d' and os.path.basename(path).endswith('.repo') + +- # If we are upgrading a RHUI system, check what repositories are provided by the (already installed) target clients +- if indata and indata.rhui_info: +- setup_info = indata.rhui_info.target_client_setup_info +- target_content_access_files = set() +- if setup_info.bootstrap_target_client: +- target_content_access_files = _query_rpm_for_pkg_files(context, indata.rhui_info.target_client_pkg_names) ++ def extract_repoid_from_line(line): ++ return line.split(':', 1)[1].strip() + +- def is_repofile(path): +- return os.path.dirname(path) == '/etc/yum.repos.d' and os.path.basename(path).endswith('.repo') ++ target_ver = api.current_actor().configuration.version.target ++ setup_tasks = rhui_info.target_client_setup_info.preinstall_tasks.files_to_copy_into_overlay + +- def extract_repoid_from_line(line): +- return line.split(':', 1)[1].strip() ++ yum_repos_d = context.full_path('/etc/yum.repos.d') ++ all_repofiles = {os.path.join(yum_repos_d, path) for path in os.listdir(yum_repos_d) if path.endswith('.repo')} ++ api.current_logger().debug('(RHUI Setup) All available repofiles: {0}'.format(' '.join(all_repofiles))) + +- target_ver = api.current_actor().configuration.version.target +- setup_tasks = indata.rhui_info.target_client_setup_info.preinstall_tasks.files_to_copy_into_overlay ++ target_access_repofiles = { ++ context.full_path(path) for path in target_content_access_files if is_repofile(path) ++ } + +- yum_repos_d = context.full_path('/etc/yum.repos.d') +- all_repofiles = {os.path.join(yum_repos_d, path) for path in os.listdir(yum_repos_d) if path.endswith('.repo')} +- api.current_logger().debug('(RHUI Setup) All available repofiles: {0}'.format(' '.join(all_repofiles))) ++ # Exclude repofiles used to setup the target rhui access as on some platforms the repos provided by ++ # the client are not sufficient to install the client into target userspace (GCP) ++ rhui_setup_repofile_tasks = [task for task in setup_tasks if task.src.endswith('repo')] ++ rhui_setup_repofiles = ( ++ get_copy_location_from_copy_in_task(context.base_dir, copy) for copy in rhui_setup_repofile_tasks ++ ) ++ rhui_setup_repofiles = {context.full_path(repofile) for repofile in rhui_setup_repofiles} + +- target_access_repofiles = { +- context.full_path(path) for path in target_content_access_files if is_repofile(path) +- } ++ foreign_repofiles = all_repofiles - target_access_repofiles - rhui_setup_repofiles + +- # Exclude repofiles used to setup the target rhui access as on some platforms the repos provided by +- # the client are not sufficient to install the client into target userspace (GCP) +- rhui_setup_repofile_tasks = [task for task in setup_tasks if task.src.endswith('repo')] +- rhui_setup_repofiles = ( +- get_copy_location_from_copy_in_task(context.base_dir, copy) for copy in rhui_setup_repofile_tasks +- ) +- rhui_setup_repofiles = {context.full_path(repofile) for repofile in rhui_setup_repofiles} ++ api.current_logger().debug( ++ 'The following repofiles are considered as unknown to' ++ ' the target RHUI content setup and will be ignored: {0}'.format(' '.join(foreign_repofiles)) ++ ) + +- foreign_repofiles = all_repofiles - target_access_repofiles - rhui_setup_repofiles ++ # Rename non-client repofiles so they will not be recognized when running dnf repolist ++ for foreign_repofile in foreign_repofiles: ++ os.rename(foreign_repofile, '{0}.back'.format(foreign_repofile)) + +- api.current_logger().debug( +- 'The following repofiles are considered as unknown to' +- ' the target RHUI content setup and will be ignored: {0}'.format(' '.join(foreign_repofiles)) ++ rhui_repoids = set() ++ try: ++ dnf_cmd = [ ++ 'dnf', 'repolist', ++ '--releasever', target_ver, '-v', ++ '--enablerepo', '*', ++ '--disablerepo', '*-source-*', ++ '--disablerepo', '*-debug-*', ++ ] ++ repolist_result = context.call(dnf_cmd)['stdout'] ++ repoid_lines = [line for line in repolist_result.split('\n') if line.startswith('Repo-id')] ++ rhui_repoids.update({extract_repoid_from_line(line) for line in repoid_lines}) ++ ++ except CalledProcessError as err: ++ details = {'err': err.stderr, 'details': str(err)} ++ raise StopActorExecutionError( ++ message='Failed to retrieve repoids provided by target RHUI clients.', ++ details=details + ) + +- # Rename non-client repofiles so they will not be recognized when running dnf repolist ++ finally: ++ # Revert the renaming of non-client repofiles + for foreign_repofile in foreign_repofiles: +- os.rename(foreign_repofile, '{0}.back'.format(foreign_repofile)) ++ os.rename('{0}.back'.format(foreign_repofile), foreign_repofile) + +- try: +- dnf_cmd = [ +- 'dnf', 'repolist', +- '--releasever', target_ver, '-v', +- '--enablerepo', '*', +- '--disablerepo', '*-source-*', +- '--disablerepo', '*-debug-*', +- ] +- repolist_result = context.call(dnf_cmd)['stdout'] +- repoid_lines = [line for line in repolist_result.split('\n') if line.startswith('Repo-id')] +- rhui_repoids = {extract_repoid_from_line(line) for line in repoid_lines} +- rh_repoids.update(rhui_repoids) +- +- except CalledProcessError as err: +- details = {'err': err.stderr, 'details': str(err)} +- raise StopActorExecutionError( +- message='Failed to retrieve repoids provided by target RHUI clients.', +- details=details +- ) ++ return rhui_repoids + +- finally: +- # Revert the renaming of non-client repofiles +- for foreign_repofile in foreign_repofiles: +- os.rename('{0}.back'.format(foreign_repofile), foreign_repofile) + +- api.current_logger().debug( +- 'The following repofiles are considered as provided by RedHat: {0}'.format(' '.join(rh_repoids)) +- ) +- return rh_repoids ++def _get_distro_available_repoids(context, indata): ++ """ ++ Get repoids provided by the distribution ++ ++ On RHEL: RH repositories are provided either by RHSM or are stored in the ++ expected repo file provided by RHUI special packages (every cloud ++ provider has itw own rpm). ++ On other: Repositories are provided in specific repofiles (e.g. centos.repo ++ and centos-addons.repo on CS) ++ ++ :return: A set of repoids provided by distribution ++ :rtype: set[str] ++ """ ++ distro_repoids = distro.get_target_distro_repoids(context) ++ distro_id = get_distro_id() ++ rhel_and_rhsm = distro_id == 'rhel' and not rhsm.skip_rhsm() ++ if distro_id != 'rhel' or rhel_and_rhsm: ++ _inhibit_if_no_base_repos(distro_repoids) ++ ++ if indata and indata.rhui_info: ++ rhui_repoids = _get_rhui_available_repoids(context, indata.rhui_info) ++ distro_repoids.extend(rhui_repoids) + ++ return set(distro_repoids) + ++ ++@suppress_deprecation(RHELTargetRepository) # member of TargetRepositories + def gather_target_repositories(context, indata): + """ + Get available required target repositories and inhibit or raise error if basic checks do not pass. +@@ -984,17 +992,31 @@ def gather_target_repositories(context, indata): + :param context: An instance of a mounting.IsolatedActions class + :type context: mounting.IsolatedActions class + :return: List of target system repoids +- :rtype: List(string) ++ :rtype: set[str] + """ +- rh_available_repoids = _get_rh_available_repoids(context, indata) +- all_available_repoids = _get_all_available_repoids(context) + +- target_repoids = [] +- missing_custom_repoids = [] ++ distro_repoids = _get_distro_available_repoids(context, indata) ++ if distro_repoids: ++ api.current_logger().info( ++ "The following repoids are considered as provided by the '{}' distribution:{}{}".format( ++ get_distro_id(), ++ FMT_LIST_SEPARATOR, ++ FMT_LIST_SEPARATOR.join(sorted(distro_repoids)), ++ ) ++ ) ++ else: ++ api.current_logger().warning( ++ "No repoids provided by the {} distribution have been discovered".format(get_distro_id()) ++ ) ++ ++ all_repoids = _get_all_available_repoids(context) ++ ++ target_repoids = set() ++ missing_custom_repoids = set() + for target_repo in api.consume(TargetRepositories): +- for rhel_repo in target_repo.rhel_repos: +- if rhel_repo.repoid in rh_available_repoids: +- target_repoids.append(rhel_repo.repoid) ++ for distro_repo in target_repo.distro_repos: ++ if distro_repo.repoid in distro_repoids: ++ target_repoids.add(distro_repo.repoid) + else: + # TODO: We shall report that the RHEL repos that we deem necessary for + # the upgrade are not available; but currently it would just print bunch of +@@ -1003,12 +1025,16 @@ def gather_target_repositories(context, indata): + # of the upgrade. Let's skip it for now until it's clear how we will deal + # with it. + pass ++ + for custom_repo in target_repo.custom_repos: +- if custom_repo.repoid in all_available_repoids: +- target_repoids.append(custom_repo.repoid) ++ if custom_repo.repoid in all_repoids: ++ target_repoids.add(custom_repo.repoid) + else: +- missing_custom_repoids.append(custom_repo.repoid) +- api.current_logger().debug("Gathered target repositories: {}".format(', '.join(target_repoids))) ++ missing_custom_repoids.add(custom_repo.repoid) ++ api.current_logger().debug( ++ "Gathered target repositories: {}".format(", ".join(sorted(target_repoids))) ++ ) ++ + if not target_repoids: + target_major_version = get_target_major_version() + reporting.create_report([ +@@ -1054,7 +1080,7 @@ def gather_target_repositories(context, indata): + ' while using the --enablerepo option of leapp, or in a third party actor that produces a' + ' CustomTargetRepositoryMessage.\n' + 'The following repositories IDs could not be found in the target configuration:\n' +- '- {}\n'.format('\n- '.join(missing_custom_repoids)) ++ '- {}\n'.format('\n- '.join(sorted(missing_custom_repoids))) + ), + reporting.Groups([reporting.Groups.REPOSITORY]), + reporting.Groups([reporting.Groups.INHIBITOR]), +@@ -1071,7 +1097,7 @@ def gather_target_repositories(context, indata): + )) + ]) + raise StopActorExecution() +- return set(target_repoids) ++ return target_repoids + + + def _install_custom_repofiles(context, custom_repofiles): +diff --git a/repos/system_upgrade/common/actors/targetuserspacecreator/tests/unit_test_targetuserspacecreator.py b/repos/system_upgrade/common/actors/targetuserspacecreator/tests/unit_test_targetuserspacecreator.py +index 7853a7ad..0bb64f6f 100644 +--- a/repos/system_upgrade/common/actors/targetuserspacecreator/tests/unit_test_targetuserspacecreator.py ++++ b/repos/system_upgrade/common/actors/targetuserspacecreator/tests/unit_test_targetuserspacecreator.py +@@ -11,9 +11,9 @@ import pytest + from leapp import models, reporting + from leapp.exceptions import StopActorExecution, StopActorExecutionError + from leapp.libraries.actor import userspacegen +-from leapp.libraries.common import overlaygen, repofileutils, rhsm ++from leapp.libraries.common import distro, overlaygen, repofileutils, rhsm + from leapp.libraries.common.config import architecture +-from leapp.libraries.common.testutils import CurrentActorMocked, logger_mocked, produce_mocked ++from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked, logger_mocked, produce_mocked + from leapp.libraries.stdlib import api, CalledProcessError + from leapp.utils.deprecation import suppress_deprecation + +@@ -36,7 +36,7 @@ def adjust_cwd(): + os.chdir(previous_cwd) + + +-class MockedMountingBase(object): ++class MockedMountingBase: + def __init__(self, **dummy_kwargs): + self.called_copytree_from = [] + self.target = '' +@@ -50,7 +50,8 @@ class MockedMountingBase(object): + def __call__(self, **dummy_kwarg): + yield self + +- def call(self, *args, **kwargs): ++ @staticmethod ++ def call(*args, **kwargs): + return {'stdout': ''} + + def nspawn(self): +@@ -95,8 +96,7 @@ def traverse_structure(structure, root=Path('/')): + filepath = root / filename + + if isinstance(links_to, dict): +- for pair in traverse_structure(links_to, filepath): +- yield pair ++ yield from traverse_structure(links_to, root=filepath) + else: + yield (filepath, links_to) + +@@ -924,7 +924,7 @@ _SAEE = StopActorExecutionError + _SAE = StopActorExecution + + +-class MockedConsume(object): ++class MockedConsume: + def __init__(self, *args): + self._msgs = [] + for arg in args: +@@ -1068,10 +1068,11 @@ def test_consume_data(monkeypatch, raised, no_rhsm, testdata): + assert raised[1] in err.value.message + else: + assert userspacegen.api.current_logger.warnmsg +- assert any([raised[1] in x for x in userspacegen.api.current_logger.warnmsg]) ++ assert any(raised[1] in x for x in userspacegen.api.current_logger.warnmsg) + + + @pytest.mark.skip(reason="Currently not implemented in the actor. It's TODO.") ++@suppress_deprecation(models.RHELTargetRepository) + def test_gather_target_repositories(monkeypatch): + monkeypatch.setattr(userspacegen.api, 'current_actor', CurrentActorMocked()) + # The available RHSM repos +@@ -1104,6 +1105,7 @@ def test_gather_target_repositories_none_available(monkeypatch): + assert inhibitors[0].get('title', '') == 'Cannot find required basic RHEL target repositories.' + + ++@suppress_deprecation(models.RHELTargetRepository) + def test_gather_target_repositories_rhui(monkeypatch): + + indata = testInData( +@@ -1113,7 +1115,9 @@ def test_gather_target_repositories_rhui(monkeypatch): + monkeypatch.setattr(userspacegen.api, 'current_actor', CurrentActorMocked()) + monkeypatch.setattr(userspacegen, '_get_all_available_repoids', lambda x: []) + monkeypatch.setattr( +- userspacegen, '_get_rh_available_repoids', lambda x, y: ['rhui-1', 'rhui-2', 'rhui-3'] ++ userspacegen, ++ "_get_distro_available_repoids", ++ lambda dummy_context, dummy_indata: {"rhui-1", "rhui-2", "rhui-3"}, + ) + monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: True) + monkeypatch.setattr( +@@ -1122,6 +1126,10 @@ def test_gather_target_repositories_rhui(monkeypatch): + rhel_repos=[ + models.RHELTargetRepository(repoid='rhui-1'), + models.RHELTargetRepository(repoid='rhui-2') ++ ], ++ distro_repos=[ ++ models.DistroTargetRepository(repoid='rhui-1'), ++ models.DistroTargetRepository(repoid='rhui-2') + ] + ) + ]) +@@ -1130,6 +1138,7 @@ def test_gather_target_repositories_rhui(monkeypatch): + assert target_repoids == set(['rhui-1', 'rhui-2']) + + ++@suppress_deprecation(models.RHELTargetRepository) + def test_gather_target_repositories_baseos_appstream_not_available(monkeypatch): + # If the repos that Leapp identifies as required for the upgrade (based on the repo mapping and PES data) are not + # available, an exception shall be raised +@@ -1188,6 +1197,54 @@ def test_gather_target_repositories_baseos_appstream_not_available(monkeypatch): + assert inhibitors[0].get('title', '') == 'Cannot find required basic RHEL target repositories.' + + ++def test__get_distro_available_repoids_norhsm_norhui(monkeypatch): ++ """ ++ Empty set should be returned when on rhel and skip_rhsm == True. ++ """ ++ monkeypatch.setattr( ++ userspacegen.api, "current_actor", CurrentActorMocked(release_id="rhel") ++ ) ++ monkeypatch.setattr(userspacegen.api.current_actor(), 'produce', produce_mocked()) ++ ++ monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: True) ++ monkeypatch.setattr(distro, 'get_target_distro_repoids', lambda ctx: []) ++ ++ indata = testInData(_PACKAGES_MSGS, None, None, _XFS_MSG, _STORAGEINFO_MSG, None) ++ # NOTE: context is not used without rhsm, for simplicity setting to None ++ repoids = userspacegen._get_distro_available_repoids(None, indata) ++ assert repoids == set() ++ ++ ++@pytest.mark.parametrize( ++ "distro_id,skip_rhsm", [("rhel", False), ("centos", True), ("almalinux", True)] ++) ++def test__get_distro_available_repoids_nobaserepos_inhibit( ++ monkeypatch, distro_id, skip_rhsm ++): ++ """ ++ Test that get_distro_available repoids reports and raises if there are no base repos. ++ """ ++ monkeypatch.setattr( ++ userspacegen.api, "current_actor", CurrentActorMocked(release_id=distro_id) ++ ) ++ monkeypatch.setattr(userspacegen.api.current_actor(), 'produce', produce_mocked()) ++ monkeypatch.setattr(reporting, "create_report", create_report_mocked()) ++ ++ monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: skip_rhsm) ++ monkeypatch.setattr(distro, 'get_target_distro_repoids', lambda ctx: []) ++ ++ indata = testInData(_PACKAGES_MSGS, None, None, _XFS_MSG, _STORAGEINFO_MSG, None) ++ with pytest.raises(StopActorExecution): ++ # NOTE: context is not used without rhsm, for simplicity setting to None ++ userspacegen._get_distro_available_repoids(None, indata) ++ ++ # TODO adjust the asserts when the report is made distro agnostic ++ assert reporting.create_report.called == 1 ++ report = reporting.create_report.reports[0] ++ assert "Cannot find required basic RHEL target repositories" in report["title"] ++ assert reporting.Groups.INHIBITOR in report["groups"] ++ ++ + def mocked_consume_data(): + packages = {'dnf', 'dnf-command(config-manager)', 'pkgA', 'pkgB'} + rhsm_info = _RHSMINFO_MSG +@@ -1333,7 +1390,7 @@ def test__get_files_owned_by_rpms_recursive(monkeypatch): + assert sorted(owned[0:4]) == sorted(out) + + def has_dbgmsg(substr): +- return any([substr in log for log in logger.dbgmsg]) ++ return any(substr in log for log in logger.dbgmsg) + + # test a few + assert has_dbgmsg( diff --git a/repos/system_upgrade/common/actors/trustedgpgkeysscanner/libraries/trustedgpgkeys.py b/repos/system_upgrade/common/actors/trustedgpgkeysscanner/libraries/trustedgpgkeys.py index 6377f767..4c5420f6 100644 --- a/repos/system_upgrade/common/actors/trustedgpgkeysscanner/libraries/trustedgpgkeys.py @@ -5798,6 +9137,41 @@ index 6377f767..4c5420f6 100644 return pubkeys +diff --git a/repos/system_upgrade/common/actors/trustedgpgkeysscanner/tests/test_trustedgpgkeys.py b/repos/system_upgrade/common/actors/trustedgpgkeysscanner/tests/test_trustedgpgkeys.py +index 0d98aad7..b8229d00 100644 +--- a/repos/system_upgrade/common/actors/trustedgpgkeysscanner/tests/test_trustedgpgkeys.py ++++ b/repos/system_upgrade/common/actors/trustedgpgkeysscanner/tests/test_trustedgpgkeys.py +@@ -32,7 +32,7 @@ def _get_test_installed_rmps(fps): + return InstalledRPM(items=rpms) + + +-class MockedGetGpgFromFile(object): ++class MockedGetGpgFromFile: + def __init__(self, file_fps_tuples): + # e.g. file_fps_tuple = [('/mydir/myfile', ['0000ff31', '0000ff32'])] + self._data = {} +@@ -40,7 +40,7 @@ class MockedGetGpgFromFile(object): + self._data[fname] = fps + + def get_files(self): +- return self._data.keys() # noqa: W1655; pylint: disable=dict-keys-not-iterating ++ return self._data.keys() + + def __call__(self, fname): + return self._data.get(fname, []) +diff --git a/repos/system_upgrade/common/actors/updategrubcore/tests/test_updategrubcore.py b/repos/system_upgrade/common/actors/updategrubcore/tests/test_updategrubcore.py +index 27a4a245..93816103 100644 +--- a/repos/system_upgrade/common/actors/updategrubcore/tests/test_updategrubcore.py ++++ b/repos/system_upgrade/common/actors/updategrubcore/tests/test_updategrubcore.py +@@ -20,7 +20,7 @@ def raise_call_error(args=None): + ) + + +-class run_mocked(object): ++class run_mocked: + def __init__(self, raise_err=False, raise_callback=raise_call_error): + self.called = 0 + self.args = [] diff --git a/repos/system_upgrade/common/actors/vendorreposignaturescanner/actor.py b/repos/system_upgrade/common/actors/vendorreposignaturescanner/actor.py new file mode 100644 index 00000000..dbf86974 @@ -5999,6 +9373,32 @@ index 00000000..6a41d4e5 + # self.produce(vendor_repomap_collection) + # for repomap in vendor_repomap_collection.maps: + # self.produce(repomap) +diff --git a/repos/system_upgrade/common/actors/verifycheckresults/tests/unit_test_verifycheckresults.py b/repos/system_upgrade/common/actors/verifycheckresults/tests/unit_test_verifycheckresults.py +index 6f459a69..6df9ff20 100644 +--- a/repos/system_upgrade/common/actors/verifycheckresults/tests/unit_test_verifycheckresults.py ++++ b/repos/system_upgrade/common/actors/verifycheckresults/tests/unit_test_verifycheckresults.py +@@ -7,7 +7,7 @@ from leapp.libraries.actor import verifycheckresults + from leapp.libraries.stdlib import api + + +-class Report(object): ++class Report: + def __init__(self, message): + self.message = message + +diff --git a/repos/system_upgrade/common/actors/xfsinfoscanner/tests/unit_test_xfsinfoscanner.py b/repos/system_upgrade/common/actors/xfsinfoscanner/tests/unit_test_xfsinfoscanner.py +index 71f46b47..34e542a8 100644 +--- a/repos/system_upgrade/common/actors/xfsinfoscanner/tests/unit_test_xfsinfoscanner.py ++++ b/repos/system_upgrade/common/actors/xfsinfoscanner/tests/unit_test_xfsinfoscanner.py +@@ -146,7 +146,7 @@ TEST_XFS_INFO_FTYPE0_MODEL = XFSInfo( + ) + + +-class run_mocked(object): ++class run_mocked: + def __init__(self): + self.called = 0 + self.args = None diff --git a/repos/system_upgrade/common/files/distro/almalinux/gpg-signatures.json b/repos/system_upgrade/common/files/distro/almalinux/gpg-signatures.json index 24bc93ba..0629d123 100644 --- a/repos/system_upgrade/common/files/distro/almalinux/gpg-signatures.json @@ -6198,11 +9598,708 @@ index 00000000..df764b53 + "10": [] + } +} +diff --git a/repos/system_upgrade/common/files/prod-certs/10.2/279.pem b/repos/system_upgrade/common/files/prod-certs/10.2/279.pem +new file mode 100644 +index 00000000..76336f82 +--- /dev/null ++++ b/repos/system_upgrade/common/files/prod-certs/10.2/279.pem +@@ -0,0 +1,35 @@ ++-----BEGIN CERTIFICATE----- ++MIIGKDCCBBCgAwIBAgIJALDxRLt/tVBkMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD ++VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI ++YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk ++IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ ++ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDcwODExMjQ0NloXDTQ1MDcw ++ODExMjQ0NlowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFsyOWJlMDI0 ++My03NGU1LTRiNDctYjEwNy1iZjhkNjRjYmNjNDhdMIICIjANBgkqhkiG9w0BAQEF ++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 ++AQQBkggJAYIXAgQGDAQxMC4yMBkGDCsGAQQBkggJAYIXAwQJDAdwcGM2NGxlMCkG ++DCsGAQQBkggJAYIXBAQZDBdyaGVsLTEwLHJoZWwtMTAtcHBjNjRsZTANBgkqhkiG ++9w0BAQsFAAOCAgEAGouNVN3DdCE2cqv3lKMNC3jit5mHi7QQt7fqN/KX4fQfArb6 ++IQ9M0GaGJM8W9rj+9s+Q9LOFjys24Pcdb9qbQWpfwvn9FY60uQw3TIXAerJaVb98 ++doxrFHjVptm0/VX2xnOa/dY97dmMT4Amwe5+y4RYlMEsYqY8dpJkVuKNdGtCg+Uf ++f9hb6XjDqRevADgskHNprXrjF65Ib3a92qJRfttnVUfqqeDkTPntIPbau9hZwLeR ++oMl8pn4kMIYLz1IolSAC8yBFe9sLxllGu8qIFqH4Efzx8BOtHkPUH/VqtgvUej+j ++boJ0EEpwYjvYbz00mZmJHFNkUheW6cDUPWmMoTzYibPzRTrBcAIfvybpeuPjFGfl ++gYZa/DpEG68hlEnSxB4TNpVCx9qfiqXvNcukmeX3Jr7DS1uC2ePBFDQKewx6WdAa ++bAmuANmBUB+NX1WMuNTfxxIzxfIoShaChiFRVjsRTkLo1ZPuMkvXOXYfyfW1PKQN ++PXHEdY9wprn8ZY2qhMwmE1sDdndNpSxB3boI9FQBUVDzbSG6KwbPfSdmrte+Wdrh ++QCIGU+0x7ulF68yOkMkz1spPNgrTXt0efaCSWqUK0nqv1s1Gh2Q6iJaE0yETpSG7 ++hFeHpENftckpmuKcJM0v/uBBeIX7X8plrL7Fkm4ND/e61tEiDwvnhxGhtBE= ++-----END CERTIFICATE----- +diff --git a/repos/system_upgrade/common/files/prod-certs/10.2/362.pem b/repos/system_upgrade/common/files/prod-certs/10.2/362.pem +new file mode 100644 +index 00000000..ebeb065c +--- /dev/null ++++ b/repos/system_upgrade/common/files/prod-certs/10.2/362.pem +@@ -0,0 +1,36 @@ ++-----BEGIN CERTIFICATE----- ++MIIGNzCCBB+gAwIBAgIJALDxRLt/tVBTMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD ++VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI ++YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk ++IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ ++ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDcwODExMjQzMVoXDTQ1MDcw ++ODExMjQzMVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFthMmU1N2Ix ++MS03ZDBiLTRiNGYtOGE5ZC03MmRkNGM2NDA2NzJdMIICIjANBgkqhkiG9w0BAQEF ++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 ++GwYMKwYBBAGSCAkBgmoCBAsMCTEwLjIgQmV0YTAZBgwrBgEEAZIICQGCagMECQwH ++cHBjNjRsZTAuBgwrBgEEAZIICQGCagQEHgwccmhlbC0xMCxyaGVsLTEwLWJldGEt ++cHBjNjRsZTANBgkqhkiG9w0BAQsFAAOCAgEAgQC6qqfeW79hSj2S+OfBT5ccNNZa ++8blVYtVJU5iTfhX29VQTdGus/ROWGqfgDe8MMOCJyt0eNeqGO70KRJsT3pGeeKcM ++UbDfdqzopgD7+/6IL1c1fw/8HijOorW+CMAzeOBdnjMwRjhZxcDlFSqxNCWtngnp ++XlDMIlUR3m0rlBwzNfUMk7KYPUESmyEiBWMSKmqRDeiUg3BSP6Ci0x3Ufnf0xTBv ++VPVKO/h3ta3+pAYzeFy/ageJ/sR9tLRZQZXzvxYvIY+8/EehafPJCHDHH3uCTpdZ ++JAeXDLf2QcOBZnl8uONdev+KaE1JFRCRmqwhliUsARv/t24CY+UBoEzzaj/py2bR ++RQqfE5WI1JSdj6HoQ6YHbtR6SF+UedfvMQoSF4zPiXAPNebiIiLkc1rtb/ycUi1f ++bUjkRfgRqlDwUcgfHrKhSDp5/XhjgxVXiESNcDe2ltKvVr09qAaPBarLolWeIXkN ++n2csdFxyiDZIhk6tFL8lUtpmXWpeEn/iBPwaiBIYoBnIbaqN4OZngwfi2QtTdl+s ++9iCuYgbGQiEZnV3g7HLsYXrAagPuJxXs0FMYJZ8x6biREgUQATwTzZMQ8vWRMmYY ++kteQBaOCDzNpb8OUgbPxgncl9kgr4NIBn+5oGeMitb+I1XvWqoCFsA7Uii6oygdk ++iE+YZEA6e/4057M= ++-----END CERTIFICATE----- +diff --git a/repos/system_upgrade/common/files/prod-certs/10.2/363.pem b/repos/system_upgrade/common/files/prod-certs/10.2/363.pem +new file mode 100644 +index 00000000..865fbda6 +--- /dev/null ++++ b/repos/system_upgrade/common/files/prod-certs/10.2/363.pem +@@ -0,0 +1,35 @@ ++-----BEGIN CERTIFICATE----- ++MIIGKTCCBBGgAwIBAgIJALDxRLt/tVBSMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD ++VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI ++YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk ++IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ ++ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDcwODExMjQzMVoXDTQ1MDcw ++ODExMjQzMVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs0NjJhNDRj ++ZC1jNWUzLTQzZGItYTExNy0zZjA5ZGU1ZDRmMzNdMIICIjANBgkqhkiG9w0BAQEF ++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 ++AgQLDAkxMC4yIEJldGEwGQYMKwYBBAGSCAkBgmsDBAkMB2FhcmNoNjQwLgYMKwYB ++BAGSCAkBgmsEBB4MHHJoZWwtMTAscmhlbC0xMC1iZXRhLWFhcmNoNjQwDQYJKoZI ++hvcNAQELBQADggIBAC/KEEZ85rdWnL/CK9q3uT/d4reNZc1WD5oWYcpj+J31u4sw ++pjAvmq/eA6DmzqGjhfEGhwu5MDbVg77OAPCcfm7qqGSDcnjqnO3ZogDjyzat1WS5 ++J2uuRcPbF6DIk/LkgIc/FgvSFG8Vc93hM+P56wTzTbnPYSRyJq3BBm8ZjSiFO5jq ++V9WOganzxsVKzifTK8RoSdWLyB0JpvL/LZKa4G97ahUctYVilhJBHCgd+uT6/IVn ++ppETnw4xo6SXg0+O+fC1P+90+GZrWWzeHeHnEgmZ8B+RTDQbx/KHQHU4UhqU5qnT ++6VngqL1453IxmlxVxwKlkwzV4SYrQnmEZPvugMhlenbx0T9pJvwg/xvWYJJTGjUy ++1l9p0LtyUHmFJxtbq50++oooUdDtQ6RDD5jtxnvWMF5PFLYGxf6gXFFCJVSgwonP ++BtqoBH2PWp8/nwumAOquzks41m+bqzaMALhp0GUGTKKTITrM4gsLVHqKh2WTCOPs ++s6mdXOyVma/o5Jri8Ec12/HGyIRlQQleb6vcC68PK3X088LZi/zENi2Bq31W5Hip ++R03YxVzmjZA3kJsA8Vim4zaG7e6puLGuXmQLawN7oScBFlvVLvZD2ycZsYLOesCz ++VSxJkmqDMb6To9RRbSmN0csPFKWNkdD8D5iBei4IaGWXyOB3GGJJ2ME/Qv65 ++-----END CERTIFICATE----- +diff --git a/repos/system_upgrade/common/files/prod-certs/10.2/419.pem b/repos/system_upgrade/common/files/prod-certs/10.2/419.pem +new file mode 100644 +index 00000000..42986ccc +--- /dev/null ++++ b/repos/system_upgrade/common/files/prod-certs/10.2/419.pem +@@ -0,0 +1,35 @@ ++-----BEGIN CERTIFICATE----- ++MIIGGjCCBAKgAwIBAgIJALDxRLt/tVBjMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD ++VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI ++YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk ++IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ ++ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDcwODExMjQ0NloXDTQ1MDcw ++ODExMjQ0NlowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs0MjIwNzhj ++OS1mY2MzLTQwMWQtOGM2Yi0yZGUwNWRmZGEyN2NdMIICIjANBgkqhkiG9w0BAQEF ++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 ++MTAuMjAZBgwrBgEEAZIICQGDIwMECQwHYWFyY2g2NDApBgwrBgEEAZIICQGDIwQE ++GQwXcmhlbC0xMCxyaGVsLTEwLWFhcmNoNjQwDQYJKoZIhvcNAQELBQADggIBAAvn ++gY6rJIku70uFkod9Xc45wNgPNMkim2p+dCOQXl5GG7rSLqBp/e6MhBOu+VfvXddF ++zEndO84pb7Evc3PjjtnBietvvcmcoJjMTrGF2oKcJWJP+x/SKMzN2qPPoQu4QoZj ++OTuaemuHLCkA9cnvRj2qxW9ZpINmr6H72jCHPoYGWD8Omupnctyt3/uu/MG7KT4y ++8B5hXLmFeuF1vgOkKnoqjZRgZ86xsJ4dig/vLWkAKdsWPlRlV0SICwgVALqFmTge ++Hgrz0A6F2BM7f0vYNFUTRv0qQwHR7EA/jEHCQByNc73cvDtHZFyODTqvEBoLFVOw ++2fad9K5EID1GKj9U1NGYAlAvEpbrgs2Xd2ugFyN5mtbSLon+VeXm5q9fB/Ca0j7z ++vvfdoKsd89R822m2Y+HB0eei63zGE6Ykr4aaTQNjQyTu5K8pUNG/y5UGWIpSM1IR ++YqOsdJvCyavBlQ98K7OfL9yqOiZFXB9VkmXPPiT1ljNgpYzK63ZWidjXkpG2I7g1 ++YoCIT0JE5xX6x2U5Ia79OFug/g9SwQn6izVYrLCgqqNqeld0WokeFBPnyZkXSYt1 ++pzY4HAjXjaDGbF1O4SmoCTtagB2vNmi1wUPazizA5SESifVcYfPeaWRk10PJT9MR ++p3EFR/BSg/hvmehuGSEfRNFV8g9Deo3EN1LHEhTY ++-----END CERTIFICATE----- +diff --git a/repos/system_upgrade/common/files/prod-certs/10.2/433.pem b/repos/system_upgrade/common/files/prod-certs/10.2/433.pem +new file mode 100644 +index 00000000..932dbf7a +--- /dev/null ++++ b/repos/system_upgrade/common/files/prod-certs/10.2/433.pem +@@ -0,0 +1,35 @@ ++-----BEGIN CERTIFICATE----- ++MIIGLDCCBBSgAwIBAgIJALDxRLt/tVBUMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD ++VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI ++YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk ++IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ ++ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDcwODExMjQzMVoXDTQ1MDcw ++ODExMjQzMVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFsxNzhhMzJi ++NC0xZWNjLTRmZDEtOTA2NS0wMGZkMjQzZDEzYzBdMIICIjANBgkqhkiG9w0BAQEF ++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 ++AZIICQGDMQIECwwJMTAuMiBCZXRhMBcGDCsGAQQBkggJAYMxAwQHDAVzMzkweDAs ++BgwrBgEEAZIICQGDMQQEHAwacmhlbC0xMCxyaGVsLTEwLWJldGEtczM5MHgwDQYJ ++KoZIhvcNAQELBQADggIBAAUwQwSc0A1Q5SiC7N5xSS1ZegZQT1hER7SRDs5p6drK ++Riayu5bER7kpQnJc/ww1/iTmHHH/H180pSP+EZEPqCLumqYmf1vW60SAR4BMklyh ++QuYqVkJCxA7uloA59cLZcPnEu+xHLfnhSQdTIXhi1uLK960mEIiexCT8xMkQ5E5A ++ZUajyEhdLp4ca8K+nUWzSzYQBpGYpkiQtniLZ/i4kzaYTfHpFGJNQQCrPlB2lMCa ++vZKseaPlFzExXfq5MJ5IX1lc2RNqeaf22p49Bia6CgVLMagsFnAr909zZ9NAaZWV ++kYqjLVMJ5EY25OJS21So0fI//lOsRVBxlfqOS7v9hYBnuLhPuiIiHEaNcQyNBI/7 ++DgT5xCmL8IDzvsBJLZ/AqolO1fo5lSVOZ5PCbwIZj7bBZJwf8gTSUu2cuhbN2Gxi ++s7R2QFVco+AAPcuoWOISG4cKwX4wDUR+rHqQMCKJM6mQGlnB2OXBwZX1fYo7k82d ++b7BygRhEML6INaweUe2Do7v8phz6TXM2lFJCQYnja2lO6GxSlaXgRNb4Rnc6ty79 ++O5S6K2g3uEc4Uc8F7echBFAudl9KQqu9il9cb3f0fI+kYX2j9ib4isdF8qIusZVp ++F191fHyl1Y6pp4eWKA48uO8Op8uO320UIX8HQnNGi74eEOvCqvZtfKZE5+Za/YT+ ++-----END CERTIFICATE----- +diff --git a/repos/system_upgrade/common/files/prod-certs/10.2/479.pem b/repos/system_upgrade/common/files/prod-certs/10.2/479.pem +new file mode 100644 +index 00000000..2c4b8db2 +--- /dev/null ++++ b/repos/system_upgrade/common/files/prod-certs/10.2/479.pem +@@ -0,0 +1,35 @@ ++-----BEGIN CERTIFICATE----- ++MIIGGDCCBACgAwIBAgIJALDxRLt/tVBmMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD ++VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI ++YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk ++IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ ++ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDcwODExMjQ0NloXDTQ1MDcw ++ODExMjQ0NlowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs5OTUxYjVm ++NC0yZTE4LTQ1OGEtYTc4ZC05NGNkZDhkN2I1ZWVdMIICIjANBgkqhkiG9w0BAQEF ++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 ++MTAuMjAYBgwrBgEEAZIICQGDXwMECAwGeDg2XzY0MCgGDCsGAQQBkggJAYNfBAQY ++DBZyaGVsLTEwLHJoZWwtMTAteDg2XzY0MA0GCSqGSIb3DQEBCwUAA4ICAQDUoyHm ++MM07NncLVGO9xO6qa3cxy8NyJO95LScKCAzlx3dHrgW+v1CcxZEzMsV6Rtpch0kH ++De61DOCn50JgQ6s7e6Cxk6nMovcxYMi5q4JxYoIlCFTbeRRGdTQv8SmndmSd7rh2 ++6mDUWoDxbw1fpeNxiWAOq8IQXrcmrEnVIpOQP4Fc+yNw/Sdsqz23o9VBlP0yBJ4W ++a6zGCwRzcisLsNOc+8mRtuirG11Zqm07V0xt2YVXlV13Wu/Dy0qKW49tPJD8WceO ++hCC/alSRh1s4YV50gVlA0IRyyezAwU/0Al+lMKfMeqqedg81QGMBiy6qzDjXllcK ++XfKYsWC2egkofpvxb5jVU0EXdl0kE+RGQfK3fVq09YwNim41n9qgJTlA1vIBrq8o ++1NMwyrbQdfndyGZLSpzWxLHpYUCe2lJomgJTNvrA6+xTnlpfEPOn2zDUxJ7CSfoQ ++ZkPhdO4UsrvJOPLt5oY5R5Q6tXLVR7xL24WeUw5FXtzFMibOaE3kT9ib0o8zluMS ++ly290tfnl8Wq7fgjFT8mt0NIH/rXC4COBw87EjLbhxUCbEHnbJiOj+JT2QRxKjWg ++9icCBbU5TEY0V8rC+vx54JCcx8NGaJDDKDmv6tgEOA0u9YEpGw44fk6RxqeNaysW ++glkF2dUoSBDKWSqiroYrjEgaFWvdSaalOSJQuA== ++-----END CERTIFICATE----- +diff --git a/repos/system_upgrade/common/files/prod-certs/10.2/486.pem b/repos/system_upgrade/common/files/prod-certs/10.2/486.pem +new file mode 100644 +index 00000000..181b7a98 +--- /dev/null ++++ b/repos/system_upgrade/common/files/prod-certs/10.2/486.pem +@@ -0,0 +1,35 @@ ++-----BEGIN CERTIFICATE----- ++MIIGJzCCBA+gAwIBAgIJALDxRLt/tVBVMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD ++VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI ++YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk ++IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ ++ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDcwODExMjQzMVoXDTQ1MDcw ++ODExMjQzMVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs2OWQ5ZGY5 ++Yy1mMGFmLTRjY2UtYTRhMi0zZDA4MDM1YjJmYjFdMIICIjANBgkqhkiG9w0BAQEF ++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 ++AgQLDAkxMC4yIEJldGEwGAYMKwYBBAGSCAkBg2YDBAgMBng4Nl82NDAtBgwrBgEE ++AZIICQGDZgQEHQwbcmhlbC0xMCxyaGVsLTEwLWJldGEteDg2XzY0MA0GCSqGSIb3 ++DQEBCwUAA4ICAQA00Q5BALEU5y1CJwF7ru1xNujrtjZvwOdXeNl+esZIqlZQqITP ++Rr6Xww0/mcMcvqEHu/PlJ2xyWC8VYrhZ+/LC6EtTbPEKSDEAHE914MU934pC02tP ++QE+a7BKsHPGhh4SyvMrZ0vWoxnwcug5g8V5uXNOQYSgnOAHdNQxMeMh8LCHO76np ++fjWL7en5dUMWHOB9W1kyZO87f2WBGhFrTyNnFTcg99G/MNMkMD5rLc+Qg8GhY1Zt ++8+AN4c5HprFI1cUz8/4osj2ZBW1xxH+mcps2oy3L8UNFceiAdewVpTmwlBN0HEUk ++3+NB64+QXLf13EowJnAunJrVms+bQbB1Y2zOL1ymiCLF6iQu4mIdEP2yqzk7lowa ++RmuxEOI/S279n+YtilUuWKoeaLcGqPd0rPS5B01M049+KXW0Vv/6OOakA0rltB76 +++RBeE4UTnPCOIBfyVCHdoCTDFaI5GavVZGTr1bLQR9FdIRzQs+nx3VUYf6o2ZHOW ++R1I794GHADaLwNfD5b5oo1XwIkuDxcvrF5kFlhnI3X9cVFDhk6uvMTzKEHPsdoYY ++Oe2PdTNfyaiAZs5RzE7If+DAK1zCHrO3GHN4tRyQEwG5p/1F91iw2/Kj67zosH38 ++Wvm4FSL0ENRPIIUt+p0zT4FBPXOr4YwQGBn0PuaIob5mymAdbUI6Q3CHqA== ++-----END CERTIFICATE----- +diff --git a/repos/system_upgrade/common/files/prod-certs/10.2/72.pem b/repos/system_upgrade/common/files/prod-certs/10.2/72.pem +new file mode 100644 +index 00000000..3d15c146 +--- /dev/null ++++ b/repos/system_upgrade/common/files/prod-certs/10.2/72.pem +@@ -0,0 +1,35 @@ ++-----BEGIN CERTIFICATE----- ++MIIGGTCCBAGgAwIBAgIJALDxRLt/tVBlMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD ++VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI ++YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk ++IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ ++ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDcwODExMjQ0NloXDTQ1MDcw ++ODExMjQ0NlowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFtmM2M4ZTQ0 ++OC1lYmY4LTQxN2MtOTI5My01ZmE5NjU2YTI4YjJdMIICIjANBgkqhkiG9w0BAQEF ++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 ++AgQGDAQxMC4yMBYGCysGAQQBkggJAUgDBAcMBXMzOTB4MCYGCysGAQQBkggJAUgE ++BBcMFXJoZWwtMTAscmhlbC0xMC1zMzkweDANBgkqhkiG9w0BAQsFAAOCAgEAMT/B ++VjMEkJIvwAShBe9XhWj1lNvd58VQNaet8eMebCOy2CN32v50zquH9QgQH4Sf/aBm ++X8HfQWl23zAQApCjMr2Sawmjmy05Oj7UGghkbANDvwHV2VKg1nOIoy4oaRvQj86m ++Hn7g0t4Iz1/kTCioZkRgj1PULeDKa7u/GKiYgpc1HVjxUUwJsC2JQwjZ1CwRsNPc ++AV6sDLveJn0doggYrxbC/+9oGYSxxUrkvaPzMmuvHa5F50NHuwgcNTL47uVkglIV +++GBQaBaOq9c/8yWbqLVVDbXu1JD6zgzGj6BYiziJEpU7cqYfCOF9qPIYTD9AnZLx ++43LHz33E6dRRCD9yTuMQEHE3uUoFi/G+yQvf/paSddE5FBX2d35jPSKk5um/x30g ++EiFhQKSuHqWIz/cfucwFBQJRHIPj/yN93RqE9u+uJQrSk8KorEg3fVTumBT6bTYh ++QprOvJBrV6UZg7oHnUC9byiyHzHRHktHv2HOPGbywbIZd0TM5R0KWaEQEVg0OAJG ++KgwEeuiEufQZGq29EZTEtyDpDIP9wNiC4pBHe9B1UpE6EdzfoZWlJb6wbUMRtTqw ++RS1ijNAFzvYy2Yuz0/aRi163qek95YwoXeeZn2QbDN+YgFjJZq6pHjNxYTyDthos ++uWfveDk3xJRFp+Ja5WbgEK9FxzdFz34OZKFlre4= ++-----END CERTIFICATE----- +diff --git a/repos/system_upgrade/common/files/prod-certs/9.8/279.pem b/repos/system_upgrade/common/files/prod-certs/9.8/279.pem +new file mode 100644 +index 00000000..8757b9b0 +--- /dev/null ++++ b/repos/system_upgrade/common/files/prod-certs/9.8/279.pem +@@ -0,0 +1,35 @@ ++-----BEGIN CERTIFICATE----- ++MIIGJTCCBA2gAwIBAgIJALDxRLt/tVAaMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD ++VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI ++YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk ++IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ ++ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDcwODExMjI0MloXDTQ1MDcw ++ODExMjI0MlowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFtkZDJiN2Jk ++OS01NmJkLTQ3YzctOWQxOS1jNWYyNmE5YWQwZTJdMIICIjANBgkqhkiG9w0BAQEF ++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 ++AQQBkggJAYIXAgQFDAM5LjgwGQYMKwYBBAGSCAkBghcDBAkMB3BwYzY0bGUwJwYM ++KwYBBAGSCAkBghcEBBcMFXJoZWwtOSxyaGVsLTktcHBjNjRsZTANBgkqhkiG9w0B ++AQsFAAOCAgEAEzlRfJCOY32tUEuMY4Z/cBUoJjM3/IoKY+7tA1xjzNWzL0hPWXcP ++Ifb2iYXG7rINxRkGk56PiFYReGjxlkhkUWRiciAZc6oHfbpw3IyeWnCgSHJXQqTc ++kUEWcUG0CJOlE9OBegvqK+PSydRx2JYhaAFza3zMvIYrdtmOvqhP3/GvuN+nnI4G ++F7GgJkOyalbaSTOWlH2+wxuXeAnlEtUTytRFBEsBywuyi6NIpBL6Oj+QoBFQdCOE ++Ot2Q3v0N4Q5+aiu5UsYPHs97NV8DPkuA0I2qDZr9j/PgxwftbMt14QHG+G9LW3Cz ++DSRIXeKfXGo0GbR7E4ZZBLpp/3LMmH5w/K13skoGtnfWC5x/yoHFRPGmSb1Rrzx2 ++kre8EMrXrFFZn4hXu/huQwLTxpg8Hn5pPzDphEksTKQxLeUF0lRj5b3NtqJbQ4he ++NDBAA9cgpifdfaFO8Ax/zppiUeoEizAyst4FFGMDC5u4EFPNQJLjh6vc/2rvP1bk ++KwH2FRxd/jyCcu6bEF4Fv/O/dpddkYtmSPQs3DLX9g9N30uOdOp9TM3W9lt/HFQE ++VpqG7mXTu+f4hx5LFqJXR1pSLzCjVPl03sVi05rjD0Tjkt//pRybpzf/66wMQ1wE ++LWoT869L+7EiL5aSPE3dX7D6IsNzqHvIPKuFAO8T2ZXdiwidAlpXlyA= ++-----END CERTIFICATE----- +diff --git a/repos/system_upgrade/common/files/prod-certs/9.8/362.pem b/repos/system_upgrade/common/files/prod-certs/9.8/362.pem +new file mode 100644 +index 00000000..cb1b7c00 +--- /dev/null ++++ b/repos/system_upgrade/common/files/prod-certs/9.8/362.pem +@@ -0,0 +1,36 @@ ++-----BEGIN CERTIFICATE----- ++MIIGNDCCBBygAwIBAgIJALDxRLt/tVAGMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD ++VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI ++YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk ++IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ ++ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDcwODExMjIxOVoXDTQ1MDcw ++ODExMjIxOVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFswMGIwYzc0 ++MS0xMDQyLTRiZGUtOTYyYy1kZjRjOGVlMmNiNjBdMIICIjANBgkqhkiG9w0BAQEF ++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 ++GgYMKwYBBAGSCAkBgmoCBAoMCDkuOCBCZXRhMBkGDCsGAQQBkggJAYJqAwQJDAdw ++cGM2NGxlMCwGDCsGAQQBkggJAYJqBAQcDBpyaGVsLTkscmhlbC05LWJldGEtcHBj ++NjRsZTANBgkqhkiG9w0BAQsFAAOCAgEAvtSvgFTBFe30H/WQcgvDjJe2ucROmr6B ++AW3OF3hvamcwciLMjzMgVyf4dwRDCsKL0q9cRmFXlMR0H36iNQnYkZU1p/sWfCIB ++HtPDPlSr3miELB6FTvod/L4zn+CqbjgN2D3wJJKVfldbQzOTV3kEFed96yB8exTV ++ObdCIzyadhtULog9mtUCe+8IxG8oDzpjAaaYfwkyq6tY3VzbvRS76292yFVQe6rG ++wc9kxhwCfprnvzH7+dTlbMJlvk7PQB7xH1CvSmrIf7C5tfLf/BrsygFtqnq8KLTx ++v644hMGkOvMBdEw5Ry3jMPAlmL+Eyc5751XkN3b5yujXA+T71t1/F0i99DM8XTO8 ++WovLAH4KjX+gvHugdsEQs0ujRpxPDgkv9/RFWs0kkBgzhUlFqOGBsi3HyGoqq770 ++/e4Fvnj/XxHzs4G3FgiyGnsKLOaKm7eFTwhePsscIckGr/6oq7U0VQF1xOc77I7n ++uPFdSXso5TUUO2UVhqmeq71hhj000wpw4vKQ71rEfgTtMiC7Et93hpk4y4iwuk9w ++mDGTksyr50QNgS9ZNWGLu2JejT3s9RcjROEJ6VOWJxorDWxEY/LXl683FtRXPEM2 ++UjHyhx8twhxbIlcD3a8S0R4BfcWCLvhtpdnmOtFGACYMaYd9TAdOG/AZoc/jBOpy ++s2OKIQwKXPY= ++-----END CERTIFICATE----- +diff --git a/repos/system_upgrade/common/files/prod-certs/9.8/363.pem b/repos/system_upgrade/common/files/prod-certs/9.8/363.pem +new file mode 100644 +index 00000000..fa09ec7c +--- /dev/null ++++ b/repos/system_upgrade/common/files/prod-certs/9.8/363.pem +@@ -0,0 +1,35 @@ ++-----BEGIN CERTIFICATE----- ++MIIGJjCCBA6gAwIBAgIJALDxRLt/tVAFMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD ++VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI ++YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk ++IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ ++ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDcwODExMjIxOVoXDTQ1MDcw ++ODExMjIxOVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs0MTFmZDc4 ++NC00ZTc4LTQ5YWQtOTNiOC0zNjc2OWY0ZDFlZTVdMIICIjANBgkqhkiG9w0BAQEF ++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 ++AgQKDAg5LjggQmV0YTAZBgwrBgEEAZIICQGCawMECQwHYWFyY2g2NDAsBgwrBgEE ++AZIICQGCawQEHAwacmhlbC05LHJoZWwtOS1iZXRhLWFhcmNoNjQwDQYJKoZIhvcN ++AQELBQADggIBAFzGv13LCdYf3XkOt3TjwVwY2ldFVMxf2Sx/uNjLFG4I1mhYwZZ9 ++0Pyz7J771yMxyhyKb8rc8XMAYxi8lOKfOpp1PpPRVC+NtKo2pdrbZhWy2qKomfyL ++S6jN/hEgg7P6LHGEnvT1Bm9e+BoED3gmOVAmupL4xKv2eRxgXuwuPHrvE6oo63SB ++xtrYIo/pmYgVFgl/d7X5vXqerF4pwLR2DwtK6O84DSyVRf35ghNET09GYm6G+URQ ++eGWi1/h0YCpS9LCXOOOv/J4MM8zr+NLbDyJWxmaG83/zvAQhX65bzJ0bBtb0avJ0 ++cgos6LBCDxt+kmipnAMqz5Cb+HVifgdBz1ep3EcoxHwmwBDpHewq0zNtPgMyjzhi ++uwB0inlcCk7JKdjdO36H7RdUYvrM7WEDUKAXtMgOXxr3o6h9v9jZKTfbk5Af91/D ++epoMULy0sErnEuzHAq9sdh3HTmDTHsMNcUpxwC+93VGaCGGrbyM2yQtdLg7dhHQK ++7d9Z9BJEzKReIy+R354M1jQsLGLQ3B8uY476dmP0G0Q01m86rsJ/gjxa8vrJpafO ++t1Up9YexwbVtEtKG7koCz4fwxPv2cauGncuUTdyHJDoS5FpPLMlaWXAfwD0Udbiv ++gZke/PD+39I+UPrxtM+XIXGoJPeZdM5Kv0+3/suvKHGqtkFa8YiK2EHA ++-----END CERTIFICATE----- +diff --git a/repos/system_upgrade/common/files/prod-certs/9.8/419.pem b/repos/system_upgrade/common/files/prod-certs/9.8/419.pem +new file mode 100644 +index 00000000..9ad33fd1 +--- /dev/null ++++ b/repos/system_upgrade/common/files/prod-certs/9.8/419.pem +@@ -0,0 +1,35 @@ ++-----BEGIN CERTIFICATE----- ++MIIGFzCCA/+gAwIBAgIJALDxRLt/tVAZMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD ++VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI ++YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk ++IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ ++ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDcwODExMjI0MloXDTQ1MDcw ++ODExMjI0MlowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFtiOWY4OWYx ++OC0xNjAzLTRlZDUtYTFmOS0xN2YyMmEwNDdlODNdMIICIjANBgkqhkiG9w0BAQEF ++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 ++OS44MBkGDCsGAQQBkggJAYMjAwQJDAdhYXJjaDY0MCcGDCsGAQQBkggJAYMjBAQX ++DBVyaGVsLTkscmhlbC05LWFhcmNoNjQwDQYJKoZIhvcNAQELBQADggIBAFu1LxAU ++wPUs7/e6mFAzT/JIzq1fQ6kMHxbrf9nS+g9pO0G0z7Imwj85Rk7qOpJpEjKaLVDy ++OJ9fXV20TNidKDvjZuL+F209NLam64MEpy7q40LgOaDYsr9tvGfJJFAQRKRszbrC ++/CGj7l/q09ym1FB3LXgpn4vHR8jD7LloGFEWq19UpRLe+L+1Frh16apy03WNYTnk ++JLALo274I3+kgO69sEemXZF+WD/O+4ySugY/ImbrIlrY1SAeAWTd/kudLMLVLYnN ++JlmB7OPUGE2ZAR0aOTvTeoDBZPz1EGItbJg2hlx4vrhrnGG9kKu+/cDOOAJ7+bgx ++fgc64NOoLTSc+9QIgKKhDt5jShXHfFjpwWbJ08/U29bTZmntcRO0h6F0WBS3ptgW ++hocfN2nDN7pPvivnrUUo+kRY7jKE57im3+mznHHw97em6YCREuvc/NwLIxi4LSiU ++cJgOQ3ltljrFSMKlv4p6evMxlX/QOwgeE+hf/QYjCODoHe/66h5bnKkLGnFdPHxk ++6btQfVePn8UpMUO64OgIcPuGyAEXu1m9N/PFL3S5JUVmfjF9COhmZQEW1x5HBF/u ++mAfwI79++xKH1nmVsgDUjm5HMVZ3qj0y3miAKtC3Ses9Ym6JawpvPSld3xFGF5Mc ++BiYQsv12swSrLy3IzdvJViXRFUFE3dWuVdG1 ++-----END CERTIFICATE----- +diff --git a/repos/system_upgrade/common/files/prod-certs/9.8/433.pem b/repos/system_upgrade/common/files/prod-certs/9.8/433.pem +new file mode 100644 +index 00000000..eaf93d90 +--- /dev/null ++++ b/repos/system_upgrade/common/files/prod-certs/9.8/433.pem +@@ -0,0 +1,35 @@ ++-----BEGIN CERTIFICATE----- ++MIIGKTCCBBGgAwIBAgIJALDxRLt/tVAHMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD ++VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI ++YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk ++IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ ++ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDcwODExMjIxOVoXDTQ1MDcw ++ODExMjIxOVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFsyYjk5MzMx ++OC0xZjFiLTRlY2UtODJiMS0wODEzYmFjOGFkNGJdMIICIjANBgkqhkiG9w0BAQEF ++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 ++AZIICQGDMQIECgwIOS44IEJldGEwFwYMKwYBBAGSCAkBgzEDBAcMBXMzOTB4MCoG ++DCsGAQQBkggJAYMxBAQaDBhyaGVsLTkscmhlbC05LWJldGEtczM5MHgwDQYJKoZI ++hvcNAQELBQADggIBACjKAgygB5V2mVD3S5snrHjFTpP2x1ODX1GdSgwrXFZ/ehom ++hf1SI9zIsmm+s96ns/Gc5BDrqS2TSil083OqG5YZ98ap+NkQPI/XqIhMRSw2z+QK ++p1i7e/Si6VZyiitnutCrbX/b1RzWCSOAfIU2m41iptvT7HATw0y/6CQpQNrhZ3wR ++TubEIEypmxO5stJt4CO/bqkU3vX+U3FdQdSJWJn3qpvErJ4qNFdwl8zX9WGoaueh ++gNbYrz2EWARVbvedp+ylB1VNdpYXQ+LUI/KwHI4Sxizgg16+IxcFoKJVCYNOH7Wh ++IoMZc7eW91oAzm57yS36RF/Z50S1x8JHHg2hgev+2czDG9dgRTsLvvAXqsnrUHuD ++lRPMDjgaSooUWJmKwIXQ7yJDAPHoxZAXWtMEc1kNLZGEPVDQbT73j4eDOxzZDZrr ++agWGoWJ3kuY9AVvv/RTi6z5VWs7ySJER7RxQcGhH8TctysW7gIMjHfgnTGN2bW5U ++mV5Ds+/i9AiA9/V+rWWsv8riz+MfEa23/J/EvOdBBCd5MuzsqkXn2gde8WP3cjes ++sgqUKQzOy7Rqr5LHT1IQl5SkyYr1QV1InghJ8dh7BjRLvWUaw0uqPRvxX1c6K1l/ ++NFsCie9RwuhdE8OBwHuBjB28k3Zs9SPaVzYRe70qwi0epbCrhwcGOkTNfCcz ++-----END CERTIFICATE----- +diff --git a/repos/system_upgrade/common/files/prod-certs/9.8/479.pem b/repos/system_upgrade/common/files/prod-certs/9.8/479.pem +new file mode 100644 +index 00000000..a0ff7061 +--- /dev/null ++++ b/repos/system_upgrade/common/files/prod-certs/9.8/479.pem +@@ -0,0 +1,35 @@ ++-----BEGIN CERTIFICATE----- ++MIIGFTCCA/2gAwIBAgIJALDxRLt/tVAcMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD ++VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI ++YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk ++IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ ++ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDcwODExMjI0MloXDTQ1MDcw ++ODExMjI0MlowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFs4ZmM5YTM4 ++Ni0wYzkzLTQ0MjctYTlhOC1kMTdkMzAwZGJmZDZdMIICIjANBgkqhkiG9w0BAQEF ++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 ++OS44MBgGDCsGAQQBkggJAYNfAwQIDAZ4ODZfNjQwJgYMKwYBBAGSCAkBg18EBBYM ++FHJoZWwtOSxyaGVsLTkteDg2XzY0MA0GCSqGSIb3DQEBCwUAA4ICAQC6vt8EEay9 ++CjdRGHmseXosuo03ub+bUt61uYVpf15IoVUV+7XT6ZHff8cPZbKBjoRbuWNILvR2 ++rCdl11bm3prCxfLNJh5u8hqNXv+iIB4k4qhCSrhPFQEf3HNJma2J67U/8Mt7oM4B ++RqpZ1CCw9VTHQSB+iraKzE+BFr9kNlQfZu75Clsgv5dZaT1WK5hKiuQy8kc2CBKy ++CuiL6i0PK2tzNtNH4ON/tMU3AM+edIiUFV6C376kewwO/omArY6FYmJVcPLKWh3h ++TSUt81CmaHmyW+XKJ2pM3f2hfHdq1Lf7lInjgw5Rolyhm/Xqrrj8j19SrUSru/tw ++WcmLMhhEyU2/jwfipbbzB9AC3tIXZjKv8539e4omsBmHwHQno1NAjq0+alGxr9pK ++AZywsuMhiGyznbYdIANGZyMUN3sULIsG649UcEsmzM5q9g1TVyuJH9m+OJSK2PGk ++UnorgDlGs1AiJhsqZuW8zxzy3nfQmniO/o/6wZbqlKiyLjQY7Fxa4Rb0hXbBJkZ7 ++TkHkjlAObUEkcjg0jUHb8sFRQ7hXx+Tk4tGk549crSZCCg951SITV5By9bAxm7fu ++DHGXgY7tOwHII51sfBfryuvIKs+JmzF9Evzssf3kLBSXylyS6pr/8dKN6sF7Pw4M ++Fe/gvJ3J/pARSVP41wR6tI0zYvqkO/ULQg== ++-----END CERTIFICATE----- +diff --git a/repos/system_upgrade/common/files/prod-certs/9.8/486.pem b/repos/system_upgrade/common/files/prod-certs/9.8/486.pem +new file mode 100644 +index 00000000..84461ed8 +--- /dev/null ++++ b/repos/system_upgrade/common/files/prod-certs/9.8/486.pem +@@ -0,0 +1,35 @@ ++-----BEGIN CERTIFICATE----- ++MIIGJDCCBAygAwIBAgIJALDxRLt/tVAIMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD ++VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI ++YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk ++IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ ++ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDcwODExMjIxOVoXDTQ1MDcw ++ODExMjIxOVowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFtkZjUwNWIw ++ZS02Y2E4LTRkODQtOTY0Mi0wNGRlYTg5NjY0MzNdMIICIjANBgkqhkiG9w0BAQEF ++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 ++AgQKDAg5LjggQmV0YTAYBgwrBgEEAZIICQGDZgMECAwGeDg2XzY0MCsGDCsGAQQB ++kggJAYNmBAQbDBlyaGVsLTkscmhlbC05LWJldGEteDg2XzY0MA0GCSqGSIb3DQEB ++CwUAA4ICAQCNeDKnDjuvHBE0Fa0cMAFM96OWn3b3wTtAx7i9BCaCe4NsRTjEMJTw ++jO4KwkfzCQWpOJuFHnOKmVZBXVZZ8aOLCfYTyQZ6nZ1UsiekL7l9sdIFCHrbgKkL ++zBFe+8cVtUMwb9f7fORPp960ImtYpvt8ERihHf2LvIBUI+BGRz/D/3NW1ehVggGI ++0VCe270sgLSl3y8lR5BrNXtKbigeI4mNMasndf/TDMFeCk5OH4FJ+DyiY0zma2IT ++x0PwQmEeI4my1KTmQSUDgIOmHtKbq1tCR2wMIh/ju/HOrvVeOnzEsBgQTiTh92qJ ++U7/++7Ayqw/6PfPCd+gOMqIPS1+Aef7w54I+zWyYeHQcXXCxcffPwO7sZV3zQJyh ++clfLJv13Oe6G5mB7ZCH+tB4LdaVBURz9G0MkLwXGfTWfnU5N61Kne8hjOriSBWP4 ++2FZEP+2BQ/1Z7aIssbQKegdRvvMd/KqJjIeiFtrz9AVSodEUZgJlxiZ9KDSysG18 ++hmZcPuk2mc9nwWQ9gHZWzatGs+uONS92QqFvXxlY7TWMDIdlscubcjV/bbDHm69P +++pqGilb3zJz8msBwFpdO+h4l8eUMMMsLzdUdH499q/enZrH3VSdmNtWtoVm9R7rp ++khFJ4DdORE9/P5lfqAObt8KNO72BQ2/KcK0FZ1lLxKWG/4dZ5oAdGw== ++-----END CERTIFICATE----- +diff --git a/repos/system_upgrade/common/files/prod-certs/9.8/72.pem b/repos/system_upgrade/common/files/prod-certs/9.8/72.pem +new file mode 100644 +index 00000000..724e0a62 +--- /dev/null ++++ b/repos/system_upgrade/common/files/prod-certs/9.8/72.pem +@@ -0,0 +1,35 @@ ++-----BEGIN CERTIFICATE----- ++MIIGFjCCA/6gAwIBAgIJALDxRLt/tVAbMA0GCSqGSIb3DQEBCwUAMIGuMQswCQYD ++VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExFjAUBgNVBAoMDVJlZCBI ++YXQsIEluYy4xGDAWBgNVBAsMD1JlZCBIYXQgTmV0d29yazEuMCwGA1UEAwwlUmVk ++IEhhdCBFbnRpdGxlbWVudCBQcm9kdWN0IEF1dGhvcml0eTEkMCIGCSqGSIb3DQEJ ++ARYVY2Etc3VwcG9ydEByZWRoYXQuY29tMB4XDTI1MDcwODExMjI0MloXDTQ1MDcw ++ODExMjI0MlowRDFCMEAGA1UEAww5UmVkIEhhdCBQcm9kdWN0IElEIFtlYjMyYzY1 ++Ny00OGY0LTRiZjUtYmY3Yy1mYjMwNWU1YjgyMDFdMIICIjANBgkqhkiG9w0BAQEF ++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 ++AgQFDAM5LjgwFgYLKwYBBAGSCAkBSAMEBwwFczM5MHgwJAYLKwYBBAGSCAkBSAQE ++FQwTcmhlbC05LHJoZWwtOS1zMzkweDANBgkqhkiG9w0BAQsFAAOCAgEADCKqieee ++Hvj06J4U23K/Wr5zn+d6AtA2vfhpicAYh5jzYqLAJHmB9T5Ql6pFqJ9lMLI2EGSg ++jhLD+lzDP9A2vk+rFWK0BEGnqlPrQtM5atTBeihRVRci1ymspPBrLwu+Zu3jromg ++I14r86EZwSXpPZLaNUsOjOi4Euc50Q3wsUJGvXCpoU4SgnnAIER3lq9HSNFDZkmp ++AjW+VHAhPIOTujm9PhCFIn5bB0jsygHHYyqV7KvQSmxoPTaLMxFpva+Xy0QNKlwg ++NXKw/JYAHX1yaskeZviqwZzhKpnvycyEgWF9f7cBD6O8Adxx9qkqXqer7YsQ/wgR ++cHjGCAKbV2OTIgyQEDie1gdPLdSUPzrbzJ9C1I85tSJH3ujdACiGG/aHPtspLb3Z ++M6265fbXDbXOqjFuP/njDUqal3WgUgw34w4Xi2JLCcqLvHLQhTmZSKiD0SJbRDL1 ++smcle/yKhTc4+7zJqQV8faR9LVEAkaLzjG3ZRiTUDq4RASr9tN/A0AfXqggG9nGL ++06m6QcXRxHM0OVgLHLksKsj3rG3VX0v3aQm353GW1sxxX0hqFnoOnGWA410GUG9S ++rg897hshyti1pn045uhhFjbpxYRKu/JY9VNNyRW0KqL1hyz4TY7OQxJxGDAPX7uJ ++7NGSWW9EsYMZNMxEee6br9lWVwGWnc8DWhA= ++-----END CERTIFICATE----- diff --git a/repos/system_upgrade/common/files/rhel_upgrade.py b/repos/system_upgrade/common/files/rhel_upgrade.py -index 4f76a61d..27824406 100644 +index 4f76a61d..4e8b380d 100644 --- a/repos/system_upgrade/common/files/rhel_upgrade.py +++ b/repos/system_upgrade/common/files/rhel_upgrade.py -@@ -185,6 +185,7 @@ class RhelUpgradeCommand(dnf.cli.Command): +@@ -40,7 +40,7 @@ class RhelUpgradeCommand(dnf.cli.Command): + summary = 'Plugin for upgrading to the next RHEL major release' + + def __init__(self, cli): +- super(RhelUpgradeCommand, self).__init__(cli) ++ super().__init__(cli) + self.plugin_data = {} + + @staticmethod +@@ -49,7 +49,8 @@ class RhelUpgradeCommand(dnf.cli.Command): + metavar="[%s]" % "|".join(CMDS)) + parser.add_argument('filename') + +- def _process_entities(self, entities, op, entity_name): ++ @staticmethod ++ def _process_entities(entities, op, entity_name): + """ + Adds list of packages for given operation to the transaction + """ +@@ -73,7 +74,8 @@ class RhelUpgradeCommand(dnf.cli.Command): + with open(self.opts.filename, 'w+') as fo: + json.dump(self.plugin_data, fo, sort_keys=True, indent=2) + +- def _read_aws_region(self, repo): ++ @staticmethod ++ def _read_aws_region(repo): + region = None + if repo.baseurl: + # baseurl is tuple (changed by Amazon-id plugin) +@@ -86,7 +88,8 @@ class RhelUpgradeCommand(dnf.cli.Command): + sys.exit(1) + return region + +- def _fix_rhui_url(self, repo, region): ++ @staticmethod ++ def _fix_rhui_url(repo, region): + if repo.baseurl: + repo.baseurl = tuple( + url.replace('REGION', region, 1) for url in repo.baseurl +@@ -185,6 +188,7 @@ class RhelUpgradeCommand(dnf.cli.Command): to_install = self.plugin_data['pkgs_info']['to_install'] to_remove = self.plugin_data['pkgs_info']['to_remove'] to_upgrade = self.plugin_data['pkgs_info']['to_upgrade'] @@ -6210,7 +10307,7 @@ index 4f76a61d..27824406 100644 # Modules to enable self._process_entities(entities=[available_modules_to_enable], -@@ -197,6 +198,9 @@ class RhelUpgradeCommand(dnf.cli.Command): +@@ -197,6 +201,9 @@ class RhelUpgradeCommand(dnf.cli.Command): self._process_entities(entities=to_install, op=self.base.install, entity_name='Package') # Packages to be upgraded self._process_entities(entities=to_upgrade, op=self.base.upgrade, entity_name='Package') @@ -6220,31 +10317,88 @@ index 4f76a61d..27824406 100644 self.base.distro_sync() if self.opts.tid[0] == 'check': +@@ -222,6 +229,6 @@ class RhelUpgradePlugin(dnf.Plugin): + name = 'rhel-upgrade' + + def __init__(self, base, cli): +- super(RhelUpgradePlugin, self).__init__(base, cli) ++ super().__init__(base, cli) + if cli: + cli.register_command(RhelUpgradeCommand) diff --git a/repos/system_upgrade/common/files/upgrade_paths.json b/repos/system_upgrade/common/files/upgrade_paths.json -index 22e0fd7d..47ca28d5 100644 +index 22e0fd7d..11158c9c 100644 --- a/repos/system_upgrade/common/files/upgrade_paths.json +++ b/repos/system_upgrade/common/files/upgrade_paths.json -@@ -32,6 +32,7 @@ +@@ -2,9 +2,10 @@ + "rhel": { + "default": { + "7.9": ["8.10"], +- "8.10": ["9.4", "9.6", "9.7"], ++ "8.10": ["9.4", "9.6", "9.7", "9.8"], + "9.6": ["10.0"], + "9.7": ["10.1"], ++ "9.8": ["10.2"], + "7": ["8.10"], + "8": ["9.4", "9.6"], + "9": ["10.0"] +@@ -15,6 +16,7 @@ + "8.10": ["9.6", "9.4"], + "8": ["9.6", "9.4"], + "9.6": ["10.0"], ++ "9.8": ["10.2"], + "9": ["10.0"] + } + }, +@@ -25,13 +27,14 @@ + }, + "_virtual_versions": { + "8": "8.10", +- "9": "9.7", +- "10": "10.1" ++ "9": "9.8", ++ "10": "10.2" + } + }, "almalinux": { "default": { - "8.10": ["9.0", "9.1", "9.2", "9.3", "9.4", "9.5", "9.6", "9.7"], +- "8.10": ["9.0", "9.1", "9.2", "9.3", "9.4", "9.5", "9.6", "9.7"], ++ "8.10": ["9.0", "9.1", "9.2", "9.3", "9.4", "9.5", "9.6", "9.7","9.8"], + "9.6": ["10.0"], "9.7": ["10.0", "10.1"] } } +diff --git a/repos/system_upgrade/common/libraries/config/version.py b/repos/system_upgrade/common/libraries/config/version.py +index 00ce3ec8..5efa932d 100644 +--- a/repos/system_upgrade/common/libraries/config/version.py ++++ b/repos/system_upgrade/common/libraries/config/version.py +@@ -106,8 +106,7 @@ class _SupportedVersionsDict(dict): + + def __iter__(self): + self._feed_supported_versions() +- for d in self.data: +- yield d ++ yield from self.data + + def __repr__(self): + self._feed_supported_versions() diff --git a/repos/system_upgrade/common/libraries/distro.py b/repos/system_upgrade/common/libraries/distro.py -index 2ed5eacd..219d31d1 100644 +index 2ed5eacd..a61aae56 100644 --- a/repos/system_upgrade/common/libraries/distro.py +++ b/repos/system_upgrade/common/libraries/distro.py -@@ -3,6 +3,7 @@ import os +@@ -2,7 +2,12 @@ import json + import os from leapp.exceptions import StopActorExecutionError ++from leapp.libraries.common import repofileutils, rhsm ++from leapp.libraries.common.config import get_distro_id ++from leapp.libraries.common.config.architecture import ARCH_ACCEPTED, ARCH_X86_64 ++from leapp.libraries.common.config.version import get_target_major_version from leapp.libraries.stdlib import api +from leapp.models import VendorSignatures def get_distribution_data(distribution): -@@ -11,8 +12,14 @@ def get_distribution_data(distribution): +@@ -11,8 +16,202 @@ def get_distribution_data(distribution): distribution_config = os.path.join(distributions_path, distribution, 'gpg-signatures.json') if os.path.exists(distribution_config): with open(distribution_config) as distro_config_file: @@ -6256,12 +10410,200 @@ index 2ed5eacd..219d31d1 100644 details={'Problem': 'Distribution {} was not found in {}.'.format(distribution, distributions_path)}) + + # Extend with Vendors signatures -+ for siglist in api.consume(VendorSignatures): ++ for siglist in api.consume(VendorSignatures): + distro_config_json["keys"].extend(siglist.sigs) + + return distro_config_json ++ ++# distro -> major_version -> repofile -> tuple of architectures where it's present ++_DISTRO_REPOFILES_MAP = { ++ 'rhel': { ++ '8': {'/etc/yum.repos.d/redhat.repo': ARCH_ACCEPTED}, ++ '9': {'/etc/yum.repos.d/redhat.repo': ARCH_ACCEPTED}, ++ '10': {'/etc/yum.repos.d/redhat.repo': ARCH_ACCEPTED}, ++ }, ++ 'centos': { ++ '8': { ++ # TODO is this true on all archs? ++ 'CentOS-Linux-AppStream.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-BaseOS.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-ContinuousRelease.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-Debuginfo.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-Devel.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-Extras.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-FastTrack.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-HighAvailability.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-Media.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-Plus.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-PowerTools.repo': ARCH_ACCEPTED, ++ 'CentOS-Linux-Sources.repo': ARCH_ACCEPTED, ++ }, ++ '9': { ++ '/etc/yum.repos.d/centos.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/centos-addons.repo': ARCH_ACCEPTED, ++ }, ++ '10': { ++ '/etc/yum.repos.d/centos.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/centos-addons.repo': ARCH_ACCEPTED, ++ }, ++ }, ++ 'almalinux': { ++ '8': { ++ # TODO is this true on all archs? ++ '/etc/yum.repos.d/almalinux-ha.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-nfv.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-plus.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-powertools.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-resilientstorage.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-rt.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-sap.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-saphana.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux.repo': ARCH_ACCEPTED, ++ }, ++ '9': { ++ '/etc/yum.repos.d/almalinux.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-appstream.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-baseos.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-crb.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-extras.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-highavailability.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-plus.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-resilientstorage.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-sap.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-saphana.repo': ARCH_ACCEPTED, ++ # RT and NFV are only on x86_64 on almalinux 9 ++ '/etc/yum.repos.d/almalinux-nfv.repo': (ARCH_X86_64,), ++ '/etc/yum.repos.d/almalinux-rt.repo': (ARCH_X86_64,), ++ }, ++ '10': { ++ # no resilientstorage on 10 ++ '/etc/yum.repos.d/almalinux-appstream.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-baseos.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-crb.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-extras.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-highavailability.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-plus.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-sap.repo': ARCH_ACCEPTED, ++ '/etc/yum.repos.d/almalinux-saphana.repo': ARCH_ACCEPTED, ++ # RT and NFV are only on x86_64 on almalinux 10 ++ '/etc/yum.repos.d/almalinux-nfv.repo': (ARCH_X86_64,), ++ '/etc/yum.repos.d/almalinux-rt.repo': (ARCH_X86_64,), ++ }, ++ }, ++} ++ ++ ++def _get_distro_repofiles(distro, major_version, arch): ++ """ ++ Get distribution provided repofiles. ++ ++ Note that this does not perform any validation, the caller must check ++ whether the files exist. ++ ++ :param distro: The distribution to get repofiles for. ++ :type distro: str ++ :param major_version: The major version to get repofiles for. ++ :type major_version: str ++ :param arch: The architecture to get repofiles for. ++ :type arch: str ++ :return: A list of paths to repofiles provided by distribution ++ :rtype: list[str] or None if no repofiles are mapped for the arguments ++ """ ++ ++ distro_repofiles = _DISTRO_REPOFILES_MAP.get(distro) ++ if not distro_repofiles: ++ return None ++ ++ version_repofiles = distro_repofiles.get(major_version, {}) ++ if not version_repofiles: ++ return None ++ ++ return [repofile for repofile, archs in version_repofiles.items() if arch in archs] ++ ++ ++def get_target_distro_repoids(context): ++ """ ++ Get repoids defined in distro provided repofiles ++ ++ See the generic :func:`_get_distro_repoids` for more details. ++ ++ :param context: An instance of mounting.IsolatedActions class ++ :type context: mounting.IsolatedActions ++ :return: Repoids of distribution provided repositories ++ :type: list[str] ++ """ ++ ++ return get_distro_repoids( ++ context, ++ get_distro_id(), ++ get_target_major_version(), ++ api.current_actor().configuration.architecture ++ ) ++ ++ ++def get_distro_repoids(context, distro, major_version, arch): ++ """ ++ Get repoids defined in distro provided repofiles ++ ++ On RHEL with RHSM this delegates to rhsm.get_available_repo_ids. ++ ++ Repofiles installed by RHUI client packages are not covered by this ++ function. ++ ++ :param context: An instance of mounting.IsolatedActions class ++ :type context: mounting.IsolatedActions ++ :param distro: The distro whose repoids to return ++ :type distro: str ++ :param major_version: The major version to get distro repoids for. ++ :type major_version: str ++ :param arch: The architecture to get distro repoids for. ++ :type arch: str ++ :return: Repoids of distribution provided repositories ++ :type: list[str] ++ """ ++ ++ if distro == 'rhel': ++ if rhsm.skip_rhsm(): ++ return [] ++ # Kept this todo here from the original code from ++ # userspacegen._get_rh_available_repoids: ++ # Get the RHSM repos available in the target RHEL container ++ # TODO: very similar thing should happens for all other repofiles in container ++ return rhsm.get_available_repo_ids(context) ++ ++ repofiles = repofileutils.get_parsed_repofiles(context) ++ distro_repofiles = _get_distro_repofiles(distro, major_version, arch) ++ if not distro_repofiles: ++ # TODO: a different way of signaling an error would be preferred (e.g. returning None), ++ # but since rhsm.get_available_repo_ids also raises StopActorExecutionError, ++ # let's make it easier for the caller for now and use it too ++ raise StopActorExecutionError( ++ "No known distro provided repofiles mapped", ++ details={ ++ "details": "distro: {}, major version: {}, architecture: {}".format( ++ distro, major_version, arch ++ ) ++ }, ++ ) ++ ++ distro_repoids = [] ++ for rfile in repofiles: ++ if rfile.file in distro_repofiles: ++ ++ if not os.path.exists(context.full_path(rfile.file)): ++ api.current_logger().debug( ++ "Expected distribution provided repofile does not exists: {}".format( ++ rfile ++ ) ++ ) ++ continue ++ ++ if rfile.data: ++ distro_repoids.extend([repo.repoid for repo in rfile.data]) ++ ++ return sorted(distro_repoids) diff --git a/repos/system_upgrade/common/libraries/dnfplugin.py b/repos/system_upgrade/common/libraries/dnfplugin.py -index 4f0c3a99..0f31f101 100644 +index 4f0c3a99..66b89aed 100644 --- a/repos/system_upgrade/common/libraries/dnfplugin.py +++ b/repos/system_upgrade/common/libraries/dnfplugin.py @@ -90,6 +90,7 @@ def build_plugin_data(target_repoids, debug, test, tasks, on_aws): @@ -6272,10 +10614,33 @@ index 4f0c3a99..0f31f101 100644 'modules_to_enable': sorted(['{}:{}'.format(m.name, m.stream) for m in tasks.modules_to_enable]), }, 'dnf_conf': { +@@ -461,9 +462,10 @@ def perform_transaction_install(target_userspace_info, storage_info, used_repos, + + @contextlib.contextmanager + def _prepare_perform(used_repos, target_userspace_info, xfs_info, storage_info, target_iso=None): +- # noqa: W0135; pylint: disable=contextmanager-generator-missing-cleanup ++ # noqa: W0135; pylint: disable=bad-option-value,contextmanager-generator-missing-cleanup + # NOTE(pstodulk): the pylint check is not valid in this case - finally is covered + # implicitly ++ # noqa: W0135 + reserve_space = overlaygen.get_recommended_leapp_free_space(target_userspace_info.path) + with _prepare_transaction(used_repos=used_repos, + target_userspace_info=target_userspace_info diff --git a/repos/system_upgrade/common/libraries/fetch.py b/repos/system_upgrade/common/libraries/fetch.py -index 82bf4ff3..cb20d775 100644 +index 82bf4ff3..44abe66b 100644 --- a/repos/system_upgrade/common/libraries/fetch.py +++ b/repos/system_upgrade/common/libraries/fetch.py +@@ -56,8 +56,8 @@ def _request_data(service_path, cert, proxies, timeout=REQUEST_TIMEOUT): + timeout = (timeout[0], timeout[1] + 10) + if attempt > MAX_ATTEMPTS: + logger.warning( +- 'Attempt {} of {} to get {} failed: {}.' +- .format(MAX_ATTEMPTS, MAX_ATTEMPTS, service_path, etype_msg) ++ 'Attempt {max} of {max} to get {service} failed: {error}.' ++ .format(max=MAX_ATTEMPTS, service=service_path, error=etype_msg) + ) + raise + @@ -146,7 +146,8 @@ def load_data_asset(actor_requesting_asset, asset_filename, asset_fulltext_name, @@ -6321,16 +10686,379 @@ index c9c3f1fc..96907be0 100644 def is_nogpgcheck_set(): +diff --git a/repos/system_upgrade/common/libraries/grub.py b/repos/system_upgrade/common/libraries/grub.py +index cd960ea4..77679d01 100644 +--- a/repos/system_upgrade/common/libraries/grub.py ++++ b/repos/system_upgrade/common/libraries/grub.py +@@ -30,11 +30,10 @@ def canonical_path_to_efi_format(canonical_path): + return canonical_path.replace(EFI_MOUNTPOINT[:-1], "").replace("/", "\\") + + +-class EFIBootLoaderEntry(object): ++class EFIBootLoaderEntry: + """ + Representation of an UEFI boot loader entry. + """ +- # pylint: disable=eq-without-hash + + def __init__(self, boot_number, label, active, efi_bin_source): + self.boot_number = boot_number +@@ -102,7 +101,7 @@ class EFIBootLoaderEntry(object): + return EFIBootLoaderEntry._efi_path_to_canonical(match.groups('path')[0]) + + +-class EFIBootInfo(object): ++class EFIBootInfo: + """ + Data about the current UEFI boot configuration. + +@@ -163,7 +162,8 @@ class EFIBootInfo(object): + # it's not expected that no entry exists + raise StopActorExecution('UEFI: Unable to detect any UEFI bootloader entry.') + +- def _parse_key_value(self, bootmgr_output, key): ++ @staticmethod ++ def _parse_key_value(bootmgr_output, key): + # e.g.: : + for line in bootmgr_output.splitlines(): + if line.startswith(key + ':'): +diff --git a/repos/system_upgrade/common/libraries/guards.py b/repos/system_upgrade/common/libraries/guards.py +index c8001817..ea2bf4dd 100644 +--- a/repos/system_upgrade/common/libraries/guards.py ++++ b/repos/system_upgrade/common/libraries/guards.py +@@ -34,7 +34,7 @@ def guarded_execution(*guards): + def connection_guard(url='https://example.com'): + def closure(): + try: +- urlopen(url) ++ urlopen(url) # pylint: disable=consider-using-with + return None + except URLError as e: + cause = '''Failed to open url '{url}' with error: {error}'''.format(url=url, error=e) +diff --git a/repos/system_upgrade/common/libraries/kernel.py b/repos/system_upgrade/common/libraries/kernel.py +index dac21b06..fc8c1167 100644 +--- a/repos/system_upgrade/common/libraries/kernel.py ++++ b/repos/system_upgrade/common/libraries/kernel.py +@@ -9,7 +9,7 @@ KernelPkgInfo = namedtuple('KernelPkgInfo', ('name', 'version', 'release', 'arch + KERNEL_UNAME_R_PROVIDES = ['kernel-uname-r', 'kernel-rt-uname-r'] + + +-class KernelType(object): ++class KernelType: + ORDINARY = 'ordinary' + REALTIME = 'realtime' + +diff --git a/repos/system_upgrade/common/libraries/mounting.py b/repos/system_upgrade/common/libraries/mounting.py +index 2eb19d31..279d31dc 100644 +--- a/repos/system_upgrade/common/libraries/mounting.py ++++ b/repos/system_upgrade/common/libraries/mounting.py +@@ -16,7 +16,7 @@ ALWAYS_BIND = [] + ErrorData = namedtuple('ErrorData', ['summary', 'details']) + + +-class MountingMode(object): ++class MountingMode: + """ + MountingMode are types of mounts supported by the library + """ +@@ -46,13 +46,13 @@ class MountError(Exception): + """ Exception that is thrown when a mount related operation failed """ + + def __init__(self, message, details): +- super(MountError, self).__init__(message) ++ super().__init__(message) + self.details = details + + +-class IsolationType(object): ++class IsolationType: + """ Implementations for the different isolated actions types """ +- class _Implementation(object): ++ class _Implementation: + """ Base class for all isolated actions """ + + def __init__(self, target, **kwargs): +@@ -66,7 +66,8 @@ class IsolationType(object): + """ Release the isolation context """ + pass + +- def make_command(self, cmd): ++ @staticmethod ++ def make_command(cmd): + """ Transform the given command to the isolated environment """ + return cmd + +@@ -74,7 +75,7 @@ class IsolationType(object): + """ systemd-nspawn implementation """ + + def __init__(self, target, binds=(), env_vars=None): +- super(IsolationType.NSPAWN, self).__init__(target=target) ++ super().__init__(target=target) + self.binds = list(binds) + ALWAYS_BIND + self.env_vars = env_vars or get_all_envs() + +@@ -97,7 +98,7 @@ class IsolationType(object): + """ chroot implementation """ + + def __init__(self, target): +- super(IsolationType.CHROOT, self).__init__(target) ++ super().__init__(target) + self.context = None + + def create(self): +@@ -129,7 +130,7 @@ class IsolationType(object): + """ Execute the given commands and perform the given operations on the real system and not isolated. """ + + +-class IsolatedActions(object): ++class IsolatedActions: + """ This class allows to perform actions in a manner as if the given base_dir would be the current root """ + + _isolated = True +@@ -261,14 +262,14 @@ class ChrootActions(IsolatedActions): + """ Isolation with chroot """ + + def __init__(self, base_dir): +- super(ChrootActions, self).__init__(base_dir=base_dir, implementation=IsolationType.CHROOT) ++ super().__init__(base_dir=base_dir, implementation=IsolationType.CHROOT) + + + class NspawnActions(IsolatedActions): + """ Isolation with systemd-nspawn """ + + def __init__(self, base_dir, binds=(), env_vars=None): +- super(NspawnActions, self).__init__( ++ super().__init__( + base_dir=base_dir, implementation=IsolationType.NSPAWN, binds=binds, env_vars=env_vars) + + +@@ -277,10 +278,10 @@ class NotIsolatedActions(IsolatedActions): + _isolated = False + + def __init__(self, base_dir): +- super(NotIsolatedActions, self).__init__(base_dir=base_dir, implementation=IsolationType.NONE) ++ super().__init__(base_dir=base_dir, implementation=IsolationType.NONE) + + +-class MountConfig(object): ++class MountConfig: + """ Options for Mount """ + _Options = namedtuple('_Options', ('should_create', 'should_cleanup')) + AttachOnly = _Options(should_create=False, should_cleanup=False) +@@ -293,7 +294,7 @@ class MountConfig(object): + """ Create all necessary directories and perform mount calls and cleanup afterwards """ + + +-class MountingBase(object): ++class MountingBase: + """ Base class for all mount operations """ + + def __init__(self, source, target, mode, config=MountConfig.Mount): +@@ -374,7 +375,7 @@ class NullMount(MountingBase): + """ This is basically a NoOp for compatibility with other mount operations, in case a mount is optional """ + + def __init__(self, target, config=MountConfig.AttachOnly): +- super(NullMount, self).__init__(source=target, target=target, mode=MountingMode.NONE, config=config) ++ super().__init__(source=target, target=target, mode=MountingMode.NONE, config=config) + + def __enter__(self): + return self +@@ -387,21 +388,21 @@ class LoopMount(MountingBase): + """ Performs loop mounts """ + + def __init__(self, source, target, config=MountConfig.Mount): +- super(LoopMount, self).__init__(source=source, target=target, mode=MountingMode.LOOP, config=config) ++ super().__init__(source=source, target=target, mode=MountingMode.LOOP, config=config) + + + class BindMount(MountingBase): + """ Performs bind mounts """ + + def __init__(self, source, target, config=MountConfig.Mount): +- super(BindMount, self).__init__(source=source, target=target, mode=MountingMode.BIND, config=config) ++ super().__init__(source=source, target=target, mode=MountingMode.BIND, config=config) + + + class TypedMount(MountingBase): + """ Performs a typed mounts """ + + def __init__(self, fstype, source, target, config=MountConfig.Mount): +- super(TypedMount, self).__init__(source=source, target=target, mode=MountingMode.FSTYPE, config=config) ++ super().__init__(source=source, target=target, mode=MountingMode.FSTYPE, config=config) + self.fstype = fstype + + def _mount_options(self): +@@ -415,8 +416,12 @@ class OverlayMount(MountingBase): + """ Performs an overlayfs mount """ + + def __init__(self, name, source, workdir, config=MountConfig.Mount): +- super(OverlayMount, self).__init__(source=source, target=os.path.join(workdir, name), +- mode=MountingMode.OVERLAY, config=config) ++ super().__init__( ++ source=source, ++ target=os.path.join(workdir, name), ++ mode=MountingMode.OVERLAY, ++ config=config ++ ) + self._upper_dir = os.path.join(workdir, 'upper') + self._work_dir = os.path.join(workdir, 'work') + self.additional_directories = (self._upper_dir, self._work_dir) +diff --git a/repos/system_upgrade/common/libraries/multipathutil.py b/repos/system_upgrade/common/libraries/multipathutil.py +index 47d0d86e..cb5c3693 100644 +--- a/repos/system_upgrade/common/libraries/multipathutil.py ++++ b/repos/system_upgrade/common/libraries/multipathutil.py +@@ -38,7 +38,7 @@ def write_config(path, contents): + ) + + +-class LineData(object): ++class LineData: + TYPE_BLANK = 0 + TYPE_SECTION_START = 1 + TYPE_SECTION_END = 2 +diff --git a/repos/system_upgrade/common/libraries/overlaygen.py b/repos/system_upgrade/common/libraries/overlaygen.py +index 867e3559..83dc33b8 100644 +--- a/repos/system_upgrade/common/libraries/overlaygen.py ++++ b/repos/system_upgrade/common/libraries/overlaygen.py +@@ -185,7 +185,7 @@ def _get_fspace(path, convert_to_mibs=False, coefficient=1): + coefficient = min(coefficient, 1) + fspace_bytes = int(stat.f_frsize * stat.f_bavail * coefficient) + if convert_to_mibs: +- return int(fspace_bytes / 1024 / 1024) # noqa: W1619; pylint: disable=old-division ++ return int(fspace_bytes / 1024 / 1024) + return fspace_bytes + + +@@ -325,7 +325,7 @@ def _prepare_required_mounts(scratch_dir, mounts_dir, storage_info, scratch_rese + + @contextlib.contextmanager + def _build_overlay_mount(root_mount, mounts): +- # noqa: W0135; pylint: disable=contextmanager-generator-missing-cleanup ++ # noqa: W0135; pylint: disable=bad-option-value,contextmanager-generator-missing-cleanup + # NOTE(pstodulk): the pylint check is not valid in this case - finally is covered + # implicitly + if not root_mount: +@@ -480,8 +480,8 @@ def _create_mount_disk_image(disk_images_directory, path, disk_size): + # NOTE(pstodulk): In case the formatting params are modified, + # the minimal required size could be different + api.current_logger().warning( +- 'The apparent size for the disk image representing {path}' +- ' is too small ({disk_size} MiBs) for a formatting. Setting 130 MiBs instead.' ++ 'The apparent size for the disk image representing {path} ' ++ 'is too small ({disk_size} MiBs) for a formatting. Setting 130 MiBs instead.' + .format(path=path, disk_size=disk_size) + ) + disk_size = 130 +@@ -489,12 +489,11 @@ def _create_mount_disk_image(disk_images_directory, path, disk_size): + cmd = [ + '/bin/dd', + 'if=/dev/zero', 'of={}'.format(diskimage_path), +- 'bs=1M', 'count=0', 'seek={}'.format(disk_size) ++ 'bs=1M', 'count=0', 'seek={}'.format(disk_size), + ] + hint = ( + 'Please ensure that there is enough diskspace on the partition hosting' +- 'the {} directory.' +- .format(disk_images_directory) ++ 'the {} directory.'.format(disk_images_directory) + ) + + api.current_logger().debug('Attempting to create disk image at %s', diskimage_path) +@@ -540,7 +539,9 @@ def _create_mounts_dir(scratch_dir, mounts_dir): + utils.makedirs(mounts_dir) + api.current_logger().debug('Done creating mount directories.') + except OSError: +- api.current_logger().error('Failed to create mounting directories %s', mounts_dir, exc_info=True) ++ api.current_logger().error( ++ 'Failed to create mounting directories %s', mounts_dir, exc_info=True ++ ) + + # This is an attempt for giving the user a chance to resolve it on their own + raise StopActorExecutionError( +@@ -556,17 +557,25 @@ def _mount_dnf_cache(overlay_target): + """ + Convenience context manager to ensure bind mounted /var/cache/dnf and removal of the mount. + """ +- # noqa: W0135; pylint: disable=contextmanager-generator-missing-cleanup ++ # noqa: W0135; pylint: disable=bad-option-value,contextmanager-generator-missing-cleanup + # NOTE(pstodulk): the pylint check is not valid in this case - finally is covered + # implicitly + with mounting.BindMount( +- source='/var/cache/dnf', +- target=os.path.join(overlay_target, 'var', 'cache', 'dnf')) as cache_mount: ++ source='/var/cache/dnf', ++ target=os.path.join(overlay_target, 'var', 'cache', 'dnf'), ++ ) as cache_mount: + yield cache_mount + + + @contextlib.contextmanager +-def create_source_overlay(mounts_dir, scratch_dir, xfs_info, storage_info, mount_target=None, scratch_reserve=0): ++def create_source_overlay( ++ mounts_dir, ++ scratch_dir, ++ xfs_info, ++ storage_info, ++ mount_target=None, ++ scratch_reserve=0, ++): + """ + Context manager that prepares the source system overlay and yields the mount. + +@@ -610,7 +619,7 @@ def create_source_overlay(mounts_dir, scratch_dir, xfs_info, storage_info, mount + :type scratch_reserve: Optional[int] + :rtype: mounting.BindMount or mounting.NullMount + """ +- # noqa: W0135; pylint: disable=contextmanager-generator-missing-cleanup ++ # noqa: W0135; pylint: disable=bad-option-value,contextmanager-generator-missing-cleanup + # NOTE(pstodulk): the pylint check is not valid in this case - finally is covered + # implicitly + api.current_logger().debug('Creating source overlay in {scratch_dir} with mounts in {mounts_dir}'.format( +@@ -710,7 +719,7 @@ def _create_mount_disk_image_old(disk_images_directory, path): + try: + utils.call_with_oserror_handled(cmd=['/sbin/mkfs.ext4', '-F', diskimage_path]) + except CalledProcessError as e: +- api.current_logger().error('Failed to create ext4 filesystem in %s', exc_info=True) ++ api.current_logger().error('Failed to create ext4 filesystem in %s', diskimage_path, exc_info=True) + raise StopActorExecutionError( + message=str(e) + ) +diff --git a/repos/system_upgrade/common/libraries/persistentnetnames.py b/repos/system_upgrade/common/libraries/persistentnetnames.py +index 8769712c..7fdf7eaa 100644 +--- a/repos/system_upgrade/common/libraries/persistentnetnames.py ++++ b/repos/system_upgrade/common/libraries/persistentnetnames.py +@@ -50,7 +50,7 @@ def interfaces(): + except Exception as e: # pylint: disable=broad-except + # FIXME(msekleta): We should probably handle errors more granularly + # Maybe we should inhibit upgrade process at this point +- api.current_logger().warning('Failed to gather information about network interface: ' + str(e)) ++ api.current_logger().warning('Failed to gather information about network interface: %s', e) + continue + + yield Interface(**attrs) +diff --git a/repos/system_upgrade/common/libraries/repofileutils.py b/repos/system_upgrade/common/libraries/repofileutils.py +index cab3c42b..376473a4 100644 +--- a/repos/system_upgrade/common/libraries/repofileutils.py ++++ b/repos/system_upgrade/common/libraries/repofileutils.py +@@ -16,7 +16,7 @@ class InvalidRepoDefinition(Exception): + 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) ++ super().__init__(message) + self.repofile = repofile + self.repoid = repoid + diff --git a/repos/system_upgrade/common/libraries/repomaputils.py b/repos/system_upgrade/common/libraries/repomaputils.py new file mode 100644 -index 00000000..39b7d662 +index 00000000..40a6f001 --- /dev/null +++ b/repos/system_upgrade/common/libraries/repomaputils.py @@ -0,0 +1,141 @@ +from collections import defaultdict +from leapp.models import PESIDRepositoryEntry, RepoMapEntry, RepositoriesMapping + -+class RepoMapData(object): ++class RepoMapData: + VERSION_FORMAT = '1.3.0' + + def __init__(self): @@ -6468,6 +11196,403 @@ index 00000000..39b7d662 + ) + + return combined_repomapping +diff --git a/repos/system_upgrade/common/libraries/rhui.py b/repos/system_upgrade/common/libraries/rhui.py +index 5c293304..c90c8c14 100644 +--- a/repos/system_upgrade/common/libraries/rhui.py ++++ b/repos/system_upgrade/common/libraries/rhui.py +@@ -21,7 +21,7 @@ RHUI_PKI_PRIVATE_DIR = os.path.join(RHUI_PKI_DIR, 'private') + AWS_DNF_PLUGIN_NAME = 'amazon-id.py' + + +-class ContentChannel(object): ++class ContentChannel: + GA = 'ga' + TUV = 'tuv' + E4S = 'e4s' +@@ -30,14 +30,14 @@ class ContentChannel(object): + BETA = 'beta' + + +-class RHUIVariant(object): ++class RHUIVariant: + ORDINARY = 'ordinary' # Special value - not displayed in report/errors + SAP = 'sap' + SAP_APPS = 'sap-apps' + SAP_HA = 'sap-ha' + + +-class RHUIProvider(object): ++class RHUIProvider: + GOOGLE = 'Google' + AZURE = 'Azure' + AWS = 'AWS' +@@ -74,7 +74,7 @@ RHUISetup = namedtuple( + """ + + +-class RHUIFamily(object): ++class RHUIFamily: + def __init__(self, provider, client_files_folder='', variant=RHUIVariant.ORDINARY, arch=arch.ARCH_X86_64,): + self.provider = provider + self.client_files_folder = client_files_folder +diff --git a/repos/system_upgrade/common/libraries/rpms.py b/repos/system_upgrade/common/libraries/rpms.py +index bd3a2961..8f98c1a4 100644 +--- a/repos/system_upgrade/common/libraries/rpms.py ++++ b/repos/system_upgrade/common/libraries/rpms.py +@@ -3,7 +3,7 @@ from leapp.libraries.common.config.version import get_source_major_version + from leapp.models import InstalledRPM + + +-class LeappComponents(object): ++class LeappComponents: + """ + Supported component values to be used with get_packages_function: + * FRAMEWORK - the core of the leapp project: the leapp executable and +diff --git a/repos/system_upgrade/common/libraries/tests/test_distro.py b/repos/system_upgrade/common/libraries/tests/test_distro.py +new file mode 100644 +index 00000000..13e782e6 +--- /dev/null ++++ b/repos/system_upgrade/common/libraries/tests/test_distro.py +@@ -0,0 +1,200 @@ ++import json ++import os ++ ++import pytest ++ ++from leapp.actors import StopActorExecutionError ++from leapp.libraries.common import distro, repofileutils, rhsm ++from leapp.libraries.common.config.architecture import ARCH_ACCEPTED, ARCH_ARM64, ARCH_PPC64LE, ARCH_S390X, ARCH_X86_64 ++from leapp.libraries.common.distro import _get_distro_repofiles, get_distribution_data, get_distro_repoids ++from leapp.libraries.common.testutils import CurrentActorMocked ++from leapp.libraries.stdlib import api ++from leapp.models import RepositoryData, RepositoryFile ++ ++_RHEL_REPOFILES = ['/etc/yum.repos.d/redhat.repo'] ++_CENTOS_REPOFILES = [ ++ "/etc/yum.repos.d/centos.repo", "/etc/yum.repos.d/centos-addons.repo" ++] ++ ++_CUR_DIR = os.path.dirname(os.path.abspath(__file__)) ++ ++ ++@pytest.mark.parametrize('distro', ['rhel', 'centos']) ++def test_get_distribution_data(monkeypatch, distro): ++ common_path = os.path.join(_CUR_DIR, "../../files/", 'distro') ++ monkeypatch.setattr( ++ api, ++ "get_common_folder_path", ++ lambda folder: common_path ++ ) ++ data_path = os.path.join(common_path, distro, "gpg-signatures.json") ++ ++ def exists_mocked(path): ++ assert path == data_path ++ return True ++ ++ monkeypatch.setattr(os.path, 'exists', exists_mocked) ++ ret = get_distribution_data(distro) ++ ++ with open(data_path) as fp: ++ assert ret == json.load(fp) ++ ++ ++@pytest.mark.parametrize('distro', ['rhel', 'centos']) ++def test_get_distribution_data_not_exists(monkeypatch, distro): ++ common_path = os.path.join(_CUR_DIR, "../../files/", 'distro') ++ monkeypatch.setattr( ++ api, ++ "get_common_folder_path", ++ lambda folder: common_path ++ ) ++ data_path = os.path.join(common_path, distro, "gpg-signatures.json") ++ ++ def exists_mocked(path): ++ assert path == data_path ++ return False ++ ++ monkeypatch.setattr(os.path, 'exists', exists_mocked) ++ ++ with pytest.raises(StopActorExecutionError) as err: ++ get_distribution_data(distro) ++ assert 'Cannot find distribution signature configuration.' in err ++ ++ ++def test_get_distro_repofiles(monkeypatch): ++ """ ++ Test the functionality, not the data. ++ """ ++ test_map = { ++ 'distro1': { ++ '8': { ++ 'repofile1': ARCH_ACCEPTED, ++ 'repofile2': [ARCH_X86_64], ++ }, ++ '9': { ++ 'repofile3': ARCH_ACCEPTED, ++ }, ++ }, ++ 'distro2': { ++ '8': {}, ++ '9': { ++ 'repofile2': [ARCH_X86_64], ++ 'repofile3': [ARCH_ARM64, ARCH_S390X, ARCH_PPC64LE], ++ }, ++ }, ++ } ++ monkeypatch.setattr(distro, '_DISTRO_REPOFILES_MAP', test_map) ++ ++ # mix of all and specific arch ++ repofiles = _get_distro_repofiles('distro1', '8', ARCH_X86_64) ++ assert repofiles == ['repofile1', 'repofile2'] ++ ++ # match all but not x86_64 ++ repofiles = _get_distro_repofiles('distro1', '8', ARCH_ARM64) ++ assert repofiles == ['repofile1'] ++ ++ repofiles = _get_distro_repofiles('distro2', '9', ARCH_X86_64) ++ assert repofiles == ['repofile2'] ++ repofiles = _get_distro_repofiles('distro2', '9', ARCH_ARM64) ++ assert repofiles == ['repofile3'] ++ repofiles = _get_distro_repofiles('distro2', '9', ARCH_S390X) ++ assert repofiles == ['repofile3'] ++ repofiles = _get_distro_repofiles('distro2', '9', ARCH_PPC64LE) ++ assert repofiles == ['repofile3'] ++ ++ # version not mapped ++ repofiles = _get_distro_repofiles('distro2', '8', ARCH_X86_64) ++ assert repofiles is None ++ ++ # distro not mapped ++ repofiles = _get_distro_repofiles('distro42', '8', ARCH_X86_64) ++ assert repofiles is None ++ ++ ++def _make_repo(repoid): ++ return RepositoryData(repoid=repoid, name='name {}'.format(repoid)) ++ ++ ++def _make_repofile(rfile, data=None): ++ if data is None: ++ data = [_make_repo("{}-{}".format(rfile.split("/")[-1], i)) for i in range(3)] ++ return RepositoryFile(file=rfile, data=data) ++ ++ ++def _make_repofiles(rfiles): ++ return [_make_repofile(rfile) for rfile in rfiles] ++ ++ ++@pytest.mark.parametrize('other_rfiles', [ ++ [], ++ [_make_repofile("foo")], ++ _make_repofiles(["foo", "bar"]), ++]) ++@pytest.mark.parametrize( ++ "distro_id,skip_rhsm,distro_rfiles", ++ [ ++ ("rhel", True, []), ++ ("rhel", True, _make_repofiles(_RHEL_REPOFILES)), ++ ("rhel", False, _make_repofiles(_RHEL_REPOFILES)), ++ ("centos", True, []), ++ ("centos", True, _make_repofiles(_CENTOS_REPOFILES)), ++ ] ++) ++def test_get_distro_repoids( ++ monkeypatch, distro_id, skip_rhsm, distro_rfiles, other_rfiles ++): ++ """ ++ Tests that the correct repoids are returned ++ ++ This is a little ugly because on RHEL the get_distro_repoids function still ++ delegates to rhsm.get_available_repo_ids and also has different behavior ++ with skip_rhsm ++ """ ++ current_actor = CurrentActorMocked(release_id=distro_id if distro_id else 'rhel') ++ monkeypatch.setattr(api, 'current_actor', current_actor) ++ monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: skip_rhsm) ++ ++ repofiles = other_rfiles ++ if distro_rfiles: ++ repofiles.extend(distro_rfiles) ++ monkeypatch.setattr(repofileutils, 'get_parsed_repofiles', lambda x: repofiles) ++ ++ distro_repoids = [] ++ for rfile in distro_rfiles: ++ distro_repoids.extend([repo.repoid for repo in rfile.data] if rfile else []) ++ distro_repoids.sort() ++ ++ monkeypatch.setattr(rhsm, 'get_available_repo_ids', lambda _: distro_repoids) ++ monkeypatch.setattr(os.path, 'exists', lambda f: f in _CENTOS_REPOFILES) ++ ++ class MockedContext: ++ @staticmethod ++ def full_path(path): ++ return path ++ ++ repoids = get_distro_repoids(MockedContext(), distro_id, '9', 'x86_64') ++ ++ if distro_id == 'rhel' and skip_rhsm: ++ assert repoids == [] ++ else: ++ assert sorted(repoids) == distro_repoids ++ ++ ++@pytest.mark.parametrize('other_rfiles', [ ++ [], ++ [_make_repofile("foo")], ++ _make_repofiles(["foo", "bar"]), ++]) ++def test_get_distro_repoids_no_distro_repofiles(monkeypatch, other_rfiles): ++ """ ++ Test that exception is thrown when there are no known distro provided repofiles. ++ """ ++ ++ def mocked_get_distro_repofiles(*args): ++ return [] ++ ++ monkeypatch.setattr(distro, '_get_distro_repofiles', mocked_get_distro_repofiles) ++ monkeypatch.setattr(repofileutils, "get_parsed_repofiles", lambda x: other_rfiles) ++ ++ with pytest.raises(StopActorExecutionError): ++ get_distro_repoids(None, 'somedistro', '8', 'x86_64') +diff --git a/repos/system_upgrade/common/libraries/tests/test_grub.py b/repos/system_upgrade/common/libraries/tests/test_grub.py +index 9bc9f682..08dc6895 100644 +--- a/repos/system_upgrade/common/libraries/tests/test_grub.py ++++ b/repos/system_upgrade/common/libraries/tests/test_grub.py +@@ -23,7 +23,7 @@ INVALID_DD = b'Nothing to see here!' + + CUR_DIR = os.path.dirname(os.path.abspath(__file__)) + +-# pylint: disable=E501 ++# pylint: disable=line-too-long + # flake8: noqa: E501 + EFIBOOTMGR_OUTPUT = r""" + BootCurrent: 0006 +@@ -98,7 +98,7 @@ def raise_call_error(args=None): + ) + + +-class RunMocked(object): ++class RunMocked: + + def __init__(self, raise_err=False, boot_on_raid=False): + self.called = 0 +diff --git a/repos/system_upgrade/common/libraries/tests/test_mdraid.py b/repos/system_upgrade/common/libraries/tests/test_mdraid.py +index d536beec..8668be8c 100644 +--- a/repos/system_upgrade/common/libraries/tests/test_mdraid.py ++++ b/repos/system_upgrade/common/libraries/tests/test_mdraid.py +@@ -20,7 +20,7 @@ def raise_call_error(args=None): + ) + + +-class RunMocked(object): ++class RunMocked: + + def __init__(self, raise_err=False): + self.called = 0 +diff --git a/repos/system_upgrade/common/libraries/tests/test_persistentnetnames_library.py b/repos/system_upgrade/common/libraries/tests/test_persistentnetnames_library.py +index 2c399888..74aa08fa 100644 +--- a/repos/system_upgrade/common/libraries/tests/test_persistentnetnames_library.py ++++ b/repos/system_upgrade/common/libraries/tests/test_persistentnetnames_library.py +@@ -3,7 +3,7 @@ from leapp.libraries.common.testutils import produce_mocked + from leapp.libraries.stdlib import api + + +-class AttributesTest(object): ++class AttributesTest: + def __init__(self): + self.attributes = { + 'address': b'fa:16:3e:cd:26:5a' +@@ -15,7 +15,7 @@ class AttributesTest(object): + raise KeyError + + +-class DeviceTest(object): ++class DeviceTest: + def __init__(self): + self.dict_data = { + 'ID_NET_DRIVER': 'virtio_net', +diff --git a/repos/system_upgrade/common/libraries/tests/test_rhsm.py b/repos/system_upgrade/common/libraries/tests/test_rhsm.py +index b643cd0d..b118da29 100644 +--- a/repos/system_upgrade/common/libraries/tests/test_rhsm.py ++++ b/repos/system_upgrade/common/libraries/tests/test_rhsm.py +@@ -62,7 +62,7 @@ RHSM_ENABLED_REPOS = [ + ] + + +-class IsolatedActionsMocked(object): ++class IsolatedActionsMocked: + def __init__(self, call_stdout=None, raise_err=False): + self.commands_called = [] + self.call_return = {'stdout': call_stdout, 'stderr': None} +@@ -73,7 +73,8 @@ class IsolatedActionsMocked(object): + # A map from called commands to their mocked output + self.mocked_command_call_outputs = dict() + +- def is_isolated(self): ++ @staticmethod ++ def is_isolated(): + return True + + def call(self, cmd, *args, **dummy_kwargs): +@@ -93,7 +94,8 @@ class IsolatedActionsMocked(object): + 'exit_code': exit_code + } + +- def full_path(self, path): ++ @staticmethod ++ def full_path(path): + return path + + def remove(self, path): +diff --git a/repos/system_upgrade/common/libraries/testutils.py b/repos/system_upgrade/common/libraries/testutils.py +index 3e145d91..e84cc03a 100644 +--- a/repos/system_upgrade/common/libraries/testutils.py ++++ b/repos/system_upgrade/common/libraries/testutils.py +@@ -10,7 +10,7 @@ from leapp.models import EnvVar, IPUSourceToPossibleTargets + from leapp.utils.deprecation import deprecated + + +-class produce_mocked(object): ++class produce_mocked: + def __init__(self): + self.called = 0 + self.model_instances = [] +@@ -20,7 +20,7 @@ class produce_mocked(object): + self.model_instances.extend(list(model_instances)) + + +-class create_report_mocked(object): ++class create_report_mocked: + def __init__(self): + self.called = 0 + self.reports = [] +@@ -38,7 +38,7 @@ class create_report_mocked(object): + return {} + + +-class logger_mocked(object): ++class logger_mocked: + def __init__(self): + self.dbgmsg = [] + self.infomsg = [] +@@ -77,7 +77,7 @@ def _make_default_config(actor_config_schema): + # 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 ++class CurrentActorMocked: # pylint:disable=R0904 + 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, +@@ -120,7 +120,7 @@ class CurrentActorMocked(object): # pylint:disable=R0904 + return os.path.join(self._common_tools_folder, name) + + def consume(self, model): +- return iter(filter( # pylint:disable=W0110,W1639 ++ return iter(filter( + lambda msg: isinstance(msg, model), self._msgs + )) + diff --git a/repos/system_upgrade/common/models/activevendorlist.py b/repos/system_upgrade/common/models/activevendorlist.py new file mode 100644 index 00000000..de4056fb @@ -6523,10 +11648,34 @@ index 7e2870d0..05d4e941 100644 modules_to_reset = fields.List(fields.Model(Module), default=[]) diff --git a/repos/system_upgrade/common/models/targetrepositories.py b/repos/system_upgrade/common/models/targetrepositories.py -index 02c6c5e5..f9fd4238 100644 +index 02c6c5e5..e1d44d80 100644 --- a/repos/system_upgrade/common/models/targetrepositories.py +++ b/repos/system_upgrade/common/models/targetrepositories.py -@@ -21,6 +21,12 @@ class CustomTargetRepository(TargetRepositoryBase): +@@ -1,4 +1,5 @@ + from leapp.models import fields, Model ++from leapp.reporting import deprecated + from leapp.topics import TransactionTopic + + +@@ -11,33 +12,66 @@ class UsedTargetRepository(TargetRepositoryBase): + pass + + ++@deprecated( ++ since="2025-07-23", ++ message="This model is deprecated, use DistroTargetRepository instead.", ++) + class RHELTargetRepository(TargetRepositoryBase): + pass + + ++class DistroTargetRepository(TargetRepositoryBase): ++ pass ++ ++ + class CustomTargetRepository(TargetRepositoryBase): + name = fields.Nullable(fields.String()) + baseurl = fields.Nullable(fields.String()) enabled = fields.Boolean(default=True) @@ -6539,6 +11688,44 @@ index 02c6c5e5..f9fd4238 100644 class TargetRepositories(Model): """ Repositories supposed to be used during the IPU process + + The list of the actually used repositories could be just subset +- of these repositoies. In case of `custom_repositories`, all such repositories ++ of these repositories. In case of `custom_repositories`, all such repositories + must be available otherwise the upgrade is inhibited. But in case of +- `rhel_repos`, only BaseOS and Appstream repos are required now. If others ++ `distro_repos`, only BaseOS and Appstream repos are required now. If others + are missing, upgrade can still continue. ++ ++ Note: `rhel_repos` are deprecated, use `distro_repos` instead. + """ + topic = TransactionTopic ++ ++ # DEPRECATED: this has been superseded by distro_repos + rhel_repos = fields.List(fields.Model(RHELTargetRepository)) + """ + Expected target YUM RHEL repositories provided via RHSM + ++ DEPRECATED - use distro_repos instead. ++ ++ These repositories are stored inside /etc/yum.repos.d/redhat.repo and ++ are expected to be used based on the provided repositories mapping. ++ """ ++ ++ distro_repos = fields.List(fields.Model(DistroTargetRepository)) ++ """ ++ Expected target DNF repositories provided by the distribution. ++ ++ On RHEL these are the repositories provided via RHSM. + These repositories are stored inside /etc/yum.repos.d/redhat.repo and + are expected to be used based on the provided repositories mapping. ++ ++ On other distributions, such as Centos Stream these are repositories ++ in /etc/yum.repos.d/ that are provided by the distribution and are expected ++ to be used based on the provided repositories mapping. + """ + + custom_repos = fields.List(fields.Model(CustomTargetRepository), default=[]) diff --git a/repos/system_upgrade/common/models/vendorsignatures.py b/repos/system_upgrade/common/models/vendorsignatures.py new file mode 100644 index 00000000..f456aec5 @@ -6618,6 +11805,194 @@ index c076fe6b..2455a2f6 100644 UPGRADE_BLS_DIR = '/boot/upgrade-loader' CONTAINER_DOWNLOAD_DIR = '/tmp_pkg_download_dir' +diff --git a/repos/system_upgrade/el8toel9/actors/addarmbootloaderworkaround/tests/test_addarmbootloaderworkaround.py b/repos/system_upgrade/el8toel9/actors/addarmbootloaderworkaround/tests/test_addarmbootloaderworkaround.py +index 4f990e00..8c41cc7b 100644 +--- a/repos/system_upgrade/el8toel9/actors/addarmbootloaderworkaround/tests/test_addarmbootloaderworkaround.py ++++ b/repos/system_upgrade/el8toel9/actors/addarmbootloaderworkaround/tests/test_addarmbootloaderworkaround.py +@@ -35,7 +35,7 @@ class MockEFIBootInfo: + } + + +-class IsolatedActionsMocked(object): ++class IsolatedActionsMocked: + def __init__(self): + self.copytree_from_calls = [] + +diff --git a/repos/system_upgrade/el8toel9/actors/checkvdo/tests/unit_test_checkvdo.py b/repos/system_upgrade/el8toel9/actors/checkvdo/tests/unit_test_checkvdo.py +index 865e036f..d7cfb4fb 100644 +--- a/repos/system_upgrade/el8toel9/actors/checkvdo/tests/unit_test_checkvdo.py ++++ b/repos/system_upgrade/el8toel9/actors/checkvdo/tests/unit_test_checkvdo.py +@@ -15,13 +15,15 @@ from leapp.utils.report import is_inhibitor + + # Mock actor base for CheckVdo tests. + class MockedActorCheckVdo(CurrentActorMocked): +- def get_vdo_answer(self): ++ @staticmethod ++ def get_vdo_answer(): + return False + + + # Mock actor for all_vdo_converted dialog response. + class MockedActorAllVdoConvertedTrue(MockedActorCheckVdo): +- def get_vdo_answer(self): ++ @staticmethod ++ def get_vdo_answer(): + return True + + +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 +index 3ba46cb5..72356172 100644 +--- a/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/tests/test_ensurevalidgrubcfghybrid.py ++++ b/repos/system_upgrade/el8toel9/actors/cloud/ensurevalidgrubcfghybrid/tests/test_ensurevalidgrubcfghybrid.py +@@ -19,7 +19,7 @@ def raise_call_error(args=None): + ) + + +-class run_mocked(object): ++class run_mocked: + def __init__(self, raise_err=False): + self.called = 0 + self.args = [] +diff --git a/repos/system_upgrade/el8toel9/actors/grub2mkconfigonppc64/tests/test_grub2mkconfigonppc64.py b/repos/system_upgrade/el8toel9/actors/grub2mkconfigonppc64/tests/test_grub2mkconfigonppc64.py +index afa999d0..9d5da4b2 100644 +--- a/repos/system_upgrade/el8toel9/actors/grub2mkconfigonppc64/tests/test_grub2mkconfigonppc64.py ++++ b/repos/system_upgrade/el8toel9/actors/grub2mkconfigonppc64/tests/test_grub2mkconfigonppc64.py +@@ -12,7 +12,7 @@ from leapp.models import DefaultGrub, DefaultGrubInfo, FirmwareFacts + CUR_DIR = os.path.dirname(os.path.abspath(__file__)) + + +-class MockedRun(object): ++class MockedRun: + def __init__(self): + self.commands = [] + +@@ -36,7 +36,7 @@ def test_run_grub2mkconfig(monkeypatch, cmd_issued): + 'menuentry "Red Hat Enterprise Linux Server (3.10.0-1160.45.1.el7.x86_64) 7.9 (Maipo)"' + ) + +- class _mock_open(object): ++ class _mock_open: + def __init__(self, path, mode): + input_ = grub2_cfg_non_bls_excerpt if cmd_issued else grub2_cfg_bls_excerpt + self._fp = StringIO(input_) +diff --git a/repos/system_upgrade/el8toel9/actors/multipathconfread/libraries/multipathconfread.py b/repos/system_upgrade/el8toel9/actors/multipathconfread/libraries/multipathconfread.py +index e5b3f06c..5b1cef50 100644 +--- a/repos/system_upgrade/el8toel9/actors/multipathconfread/libraries/multipathconfread.py ++++ b/repos/system_upgrade/el8toel9/actors/multipathconfread/libraries/multipathconfread.py +@@ -68,12 +68,16 @@ def _parse_config_dir(config_dir): + res.append(conf) + except OSError as e: + if e.errno == errno.ENOENT: +- api.current_logger().debug('Multipath conf directory ' + +- '"{}" doesn\'t exist'.format(config_dir)) ++ api.current_logger().debug( ++ 'Multipath conf directory "%s" doesn\'t exist', ++ config_dir ++ ) + else: +- api.current_logger().warning('Failed to read multipath config ' + +- 'directory ' + +- '"{}": {}'.format(config_dir, e)) ++ api.current_logger().warning( ++ 'Failed to read multipath config directory "%s": %s', ++ config_dir, ++ e ++ ) + return res + + +diff --git a/repos/system_upgrade/el8toel9/actors/networkmanagerconnectionscanner/tests/unit_test_networkmanagerconnectionscanner.py b/repos/system_upgrade/el8toel9/actors/networkmanagerconnectionscanner/tests/unit_test_networkmanagerconnectionscanner.py +index 46af07c1..7558b307 100644 +--- a/repos/system_upgrade/el8toel9/actors/networkmanagerconnectionscanner/tests/unit_test_networkmanagerconnectionscanner.py ++++ b/repos/system_upgrade/el8toel9/actors/networkmanagerconnectionscanner/tests/unit_test_networkmanagerconnectionscanner.py +@@ -1,4 +1,5 @@ + import errno ++import sys + import textwrap + + import pytest +@@ -57,7 +58,16 @@ def test_no_conf(monkeypatch): + assert not api.produce.called + + +-@pytest.mark.skipif(not nmconnscanner.libnm_available, reason="NetworkManager g-ir not installed") ++@pytest.mark.skipif( ++ sys.version_info.major != 3 or sys.version_info.minor != 6, ++ # On Python > 3.6 the GLib and NM libraries apparently behave differently and ++ # the test fails. Let's skip it since the actor it's only ever run with ++ # Python3.6 (el8toel9 repo and FactsPhase) ++ reason="Only runs on Python 3.6", ++) ++@pytest.mark.skipif( ++ not nmconnscanner.libnm_available, reason="NetworkManager g-ir not installed" ++) + def test_nm_conn(monkeypatch): + """ + Check a basic keyfile +diff --git a/repos/system_upgrade/el8toel9/actors/nisscanner/libraries/nisscan.py b/repos/system_upgrade/el8toel9/actors/nisscanner/libraries/nisscan.py +index 9910f748..ae51c69d 100644 +--- a/repos/system_upgrade/el8toel9/actors/nisscanner/libraries/nisscan.py ++++ b/repos/system_upgrade/el8toel9/actors/nisscanner/libraries/nisscan.py +@@ -14,7 +14,8 @@ class NISScanLibrary: + Helper library for NISScan actor. + """ + +- def client_has_non_default_configuration(self): ++ @staticmethod ++ def client_has_non_default_configuration(): + """ + Check for any significant ypbind configuration lines in .conf file. + """ +@@ -31,7 +32,8 @@ class NISScanLibrary: + return True + return False + +- def server_has_non_default_configuration(self): ++ @staticmethod ++ def server_has_non_default_configuration(): + """ + Check for any additional (not default) files in ypserv DIR. + """ +diff --git a/repos/system_upgrade/el8toel9/actors/opensshdropindirectory/tests/test_opensshdropindirectory_prepend.py b/repos/system_upgrade/el8toel9/actors/opensshdropindirectory/tests/test_opensshdropindirectory_prepend.py +index bccadf4b..a6665313 100644 +--- a/repos/system_upgrade/el8toel9/actors/opensshdropindirectory/tests/test_opensshdropindirectory_prepend.py ++++ b/repos/system_upgrade/el8toel9/actors/opensshdropindirectory/tests/test_opensshdropindirectory_prepend.py +@@ -3,7 +3,7 @@ import pytest + from leapp.libraries.actor.opensshdropindirectory import prepend_string_if_not_present + + +-class MockFile(object): ++class MockFile: + def __init__(self, path, content=None): + self.path = path + self.content = content +diff --git a/repos/system_upgrade/el8toel9/actors/opensslconfigcheck/libraries/opensslconfigcheck.py b/repos/system_upgrade/el8toel9/actors/opensslconfigcheck/libraries/opensslconfigcheck.py +index f36a62e1..07c1b22f 100644 +--- a/repos/system_upgrade/el8toel9/actors/opensslconfigcheck/libraries/opensslconfigcheck.py ++++ b/repos/system_upgrade/el8toel9/actors/opensslconfigcheck/libraries/opensslconfigcheck.py +@@ -115,7 +115,8 @@ def _openssl_reachable_key(config, key, value=None): + return False + + +-# pylint: disable=too-many-return-statements -- could not simplify more ++# pylint: disable=too-many-return-statements ++# could not simplify more + def _openssl_reachable_path(config, path, value=None): + """ + Check if the given path is reachable in OpenSSL configuration +diff --git a/repos/system_upgrade/el8toel9/actors/opensslproviders/tests/test_add_provider.py b/repos/system_upgrade/el8toel9/actors/opensslproviders/tests/test_add_provider.py +index 1c1cd209..78f2e9c6 100644 +--- a/repos/system_upgrade/el8toel9/actors/opensslproviders/tests/test_add_provider.py ++++ b/repos/system_upgrade/el8toel9/actors/opensslproviders/tests/test_add_provider.py +@@ -64,7 +64,7 @@ def test_append(lines, add, comment, expected): + assert r == expected + + +-class MockFile(object): ++class MockFile: + def __init__(self, content=None): + self.content = content + self.error = False diff --git a/repos/system_upgrade/el8toel9/actors/removeupgradeefientry/libraries/removeupgradeefientry.py b/repos/system_upgrade/el8toel9/actors/removeupgradeefientry/libraries/removeupgradeefientry.py index daa7b2ca..dd604d8b 100644 --- a/repos/system_upgrade/el8toel9/actors/removeupgradeefientry/libraries/removeupgradeefientry.py @@ -6649,3 +12024,392 @@ index daa7b2ca..dd604d8b 100644 def get_workaround_efi_info(): +diff --git a/repos/system_upgrade/el8toel9/actors/rocecheck/tests/unit_test_rocecheck.py b/repos/system_upgrade/el8toel9/actors/rocecheck/tests/unit_test_rocecheck.py +index a36cc8ed..b5511d17 100644 +--- a/repos/system_upgrade/el8toel9/actors/rocecheck/tests/unit_test_rocecheck.py ++++ b/repos/system_upgrade/el8toel9/actors/rocecheck/tests/unit_test_rocecheck.py +@@ -91,7 +91,10 @@ def test_roce_old_rhel(monkeypatch, msgs, version): + monkeypatch.setattr(reporting, "create_report", create_report_mocked()) + rocecheck.process() + assert reporting.create_report.called +- assert any(['version of RHEL' in report['title'] for report in reporting.create_report.reports]) ++ assert any( ++ 'version of RHEL' in report['title'] ++ for report in reporting.create_report.reports ++ ) + + + # NOTE: what about the situation when net.naming-scheme is configured multiple times??? +@@ -113,4 +116,7 @@ def test_roce_wrong_configuration(monkeypatch, msgs, version): + monkeypatch.setattr(reporting, "create_report", create_report_mocked()) + rocecheck.process() + assert reporting.create_report.called +- assert any(['RoCE configuration' in report['title'] for report in reporting.create_report.reports]) ++ assert any( ++ 'RoCE configuration' in report['title'] ++ for report in reporting.create_report.reports ++ ) +diff --git a/repos/system_upgrade/el8toel9/actors/scanblacklistca/tests/unit_test_scanblacklistca.py b/repos/system_upgrade/el8toel9/actors/scanblacklistca/tests/unit_test_scanblacklistca.py +index 4eab6df5..c2ae4639 100644 +--- a/repos/system_upgrade/el8toel9/actors/scanblacklistca/tests/unit_test_scanblacklistca.py ++++ b/repos/system_upgrade/el8toel9/actors/scanblacklistca/tests/unit_test_scanblacklistca.py +@@ -14,7 +14,7 @@ TESTLINK = "linkca.cert" + SUBDIR = "casdir" + + +-class MockedGetFiles(object): ++class MockedGetFiles: + def __init__(self, files=None, error=None): + self.called = 0 + self.files = files +@@ -33,7 +33,7 @@ class MockedGetFiles(object): + return ret + + +-class MockedGetDirs(object): ++class MockedGetDirs: + def __init__(self, dirs): + self.called = 0 + self.dirs = dirs +diff --git a/repos/system_upgrade/el8toel9/actors/sssdfacts/libraries/sssdfacts8to9.py b/repos/system_upgrade/el8toel9/actors/sssdfacts/libraries/sssdfacts8to9.py +index a2537eeb..1482373e 100644 +--- a/repos/system_upgrade/el8toel9/actors/sssdfacts/libraries/sssdfacts8to9.py ++++ b/repos/system_upgrade/el8toel9/actors/sssdfacts/libraries/sssdfacts8to9.py +@@ -1,7 +1,7 @@ + from leapp.models import SSSDConfig8to9 + + +-class SSSDFactsLibrary(object): ++class SSSDFactsLibrary: + """ + Helper library from SSSDFacts actor to allow unit testing. + """ +diff --git a/repos/system_upgrade/el9toel10/actors/sssd/sssdchecks/libraries/sssdchecks.py b/repos/system_upgrade/el9toel10/actors/sssd/sssdchecks/libraries/sssdchecks.py +index 0a86fa7b..cb95026c 100644 +--- a/repos/system_upgrade/el9toel10/actors/sssd/sssdchecks/libraries/sssdchecks.py ++++ b/repos/system_upgrade/el9toel10/actors/sssd/sssdchecks/libraries/sssdchecks.py +@@ -15,8 +15,8 @@ def check_config(model): + 'SSSD\'s sss_ssh_knownhostsproxy tool is replaced by the more ' + 'reliable sss_ssh_knownhosts tool. SSH\'s configuration will be updated ' + 'to reflect this by updating every mention of sss_ssh_knownhostsproxy by ' +- 'the corresponding mention of sss_ssh_knownhosts, even those commented out.\n' +- 'SSSD\'s ssh service will be enabled if not already done.\n' ++ 'the corresponding mention of sss_ssh_knownhosts, even those commented out. ' ++ 'SSSD\'s ssh service will be enabled if not already done.\n\n' + 'The following files will be updated:{}{}'.format( + FMT_LIST_SEPARATOR, + FMT_LIST_SEPARATOR.join(model.sssd_config_files + model.ssh_config_files) +diff --git a/repos/system_upgrade/el9toel10/actors/sssd/sssdfacts/libraries/sssdfacts.py b/repos/system_upgrade/el9toel10/actors/sssd/sssdfacts/libraries/sssdfacts.py +index 0ae9d93f..7d343229 100644 +--- a/repos/system_upgrade/el9toel10/actors/sssd/sssdfacts/libraries/sssdfacts.py ++++ b/repos/system_upgrade/el9toel10/actors/sssd/sssdfacts/libraries/sssdfacts.py +@@ -19,7 +19,10 @@ def _does_file_contain_expression(file_path, expression): + ) + return False + except OSError as e: +- raise StopActorExecutionError('Could not open file ' + file_path, details={'details': str(e)}) ++ raise StopActorExecutionError( ++ 'Could not open configuration file', ++ details={'details': 'Coudn\'t open {} file with error: {}.'.format(file_path, str(e))} ++ ) + + + def _look_for_files(expression: str, path_list: list[str]) -> list[str]: +diff --git a/repos/system_upgrade/el9toel10/actors/sssd/sssdupdate/libraries/sssdupdate.py b/repos/system_upgrade/el9toel10/actors/sssd/sssdupdate/libraries/sssdupdate.py +index 6d745ead..5b96bcc6 100644 +--- a/repos/system_upgrade/el9toel10/actors/sssd/sssdupdate/libraries/sssdupdate.py ++++ b/repos/system_upgrade/el9toel10/actors/sssd/sssdupdate/libraries/sssdupdate.py +@@ -1,7 +1,7 @@ + import os + import re + +-from leapp.exceptions import StopActorExecutionError ++from leapp.libraries.stdlib import api + + + def _process_knownhosts(line: str) -> str: +@@ -29,30 +29,26 @@ def _process_enable_svc(line: str) -> str: + + + def _update_file(filename, process_function): +- newname = filename + '.new' +- oldname = filename + '.old' ++ newname = '{}.leappnew'.format(filename) ++ oldname = '{}.leappsave'.format(filename) + try: +- with open(filename, 'r') as input_file, open(newname, 'x') as output_file: ++ with open(filename, 'r') as input_file, open(newname, 'w') as output_file: + istat = os.fstat(input_file.fileno()) + os.fchmod(output_file.fileno(), istat.st_mode) + for line in input_file: + try: + output_file.write(process_function(line)) + except OSError as e: +- raise StopActorExecutionError('Failed to write to {}'.format(newname), +- details={'details': str(e)}) ++ api.current_logger().warning('Failed to write to {}'.format(newname), details={'details': str(e)}) + +- except FileExistsError as e: +- raise StopActorExecutionError('Temporary file already exists: {}'.format(newname), +- details={'details': str(e)}) + except OSError as e: + try: + os.unlink(newname) + except FileNotFoundError: + pass +- raise StopActorExecutionError('Failed to access the required files', details={'details': str(e)}) ++ api.current_logger().error('Failed to access the required files', details={'details': str(e)}) + +- # Let's make sure the old configuration is preserverd if something goes wrong ++ # Let's make sure the old configuration is preserved if something goes wrong + os.replace(filename, oldname) + os.replace(newname, filename) + os.unlink(oldname) +diff --git a/utils/container-builds/Containerfile.centos7 b/utils/container-builds/Containerfile.centos7 +deleted file mode 100644 +index af00eddb..00000000 +--- a/utils/container-builds/Containerfile.centos7 ++++ /dev/null +@@ -1,15 +0,0 @@ +-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 +- +-WORKDIR /repo +-ENV DIST_VERSION 7 +-ENTRYPOINT make _build_local +diff --git a/utils/container-builds/Containerfile.ubi8 b/utils/container-builds/Containerfile.el8 +similarity index 100% +rename from utils/container-builds/Containerfile.ubi8 +rename to utils/container-builds/Containerfile.el8 +diff --git a/utils/container-builds/Containerfile.ubi9 b/utils/container-builds/Containerfile.el9 +similarity index 100% +rename from utils/container-builds/Containerfile.ubi9 +rename to utils/container-builds/Containerfile.el9 +diff --git a/utils/container-tests/Containerfile.el8 b/utils/container-tests/Containerfile.el8 +new file mode 100644 +index 00000000..b92e8742 +--- /dev/null ++++ b/utils/container-tests/Containerfile.el8 +@@ -0,0 +1,24 @@ ++FROM centos:8 ++ ++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 ++ ++VOLUME /repo ++ ++RUN dnf update -y && \ ++ dnf install -y git make rsync \ ++ python3-virtualenv python3-setuptools python3-pip \ ++ python3-gobject NetworkManager-libnm ++ ++ENV PYTHON_VENV python3.6 ++ ++COPY . /repocopy ++ ++WORKDIR /repocopy ++ ++RUN rm -rf tut* ++ ++RUN make clean && make install-deps-fedora ++ ++WORKDIR / +diff --git a/utils/container-tests/Containerfile.rhel9 b/utils/container-tests/Containerfile.el9 +similarity index 100% +rename from utils/container-tests/Containerfile.rhel9 +rename to utils/container-tests/Containerfile.el9 +diff --git a/utils/container-tests/Containerfile.f34 b/utils/container-tests/Containerfile.f42 +similarity index 84% +rename from utils/container-tests/Containerfile.f34 +rename to utils/container-tests/Containerfile.f42 +index a9346635..46f0f63a 100644 +--- a/utils/container-tests/Containerfile.f34 ++++ b/utils/container-tests/Containerfile.f42 +@@ -1,11 +1,11 @@ +-FROM fedora:34 ++FROM fedora:42 + + VOLUME /repo + + RUN dnf update -y && \ + dnf install -y findutils make rsync python3-gobject-base NetworkManager-libnm + +-ENV PYTHON_VENV python3.9 ++ENV PYTHON_VENV python3.13 + + COPY . /repocopy + +diff --git a/utils/container-tests/Containerfile.rhel7 b/utils/container-tests/Containerfile.rhel7 +deleted file mode 100644 +index 0a0c384a..00000000 +--- a/utils/container-tests/Containerfile.rhel7 ++++ /dev/null +@@ -1,24 +0,0 @@ +-FROM registry.access.redhat.com/ubi7/ubi:7.9 +- +-VOLUME /repo +- +-RUN yum update -y && \ +- yum install -y python-virtualenv python-setuptools make git rsync +- +-# see ./Containerfile.ubi7 for explanation +-RUN yum -y install python27-python-pip && \ +- scl enable python27 -- pip install -U --target /usr/lib/python2.7/site-packages/ pip==20.3.0 && \ +- python -m pip install --ignore-installed pip==20.3.4 ipaddress virtualenv +- +-ENV PYTHON_VENV python2.7 +- +-COPY . /repocopy +- +-WORKDIR /repocopy +- +-RUN rm -rf tut* +- +-RUN make clean && make install-deps +- +-WORKDIR / +- +diff --git a/utils/container-tests/Containerfile.rhel8 b/utils/container-tests/Containerfile.rhel8 +deleted file mode 100644 +index 6f21839b..00000000 +--- a/utils/container-tests/Containerfile.rhel8 ++++ /dev/null +@@ -1,18 +0,0 @@ +-FROM registry.access.redhat.com/ubi8/ubi:latest +- +-VOLUME /repo +- +-RUN dnf update -y && \ +- dnf install -y python3-virtualenv python3-setuptools python3-pip make git rsync +- +-ENV PYTHON_VENV python3.6 +- +-COPY . /repocopy +- +-WORKDIR /repocopy +- +-RUN rm -rf tut* +- +-RUN make clean && make install-deps-fedora +- +-WORKDIR / +diff --git a/utils/container-tests/Containerfile.ubi7 b/utils/container-tests/Containerfile.ubi7 +deleted file mode 100644 +index 44625a76..00000000 +--- a/utils/container-tests/Containerfile.ubi7 ++++ /dev/null +@@ -1,25 +0,0 @@ +-FROM registry.access.redhat.com/ubi7/ubi:7.9 +- +-VOLUME /payload +- +-RUN yum update -y && \ +- yum install python-virtualenv python-setuptools make git -y +- +-# NOTE(ivasilev,pstodulk) We need at least pip v10.0.1, however centos:7 +-# provides just v8.1.2 (via EPEL). So do this: install epel repos -> install +-# python2-pip -> use pip to update to specific pip version we require. period +-# NOTE(pstodulk) I see we take care about pip for py3 inside the Makefile, +-# however I am afraid of additional possible troubles in future because of the +-# archaic pip3 version (v9.0.1). As we want to run tests for Py2 and Py3 in ci +-# always anyway, let's put py3 installation here as well.. +-# Dropped Python3 as it is now added in its own container on RHEL8 +- +-# This is some trickery: We install python27-python-pip from the scl, use the scl to bootstrap the python +-# module of pip version 20.3.0 and then make it update to 20.3.4 resulting the 'pip' command to be available. +-# The --target approach doesn't add it, but at least we now have pip 20.3.4 installed ;-) +-RUN yum -y install python27-python-pip && \ +- scl enable python27 -- pip install -U --target /usr/lib/python2.7/site-packages/ pip==20.3.0 && \ +- python -m pip install --ignore-installed pip==20.3.4 ipaddress virtualenv +- +-WORKDIR /payload +-ENTRYPOINT make install-deps && make test_no_lint +diff --git a/utils/container-tests/Containerfile.ubi7-lint b/utils/container-tests/Containerfile.ubi7-lint +deleted file mode 100644 +index ed548985..00000000 +--- a/utils/container-tests/Containerfile.ubi7-lint ++++ /dev/null +@@ -1,25 +0,0 @@ +-FROM registry.access.redhat.com/ubi7/ubi:7.9 +- +-VOLUME /payload +- +-RUN yum update -y && \ +- yum install python-virtualenv python-setuptools make git -y +- +-# NOTE(ivasilev,pstodulk) We need at least pip v10.0.1, however centos:7 +-# provides just v8.1.2 (via EPEL). So do this: install epel repos -> install +-# python2-pip -> use pip to update to specific pip version we require. period +-# NOTE(pstodulk) I see we take care about pip for py3 inside the Makefile, +-# however I am afraid of additional possible troubles in future because of the +-# archaic pip3 version (v9.0.1). As we want to run tests for Py2 and Py3 in ci +-# always anyway, let's put py3 installation here as well.. +-# Dropped Python3 as it is now added in its own container on RHEL8 +- +-# This is some trickery: We install python27-python-pip from the scl, use the scl to bootstrap the python +-# module of pip version 20.3.0 and then make it update to 20.3.4 resulting the 'pip' command to be available. +-# The --target approach doesn't add it, but at least we now have pip 20.3.4 installed ;-) +-RUN yum -y install python27-python-pip && \ +- scl enable python27 -- pip install -U --target /usr/lib/python2.7/site-packages/ pip==20.3.0 && \ +- python -m pip install --ignore-installed pip==20.3.4 ipaddress virtualenv +- +-WORKDIR /payload +-ENTRYPOINT make install-deps && make lint +diff --git a/utils/container-tests/Containerfile.ubi8 b/utils/container-tests/Containerfile.ubi8 +deleted file mode 100644 +index 4da60c18..00000000 +--- a/utils/container-tests/Containerfile.ubi8 ++++ /dev/null +@@ -1,9 +0,0 @@ +-FROM registry.access.redhat.com/ubi8/ubi:latest +- +-VOLUME /payload +- +-RUN dnf update -y && \ +- dnf install python3-virtualenv python3-setuptools python3-pip make git -y +- +-WORKDIR /payload +-ENTRYPOINT make install-deps && make test_no_lint +diff --git a/utils/container-tests/ci/Containerfile.el8 b/utils/container-tests/ci/Containerfile.el8 +new file mode 100644 +index 00000000..4a19092e +--- /dev/null ++++ b/utils/container-tests/ci/Containerfile.el8 +@@ -0,0 +1,15 @@ ++FROM centos:8 ++ ++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 ++ ++VOLUME /payload ++ ++RUN dnf update -y && \ ++ dnf install -y make git \ ++ python3-virtualenv python3-setuptools python3-pip \ ++ python3-gobject NetworkManager-libnm ++ ++WORKDIR /payload ++ENTRYPOINT make install-deps && make test_no_lint +diff --git a/utils/container-tests/Containerfile.ubi8-lint b/utils/container-tests/ci/Containerfile.el8-lint +similarity index 100% +rename from utils/container-tests/Containerfile.ubi8-lint +rename to utils/container-tests/ci/Containerfile.el8-lint +diff --git a/utils/container-tests/Containerfile.ubi9 b/utils/container-tests/ci/Containerfile.el9 +similarity index 100% +rename from utils/container-tests/Containerfile.ubi9 +rename to utils/container-tests/ci/Containerfile.el9 +diff --git a/utils/container-tests/Containerfile.ubi9-lint b/utils/container-tests/ci/Containerfile.el9-lint +similarity index 100% +rename from utils/container-tests/Containerfile.ubi9-lint +rename to utils/container-tests/ci/Containerfile.el9-lint diff --git a/SPECS/leapp-repository.spec b/SPECS/leapp-repository.spec index 058dd24..e515d52 100644 --- a/SPECS/leapp-repository.spec +++ b/SPECS/leapp-repository.spec @@ -53,7 +53,7 @@ py2_byte_compile "%1" "%2"} Epoch: 1 Name: leapp-repository Version: 0.23.0 -Release: 1%{?dist}.elevate.2 +Release: 1%{?dist}.elevate.3 Summary: Repositories for leapp License: ASL 2.0 @@ -350,6 +350,9 @@ fi %changelog +* Mon Oct 27 2025 Yuriy Kohut - 0.23.0-1.elevate.3 +- ELevate vendors support for upstream 0.23.0-1 version (215f307eeb1362e420ac08f528f9f11d6c1c974d) + * Tue Sep 30 2025 Yuriy Kohut - 0.23.0-1.elevate.2 - ELevate vendors support for upstream 0.23.0-1 version (47fce173e75408d9a7a26225d389161caf72e244)