From 130df259a6be9993ceb31487c87f02b9c9613fc2 Mon Sep 17 00:00:00 2001 From: Roman Prilipskii Date: Mon, 19 May 2025 07:41:11 +0200 Subject: [PATCH] CLOS-3344: Add a check for leftover cldeploy package repository files These files are created and used during cldeploy conversions. They have the following naming scheme: repo.cloudlinux.com_cloudlinux_8_BaseOS_x86_64_os_.repo Normally these files are cleaned up by cldeploy before it finishes, but in some cases they can remain on the system. When that happens, they can introduce issues with Elevate upgrades. Therefore, we add a check to catch these cases in pre-upgrade. --- .../actors/checkcldeployrepofile/actor.py | 33 +++++++++++ .../libraries/checkcldeployrepofile.py | 58 +++++++++++++++++++ .../tests/unit_test_checkcldeployrepofile.py | 32 ++++++++++ 3 files changed, 123 insertions(+) create mode 100644 repos/system_upgrade/cloudlinux/actors/checkcldeployrepofile/actor.py create mode 100644 repos/system_upgrade/cloudlinux/actors/checkcldeployrepofile/libraries/checkcldeployrepofile.py create mode 100644 repos/system_upgrade/cloudlinux/actors/checkcldeployrepofile/tests/unit_test_checkcldeployrepofile.py diff --git a/repos/system_upgrade/cloudlinux/actors/checkcldeployrepofile/actor.py b/repos/system_upgrade/cloudlinux/actors/checkcldeployrepofile/actor.py new file mode 100644 index 0000000000..3b40470969 --- /dev/null +++ b/repos/system_upgrade/cloudlinux/actors/checkcldeployrepofile/actor.py @@ -0,0 +1,33 @@ +from leapp.actors import Actor +from leapp.libraries.common.cllaunch import run_on_cloudlinux +from leapp.models import Report, RepositoriesFacts +from leapp.tags import ChecksPhaseTag, IPUWorkflowTag +from leapp.libraries.actor import checkcldeployrepofile + + +class CheckCldeployRepofile(Actor): + """ + Check for leftover repository configuration files from a cldeploy conversion. + + These repofiles, also known as "base repos" in the cldeploy context, are + used to bootstrap the CL systems during the conversion process. + Normally, they are removed by the cldeploy tool itself, but in some + cases, they may be left behind. + If that happens, they can cause problems with the upgrade process, + since neither leapp nor the upgrade process itself expect them to be present. + + This actor checks for the presence of these files and warns the user to remove them if found. + + The files are located in the /etc/yum.repos.d directory and have names based on + the URL of the repository they point to. For example: + repo.cloudlinux.com_cloudlinux_8_BaseOS_x86_64_os_.repo + """ + + name = "check_cldeploy_repofile" + consumes = (RepositoriesFacts,) + produces = (Report,) + tags = (ChecksPhaseTag, IPUWorkflowTag) + + @run_on_cloudlinux + def process(self): + checkcldeployrepofile.process() diff --git a/repos/system_upgrade/cloudlinux/actors/checkcldeployrepofile/libraries/checkcldeployrepofile.py b/repos/system_upgrade/cloudlinux/actors/checkcldeployrepofile/libraries/checkcldeployrepofile.py new file mode 100644 index 0000000000..2dd8c265a1 --- /dev/null +++ b/repos/system_upgrade/cloudlinux/actors/checkcldeployrepofile/libraries/checkcldeployrepofile.py @@ -0,0 +1,58 @@ +import os + +from leapp import reporting +from leapp.libraries.stdlib import api +from leapp.models import RepositoriesFacts + + +def get_cldeploy_repo_files(repo_file_paths): + """ + Get the list of cldeploy repository files. + + Keep in mind that the incoming repository file paths are absolute paths to the repository files. + """ + # Base path for repo files + repo_base_path = "/etc/yum.repos.d/" + # Name prefix for cldeploy repo files + repo_prefix = "repo.cloudlinux.com_" + expected_startswith = repo_base_path + repo_prefix + + return [repo_file for repo_file in repo_file_paths if repo_file.startswith(expected_startswith)] + + +def create_report(cldeploy_repo_files): + title = "Leftover cldeploy repository files found" + summary = ( + "The following leftover cldeploy repository files were found on the system. " + "If not removed, they will cause issues with the upgrade process." + ) + + for repo_file in cldeploy_repo_files: + summary += "\n- {}".format(repo_file) + + remediation = "Remove the leftover cldeploy repository files before running Leapp again." + reporting.create_report( + [ + reporting.Title(title), + reporting.Summary(summary), + reporting.Severity(reporting.Severity.HIGH), + reporting.Groups([reporting.Groups.OS_FACTS, reporting.Groups.REPOSITORY]), + reporting.Groups([reporting.Groups.INHIBITOR]), + reporting.Remediation(hint=remediation), + reporting.RelatedResource('directory', '/etc/yum.repos.d') + ] + ) + + +def process(): + repository_file_paths = [] + # RepositoriesFacts.repositories is a list of RepositoryFile objects + for repos_facts in api.consume(RepositoriesFacts): + # The file field of RepositoryFile objects is an absolute path to the repository file + for repo_file in repos_facts.repositories: + repository_file_paths.append(repo_file.file) + + cldeploy_repo_files = get_cldeploy_repo_files(repository_file_paths) + + if cldeploy_repo_files: + create_report(cldeploy_repo_files) diff --git a/repos/system_upgrade/cloudlinux/actors/checkcldeployrepofile/tests/unit_test_checkcldeployrepofile.py b/repos/system_upgrade/cloudlinux/actors/checkcldeployrepofile/tests/unit_test_checkcldeployrepofile.py new file mode 100644 index 0000000000..fecbd5c24e --- /dev/null +++ b/repos/system_upgrade/cloudlinux/actors/checkcldeployrepofile/tests/unit_test_checkcldeployrepofile.py @@ -0,0 +1,32 @@ +import pytest + +# from leapp import reporting +from leapp.libraries.actor import checkcldeployrepofile + + +@pytest.mark.parametrize( + "repo_file_paths,expected_res", + ( + ( + [ + "/etc/yum.repos.d/almalinux-appstream.repo", + "/etc/yum.repos.d/cloudlinux.repo", + "/etc/yum.repos.d/cloudlinux-rollout.repo", + "/etc/yum.repos.d/repo.cloudlinux.com_cloudlinux_8_BaseOS_x86_64_os_", + ], + [ + "/etc/yum.repos.d/repo.cloudlinux.com_cloudlinux_8_BaseOS_x86_64_os_", + ], + ), + ( + [ + "/etc/yum.repos.d/almalinux-appstream.repo", + "/etc/yum.repos.d/cloudlinux.repo", + "/etc/yum.repos.d/cloudlinux-rollout.repo", + ], + [], + ), + ), +) +def test_problem_packages_installed(repo_file_paths, expected_res): + assert expected_res == checkcldeployrepofile.get_cldeploy_repo_files(repo_file_paths)