diff --git a/.packit.yaml b/.packit.yaml
index a36a20b12c..e4bdce5110 100644
--- a/.packit.yaml
+++ b/.packit.yaml
@@ -43,6 +43,6 @@ jobs:
epel-7-x86_64:
distros: [centos-7, oraclelinux-7]
epel-8-x86_64:
- distros: [centos-8, oraclelinux-8]
+ distros: [centos-8.4, centos-8, oraclelinux-8.4, oraclelinux-8]
use_internal_tf: True
trigger: pull_request
diff --git a/convert2rhel/backup.py b/convert2rhel/backup.py
new file mode 100644
index 0000000000..5c09b35b12
--- /dev/null
+++ b/convert2rhel/backup.py
@@ -0,0 +1,209 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright(C) 2022 Red Hat, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import logging
+import os
+import shutil
+
+from convert2rhel.repo import get_hardcoded_repofiles_dir
+from convert2rhel.systeminfo import system_info
+from convert2rhel.utils import BACKUP_DIR, download_pkg, remove_orphan_folders, run_subprocess
+
+
+loggerinst = logging.getLogger(__name__)
+
+
+class ChangedRPMPackagesController(object):
+ """Keep control of installed/removed RPM pkgs for backup/restore."""
+
+ def __init__(self):
+ self.installed_pkgs = []
+ self.removed_pkgs = []
+
+ def track_installed_pkg(self, pkg):
+ """Add a installed RPM pkg to the list of installed pkgs."""
+ self.installed_pkgs.append(pkg)
+
+ def track_installed_pkgs(self, pkgs):
+ """Track packages installed before the PONR to be able to remove them later (roll them back) if needed."""
+ self.installed_pkgs += pkgs
+
+ def backup_and_track_removed_pkg(self, pkg):
+ """Add a removed RPM pkg to the list of removed pkgs."""
+ restorable_pkg = RestorablePackage(pkg)
+ restorable_pkg.backup()
+ self.removed_pkgs.append(restorable_pkg)
+
+ def _remove_installed_pkgs(self):
+ """For each package installed during conversion remove it."""
+ loggerinst.task("Rollback: Removing installed packages")
+ remove_pkgs(self.installed_pkgs, backup=False, critical=False)
+
+ def _install_removed_pkgs(self):
+ """For each package removed during conversion install it."""
+ loggerinst.task("Rollback: Installing removed packages")
+ pkgs_to_install = []
+ for restorable_pkg in self.removed_pkgs:
+ if restorable_pkg.path is None:
+ loggerinst.warning("Couldn't find a backup for %s package." % restorable_pkg.name)
+ continue
+ pkgs_to_install.append(restorable_pkg.path)
+
+ self._install_local_rpms(pkgs_to_install, replace=True, critical=False)
+
+ def _install_local_rpms(self, pkgs_to_install, replace=False, critical=True):
+ """Install packages locally available."""
+
+ if not pkgs_to_install:
+ loggerinst.info("No package to install")
+ return False
+
+ cmd_param = ["rpm", "-i"]
+ if replace:
+ cmd_param.append("--replacepkgs")
+
+ loggerinst.info("Installing packages:")
+ for pkg in pkgs_to_install:
+ loggerinst.info("\t%s" % pkg)
+
+ cmd = cmd_param + pkgs_to_install
+ output, ret_code = run_subprocess(cmd, print_output=False)
+ if ret_code != 0:
+ pkgs_as_str = " ".join(pkgs_to_install)
+ loggerinst.debug(output.strip())
+ if critical:
+ loggerinst.critical("Error: Couldn't install %s packages." % pkgs_as_str)
+
+ loggerinst.warning("Couldn't install %s packages." % pkgs_as_str)
+ return False
+
+ for path in pkgs_to_install:
+ nvra, _ = os.path.splitext(os.path.basename(path))
+ self.track_installed_pkg(nvra)
+
+ return True
+
+ def restore_pkgs(self):
+ """Restore system to the original state."""
+ self._remove_installed_pkgs()
+ remove_orphan_folders()
+ self._install_removed_pkgs()
+
+
+class RestorableFile(object):
+ def __init__(self, filepath):
+ self.filepath = filepath
+
+ def backup(self):
+ """Save current version of a file"""
+ loggerinst.info("Backing up %s." % self.filepath)
+ if os.path.isfile(self.filepath):
+ try:
+ loggerinst.debug("Copying %s to %s." % (self.filepath, BACKUP_DIR))
+ shutil.copy2(self.filepath, BACKUP_DIR)
+ except (OSError, IOError) as err:
+ # IOError for py2 and OSError for py3
+ loggerinst.critical("Error(%s): %s" % (err.errno, err.strerror))
+ else:
+ loggerinst.info("Can't find %s.", self.filepath)
+
+ def restore(self):
+ """Restore a previously backed up file"""
+ backup_filepath = os.path.join(BACKUP_DIR, os.path.basename(self.filepath))
+ loggerinst.task("Rollback: Restoring %s from backup" % self.filepath)
+
+ if not os.path.isfile(backup_filepath):
+ loggerinst.warning("%s hasn't been backed up" % self.filepath)
+ return
+ try:
+ shutil.copy2(backup_filepath, self.filepath)
+ except (OSError, IOError) as err:
+ # Do not call 'critical' which would halt the program. We are in
+ # a rollback phase now and we want to rollback as much as possible.
+ # IOError for py2 and OSError for py3
+ loggerinst.warning("Error(%s): %s" % (err.errno, err.strerror))
+ return
+ loggerinst.info("File %s restored" % self.filepath)
+
+
+class RestorablePackage(object):
+ def __init__(self, pkgname):
+ self.name = pkgname
+ self.path = None
+
+ def backup(self):
+ """Save version of RPM package"""
+ loggerinst.info("Backing up %s" % self.name)
+ if os.path.isdir(BACKUP_DIR):
+ reposdir = get_hardcoded_repofiles_dir()
+
+ # One of the reasons we hardcode repofiles pointing to archived repositories of older system
+ # minor versions is that we need to be able to download an older package version as a backup.
+ # Because for example the default repofiles on CentOS Linux 8.4 point only to 8.latest repositories
+ # that already don't contain 8.4 packages.
+ if not system_info.has_internet_access:
+ if reposdir:
+ loggerinst.debug(
+ "Not using repository files stored in %s due to the absence of internet access." % reposdir
+ )
+ self.path = download_pkg(self.name, dest=BACKUP_DIR, set_releasever=False)
+ else:
+ if reposdir:
+ loggerinst.debug("Using repository files stored in %s." % reposdir)
+ self.path = download_pkg(
+ self.name,
+ dest=BACKUP_DIR,
+ set_releasever=False,
+ reposdir=reposdir,
+ )
+ else:
+ loggerinst.warning("Can't access %s" % BACKUP_DIR)
+
+
+def remove_pkgs(pkgs_to_remove, backup=True, critical=True):
+ """Remove packages not heeding to their dependencies."""
+
+ # NOTE(r0x0d): This function is tied to the class ChangedRPMPackagesController and
+ # a couple of other places too, ideally, we should decide if we want to use
+ # this function as an entrypoint or the variable `changed_pkgs_control`, so
+ # we can move this piece of code to the `pkghandler.py` where it should be.
+ # Right now, if we move this code to the `pkghandler.py`, we have a
+ # *circular import dependency error*.
+ # @abadger has an implementation in mind to address some of those issues
+ # and actually place a controller in front of classes like this.
+ if backup:
+ # Some packages, when removed, will also remove repo files, making it
+ # impossible to access the repositories to download a backup. For this
+ # reason we first backup all packages and only after that we remove
+ for nvra in pkgs_to_remove:
+ changed_pkgs_control.backup_and_track_removed_pkg(nvra)
+
+ if not pkgs_to_remove:
+ loggerinst.info("No package to remove")
+ return
+
+ for nvra in pkgs_to_remove:
+ loggerinst.info("Removing package: %s" % nvra)
+ _, ret_code = run_subprocess(["rpm", "-e", "--nodeps", nvra])
+ if ret_code != 0:
+ if critical:
+ loggerinst.critical("Error: Couldn't remove %s." % nvra)
+ else:
+ loggerinst.warning("Couldn't remove %s." % nvra)
+
+
+changed_pkgs_control = ChangedRPMPackagesController() # pylint: disable=C0103
diff --git a/convert2rhel/checks.py b/convert2rhel/checks.py
index 2fdc3a370d..3728e884d7 100644
--- a/convert2rhel/checks.py
+++ b/convert2rhel/checks.py
@@ -29,6 +29,7 @@
get_pkg_fingerprint,
get_total_packages_to_update,
)
+from convert2rhel.repo import get_hardcoded_repofiles_dir
from convert2rhel.systeminfo import system_info
from convert2rhel.toolopts import tool_opts
from convert2rhel.utils import ask_to_continue, get_file_content, run_subprocess
@@ -466,9 +467,26 @@ def check_package_updates():
"""Ensure that the system packages installed are up-to-date."""
logger.task("Prepare: Checking if the packages are up-to-date")
+ if system_info.id == "oracle" and system_info.corresponds_to_rhel_eus_release():
+ logger.info(
+ "Skipping the check because there are no publicly available %s %d.%d repositories available."
+ % (system_info.name, system_info.version.major, system_info.version.minor)
+ )
+ return
+
+ reposdir = get_hardcoded_repofiles_dir()
+
+ if reposdir and not system_info.has_internet_access:
+ logger.warning("Skipping the check as no internet connection has been detected.")
+ return
+
try:
- packages_to_update = get_total_packages_to_update()
+ packages_to_update = get_total_packages_to_update(reposdir=reposdir)
except pkgmanager.RepoError as e:
+ # As both yum and dnf have the same error class (RepoError), to identify any problems when interacting with the
+ # repositories, we use this to catch exceptions when verifying if there is any packages to update on the system.
+ # Beware that the `RepoError` exception is based on the `pkgmanager` module and the message sent to the output
+ # can differ depending if the code is running in RHEL7 (yum) or RHEL8 (dnf).
logger.warning(
"There was an error while checking whether the installed packages are up-to-date. Having updated system is "
"an important prerequisite for a successful conversion. Consider stopping the conversion to "
@@ -479,12 +497,15 @@ def check_package_updates():
return
if len(packages_to_update) > 0:
+ repos_message = (
+ "on the enabled system repos" if not reposdir else "on repositories defined in the %s folder" % reposdir
+ )
logger.warning(
- "The system has %s packages not updated.\n"
+ "The system has %s packages not updated based %s.\n"
"List of packages to update: %s.\n\n"
"Not updating the packages may cause the conversion to fail.\n"
"Consider stopping the conversion and update the packages before re-running convert2rhel."
- % (len(packages_to_update), " ".join(packages_to_update))
+ % (len(packages_to_update), repos_message, " ".join(packages_to_update))
)
ask_to_continue()
else:
@@ -495,15 +516,40 @@ def is_loaded_kernel_latest():
"""Check if the loaded kernel is behind or of the same version as in yum repos."""
logger.task("Prepare: Checking if the loaded kernel version is the most recent")
+ if system_info.id == "oracle" and system_info.corresponds_to_rhel_eus_release():
+ logger.info(
+ "Skipping the check because there are no publicly available %s %d.%d repositories available."
+ % (system_info.name, system_info.version.major, system_info.version.minor)
+ )
+ return
+
+ reposdir = get_hardcoded_repofiles_dir()
+
+ if reposdir and not system_info.has_internet_access:
+ logger.warning("Skipping the check as no internet connection has been detected.")
+ return
+
+ cmd = ["repoquery", "--quiet", "--qf", '"%{BUILDTIME}\\t%{VERSION}-%{RELEASE}\\t%{REPOID}"']
+
+ # If the reposdir variable is not empty, meaning that it detected the hardcoded repofiles, we should use that
+ # instead of the system repositories located under /etc/yum.repos.d
+ if reposdir:
+ cmd.append("--setopt=reposdir=%s" % reposdir)
+
# For Oracle/CentOS Linux 8 the `kernel` is just a meta package, instead, we check for `kernel-core`.
# But for 6 and 7 releases, the correct way to check is using `kernel`.
package_to_check = "kernel-core" if system_info.version.major >= 8 else "kernel"
- # The latest kernel version on repo
- repoquery_output, _ = run_subprocess(
- ["repoquery", "--quiet", "--qf", '"%{BUILDTIME}\\t%{VERSION}-%{RELEASE}"', package_to_check],
- print_output=False,
- )
+ # Append the package name as the last item on the list
+ cmd.append(package_to_check)
+
+ # Search for available kernel package versions available in different repositories using the `repoquery` command.
+ # If convert2rhel is running on a EUS system, then repoquery will use the hardcoded repofiles available under
+ # /usr/share/convert2rhel/repos, meaning that the tool will fetch only the latest kernels available for that EUS
+ # version, and not the most updated version from other newer versions.
+ # If the case is that convert2rhel is not running on a EUS system, for example, Oracle Linux 8.5, then it will use
+ # the system repofiles.
+ repoquery_output, _ = run_subprocess(cmd, print_output=False)
# Repoquery doesn't return any text at all when it can't find any matches for the query (when used with --quiet)
if len(repoquery_output) > 0:
@@ -513,7 +559,7 @@ def is_loaded_kernel_latest():
# This later check is supposed to avoid duplicate repofiles being defined in the system,
# this is a super corner case and should not happen everytime, but if it does, we are aware now.
packages = [
- tuple(str(line).split("\t"))
+ tuple(str(line).replace('"', "").split("\t"))
for line in repoquery_output.split("\n")
if (line.strip() and "listed more than once in the configuration" not in line.lower())
]
@@ -521,8 +567,9 @@ def is_loaded_kernel_latest():
# Sort out for the most recent kernel with reverse order
# In case `repoquery` returns more than one kernel in the output
# We display the latest one to the user.
- _, latest_kernel = sorted(packages, reverse=True)[0]
- latest_kernel = latest_kernel.replace('"', "")
+ packages.sort(key=lambda x: x[0], reverse=True)
+
+ _, latest_kernel, repoid = packages[0]
# The loaded kernel version
uname_output, _ = run_subprocess(["uname", "-r"], print_output=False)
@@ -532,13 +579,18 @@ def is_loaded_kernel_latest():
if match == 0:
logger.info("Kernel currently loaded is at the latest version.")
else:
+ repos_message = (
+ "on the enabled system repositories"
+ if not reposdir
+ else "on repositories defined in the %s folder" % reposdir
+ )
logger.critical(
- "The current kernel version loaded is different from the latest version in your repos.\n"
- " Latest kernel version: %s\n"
- " Current loaded kernel: %s\n\n"
+ "The version of the loaded kernel is different from the latest version %s.\n"
+ " Latest kernel version available in %s: %s\n"
+ " Loaded kernel version: %s\n\n"
"To proceed with the conversion, update the kernel version by executing the following step:\n\n"
"1. yum install %s-%s -y\n"
- "2. reboot" % (latest_kernel, loaded_kernel, package_to_check, latest_kernel)
+ "2. reboot" % (repos_message, repoid, latest_kernel, loaded_kernel, package_to_check, latest_kernel)
)
else:
# Repoquery failed to detected any kernel or kernel-core packages in it's repositories
diff --git a/convert2rhel/data/7/x86_64/configs/centos-7-x86_64.cfg b/convert2rhel/data/7/x86_64/configs/centos-7-x86_64.cfg
index 5f76e4bc89..dcf97562da 100644
--- a/convert2rhel/data/7/x86_64/configs/centos-7-x86_64.cfg
+++ b/convert2rhel/data/7/x86_64/configs/centos-7-x86_64.cfg
@@ -31,6 +31,10 @@ repofile_pkgs =
# Delimited by any whitespace(s).
default_rhsm_repoids = rhel-7-server-rpms
+# List of Extended Update Support (EUS) repoids to enable through subscription-manager when the --enablerepo option is
+# not used. Delimited by any whitespace(s).
+eus_rhsm_repoids =
+
# If defined, it overrides the default releasever defined by RELEASE_VER_MAPPING.
# The value is passed to the yum calls through the --releasever option when accessing RHEL repos. Its purpose is to
# substitute the $releasever variable in a repository baseurl.
diff --git a/convert2rhel/data/7/x86_64/configs/oracle-7-x86_64.cfg b/convert2rhel/data/7/x86_64/configs/oracle-7-x86_64.cfg
index c323b5da00..34809330dd 100644
--- a/convert2rhel/data/7/x86_64/configs/oracle-7-x86_64.cfg
+++ b/convert2rhel/data/7/x86_64/configs/oracle-7-x86_64.cfg
@@ -37,6 +37,10 @@ repofile_pkgs =
# Delimited by any whitespace(s).
default_rhsm_repoids = rhel-7-server-rpms
+# List of Extended Update Support (EUS) repoids to enable through subscription-manager when the --enablerepo option is
+# not used. Delimited by any whitespace(s).
+eus_rhsm_repoids =
+
# If defined, it overrides the default releasever defined by RELEASE_VER_MAPPING.
# The value is passed to the yum calls through the --releasever option when accessing RHEL repos. Its purpose is to
# substitute the $releasever variable in a repository baseurl.
diff --git a/convert2rhel/data/7/x86_64/configs/scientific-7-x86_64.cfg b/convert2rhel/data/7/x86_64/configs/scientific-7-x86_64.cfg
index fbbfd5b6a4..6550f6940d 100644
--- a/convert2rhel/data/7/x86_64/configs/scientific-7-x86_64.cfg
+++ b/convert2rhel/data/7/x86_64/configs/scientific-7-x86_64.cfg
@@ -45,6 +45,10 @@ repofile_pkgs =
# Delimited by any whitespace(s).
default_rhsm_repoids = rhel-7-server-rpms rhel-7-server-optional-rpms
+# List of Extended Update Support (EUS) repoids to enable through subscription-manager when the --enablerepo option is
+# not used. Delimited by any whitespace(s).
+eus_rhsm_repoids =
+
# If defined, it overrides the default releasever defined by RELEASE_VER_MAPPING.
# The value is passed to the yum calls through the --releasever option when accessing RHEL repos. Its purpose is to
# substitute the $releasever variable in a repository baseurl.
diff --git a/convert2rhel/data/8/x86_64/configs/almalinux-8-x86_64.cfg b/convert2rhel/data/8/x86_64/configs/almalinux-8-x86_64.cfg
index e928e774f7..4abe5e3438 100644
--- a/convert2rhel/data/8/x86_64/configs/almalinux-8-x86_64.cfg
+++ b/convert2rhel/data/8/x86_64/configs/almalinux-8-x86_64.cfg
@@ -12,8 +12,6 @@ excluded_pkgs =
almalinux-indexhtml
almalinux-gpg-keys
almalinux-backgrounds*
- rhn*
- python3-rhn*
# List of packages that either contain repofiles or affect variables in the repofiles (e.g. $releasever).
# Delimited by any whitespace(s).
@@ -29,6 +27,12 @@ default_rhsm_repoids =
rhel-8-for-x86_64-baseos-rpms
rhel-8-for-x86_64-appstream-rpms
+# List of Extended Update Support (EUS) repoids to enable through subscription-manager when the --enablerepo option is
+# not used. Delimited by any whitespace(s).
+eus_rhsm_repoids =
+ rhel-8-for-x86_64-baseos-eus-rpms
+ rhel-8-for-x86_64-appstream-eus-rpms
+
# If defined, it overrides the default releasever defined by RELEASE_VER_MAPPING.
# The value is passed to the yum calls through the --releasever option when accessing RHEL repos. Its purpose is to
# substitute the $releasever variable in a repository baseurl.
diff --git a/convert2rhel/data/8/x86_64/configs/centos-8-x86_64.cfg b/convert2rhel/data/8/x86_64/configs/centos-8-x86_64.cfg
index af88601258..ae3870b4e1 100644
--- a/convert2rhel/data/8/x86_64/configs/centos-8-x86_64.cfg
+++ b/convert2rhel/data/8/x86_64/configs/centos-8-x86_64.cfg
@@ -11,8 +11,6 @@ excluded_pkgs =
centos-logos*
centos-indexhtml
centos-obsolete-packages
- rhn*
- python3-rhn*
centos-gpg-keys
centos-backgrounds
@@ -32,6 +30,12 @@ default_rhsm_repoids =
rhel-8-for-x86_64-baseos-rpms
rhel-8-for-x86_64-appstream-rpms
+# List of Extended Update Support (EUS) repoids to enable through subscription-manager when the --enablerepo option is
+# not used. Delimited by any whitespace(s).
+eus_rhsm_repoids =
+ rhel-8-for-x86_64-baseos-eus-rpms
+ rhel-8-for-x86_64-appstream-eus-rpms
+
# If defined, it overrides the default releasever defined by RELEASE_VER_MAPPING.
# The value is passed to the yum calls through the --releasever option when accessing RHEL repos. Its purpose is to
# substitute the $releasever variable in a repository baseurl.
diff --git a/convert2rhel/data/8/x86_64/configs/oracle-8-x86_64.cfg b/convert2rhel/data/8/x86_64/configs/oracle-8-x86_64.cfg
index 417eadadf6..63764a3632 100644
--- a/convert2rhel/data/8/x86_64/configs/oracle-8-x86_64.cfg
+++ b/convert2rhel/data/8/x86_64/configs/oracle-8-x86_64.cfg
@@ -11,8 +11,6 @@ excluded_pkgs =
oracle-logos*
oracle-indexhtml
oracle-backgrounds
- rhn*
- python3-rhn*
# List of packages that either contain repofiles or affect variables in the repofiles (e.g. $releasever).
# Delimited by any whitespace(s).
@@ -27,6 +25,12 @@ default_rhsm_repoids =
rhel-8-for-x86_64-baseos-rpms
rhel-8-for-x86_64-appstream-rpms
+# List of Extended Update Support (EUS) repoids to enable through subscription-manager when the --enablerepo option is
+# not used. Delimited by any whitespace(s).
+eus_rhsm_repoids =
+ rhel-8-for-x86_64-baseos-eus-rpms
+ rhel-8-for-x86_64-appstream-eus-rpms
+
# If defined, it overrides the default releasever defined by RELEASE_VER_MAPPING.
# The value is passed to the yum calls through the --releasever option when accessing RHEL repos. Its purpose is to
# substitute the $releasever variable in a repository baseurl.
diff --git a/convert2rhel/data/8/x86_64/configs/rocky-8-x86_64.cfg b/convert2rhel/data/8/x86_64/configs/rocky-8-x86_64.cfg
index 9632a793fb..77bfe2af77 100644
--- a/convert2rhel/data/8/x86_64/configs/rocky-8-x86_64.cfg
+++ b/convert2rhel/data/8/x86_64/configs/rocky-8-x86_64.cfg
@@ -11,8 +11,6 @@ excluded_pkgs =
rocky-logos*
rocky-indexhtml
rocky-obsolete-packages
- rhn*
- python3-rhn*
rocky-gpg-keys
rocky-backgrounds
@@ -31,6 +29,12 @@ default_rhsm_repoids =
rhel-8-for-x86_64-baseos-rpms
rhel-8-for-x86_64-appstream-rpms
+# List of Extended Update Support (EUS) repoids to enable through subscription-manager when the --enablerepo option is
+# not used. Delimited by any whitespace(s).
+eus_rhsm_repoids =
+ rhel-8-for-x86_64-baseos-eus-rpms
+ rhel-8-for-x86_64-appstream-eus-rpms
+
# If defined, it overrides the default releasever defined by RELEASE_VER_MAPPING.
# The value is passed to the yum calls through the --releasever option when accessing RHEL repos. Its purpose is to
# substitute the $releasever variable in a repository baseurl.
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-AppStream.repo b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-AppStream.repo
new file mode 100644
index 0000000000..185b2b8f45
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-AppStream.repo
@@ -0,0 +1,17 @@
+# CentOS-Linux-AppStream.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+
+[appstream]
+name=CentOS Linux 8.4.2105 - AppStream
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.4.2105&arch=$basearch&repo=AppStream&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.4.2105/AppStream/$basearch/os/
+gpgcheck=1
+enabled=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-BaseOS.repo b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-BaseOS.repo
new file mode 100644
index 0000000000..a2411f416c
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-BaseOS.repo
@@ -0,0 +1,17 @@
+# CentOS-Linux-BaseOS.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+
+[baseos]
+name=CentOS Linux 8.4.2105 - BaseOS
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.4.2105&arch=$basearch&repo=BaseOS&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.4.2105/BaseOS/$basearch/os/
+gpgcheck=1
+enabled=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-ContinuousRelease.repo b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-ContinuousRelease.repo
new file mode 100644
index 0000000000..f6281c8744
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-ContinuousRelease.repo
@@ -0,0 +1,35 @@
+# CentOS-Linux-ContinuousRelease.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+#
+# The Continuous Release (CR) repository contains packages for the next minor
+# release of CentOS Linux. This repository only has content in the time period
+# between an upstream release and the official CentOS Linux release. These
+# packages have not been fully tested yet and should be considered beta
+# quality. They are made available for people willing to test and provide
+# feedback for the next release.
+
+[cr]
+name=CentOS Linux 8.4.2105 - ContinuousRelease
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.4.2105&arch=$basearch&repo=cr&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.4.2105/cr/$basearch/os/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+# CentOS-Linux-Debuginfo.repo
+#
+# All debug packages are merged into a single repo, split by basearch, and are
+# not signed.
+
+[debuginfo]
+name=CentOS Linux 8.4.2105 - Debuginfo
+baseurl=http://debuginfo.centos.org/8.4.2105/$basearch/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-Devel.repo b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-Devel.repo
new file mode 100644
index 0000000000..c391f8b6ca
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-Devel.repo
@@ -0,0 +1,17 @@
+# CentOS-Linux-Devel.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+
+[devel]
+name=CentOS Linux 8.4.2105 - Devel WARNING! FOR BUILDROOT USE ONLY!
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.4.2105&arch=$basearch&repo=Devel&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.4.2105/Devel/$basearch/os/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-Extras.repo b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-Extras.repo
new file mode 100644
index 0000000000..b2c06c7a9d
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-Extras.repo
@@ -0,0 +1,17 @@
+# CentOS-Linux-Extras.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+
+[extras]
+name=CentOS Linux 8.4.2105 - Extras
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.4.2105&arch=$basearch&repo=extras&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.4.2105/extras/$basearch/os/
+gpgcheck=1
+enabled=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-FastTrack.repo b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-FastTrack.repo
new file mode 100644
index 0000000000..ca53e77632
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-FastTrack.repo
@@ -0,0 +1,17 @@
+# CentOS-Linux-FastTrack.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+
+[fasttrack]
+name=CentOS Linux 8.4.2105 - FastTrack
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.4.2105&arch=$basearch&repo=fasttrack&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.4.2105/fasttrack/$basearch/os/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-HighAvailability.repo b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-HighAvailability.repo
new file mode 100644
index 0000000000..00fa639bec
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-HighAvailability.repo
@@ -0,0 +1,17 @@
+# CentOS-Linux-HighAvailability.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+
+[ha]
+name=CentOS Linux 8.4.2105 - HighAvailability
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.4.2105&arch=$basearch&repo=HighAvailability&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.4.2105/HighAvailability/$basearch/os/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-Plus.repo b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-Plus.repo
new file mode 100644
index 0000000000..d203a63ae6
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-Plus.repo
@@ -0,0 +1,17 @@
+# CentOS-Linux-Plus.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+
+[plus]
+name=CentOS Linux 8.4.2105 - Plus
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.4.2105&arch=$basearch&repo=centosplus&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.4.2105/centosplus/$basearch/os/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-PowerTools.repo b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-PowerTools.repo
new file mode 100644
index 0000000000..234c4196e3
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-PowerTools.repo
@@ -0,0 +1,17 @@
+# CentOS-Linux-PowerTools.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+
+[powertools]
+name=CentOS Linux 8.4.2105 - PowerTools
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.4.2105&arch=$basearch&repo=PowerTools&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.4.2105/PowerTools/$basearch/os/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-Sources.repo b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-Sources.repo
new file mode 100644
index 0000000000..6ac45b3045
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.4/CentOS-Linux-Sources.repo
@@ -0,0 +1,36 @@
+# CentOS-Linux-Sources.repo
+
+[baseos-source]
+name=CentOS Linux 8.4.2105 - BaseOS - Source
+baseurl=https://vault.centos.org/$contentdir/8.4.2105/BaseOS/Source/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+
+[appstream-source]
+name=CentOS Linux 8.4.2105 - AppStream - Source
+baseurl=https://vault.centos.org/$contentdir/8.4.2105/AppStream/Source/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+
+[powertools-source]
+name=CentOS Linux 8.4.2105 - PowerTools - Source
+baseurl=https://vault.centos.org/$contentdir/8.4.2105/PowerTools/Source/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+
+[extras-source]
+name=CentOS Linux 8.4.2105 - Extras - Source
+baseurl=https://vault.centos.org/$contentdir/8.4.2105/extras/Source/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+
+[plus-source]
+name=CentOS Linux 8.4.2105 - Plus - Source
+baseurl=https://vault.centos.org/$contentdir/8.4.2105/centosplus/Source/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-AppStream.repo b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-AppStream.repo
new file mode 100644
index 0000000000..6f069267cb
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-AppStream.repo
@@ -0,0 +1,17 @@
+# CentOS-Linux-AppStream.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+
+[appstream]
+name=CentOS Linux 8.5.2111 - AppStream
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.5.2111&arch=$basearch&repo=AppStream&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.5.2111/AppStream/$basearch/os/
+gpgcheck=1
+enabled=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-BaseOS.repo b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-BaseOS.repo
new file mode 100644
index 0000000000..b8a127d321
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-BaseOS.repo
@@ -0,0 +1,17 @@
+# CentOS-Linux-BaseOS.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+
+[baseos]
+name=CentOS Linux 8.5.2111 - BaseOS
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.5.2111&arch=$basearch&repo=BaseOS&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.5.2111/BaseOS/$basearch/os/
+gpgcheck=1
+enabled=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-Debuginfo.repo b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-Debuginfo.repo
new file mode 100644
index 0000000000..2ef5ed0873
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-Debuginfo.repo
@@ -0,0 +1,11 @@
+# CentOS-Linux-Debuginfo.repo
+#
+# All debug packages are merged into a single repo, split by basearch, and are
+# not signed.
+
+[debuginfo]
+name=CentOS Linux 8.5.2111 - Debuginfo
+baseurl=http://debuginfo.centos.org/8.5.2111/$basearch/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-Devel.repo b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-Devel.repo
new file mode 100644
index 0000000000..5e2ef09ea6
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-Devel.repo
@@ -0,0 +1,17 @@
+# CentOS-Linux-Devel.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+
+[devel]
+name=CentOS Linux 8.5.2111 - Devel WARNING! FOR BUILDROOT USE ONLY!
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.5.2111&arch=$basearch&repo=Devel&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.5.2111/Devel/$basearch/os/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-Extras.repo b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-Extras.repo
new file mode 100644
index 0000000000..ddc32ad737
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-Extras.repo
@@ -0,0 +1,17 @@
+# CentOS-Linux-Extras.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+
+[extras]
+name=CentOS Linux 8.5.2111 - Extras
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.5.2111&arch=$basearch&repo=extras&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.5.2111/extras/$basearch/os/
+gpgcheck=1
+enabled=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-FastTrack.repo b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-FastTrack.repo
new file mode 100644
index 0000000000..91aefbe490
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-FastTrack.repo
@@ -0,0 +1,17 @@
+# CentOS-Linux-FastTrack.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+
+[fasttrack]
+name=CentOS Linux 8.5.2111 - FastTrack
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.5.2111&arch=$basearch&repo=fasttrack&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.5.2111/fasttrack/$basearch/os/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-HighAvailability.repo b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-HighAvailability.repo
new file mode 100644
index 0000000000..c913c7d670
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-HighAvailability.repo
@@ -0,0 +1,17 @@
+# CentOS-Linux-HighAvailability.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+
+[ha]
+name=CentOS Linux 8.5.2111 - HighAvailability
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.5.2111&arch=$basearch&repo=HighAvailability&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.5.2111/HighAvailability/$basearch/os/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-Plus.repo b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-Plus.repo
new file mode 100644
index 0000000000..65b46d3146
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-Plus.repo
@@ -0,0 +1,17 @@
+# CentOS-Linux-Plus.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+
+[plus]
+name=CentOS Linux 8.5.2111 - Plus
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.5.2111&arch=$basearch&repo=centosplus&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.5.2111/centosplus/$basearch/os/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-PowerTools.repo b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-PowerTools.repo
new file mode 100644
index 0000000000..827b4ce959
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-PowerTools.repo
@@ -0,0 +1,17 @@
+# CentOS-Linux-PowerTools.repo
+#
+# The #mirrorlist system uses the connecting IP address of the client and the
+# update status of each mirror to pick current mirrors that are geographically
+# close to the client. You should use this for CentOS updates unless you are
+# manually picking other mirrors.
+#
+# If the #mirrorlist does not work for you, you can try the commented out
+# baseurl line instead.
+
+[powertools]
+name=CentOS Linux 8.5.2111 - PowerTools
+#mirrorlist=http://#mirrorlist.centos.org/?release=8.5.2111&arch=$basearch&repo=PowerTools&infra=$infra
+baseurl=https://vault.centos.org/$contentdir/8.5.2111/PowerTools/$basearch/os/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-Sources.repo b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-Sources.repo
new file mode 100644
index 0000000000..0b1ce5c0b1
--- /dev/null
+++ b/convert2rhel/data/8/x86_64/repos/centos-8.5/CentOS-Linux-Sources.repo
@@ -0,0 +1,36 @@
+# CentOS-Linux-Sources.repo
+
+[baseos-source]
+name=CentOS Linux 8.5.2111 - BaseOS - Source
+baseurl=https://vault.centos.org/$contentdir/8.5.2111/BaseOS/Source/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+
+[appstream-source]
+name=CentOS Linux 8.5.2111 - AppStream - Source
+baseurl=https://vault.centos.org/$contentdir/8.5.2111/AppStream/Source/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+
+[powertools-source]
+name=CentOS Linux 8.5.2111 - PowerTools - Source
+baseurl=https://vault.centos.org/$contentdir/8.5.2111/PowerTools/Source/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+
+[extras-source]
+name=CentOS Linux 8.5.2111 - Extras - Source
+baseurl=https://vault.centos.org/$contentdir/8.5.2111/extras/Source/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+
+[plus-source]
+name=CentOS Linux 8.5.2111 - Plus - Source
+baseurl=https://vault.centos.org/$contentdir/8.5.2111/centosplus/Source/
+gpgcheck=1
+enabled=0
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
diff --git a/convert2rhel/main.py b/convert2rhel/main.py
index 0d61191d97..e752baa139 100644
--- a/convert2rhel/main.py
+++ b/convert2rhel/main.py
@@ -19,7 +19,7 @@
import os
import sys
-from convert2rhel import breadcrumbs, cert, checks, grub
+from convert2rhel import backup, breadcrumbs, cert, checks, grub
from convert2rhel import logger as logger_module
from convert2rhel import pkghandler, redhatrelease, repo, special_cases, subscription, systeminfo, toolopts, utils
@@ -234,6 +234,8 @@ def post_ponr_conversion():
grub.post_ponr_set_efi_configuration()
loggerinst.task("Convert: Patch yum configuration file")
redhatrelease.YumConf().patch()
+ loggerinst.task("Convert: Lock releasever in RHEL repositories")
+ subscription.lock_releasever_in_rhel_repositories()
breadcrumbs.breadcrumbs.finish_success()
@@ -254,7 +256,7 @@ def rollback_changes():
loggerinst.warning("Abnormal exit! Performing rollback ...")
subscription.rollback()
- utils.changed_pkgs_control.restore_pkgs()
+ backup.changed_pkgs_control.restore_pkgs()
repo.restore_yum_repos()
redhatrelease.system_release_file.restore()
redhatrelease.os_release_file.restore()
diff --git a/convert2rhel/pkghandler.py b/convert2rhel/pkghandler.py
index b1209e9bcc..01cb6af079 100644
--- a/convert2rhel/pkghandler.py
+++ b/convert2rhel/pkghandler.py
@@ -24,6 +24,7 @@
import rpm
from convert2rhel import pkgmanager, utils
+from convert2rhel.backup import RestorableFile, remove_pkgs
from convert2rhel.systeminfo import system_info
from convert2rhel.toolopts import tool_opts
@@ -35,7 +36,7 @@
MAX_YUM_CMD_CALLS = 3
_VERSIONLOCK_FILE_PATH = "/etc/yum/pluginconf.d/versionlock.list" # This file is used by the dnf plugin as well
-versionlock_file = utils.RestorableFile(_VERSIONLOCK_FILE_PATH) # pylint: disable=C0103
+versionlock_file = RestorableFile(_VERSIONLOCK_FILE_PATH) # pylint: disable=C0103
#
# Regular expressions used to find package names in yum output
@@ -104,7 +105,7 @@ def call_yum_cmd_w_downgrades(cmd, pkgs, retries=MAX_YUM_CMD_CALLS):
to_remove = problematic_pkgs["errors"] | problematic_pkgs["mismatches"]
if to_remove:
loggerinst.warning("Removing problematic packages to continue with conversion:\n%s" % "\n".join(to_remove))
- utils.remove_pkgs(to_remove, backup=False, critical=False)
+ remove_pkgs(to_remove, backup=False, critical=False)
return call_yum_cmd_w_downgrades(cmd, pkgs, retries - 1)
@@ -604,7 +605,7 @@ def remove_pkgs_with_confirm(pkgs, backup=True):
loggerinst.warning("The following packages will be removed...")
print_pkg_info(pkgs_to_remove)
utils.ask_to_continue()
- utils.remove_pkgs([get_pkg_nvra(pkg) for pkg in pkgs_to_remove], backup=backup)
+ remove_pkgs([get_pkg_nvra(pkg) for pkg in pkgs_to_remove], backup=backup)
loggerinst.debug("Successfully removed %s packages" % str(len(pkgs_to_remove)))
@@ -714,7 +715,7 @@ def handle_no_newer_rhel_kernel_available():
# of them - the one that has the same version as the available RHEL
# kernel
older = available[-1]
- utils.remove_pkgs(pkgs_to_remove=["kernel-%s" % older], backup=False)
+ remove_pkgs(pkgs_to_remove=["kernel-%s" % older], backup=False)
call_yum_cmd(command="install", args=["kernel-%s" % older])
else:
replace_non_rhel_installed_kernel(installed[0])
@@ -769,7 +770,14 @@ def replace_non_rhel_installed_kernel(version):
output, ret_code = utils.run_subprocess(
# The --nodeps is needed as some kernels depend on system-release (alias for redhat-release) and that package
# is not installed at this stage.
- ["rpm", "-i", "--force", "--nodeps", "--replacepkgs", "%s*" % os.path.join(utils.TMP_DIR, pkg)],
+ [
+ "rpm",
+ "-i",
+ "--force",
+ "--nodeps",
+ "--replacepkgs",
+ "%s*" % os.path.join(utils.TMP_DIR, pkg),
+ ],
print_output=False,
)
if ret_code != 0:
@@ -799,7 +807,7 @@ def remove_non_rhel_kernels():
if non_rhel_kernels:
loggerinst.info("Removing non-RHEL kernels")
print_pkg_info(non_rhel_kernels)
- utils.remove_pkgs(
+ remove_pkgs(
pkgs_to_remove=[get_pkg_nvra(pkg) for pkg in non_rhel_kernels],
backup=False,
)
@@ -1004,21 +1012,28 @@ def compare_package_versions(version1, version2):
return rpm.labelCompare(evr1, evr2)
-def get_total_packages_to_update():
+def get_total_packages_to_update(reposdir):
"""Return the total number of packages to update in the system
- It uses both yum/dnf depending on weather they are installed on the system,
- if it's Oracle/CentOS Linux 7 or 6, it will use `yum`, otherwise it should use `dnf`.
+ It uses both yum/dnf depending on whether they are installed on the system,
+ In case of RHEL 6 or 7 derivative distributions, it uses `yum`, otherwise it uses `dnf`.
+
+ To check whether the system is updated or not, we use original vendor repofiles which we ship within the
+ convert2rhel RPM. The reason is that we can't rely on the repofiles available on the to-be-converted system.
+
+ :param reposdir: The path to the hardcoded repositories for EUS (If any).
+ :type reposdir: str | None
:return: The packages that need to be updated.
- :rtype: List[str]
+ :rtype: list[str]
"""
packages = []
if pkgmanager.TYPE == "yum":
packages = _get_packages_to_update_yum()
elif pkgmanager.TYPE == "dnf":
- packages = _get_packages_to_update_dnf()
+ # We're using the reposdir with dnf only because we currently hardcode the repofiles for RHEL 8 derivatives only.
+ packages = _get_packages_to_update_dnf(reposdir=reposdir)
return set(packages)
@@ -1034,22 +1049,32 @@ def _get_packages_to_update_yum():
return all_packages
-def _get_packages_to_update_dnf():
- """Query all the packages with dnf that has an update pending on the system."""
+def _get_packages_to_update_dnf(reposdir):
+ """Query all the packages with dnf that has an update pending on the
+ system.
+
+ :param reposdir: The path to the hardcoded repositories for EUS (If any).
+ :type reposdir: str | None
+ """
packages = []
base = pkgmanager.Base()
- # Fix the case when we are trying to query packages in Oracle Linux 8
- # when the DNF API gets called, those variables are not populated by default.
- if system_info.id == "oracle":
- base.conf.substitutions["ocidomain"] = "oracle.com"
- base.conf.substitutions["ociregion"] = ""
-
- # Same thing for CentOS, but this time, the URL for the vault has changed
- # and instead of just ussing $releasever (8.5, 8.4...), we need either
- # using the correct $releasever (8.5.2111) or setting up the $contentdir
- elif system_info.id == "centos":
- base.conf.substitutions["contentdir"] = system_info.id
+ # If we have an reposdir, that means we are trying to check the packages under
+ # CentOS Linux 8.4 or 8.5 and Oracle Linux 8.4.
+ # That means we need to use our hardcoded repository files instead of the system ones.
+ if reposdir:
+ base.conf.reposdir = reposdir
+
+ # Set DNF to read from the proper config files, at this moment, DNF can't
+ # automatically read and load the config files
+ # so we have to specify it to him.
+ # We set the PRIO_MAINCONFIG as the base config file to be read.
+ # We also set the folder /etc/dnf/vars as the main point for vars
+ # replacement in repo files.
+ # See this bugzilla comment:
+ # https://bugzilla.redhat.com/show_bug.cgi?id=1920735#c2
+ base.conf.read(priority=pkgmanager.dnf.conf.PRIO_MAINCONFIG)
+ base.conf.substitutions.update_from_etc(installroot=base.conf.installroot, varsdir=base.conf.varsdir)
base.read_all_repos()
base.fill_sack()
diff --git a/convert2rhel/redhatrelease.py b/convert2rhel/redhatrelease.py
index a34388e640..aad4958047 100644
--- a/convert2rhel/redhatrelease.py
+++ b/convert2rhel/redhatrelease.py
@@ -19,7 +19,7 @@
import os
import re
-from convert2rhel import pkgmanager, utils
+from convert2rhel import backup, pkgmanager, utils
from convert2rhel.systeminfo import system_info
@@ -107,5 +107,5 @@ def is_modified():
# Code to be executed upon module import
-system_release_file = utils.RestorableFile(get_system_release_filepath()) # pylint: disable=C0103
-os_release_file = utils.RestorableFile(OS_RELEASE_FILEPATH) # pylint: disable=C0103
+system_release_file = backup.RestorableFile(get_system_release_filepath()) # pylint: disable=C0103
+os_release_file = backup.RestorableFile(OS_RELEASE_FILEPATH) # pylint: disable=C0103
diff --git a/convert2rhel/repo.py b/convert2rhel/repo.py
index d11b59b8c5..b6d22da2be 100644
--- a/convert2rhel/repo.py
+++ b/convert2rhel/repo.py
@@ -20,15 +20,24 @@
import shutil
from convert2rhel.systeminfo import system_info
-from convert2rhel.utils import BACKUP_DIR
+from convert2rhel.utils import BACKUP_DIR, DATA_DIR
loggerinst = logging.getLogger(__name__)
def get_rhel_repoids():
- """Get IDs of the Red Hat CDN repositories that correspond to the current system."""
- repos_needed = system_info.default_rhsm_repoids
+ """Get IDs of the Red Hat CDN repositories that correspond to the current system.
+
+ In case the to-be-converted-OS minor version corresponds to RHEL Extended Update Support (EUS) release,
+ we preferably enable the RHEL EUS repoids as those provide security updates over two years, in comparison to 6 months
+ in case of the standard non-EUS repoids.
+ """
+
+ if system_info.corresponds_to_rhel_eus_release():
+ repos_needed = system_info.eus_rhsm_repoids
+ else:
+ repos_needed = system_info.default_rhsm_repoids
loggerinst.info("RHEL repository IDs to enable: %s" % ", ".join(repos_needed))
@@ -68,3 +77,28 @@ def restore_yum_repos():
if not repo_has_restored:
loggerinst.info("No .repo files to rollback")
+
+
+def get_hardcoded_repofiles_dir():
+ """Get the path to the hardcoded repofiles for CentOS/Oracle Linux.
+
+ We use hardcoded original vendor repofiles to be able to check whether the system is updated before the conversion.
+ To be able to download backup of packages before we remove them, we can't rely on the repofiles available on
+ the system.
+
+ :return: The return can be either the path to the eus repos, or None, meaning we don't have any hardcoded repo files.
+ :rtype: str | None
+ """
+ hardcoded_repofiles = os.path.join(
+ DATA_DIR,
+ "repos/%s-%s.%s"
+ % (
+ system_info.id,
+ system_info.version.major,
+ system_info.version.minor,
+ ),
+ )
+ if os.path.exists(hardcoded_repofiles):
+ return hardcoded_repofiles
+
+ return None
diff --git a/convert2rhel/special_cases.py b/convert2rhel/special_cases.py
index 47e193ef93..1ae70c9bcd 100644
--- a/convert2rhel/special_cases.py
+++ b/convert2rhel/special_cases.py
@@ -18,9 +18,10 @@
import logging
import os
+from convert2rhel.backup import RestorableFile
from convert2rhel.grub import is_efi
from convert2rhel.systeminfo import system_info
-from convert2rhel.utils import RestorableFile, mkdir_p, run_subprocess
+from convert2rhel.utils import mkdir_p, run_subprocess
OPENJDK_RPM_STATE_DIR = "/var/lib/rpm-state/"
diff --git a/convert2rhel/subscription.py b/convert2rhel/subscription.py
index c990e4c1c3..dcdaf4e19a 100644
--- a/convert2rhel/subscription.py
+++ b/convert2rhel/subscription.py
@@ -22,7 +22,7 @@
from collections import namedtuple
from time import sleep
-from convert2rhel import pkghandler, utils
+from convert2rhel import backup, pkghandler, utils
from convert2rhel.systeminfo import system_info
from convert2rhel.toolopts import tool_opts
@@ -99,7 +99,11 @@ def unregister_system():
unregistration_cmd = ["subscription-manager", "unregister"]
output, ret_code = utils.run_subprocess(unregistration_cmd, print_output=False)
if ret_code != 0:
- loggerinst.warning("System unregistration failed with return code %d and message:\n%s", ret_code, output)
+ loggerinst.warning(
+ "System unregistration failed with return code %d and message:\n%s",
+ ret_code,
+ output,
+ )
else:
loggerinst.info("System unregistered successfully.")
@@ -113,8 +117,14 @@ def register_system():
registration_cmd = RegistrationCommand.from_tool_opts(tool_opts)
attempt_msg = ""
if attempt > 0:
- attempt_msg = "Attempt %d of %d: " % (attempt + 1, MAX_NUM_OF_ATTEMPTS_TO_SUBSCRIBE)
- loggerinst.info("%sRegistering the system using subscription-manager ...", attempt_msg)
+ attempt_msg = "Attempt %d of %d: " % (
+ attempt + 1,
+ MAX_NUM_OF_ATTEMPTS_TO_SUBSCRIBE,
+ )
+ loggerinst.info(
+ "%sRegistering the system using subscription-manager ...",
+ attempt_msg,
+ )
output, ret_code = registration_cmd()
if ret_code == 0:
@@ -383,11 +393,11 @@ def remove_original_subscription_manager():
# removed from CentOS Linux 8.5 and causes conversion to fail if
# it's installed on that system because it's not possible to back it up.
# https://bugzilla.redhat.com/show_bug.cgi?id=2046292
- utils.remove_pkgs([_SUBMGR_PKG_REMOVED_IN_CL_85], backup=False, critical=False)
+ backup.remove_pkgs([_SUBMGR_PKG_REMOVED_IN_CL_85], backup=False, critical=False)
submgr_pkg_names.remove(_SUBMGR_PKG_REMOVED_IN_CL_85)
# Remove any oter subscription-manager packages present on the system
- utils.remove_pkgs(submgr_pkg_names, critical=False)
+ backup.remove_pkgs(submgr_pkg_names, critical=False)
def install_rhel_subscription_manager():
@@ -446,7 +456,7 @@ def track_installed_submgr_pkgs(installed_pkg_names, pkgs_to_not_track):
loggerinst.debug("Skipping tracking previously installed package: %s" % installed_pkg)
loggerinst.debug("Tracking installed packages: %r" % pkgs_to_track)
- utils.changed_pkgs_control.track_installed_pkgs(pkgs_to_track)
+ backup.changed_pkgs_control.track_installed_pkgs(pkgs_to_track)
def attach_subscription():
@@ -514,7 +524,11 @@ def get_avail_subs():
def get_sub(subs_raw):
"""Generator that provides subscriptions available to a logged-in user."""
# Split all the available subscriptions per one subscription
- for sub_raw in re.findall(r"Subscription Name.*?Type:\s+\w+\n\n", subs_raw, re.DOTALL | re.MULTILINE):
+ for sub_raw in re.findall(
+ r"Subscription Name.*?Type:\s+\w+\n\n",
+ subs_raw,
+ re.DOTALL | re.MULTILINE,
+ ):
pool_id = get_pool_id(sub_raw)
yield namedtuple("Sub", ["pool_id", "sub_raw"])(pool_id, sub_raw)
@@ -599,6 +613,33 @@ def enable_repos(rhel_repoids):
else:
repos_to_enable = rhel_repoids
+ if repos_to_enable == system_info.eus_rhsm_repoids:
+ try:
+ loggerinst.info(
+ "The system version corresponds to a RHEL Extended Update Support (EUS) release. "
+ "Trying to enable RHEL EUS repositories."
+ )
+ # Try first if it's possible to enable EUS repoids. Otherwise try enabling the default RHSM repoids.
+ # Otherwise, if it raiess an exception, try to enable the default rhsm-repos
+ _submgr_enable_repos(repos_to_enable)
+ except SystemExit:
+ loggerinst.info(
+ "The RHEL EUS repositories are not possible to enable.\n"
+ "Trying to enable standard RHEL repositories as a fallback."
+ )
+ # Fallback to the default_rhsm_repoids
+ repos_to_enable = system_info.default_rhsm_repoids
+ _submgr_enable_repos(repos_to_enable)
+ else:
+ # This could be either the default_rhsm repos or any user specific
+ # repoids
+ _submgr_enable_repos(repos_to_enable)
+
+ system_info.submgr_enabled_repos = repos_to_enable
+
+
+def _submgr_enable_repos(repos_to_enable):
+ """Go through subscription manager repos and try to enable them through subscription-manager."""
enable_cmd = ["subscription-manager", "repos"]
for repo in repos_to_enable:
enable_cmd.append("--enable=%s" % repo)
@@ -607,8 +648,6 @@ def enable_repos(rhel_repoids):
loggerinst.critical("Repos were not possible to enable through subscription-manager:\n%s" % output)
loggerinst.info("Repositories enabled through subscription-manager")
- system_info.submgr_enabled_repos = repos_to_enable
-
def rollback():
"""Rollback subscription related changes"""
@@ -651,7 +690,10 @@ def download_rhsm_pkgs():
loggerinst.info("Skipping due to the use of --keep-rhsm.")
return
utils.mkdir_p(_RHSM_TMP_DIR)
- pkgs_to_download = ["subscription-manager", "subscription-manager-rhsm-certificates"]
+ pkgs_to_download = [
+ "subscription-manager",
+ "subscription-manager-rhsm-certificates",
+ ]
if system_info.version.major == 6:
pkgs_to_download.append("subscription-manager-rhsm")
@@ -686,3 +728,37 @@ def exit_on_failed_download(paths):
" the failed yumdownloader call above. These packages are necessary for the conversion"
" unless you use the --no-rhsm option."
)
+
+
+def lock_releasever_in_rhel_repositories():
+ """Lock the releasever in the RHEL repositories located under /etc/yum.repos.d/redhat.repo
+
+ After converting to a RHEL EUS minor version, we need to lock the releasever in the redhat.repo file
+ to prevent future errors such as, running `yum update` and not being able to find the repositories metadata.
+
+ .. note::
+ This function should only run if the system corresponds to a RHEL EUS version to make sure the converted system
+ keeps receiving updates for the specific EUS minor version instead of the latest minor version which is the
+ default.
+ """
+
+ # We only lock the releasever on rhel repos if we detect that the running system is an EUS correspondent and if
+ # rhsm is used, otherwise, there's no need to lock the releasever as the subscription-manager won't be available.
+ if system_info.corresponds_to_rhel_eus_release() and not tool_opts.no_rhsm:
+ loggerinst.info(
+ "Updating /etc/yum.repos.d/rehat.repo to point to RHEL %s instead of the default latest minor version."
+ % system_info.releasever
+ )
+ cmd = ["subscription-manager", "release", "--set=%s" % system_info.releasever]
+
+ output, ret_code = utils.run_subprocess(cmd, print_output=False)
+ if ret_code != 0:
+ loggerinst.warning(
+ "Locking RHEL repositories failed with return code %d and message:\n%s",
+ ret_code,
+ output,
+ )
+ else:
+ loggerinst.info("RHEL repositories locked to the %s minor version." % system_info.releasever)
+ else:
+ loggerinst.info("Skipping locking RHEL repositories to a specific EUS minor version.")
diff --git a/convert2rhel/systeminfo.py b/convert2rhel/systeminfo.py
index 62410e0eb3..8d1fcea6ad 100644
--- a/convert2rhel/systeminfo.py
+++ b/convert2rhel/systeminfo.py
@@ -14,6 +14,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
+import socket
from collections import namedtuple
@@ -35,7 +36,7 @@
# Allowed conversion paths to RHEL. We want to prevent a conversion and minor
-# version update at the same time.
+# version update at the same time.
RELEASE_VER_MAPPING = {
"8.10": "8.10",
"8.9": "8.9",
@@ -54,6 +55,9 @@
# For a list of modified rpm files after the conversion finishes for comparison purposes
POST_RPM_VA_LOG_FILENAME = "rpm_va_after_conversion.log"
+# List of EUS minor versions supported
+EUS_MINOR_VERSIONS = ["8.4"]
+
Version = namedtuple("Version", ["major", "minor"])
@@ -89,6 +93,8 @@ def __init__(self):
self.logger = None
# IDs of the default Red Hat CDN repositories that correspond to the current system
self.default_rhsm_repoids = None
+ # IDs of the Extended Update Support (EUS) Red Hat CDN repositories that correspond to the current system
+ self.eus_rhsm_repoids = None
# List of repositories enabled through subscription-manager
self.submgr_enabled_repos = []
# Value to use for substituting the $releasever variable in the url of RHEL repositories
@@ -111,11 +117,13 @@ def resolve_system_info(self):
self.excluded_pkgs = self._get_excluded_pkgs()
self.repofile_pkgs = self._get_repofile_pkgs()
self.default_rhsm_repoids = self._get_default_rhsm_repoids()
+ self.eus_rhsm_repoids = self._get_eus_rhsm_repoids()
self.fingerprints_orig_os = self._get_gpg_key_fingerprints()
self.generate_rpm_va()
self.releasever = self._get_releasever()
self.kmods_to_ignore = self._get_kmods_to_ignore()
self.booted_kernel = self._get_booted_kernel()
+ self.has_internet_access = self._check_internet_access()
@staticmethod
def _get_system_release_file_content():
@@ -190,6 +198,9 @@ def _get_cfg_section(self, section_name):
def _get_default_rhsm_repoids(self):
return self._get_cfg_opt("default_rhsm_repoids").split()
+ def _get_eus_rhsm_repoids(self):
+ return self._get_cfg_opt("eus_rhsm_repoids").split()
+
def _get_cfg_opt(self, option_name):
"""Return value of a specific configuration file option."""
if option_name in self.cfg_content:
@@ -227,7 +238,12 @@ def _get_releasever(self):
self.logger.critical(
"%s of version %d.%d is not allowed for conversion.\n"
"Allowed versions are: %s"
- % (self.name, self.version.major, self.version.minor, list(RELEASE_VER_MAPPING.keys()))
+ % (
+ self.name,
+ self.version.major,
+ self.version.minor,
+ list(RELEASE_VER_MAPPING.keys()),
+ )
)
def _get_kmods_to_ignore(self):
@@ -305,6 +321,50 @@ def get_enabled_rhel_repos(self):
# )
return self.submgr_enabled_repos if not tool_opts.no_rhsm else tool_opts.enablerepo
+ def _check_internet_access(self, host="8.8.8.8", port=53, timeout=3):
+ """Check whether or not the machine is connected to the internet.
+
+ This method will try to estabilish a socket connection through the
+ default host in the method signature (8.8.8.8). If it's connected
+ successfully, then we know that internet is accessible from the host.
+
+ .. warnings::
+ We might have some problems with this if the host machine is using
+ a NAT gateway to route the outbound requests
+
+ .. seealso::
+ * Comparison of different methods to check internet connections: https://stackoverflow.com/a/33117579
+ * Redirecting IP addresses: https://superuser.com/questions/954665/how-to-redirect-route-ip-address-to-another-ip-address
+
+ :param host: The host to establish a connection to. Defaults to "8.8.8.8".
+ :type host: str
+ :param port: The port for the connection. Defaults to 53.
+ :type port: int
+ :param timeout: The timeout in seconds for the connection. Defaults to 3.
+ :type port: int
+ :return: Return boolean indicating whether or not we have internet access.
+ :rtype: bool
+ """
+ try:
+ self.logger.info("Checking internet connectivity using host '%s' and port '%s'." % (host, port))
+ socket.setdefaulttimeout(timeout)
+ socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
+ return True
+ except (socket.timeout, socket.error):
+ self.logger.warning("Couldn't connect to the host '%s'." % host)
+ return False
+
+ def corresponds_to_rhel_eus_release(self):
+ """Return whether the current minor version corresponds to a RHEL Extended Update Support (EUS) release.
+
+ For example if we detect CentOS Linux 8.4, the corresponding RHEL 8.4 is an EUS release, but if we detect
+ CentOS Linux 8.5, the corresponding RHEL 8.5 is not an EUS release.
+
+ :return: Whether or not the current system has a EUS correspondent in RHEL.
+ :rtype: bool
+ """
+ return self.releasever in EUS_MINOR_VERSIONS
+
# Code to be executed upon module import
system_info = SystemInfo() # pylint: disable=C0103
diff --git a/convert2rhel/unit_tests/backup_test.py b/convert2rhel/unit_tests/backup_test.py
new file mode 100644
index 0000000000..5c3a63338c
--- /dev/null
+++ b/convert2rhel/unit_tests/backup_test.py
@@ -0,0 +1,401 @@
+import os
+import sys
+import unittest
+
+import pytest
+
+from convert2rhel import backup, repo, unit_tests # Imports unit_tests/__init__.py
+from convert2rhel.unit_tests.conftest import all_systems, centos8
+
+
+if sys.version_info[:2] <= (2, 7):
+ import mock # pylint: disable=import-error
+else:
+ from unittest import mock # pylint: disable=no-name-in-module
+
+
+class TestBackup(unittest.TestCase):
+ class RunSubprocessMocked(unit_tests.MockFunction):
+ def __init__(self, output="Test output", ret_code=0):
+ self.cmd = []
+ self.cmds = []
+ self.called = 0
+ self.output = output
+ self.ret_code = ret_code
+
+ def __call__(self, cmd, print_cmd=True, print_output=True):
+ self.cmd = cmd
+ self.cmds.append(cmd)
+ self.called += 1
+ return self.output, self.ret_code
+
+ class DummyFuncMocked(unit_tests.MockFunction):
+ def __init__(self):
+ self.called = 0
+
+ def __call__(self, *args, **kargs):
+ self.called += 1
+
+ class RemovePkgsMocked(unit_tests.MockFunction):
+ def __init__(self):
+ self.pkgs = None
+ self.should_bkp = False
+ self.critical = False
+
+ def __call__(self, pkgs_to_remove, backup=False, critical=False):
+ self.pkgs = pkgs_to_remove
+ self.should_bkp = backup
+ self.critical = critical
+
+ @unit_tests.mock(
+ backup.changed_pkgs_control,
+ "backup_and_track_removed_pkg",
+ DummyFuncMocked(),
+ )
+ @unit_tests.mock(backup, "run_subprocess", RunSubprocessMocked())
+ def test_remove_pkgs_without_backup(self):
+ pkgs = ["pkg1", "pkg2", "pkg3"]
+ backup.remove_pkgs(pkgs, False)
+ self.assertEqual(backup.changed_pkgs_control.backup_and_track_removed_pkg.called, 0)
+
+ self.assertEqual(backup.run_subprocess.called, len(pkgs))
+
+ rpm_remove_cmd = ["rpm", "-e", "--nodeps"]
+ for cmd, pkg in zip(backup.run_subprocess.cmds, pkgs):
+ self.assertEqual(rpm_remove_cmd + [pkg], cmd)
+
+ @unit_tests.mock(
+ backup.ChangedRPMPackagesController,
+ "backup_and_track_removed_pkg",
+ DummyFuncMocked(),
+ )
+ @unit_tests.mock(backup, "run_subprocess", RunSubprocessMocked())
+ def test_remove_pkgs_with_backup(self):
+ pkgs = ["pkg1", "pkg2", "pkg3"]
+ backup.remove_pkgs(pkgs)
+ self.assertEqual(
+ backup.ChangedRPMPackagesController.backup_and_track_removed_pkg.called,
+ len(pkgs),
+ )
+
+ self.assertEqual(backup.run_subprocess.called, len(pkgs))
+
+ rpm_remove_cmd = ["rpm", "-e", "--nodeps"]
+ for cmd, pkg in zip(backup.run_subprocess.cmds, pkgs):
+ self.assertEqual(rpm_remove_cmd + [pkg], cmd)
+
+ @unit_tests.mock(backup.RestorablePackage, "backup", DummyFuncMocked())
+ def test_backup_and_track_removed_pkg(self):
+ control = backup.ChangedRPMPackagesController()
+ pkgs = ["pkg1", "pkg2", "pkg3"]
+ for pkg in pkgs:
+ control.backup_and_track_removed_pkg(pkg)
+ self.assertEqual(backup.RestorablePackage.backup.called, len(pkgs))
+ self.assertEqual(len(control.removed_pkgs), len(pkgs))
+
+ @unit_tests.mock(backup, "run_subprocess", RunSubprocessMocked())
+ def test_install_local_rpms_with_empty_list(self):
+ backup.changed_pkgs_control._install_local_rpms([])
+ self.assertEqual(backup.run_subprocess.called, 0)
+
+ @unit_tests.mock(backup.changed_pkgs_control, "track_installed_pkg", DummyFuncMocked())
+ @unit_tests.mock(backup, "run_subprocess", RunSubprocessMocked())
+ def test_install_local_rpms_without_replace(self):
+ pkgs = ["pkg1", "pkg2", "pkg3"]
+ backup.changed_pkgs_control._install_local_rpms(pkgs)
+ self.assertEqual(backup.changed_pkgs_control.track_installed_pkg.called, len(pkgs))
+
+ self.assertEqual(backup.run_subprocess.called, 1)
+ self.assertEqual(["rpm", "-i", "pkg1", "pkg2", "pkg3"], backup.run_subprocess.cmd)
+
+ @unit_tests.mock(backup.changed_pkgs_control, "track_installed_pkg", DummyFuncMocked())
+ @unit_tests.mock(backup, "run_subprocess", RunSubprocessMocked())
+ def test_install_local_rpms_with_replace(self):
+ pkgs = ["pkg1", "pkg2", "pkg3"]
+ backup.changed_pkgs_control._install_local_rpms(pkgs, replace=True)
+ self.assertEqual(backup.changed_pkgs_control.track_installed_pkg.called, len(pkgs))
+
+ self.assertEqual(backup.run_subprocess.called, 1)
+ self.assertEqual(
+ ["rpm", "-i", "--replacepkgs", "pkg1", "pkg2", "pkg3"],
+ backup.run_subprocess.cmd,
+ )
+
+
+def test_remove_pkgs_with_empty_list(caplog):
+ backup.remove_pkgs([])
+ assert "No package to remove" in caplog.messages[-1]
+
+
+def test_track_installed_pkg():
+ control = backup.ChangedRPMPackagesController()
+ pkgs = ["pkg1", "pkg2", "pkg3"]
+ for pkg in pkgs:
+ control.track_installed_pkg(pkg)
+ assert control.installed_pkgs == pkgs
+
+
+def test_track_installed_pkgs():
+ control = backup.ChangedRPMPackagesController()
+ pkgs = ["pkg1", "pkg2", "pkg3"]
+ control.track_installed_pkgs(pkgs)
+ assert control.installed_pkgs == pkgs
+
+
+def test_changed_pkgs_control_remove_installed_pkgs(monkeypatch, caplog):
+ removed_pkgs = ["pkg_1"]
+ run_subprocess_mock = mock.Mock(
+ side_effect=unit_tests.run_subprocess_side_effect(
+ (("rpm", "-e", "--nodeps", removed_pkgs[0]), ("test", 0)),
+ )
+ )
+ monkeypatch.setattr(
+ backup,
+ "run_subprocess",
+ value=run_subprocess_mock,
+ )
+
+ control = backup.ChangedRPMPackagesController()
+ control.installed_pkgs = removed_pkgs
+ control._remove_installed_pkgs()
+ assert "Removing package: %s" % removed_pkgs[0] in caplog.records[-1].message
+
+
+def test_changed_pkgs_control_install_removed_pkgs(monkeypatch):
+ install_local_rpms_mock = mock.Mock()
+ removed_pkgs = [mock.Mock()]
+ monkeypatch.setattr(
+ backup.changed_pkgs_control,
+ "_install_local_rpms",
+ value=install_local_rpms_mock,
+ )
+ backup.changed_pkgs_control.removed_pkgs = removed_pkgs
+ backup.changed_pkgs_control._install_removed_pkgs()
+ assert install_local_rpms_mock.call_count == 1
+
+
+def test_changed_pkgs_control_install_removed_pkgs_without_path(monkeypatch, caplog):
+ install_local_rpms_mock = mock.Mock()
+ removed_pkgs = [mock.Mock()]
+ monkeypatch.setattr(
+ backup.changed_pkgs_control,
+ "_install_local_rpms",
+ value=install_local_rpms_mock,
+ )
+ backup.changed_pkgs_control.removed_pkgs = removed_pkgs
+ backup.changed_pkgs_control.removed_pkgs[0].path = None
+ backup.changed_pkgs_control._install_removed_pkgs()
+ assert install_local_rpms_mock.call_count == 1
+ assert "Couldn't find a backup" in caplog.records[-1].message
+
+
+def test_changed_pkgs_control_restore_pkgs(monkeypatch):
+ install_local_rpms_mock = mock.Mock()
+ remove_pkgs_mock = mock.Mock()
+ monkeypatch.setattr(
+ backup.changed_pkgs_control,
+ "_install_local_rpms",
+ value=install_local_rpms_mock,
+ )
+ monkeypatch.setattr(backup, "remove_pkgs", value=remove_pkgs_mock)
+
+ backup.changed_pkgs_control.restore_pkgs()
+ assert install_local_rpms_mock.call_count == 1
+ assert remove_pkgs_mock.call_count == 1
+
+
+@pytest.mark.parametrize(
+ ("filepath", "backup_dir", "file_content", "expected"),
+ (
+ ("test.rpm", "backup", "test", None),
+ ("test.rpm", "backup", "", "Can't find"),
+ ),
+)
+def test_restorable_file_backup(filepath, backup_dir, file_content, expected, tmpdir, monkeypatch, caplog):
+ tmp_file = tmpdir.join(filepath)
+ tmp_backup = tmpdir.mkdir(backup_dir)
+ if file_content:
+ tmp_file.write(file_content)
+
+ monkeypatch.setattr(backup, "BACKUP_DIR", str(tmp_backup))
+ rf = backup.RestorableFile(filepath=str(tmp_file))
+ rf.backup()
+
+ if expected:
+ assert expected in caplog.records[-1].message
+
+
+def test_restorable_file_backup_oserror(tmpdir, caplog):
+ tmp_file = tmpdir.join("test.rpm")
+ tmp_file.write("test")
+ rf = backup.RestorableFile(filepath=str(tmp_file))
+
+ with pytest.raises(SystemExit):
+ rf.backup()
+
+ assert "Error(2): No such file or directory" in caplog.records[-1].message
+
+
+@pytest.mark.parametrize(
+ ("filepath", "backup_dir", "file_content", "expected"),
+ (
+ ("test.rpm", "backup", "test", "restored"),
+ ("test.rpm", "backup", "", "hasn't been backed up"),
+ ),
+)
+def test_restorable_file_restore(filepath, backup_dir, file_content, expected, tmpdir, monkeypatch, caplog):
+ tmp_backup = tmpdir
+ tmp_file = tmpdir.join(filepath)
+ tmp_backup = tmp_backup.mkdir(backup_dir).join(filepath)
+ if file_content:
+ tmp_backup.write(file_content)
+
+ monkeypatch.setattr(backup, "BACKUP_DIR", os.path.dirname(str(tmp_backup)))
+ rf = backup.RestorableFile(filepath=str(tmp_file))
+ rf.restore()
+
+ if expected:
+ assert expected in caplog.records[-1].message
+
+
+def test_restorable_file_restore_oserror(tmpdir, caplog, monkeypatch):
+ tmp_backup = tmpdir
+ tmp_backup = tmp_backup.mkdir("backup").join("test.rpm")
+ tmp_backup.write("test")
+
+ monkeypatch.setattr(backup, "BACKUP_DIR", os.path.dirname(str(tmp_backup)))
+
+ rf = backup.RestorableFile(filepath="/non-existing/test.rpm")
+ rf.restore()
+
+ # Source and dest files are the same, which throws this error
+ assert "Error(2): No such file or directory" in caplog.records[-1].message
+
+
+@pytest.mark.parametrize(
+ ("pkgs_to_remove", "ret_code", "backup_pkg", "critical", "expected"),
+ (
+ (["pkg1"], 1, False, True, "Error: Couldn't remove {}."),
+ (["pkg1"], 1, False, False, "Couldn't remove {}."),
+ ),
+)
+def test_remove_pkgs_failed_to_remove(
+ pkgs_to_remove,
+ ret_code,
+ backup_pkg,
+ critical,
+ expected,
+ monkeypatch,
+ caplog,
+):
+ run_subprocess_mock = mock.Mock(
+ side_effect=unit_tests.run_subprocess_side_effect(
+ (("rpm", "-e", "--nodeps", pkgs_to_remove[0]), ("test", ret_code)),
+ )
+ )
+ monkeypatch.setattr(
+ backup,
+ "run_subprocess",
+ value=run_subprocess_mock,
+ )
+
+ if critical:
+ with pytest.raises(SystemExit):
+ backup.remove_pkgs(
+ pkgs_to_remove=pkgs_to_remove,
+ backup=backup_pkg,
+ critical=critical,
+ )
+ else:
+ backup.remove_pkgs(pkgs_to_remove=pkgs_to_remove, backup=backup_pkg, critical=critical)
+
+ assert expected.format(pkgs_to_remove[0]) in caplog.records[-1].message
+
+
+@centos8
+def test_restorable_package_backup(pretend_os, monkeypatch, tmpdir):
+ backup_dir = str(tmpdir)
+ data_dir = str(tmpdir.join("data-dir"))
+ dowloaded_pkg_dir = str(tmpdir.join("some-path"))
+ download_pkg_mock = mock.Mock(return_value=dowloaded_pkg_dir)
+ monkeypatch.setattr(backup, "BACKUP_DIR", backup_dir)
+ monkeypatch.setattr(repo, "DATA_DIR", data_dir)
+ monkeypatch.setattr(backup, "download_pkg", download_pkg_mock)
+ rp = backup.RestorablePackage(pkgname="pkg-1")
+ rp.backup()
+
+ assert download_pkg_mock.call_count == 1
+ assert rp.path == dowloaded_pkg_dir
+
+
+def test_restorable_package_backup_without_dir(monkeypatch, tmpdir, caplog):
+ backup_dir = str(tmpdir.join("non-existing"))
+ monkeypatch.setattr(backup, "BACKUP_DIR", backup_dir)
+ rp = backup.RestorablePackage(pkgname="pkg-1")
+ rp.backup()
+
+ assert "Can't access %s" % backup_dir in caplog.records[-1].message
+
+
+def test_changedrpms_packages_controller_install_local_rpms(monkeypatch, caplog):
+ pkgs = ["pkg-1"]
+ run_subprocess_mock = mock.Mock(
+ side_effect=unit_tests.run_subprocess_side_effect(
+ (("rpm", "-i", pkgs[0]), ("test", 1)),
+ )
+ )
+ monkeypatch.setattr(
+ backup,
+ "run_subprocess",
+ value=run_subprocess_mock,
+ )
+
+ control = backup.ChangedRPMPackagesController()
+ result = control._install_local_rpms(pkgs_to_install=pkgs, replace=False, critical=False)
+
+ assert result == False
+ assert run_subprocess_mock.call_count == 1
+ assert "Couldn't install %s packages." % pkgs[0] in caplog.records[-1].message
+
+
+def test_changedrpms_packages_controller_install_local_rpms_system_exit(monkeypatch, caplog):
+ pkgs = ["pkg-1"]
+ run_subprocess_mock = mock.Mock(
+ side_effect=unit_tests.run_subprocess_side_effect(
+ (("rpm", "-i", pkgs[0]), ("test", 1)),
+ )
+ )
+ monkeypatch.setattr(
+ backup,
+ "run_subprocess",
+ value=run_subprocess_mock,
+ )
+
+ control = backup.ChangedRPMPackagesController()
+ with pytest.raises(SystemExit):
+ control._install_local_rpms(pkgs_to_install=pkgs, replace=False, critical=True)
+
+ assert run_subprocess_mock.call_count == 1
+ assert "Error: Couldn't install %s packages." % pkgs[0] in caplog.records[-1].message
+
+
+@pytest.mark.parametrize(
+ ("is_eus_system", "has_internet_access"),
+ ((True, True), (False, False), (True, False), (False, True)),
+)
+@centos8
+def test_restorable_package_backup(pretend_os, is_eus_system, has_internet_access, tmpdir, monkeypatch):
+ pkg_to_backup = "pkg-1"
+
+ # Python 2.7 needs a string or buffer and not a LocalPath
+ tmpdir = str(tmpdir)
+ download_pkg_mock = mock.Mock()
+ monkeypatch.setattr(backup, "download_pkg", value=download_pkg_mock)
+ monkeypatch.setattr(backup, "BACKUP_DIR", value=tmpdir)
+ monkeypatch.setattr(backup.system_info, "corresponds_to_rhel_eus_release", value=lambda: is_eus_system)
+ monkeypatch.setattr(backup, "get_hardcoded_repofiles_dir", value=lambda: tmpdir if is_eus_system else None)
+ backup.system_info.has_internet_access = has_internet_access
+
+ rp = backup.RestorablePackage(pkgname=pkg_to_backup)
+ rp.backup()
+ assert download_pkg_mock.call_count == 1
diff --git a/convert2rhel/unit_tests/checks_test.py b/convert2rhel/unit_tests/checks_test.py
index d4f6d017e1..d7c1401730 100644
--- a/convert2rhel/unit_tests/checks_test.py
+++ b/convert2rhel/unit_tests/checks_test.py
@@ -36,7 +36,7 @@
from convert2rhel.systeminfo import system_info
from convert2rhel.toolopts import tool_opts
from convert2rhel.unit_tests import GetFileContentMocked, GetLoggerMocked, run_subprocess_side_effect
-from convert2rhel.unit_tests.conftest import centos7, centos8
+from convert2rhel.unit_tests.conftest import centos7, centos8, oracle8
from convert2rhel.utils import run_subprocess
@@ -830,15 +830,27 @@ def test_custom_repos_are_invalid(self):
self.assertTrue("Unable to access the repositories passed through " in checks.logger.critical_msgs[0])
+@oracle8
+def test_check_package_updates_skip_on_not_latest_ol(pretend_os, caplog):
+ message = (
+ "Skipping the check because there are no publicly available Oracle Linux Server 8.4 repositories available."
+ )
+
+ check_package_updates()
+
+ assert message in caplog.records[-1].message
+
+
@pytest.mark.parametrize(
("packages", "exception", "expected"),
(
- (["package-1", "package-2"], True, "The system has {} packages not updated."),
+ (["package-1", "package-2"], True, "The system has {} packages not updated"),
([], False, "System is up-to-date."),
),
)
-def test_check_package_updates(packages, exception, expected, monkeypatch, caplog):
- monkeypatch.setattr(checks, "get_total_packages_to_update", value=lambda: packages)
+@centos8
+def test_check_package_updates(pretend_os, packages, exception, expected, monkeypatch, caplog):
+ monkeypatch.setattr(checks, "get_total_packages_to_update", value=lambda reposdir: packages)
monkeypatch.setattr(checks, "ask_to_continue", value=lambda: mock.Mock())
check_package_updates()
@@ -860,24 +872,108 @@ def test_check_package_updates_with_repoerror(monkeypatch, caplog):
)
+@centos8
+def test_check_package_updates_without_internet(pretend_os, tmpdir, monkeypatch, caplog):
+ monkeypatch.setattr(checks, "get_hardcoded_repofiles_dir", value=lambda: str(tmpdir))
+ system_info.has_internet_access = False
+ check_package_updates()
+
+ assert "Skipping the check as no internet connection has been detected." in caplog.records[-1].message
+
+
+@oracle8
+def test_is_loaded_kernel_latest_skip_on_not_latest_ol(pretend_os, caplog):
+ message = (
+ "Skipping the check because there are no publicly available Oracle Linux Server 8.4 repositories available."
+ )
+
+ is_loaded_kernel_latest()
+
+ assert message in caplog.records[-1].message
+
+
@pytest.mark.parametrize(
("repoquery_version", "uname_version", "return_code", "major_ver", "package_name", "raise_system_exit"),
(
- ("1634146676\t3.10.0-1160.45.1.el7", "3.10.0-1160.42.2.el7.x86_64", 0, 8, "kernel-core", True),
- ("1634146676\t3.10.0-1160.45.1.el7", "3.10.0-1160.45.1.el7.x86_64", 0, 7, "kernel", False),
- ("1634146676\t3.10.0-1160.45.1.el7", "3.10.0-1160.45.1.el7.x86_64", 0, 6, "kernel", False),
+ ("1634146676\t3.10.0-1160.45.1.el7\tbaseos", "3.10.0-1160.42.2.el7.x86_64", 0, 8, "kernel-core", True),
+ ("1634146676\t3.10.0-1160.45.1.el7\tbaseos", "3.10.0-1160.45.1.el7.x86_64", 0, 7, "kernel", False),
+ ("1634146676\t3.10.0-1160.45.1.el7\tbaseos", "3.10.0-1160.45.1.el7.x86_64", 0, 6, "kernel", False),
),
)
def test_is_loaded_kernel_latest(
repoquery_version, uname_version, return_code, major_ver, package_name, raise_system_exit, monkeypatch, caplog
):
Version = namedtuple("Version", ("major", "minor"))
+ # Using the minor version as 99, so the tests should never fail because of a constraint in the code, since we don't
+ # mind the minor version number (for now), and require only that the major version to be in the range of 6 to 8,
+ # we can set the minor version to 99 to avoid hardcoded checks in the code.
monkeypatch.setattr(
checks.system_info,
"version",
- value=Version(major=major_ver, minor=0),
+ value=Version(major=major_ver, minor=99),
)
+ system_info.id = "centos"
+ run_subprocess_mocked = mock.Mock(
+ spec=run_subprocess,
+ side_effect=run_subprocess_side_effect(
+ (
+ (
+ "repoquery",
+ "--quiet",
+ "--qf",
+ '"%{BUILDTIME}\\t%{VERSION}-%{RELEASE}\\t%{REPOID}"',
+ package_name,
+ ),
+ (
+ repoquery_version,
+ return_code,
+ ),
+ ),
+ (("uname", "-r"), (uname_version, return_code)),
+ ),
+ )
+ monkeypatch.setattr(
+ checks,
+ "run_subprocess",
+ value=run_subprocess_mocked,
+ )
+
+ if raise_system_exit:
+ with pytest.raises(SystemExit):
+ is_loaded_kernel_latest()
+
+ repoquery_kernel_version = repoquery_version.split("\t")[1]
+ uname_kernel_version = uname_version.rsplit(".", 1)[0]
+ assert (
+ "Latest kernel version available in baseos: %s\n" % repoquery_kernel_version in caplog.records[-1].message
+ )
+ assert "Loaded kernel version: %s\n" % uname_kernel_version in caplog.records[-1].message
+ else:
+ is_loaded_kernel_latest()
+ assert "Kernel currently loaded is at the latest version." in caplog.records[-1].message
+
+@pytest.mark.parametrize(
+ ("repoquery_version", "uname_version", "return_code", "package_name", "raise_system_exit"),
+ (
+ ("1634146676\t3.10.0-1160.45.1.el7\tbaseos", "3.10.0-1160.42.2.el7.x86_64", 0, "kernel-core", True),
+ ("1634146676\t3.10.0-1160.45.1.el7\tbaseos", "3.10.0-1160.45.1.el7.x86_64", 0, "kernel-core", False),
+ ),
+)
+@centos8
+def test_is_loaded_kernel_latest_eus_system(
+ pretend_os,
+ repoquery_version,
+ uname_version,
+ return_code,
+ package_name,
+ raise_system_exit,
+ tmpdir,
+ monkeypatch,
+ caplog,
+):
+ fake_reposdir_path = str(tmpdir)
+ monkeypatch.setattr(checks, "get_hardcoded_repofiles_dir", value=lambda: fake_reposdir_path)
run_subprocess_mocked = mock.Mock(
spec=run_subprocess,
side_effect=run_subprocess_side_effect(
@@ -886,7 +982,8 @@ def test_is_loaded_kernel_latest(
"repoquery",
"--quiet",
"--qf",
- '"%{BUILDTIME}\\t%{VERSION}-%{RELEASE}"',
+ '"%{BUILDTIME}\\t%{VERSION}-%{RELEASE}\\t%{REPOID}"',
+ "--setopt=reposdir=%s" % fake_reposdir_path,
package_name,
),
(
@@ -907,15 +1004,30 @@ def test_is_loaded_kernel_latest(
with pytest.raises(SystemExit):
is_loaded_kernel_latest()
- repoquery_kernel_version = repoquery_version.split("\t", 1)[1]
+ repoquery_kernel_version = repoquery_version.split("\t")[1]
uname_kernel_version = uname_version.rsplit(".", 1)[0]
- assert "Latest kernel version: %s\n" % repoquery_kernel_version in caplog.records[-1].message
- assert "Current loaded kernel: %s\n" % uname_kernel_version in caplog.records[-1].message
+ assert (
+ "The version of the loaded kernel is different from the latest version in repositories defined in the %s folder"
+ % fake_reposdir_path
+ )
+ assert (
+ "Latest kernel version available in baseos: %s\n" % repoquery_kernel_version in caplog.records[-1].message
+ )
+ assert "Loaded kernel version: %s\n" % uname_kernel_version in caplog.records[-1].message
else:
is_loaded_kernel_latest()
assert "Kernel currently loaded is at the latest version." in caplog.records[-1].message
+@centos8
+def test_is_loaded_kernel_latest_eus_system_no_connection(pretend_os, monkeypatch, tmpdir, caplog):
+ monkeypatch.setattr(checks, "get_hardcoded_repofiles_dir", value=lambda: str(tmpdir))
+ system_info.has_internet_access = False
+
+ is_loaded_kernel_latest()
+ assert "Skipping the check as no internet connection has been detected." in caplog.records[-1].message
+
+
@pytest.mark.parametrize(
("repoquery_version", "return_code", "major_ver", "package_name", "unsupported_skip", "expected"),
(
@@ -943,7 +1055,7 @@ def test_is_loaded_kernel_latest_unsupported_skip(
"repoquery",
"--quiet",
"--qf",
- '"%{BUILDTIME}\\t%{VERSION}-%{RELEASE}"',
+ '"%{BUILDTIME}\\t%{VERSION}-%{RELEASE}\\t%{REPOID}"',
package_name,
),
(
diff --git a/convert2rhel/unit_tests/main_test.py b/convert2rhel/unit_tests/main_test.py
index 02f2e7a5ea..eec766b217 100644
--- a/convert2rhel/unit_tests/main_test.py
+++ b/convert2rhel/unit_tests/main_test.py
@@ -28,7 +28,9 @@
import pytest
+from convert2rhel import backup, grub
from convert2rhel import logger as logger_module
+from convert2rhel.breadcrumbs import breadcrumbs
try:
@@ -142,7 +144,7 @@ def test_show_eula_nonexisting_file(self):
self.assertEqual(len(main.loggerinst.critical_msgs), 1)
@unit_tests.mock(
- utils.changed_pkgs_control,
+ backup.changed_pkgs_control,
"restore_pkgs",
unit_tests.CountableMockObject(),
)
@@ -172,7 +174,7 @@ def test_show_eula_nonexisting_file(self):
@unit_tests.mock(cert.SystemCert, "remove", unit_tests.CountableMockObject())
def test_rollback_changes(self):
main.rollback_changes()
- self.assertEqual(utils.changed_pkgs_control.restore_pkgs.called, 1)
+ self.assertEqual(backup.changed_pkgs_control.restore_pkgs.called, 1)
self.assertEqual(repo.restore_yum_repos.called, 1)
self.assertEqual(redhatrelease.system_release_file.restore.called, 1)
self.assertEqual(redhatrelease.os_release_file.restore.called, 1)
@@ -305,3 +307,34 @@ def test_initialize_logger(exception_type, exception, monkeypatch, capsys):
main.initialize_logger("convert2rhel.log", "/tmp")
setup_logger_handler_mock.assert_called_once()
archive_old_logger_files_mock.assert_called_once()
+
+
+def test_post_ponr_conversion(monkeypatch):
+ install_gpg_keys_mock = mock.Mock()
+ perserve_only_rhel_kernel_mock = mock.Mock()
+ replace_non_red_hat_pkgs_left_mock = mock.Mock()
+ list_non_red_hat_pkgs_left_mock = mock.Mock()
+ post_ponr_set_efi_configuration_mock = mock.Mock()
+ yum_conf_patch_mock = mock.Mock()
+ lock_releasever_in_rhel_repositories_mock = mock.Mock()
+ finish_success_mock = mock.Mock()
+
+ monkeypatch.setattr(pkghandler, "install_gpg_keys", install_gpg_keys_mock)
+ monkeypatch.setattr(pkghandler, "preserve_only_rhel_kernel", perserve_only_rhel_kernel_mock)
+ monkeypatch.setattr(pkghandler, "replace_non_red_hat_packages", replace_non_red_hat_pkgs_left_mock)
+ monkeypatch.setattr(pkghandler, "list_non_red_hat_pkgs_left", list_non_red_hat_pkgs_left_mock)
+ monkeypatch.setattr(grub, "post_ponr_set_efi_configuration", post_ponr_set_efi_configuration_mock)
+ monkeypatch.setattr(redhatrelease.YumConf, "patch", yum_conf_patch_mock)
+ monkeypatch.setattr(subscription, "lock_releasever_in_rhel_repositories", lock_releasever_in_rhel_repositories_mock)
+ monkeypatch.setattr(breadcrumbs, "finish_success", finish_success_mock)
+
+ main.post_ponr_conversion()
+
+ assert install_gpg_keys_mock.call_count == 1
+ assert perserve_only_rhel_kernel_mock.call_count == 1
+ assert replace_non_red_hat_pkgs_left_mock.call_count == 1
+ assert list_non_red_hat_pkgs_left_mock.call_count == 1
+ assert post_ponr_set_efi_configuration_mock.call_count == 1
+ assert yum_conf_patch_mock.call_count == 1
+ assert lock_releasever_in_rhel_repositories_mock.call_count == 1
+ assert finish_success_mock.call_count == 1
diff --git a/convert2rhel/unit_tests/pkghandler_test.py b/convert2rhel/unit_tests/pkghandler_test.py
index 4f977def78..228977be02 100644
--- a/convert2rhel/unit_tests/pkghandler_test.py
+++ b/convert2rhel/unit_tests/pkghandler_test.py
@@ -31,8 +31,7 @@
else:
from unittest import mock # pylint: disable=no-name-in-module
-from convert2rhel import unit_tests # Imports unit_tests/__init__.py
-from convert2rhel import pkghandler, pkgmanager, utils
+from convert2rhel import backup, pkghandler, pkgmanager, unit_tests, utils # Imports unit_tests/__init__.py
from convert2rhel.pkghandler import (
_get_packages_to_update_dnf,
_get_packages_to_update_yum,
@@ -41,7 +40,7 @@
from convert2rhel.systeminfo import system_info
from convert2rhel.toolopts import tool_opts
from convert2rhel.unit_tests import GetLoggerMocked, is_rpm_based_os
-from convert2rhel.unit_tests.conftest import all_systems
+from convert2rhel.unit_tests.conftest import all_systems, centos8
if sys.version_info[:2] <= (2, 7):
@@ -170,8 +169,8 @@ def test_clear_versionlock_plugin_not_enabled(self):
@unit_tests.mock(os.path, "isfile", IsFileMocked(is_file=True))
@unit_tests.mock(os.path, "getsize", GetSizeMocked(file_size=1))
@unit_tests.mock(pkghandler, "call_yum_cmd", CallYumCmdMocked())
- @unit_tests.mock(utils.RestorableFile, "backup", DumbCallableObject)
- @unit_tests.mock(utils.RestorableFile, "restore", DumbCallableObject)
+ @unit_tests.mock(backup.RestorableFile, "backup", DumbCallableObject)
+ @unit_tests.mock(backup.RestorableFile, "restore", DumbCallableObject)
def test_clear_versionlock_user_says_yes(self):
pkghandler.clear_versionlock()
self.assertEqual(pkghandler.call_yum_cmd.called, 1)
@@ -313,7 +312,7 @@ def test_call_yum_cmd_w_downgrades_one_fail(self):
"get_problematic_pkgs",
lambda pkg: {"errors": set([pkg]), "mismatches": set()},
)
- @unit_tests.mock(utils, "remove_pkgs", RemovePkgsMocked())
+ @unit_tests.mock(pkghandler, "remove_pkgs", RemovePkgsMocked())
def test_call_yum_cmd_w_downgrades_remove_problematic_pkgs(self):
pkghandler.call_yum_cmd.return_code = 1
pkghandler.MAX_YUM_CMD_CALLS = 1
@@ -325,8 +324,8 @@ def test_call_yum_cmd_w_downgrades_remove_problematic_pkgs(self):
["fingerprint"],
)
- self.assertIn(pkghandler.call_yum_cmd.return_string, utils.remove_pkgs.pkgs)
- self.assertEqual(utils.remove_pkgs.critical, False)
+ self.assertIn(pkghandler.call_yum_cmd.return_string, pkghandler.remove_pkgs.pkgs)
+ self.assertEqual(pkghandler.remove_pkgs.critical, False)
def test_get_pkgs_to_distro_sync(self):
problematic_pkgs = {
@@ -853,7 +852,7 @@ def __call__(self, fingerprints, name=""):
@unit_tests.mock(utils, "ask_to_continue", DumbCallableObject())
@unit_tests.mock(pkghandler, "print_pkg_info", DumbCallableObject())
@unit_tests.mock(system_info, "fingerprints_rhel", ["rhel_fingerprint"])
- @unit_tests.mock(utils, "remove_pkgs", RemovePkgsMocked())
+ @unit_tests.mock(pkghandler, "remove_pkgs", RemovePkgsMocked())
@unit_tests.mock(
pkghandler,
"get_installed_pkgs_w_different_fingerprint",
@@ -862,8 +861,8 @@ def __call__(self, fingerprints, name=""):
def test_remove_pkgs_with_confirm(self):
pkghandler.remove_pkgs_with_confirm(["installed_pkg", "not_installed_pkg"])
- self.assertEqual(len(utils.remove_pkgs.pkgs), 1)
- self.assertEqual(utils.remove_pkgs.pkgs[0], "installed_pkg-0.1-1.x86_64")
+ self.assertEqual(len(pkghandler.remove_pkgs.pkgs), 1)
+ self.assertEqual(pkghandler.remove_pkgs.pkgs[0], "installed_pkg-0.1-1.x86_64")
class CallYumCmdWDowngradesMocked(unit_tests.MockFunction):
def __init__(self):
@@ -1115,19 +1114,23 @@ def test_handle_older_rhel_kernel_not_available(self):
@unit_tests.mock(system_info, "version", namedtuple("Version", ["major", "minor"])(7, 0))
@unit_tests.mock(system_info, "releasever", None)
+ @unit_tests.mock(backup, "run_subprocess", RunSubprocessMocked())
@unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
- @unit_tests.mock(utils, "remove_pkgs", RemovePkgsMocked())
+ @unit_tests.mock(pkghandler, "remove_pkgs", RemovePkgsMocked())
def test_handle_older_rhel_kernel_not_available_multiple_installed(self):
utils.run_subprocess.output = YUM_KERNEL_LIST_OLDER_NOT_AVAILABLE_MULTIPLE_INSTALLED
pkghandler.handle_no_newer_rhel_kernel_available()
- self.assertEqual(len(utils.remove_pkgs.pkgs), 1)
- self.assertEqual(utils.remove_pkgs.pkgs[0], "kernel-4.7.4-200.fc24")
+ self.assertEqual(len(pkghandler.remove_pkgs.pkgs), 1)
+ self.assertEqual(pkghandler.remove_pkgs.pkgs[0], "kernel-4.7.4-200.fc24")
self.assertEqual(
utils.run_subprocess.cmd,
["yum", "install", "-y", "kernel-4.7.4-200.fc24"],
)
+ self.assertEqual(len(pkghandler.remove_pkgs.pkgs), 1)
+ self.assertEqual(pkghandler.remove_pkgs.pkgs[0], "kernel-4.7.4-200.fc24")
+ self.assertEqual(utils.run_subprocess.cmd, ["yum", "install", "-y", "kernel-4.7.4-200.fc24"])
class DownloadPkgMocked(unit_tests.MockFunction):
def __init__(self):
@@ -1224,7 +1227,7 @@ def test_is_rhel_kernel_installed_yes(self):
GetInstalledPkgsWDifferentFingerprintMocked(),
)
@unit_tests.mock(pkghandler, "print_pkg_info", DumbCallableObject())
- @unit_tests.mock(utils, "remove_pkgs", RemovePkgsMocked())
+ @unit_tests.mock(pkghandler, "remove_pkgs", RemovePkgsMocked())
def test_remove_non_rhel_kernels(self):
removed_pkgs = pkghandler.remove_non_rhel_kernels()
@@ -1285,7 +1288,7 @@ def test_fix_invalid_grub2_entries(self):
GetInstalledPkgsWDifferentFingerprintMocked(),
)
@unit_tests.mock(pkghandler, "print_pkg_info", DumbCallableObject())
- @unit_tests.mock(utils, "remove_pkgs", RemovePkgsMocked())
+ @unit_tests.mock(pkghandler, "remove_pkgs", RemovePkgsMocked())
@unit_tests.mock(pkghandler, "call_yum_cmd", CallYumCmdMocked())
def test_install_additional_rhel_kernel_pkgs(self):
removed_pkgs = pkghandler.remove_non_rhel_kernels()
@@ -1466,7 +1469,7 @@ def test_compare_package_versions(version1, version2, expected):
@pytest.mark.parametrize(
- ("package_manager_type", "packages", "expected"),
+ ("package_manager_type", "packages", "expected", "reposdir"),
(
(
"yum",
@@ -1478,6 +1481,7 @@ def test_compare_package_versions(version1, version2, expected):
"convert2rhel.noarch-0.24-1.20211111151554764702.pr356.28.ge9ed160.el8",
"convert2rhel.src-0.24-1.20211111151554764702.pr356.28.ge9ed160.el8",
},
+ None,
),
(
"yum",
@@ -1486,6 +1490,7 @@ def test_compare_package_versions(version1, version2, expected):
"convert2rhel.noarch-0.24-1.20211111151554764702.pr356.28.ge9ed160.el8",
],
{"convert2rhel.noarch-0.24-1.20211111151554764702.pr356.28.ge9ed160.el8"},
+ None,
),
(
"dnf",
@@ -1499,6 +1504,21 @@ def test_compare_package_versions(version1, version2, expected):
"dunst-1.7.0-1.fc35.x86_64",
"java-11-openjdk-headless-1:11.0.13.0.8-2.fc35.x86_64",
},
+ None,
+ ),
+ (
+ "dnf",
+ [
+ "dunst-1.7.1-1.fc35.x86_64",
+ "dunst-1.7.0-1.fc35.x86_64",
+ "java-11-openjdk-headless-1:11.0.13.0.8-2.fc35.x86_64",
+ ],
+ {
+ "dunst-1.7.1-1.fc35.x86_64",
+ "dunst-1.7.0-1.fc35.x86_64",
+ "java-11-openjdk-headless-1:11.0.13.0.8-2.fc35.x86_64",
+ },
+ "test/reposdir",
),
(
"dnf",
@@ -1511,18 +1531,33 @@ def test_compare_package_versions(version1, version2, expected):
"dunst-1.7.1-1.fc35.x86_64",
"java-11-openjdk-headless-1:11.0.13.0.8-2.fc35.x86_64",
},
+ "test/reposdir",
),
),
)
-def test_get_total_packages_to_update(package_manager_type, packages, expected, monkeypatch):
+@centos8
+def test_get_total_packages_to_update(
+ package_manager_type,
+ packages,
+ expected,
+ reposdir,
+ pretend_os,
+ monkeypatch,
+):
monkeypatch.setattr(pkgmanager, "TYPE", package_manager_type)
- monkeypatch.setattr(
- pkghandler,
- "_get_packages_to_update_%s" % package_manager_type,
- value=lambda: packages,
- )
-
- assert get_total_packages_to_update() == expected
+ if package_manager_type == "dnf":
+ monkeypatch.setattr(
+ pkghandler,
+ "_get_packages_to_update_%s" % package_manager_type,
+ value=lambda reposdir: packages,
+ )
+ else:
+ monkeypatch.setattr(
+ pkghandler,
+ "_get_packages_to_update_%s" % package_manager_type,
+ value=lambda: packages,
+ )
+ assert get_total_packages_to_update(reposdir=reposdir) == expected
@pytest.mark.skipif(
@@ -1531,7 +1566,6 @@ def test_get_total_packages_to_update(package_manager_type, packages, expected,
)
@pytest.mark.parametrize(("packages"), ((["package-1", "package-2", "package-3"],)))
def test_get_packages_to_update_yum(packages, monkeypatch):
-
PkgName = namedtuple("PkgNames", ["name"])
PkgUpdates = namedtuple("PkgUpdates", ["updates"])
transaction_pkgs = []
@@ -1549,9 +1583,21 @@ def test_get_packages_to_update_yum(packages, monkeypatch):
pkgmanager.TYPE != "dnf",
reason="No dnf module detected on the system, skipping it.",
)
-@pytest.mark.parametrize(("packages"), ((["package-1", "package-2", "package-3"],)))
+@pytest.mark.parametrize(
+ ("packages", "reposdir"),
+ (
+ (
+ ["package-1", "package-2", "package-i3"],
+ None,
+ ),
+ (
+ ["package-1"],
+ "test/reposdir",
+ ),
+ ),
+)
@all_systems
-def test_get_packages_to_update_dnf(packages, pretend_os, monkeypatch):
+def test_get_packages_to_update_dnf(packages, reposdir, pretend_os, monkeypatch):
dummy_mock = mock.Mock()
PkgName = namedtuple("PkgNames", ["name"])
transaction_pkgs = [PkgName(package) for package in packages]
@@ -1562,7 +1608,7 @@ def test_get_packages_to_update_dnf(packages, pretend_os, monkeypatch):
monkeypatch.setattr(pkgmanager.Base, "resolve", value=dummy_mock)
monkeypatch.setattr(pkgmanager.Base, "transaction", value=transaction_pkgs)
- assert _get_packages_to_update_dnf() == packages
+ assert _get_packages_to_update_dnf(reposdir=reposdir) == packages
YUM_PROTECTED_ERROR = """Error: Trying to remove "systemd", which is protected
diff --git a/convert2rhel/unit_tests/repo_test.py b/convert2rhel/unit_tests/repo_test.py
index c6189888d7..6a5dcb0780 100644
--- a/convert2rhel/unit_tests/repo_test.py
+++ b/convert2rhel/unit_tests/repo_test.py
@@ -15,14 +15,59 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-from convert2rhel import unit_tests # Imports unit_tests/__init__.py
+import os
+
+import pytest
+
from convert2rhel import repo
from convert2rhel.systeminfo import system_info
+from convert2rhel.unit_tests.conftest import centos8
+
+@pytest.mark.parametrize(
+ ("is_eus_release", "expected"),
+ (
+ (
+ True,
+ [
+ "rhel-8-for-x86_64-baseos-eus-rpms",
+ "rhel-8-for-x86_64-appstream-eus-rpms",
+ ],
+ ),
+ (
+ False,
+ [
+ "rhel-8-for-x86_64-baseos-rpms",
+ "rhel-8-for-x86_64-appstream-rpms",
+ ],
+ ),
+ ),
+)
+@centos8
+def test_get_rhel_repoids(pretend_os, is_eus_release, expected, monkeypatch):
+ monkeypatch.setattr(repo.system_info, "corresponds_to_rhel_eus_release", value=lambda: is_eus_release)
+ repos = repo.get_rhel_repoids()
+ assert repos == expected
-class TestRepo(unit_tests.ExtendedTestCase):
- @unit_tests.mock(system_info, "default_rhsm_repoids", ["rhel_server"])
- def test_get_rhel_repoids(self):
- repos = repo.get_rhel_repoids()
- self.assertEqual(repos, ["rhel_server"])
+@pytest.mark.parametrize(
+ ("path_exists", "expected"),
+ (
+ (
+ True,
+ "/usr/share/convert2rhel/repos/centos-8.4",
+ ),
+ (
+ False,
+ None,
+ ),
+ (
+ False,
+ None,
+ ),
+ ),
+)
+@centos8
+def test_get_hardcoded_repofiles_dir(pretend_os, path_exists, expected, monkeypatch):
+ monkeypatch.setattr(os.path, "exists", value=lambda _: path_exists)
+ assert repo.get_hardcoded_repofiles_dir() == expected
diff --git a/convert2rhel/unit_tests/subscription_test.py b/convert2rhel/unit_tests/subscription_test.py
index 6073983a7e..79303c85cc 100644
--- a/convert2rhel/unit_tests/subscription_test.py
+++ b/convert2rhel/unit_tests/subscription_test.py
@@ -25,11 +25,10 @@
import pexpect
import pytest
-from convert2rhel import unit_tests # Imports unit_tests/__init__.py
-from convert2rhel import pkghandler, subscription, toolopts, utils
+from convert2rhel import backup, pkghandler, subscription, toolopts, unit_tests, utils
from convert2rhel.systeminfo import system_info
-from convert2rhel.toolopts import tool_opts
from convert2rhel.unit_tests import GetLoggerMocked, run_subprocess_side_effect
+from convert2rhel.unit_tests.conftest import centos7, centos8
if sys.version_info[:2] <= (2, 7):
@@ -256,10 +255,11 @@ def test_replace_subscription_manager_rpms_not_available(self):
@unit_tests.mock(pkghandler, "get_installed_pkg_objects", lambda _: [namedtuple("Pkg", ["name"])("submgr")])
@unit_tests.mock(pkghandler, "print_pkg_info", lambda x: None)
@unit_tests.mock(utils, "ask_to_continue", PromptUserMocked())
- @unit_tests.mock(utils, "remove_pkgs", DumbCallable())
+ @unit_tests.mock(backup, "remove_pkgs", DumbCallable())
def test_remove_original_subscription_manager(self):
subscription.remove_original_subscription_manager()
- self.assertEqual(utils.remove_pkgs.called, 1)
+
+ self.assertEqual(backup.remove_pkgs.called, 1)
@unit_tests.mock(
pkghandler,
@@ -270,10 +270,10 @@ def test_remove_original_subscription_manager(self):
@unit_tests.mock(system_info, "id", "centos")
@unit_tests.mock(pkghandler, "print_pkg_info", lambda x: None)
@unit_tests.mock(utils, "ask_to_continue", PromptUserMocked())
- @unit_tests.mock(utils, "remove_pkgs", DumbCallable())
+ @unit_tests.mock(backup, "remove_pkgs", DumbCallable())
def test_remove_original_subscription_manager_missing_package_ol_85(self):
subscription.remove_original_subscription_manager()
- self.assertEqual(utils.remove_pkgs.called, 2)
+ self.assertEqual(backup.remove_pkgs.called, 2)
@unit_tests.mock(pkghandler, "get_installed_pkg_objects", lambda _: [])
@unit_tests.mock(subscription, "loggerinst", GetLoggerMocked())
@@ -295,7 +295,7 @@ def test_remove_original_subscription_manager_no_pkgs(self):
)
@unit_tests.mock(pkghandler, "filter_installed_pkgs", DumbCallable())
@unit_tests.mock(pkghandler, "get_pkg_names_from_rpm_paths", DumbCallable())
- @unit_tests.mock(utils.changed_pkgs_control, "track_installed_pkgs", DumbCallable())
+ @unit_tests.mock(backup.changed_pkgs_control, "track_installed_pkgs", DumbCallable())
@unit_tests.mock(subscription, "track_installed_submgr_pkgs", DumbCallable())
def test_install_rhel_subscription_manager(self):
subscription.install_rhel_subscription_manager()
@@ -1056,7 +1056,7 @@ def test_verify_rhsm_installed(submgr_installed, keep_rhsm, critical_string, mon
)
def test_track_installed_submgr_pkgs(installed_pkgs, not_tracked_pkgs, skip_pkg_msg, expected, monkeypatch, caplog):
track_installed_pkgs_mock = mock.Mock()
- monkeypatch.setattr(utils.changed_pkgs_control, "track_installed_pkgs", track_installed_pkgs_mock)
+ monkeypatch.setattr(backup.changed_pkgs_control, "track_installed_pkgs", track_installed_pkgs_mock)
subscription.track_installed_submgr_pkgs(installed_pkgs, not_tracked_pkgs)
@@ -1064,3 +1064,214 @@ def test_track_installed_submgr_pkgs(installed_pkgs, not_tracked_pkgs, skip_pkg_
assert skip_pkg_msg in caplog.records[-2].message
assert expected in caplog.records[-1].message
assert track_installed_pkgs_mock.called == 1
+
+
+# ----
+
+
+@pytest.mark.parametrize(
+ ("rhel_repoids", "subprocess", "should_raise", "expected", "expected_message"),
+ (
+ (
+ ["repo-1", "repo-2"],
+ ("repo-1, repo-2", 0),
+ False,
+ ["repo-1", "repo-2"],
+ "Repositories enabled through subscription-manager",
+ ),
+ (
+ ["repo-1", "repo-2"],
+ ("repo-1, repo-2", 1),
+ True,
+ ["repo-1", "repo-2"],
+ "Repos were not possible to enable through subscription-manager:\nrepo-1, repo-2",
+ ),
+ (
+ ["rhel-8-for-x86_64-baseos-eus-rpms", "rhel-8-for-x86_64-appstream-eus-rpms"],
+ ("repo-1, repo-2", 0),
+ False,
+ ["rhel-8-for-x86_64-baseos-eus-rpms", "rhel-8-for-x86_64-appstream-eus-rpms"],
+ "Repositories enabled through subscription-manager",
+ ),
+ ),
+)
+@centos8
+def test_enable_repos_rhel_repoids(
+ pretend_os, rhel_repoids, subprocess, should_raise, expected, expected_message, monkeypatch, caplog
+):
+ cmd_mock = ["subscription-manager", "repos"]
+ for repo in rhel_repoids:
+ cmd_mock.append("--enable=%s" % repo)
+
+ run_subprocess_mock = mock.Mock(
+ side_effect=unit_tests.run_subprocess_side_effect(
+ (cmd_mock, subprocess),
+ )
+ )
+ monkeypatch.setattr(
+ utils,
+ "run_subprocess",
+ value=run_subprocess_mock,
+ )
+
+ if should_raise:
+ with pytest.raises(SystemExit):
+ subscription.enable_repos(rhel_repoids=rhel_repoids)
+ else:
+ subscription.enable_repos(rhel_repoids=rhel_repoids)
+ assert system_info.submgr_enabled_repos == expected
+
+ assert expected_message in caplog.records[-1].message
+ assert run_subprocess_mock.call_count == 1
+
+
+@pytest.mark.parametrize(
+ ("rhel_repoids", "default_rhsm_repoids", "subprocess", "subprocess2", "should_raise", "expected"),
+ (
+ (
+ ["rhel-8-for-x86_64-baseos-eus-rpms", "rhel-8-for-x86_64-appstream-eus-rpms"],
+ ["test-repo-1", "test-repo-2"],
+ ("rhel-8-for-x86_64-baseos-eus-rpms, rhel-8-for-x86_64-appstream-eus-rpms", 1),
+ ("test-repo-1, test-repo-2", 1),
+ True,
+ "Repos were not possible to enable through subscription-manager:\ntest-repo-1, test-repo-2",
+ ),
+ (
+ ["rhel-8-for-x86_64-baseos-eus-rpms", "rhel-8-for-x86_64-appstream-eus-rpms"],
+ ["test-repo-1", "test-repo-2"],
+ ("rhel-8-for-x86_64-baseos-eus-rpms, rhel-8-for-x86_64-appstream-eus-rpms", 1),
+ ("test-repo-1, test-repo-2", 0),
+ False,
+ "Repositories enabled through subscription-manager",
+ ),
+ ),
+)
+@centos8
+def test_enable_repos_rhel_repoids_fallback_default_rhsm(
+ pretend_os,
+ rhel_repoids,
+ default_rhsm_repoids,
+ subprocess,
+ subprocess2,
+ should_raise,
+ expected,
+ monkeypatch,
+ caplog,
+):
+ cmd_mock = ["subscription-manager", "repos"]
+ for repo in rhel_repoids:
+ cmd_mock.append("--enable=%s" % repo)
+
+ run_subprocess_mock = mock.Mock(side_effect=[subprocess, subprocess2])
+ monkeypatch.setattr(
+ utils,
+ "run_subprocess",
+ value=run_subprocess_mock,
+ )
+ monkeypatch.setattr(system_info, "default_rhsm_repoids", value=default_rhsm_repoids)
+
+ if should_raise:
+ with pytest.raises(SystemExit):
+ subscription.enable_repos(rhel_repoids=rhel_repoids)
+ else:
+ subscription.enable_repos(rhel_repoids=rhel_repoids)
+ assert system_info.submgr_enabled_repos == default_rhsm_repoids
+
+ assert expected in caplog.records[-1].message
+ assert run_subprocess_mock.call_count == 2
+
+
+@pytest.mark.parametrize(
+ ("toolopts_enablerepo", "subprocess", "should_raise", "expected", "expected_message"),
+ (
+ (
+ ["repo-1", "repo-2"],
+ ("repo-1, repo-2", 0),
+ False,
+ ["repo-1", "repo-2"],
+ "Repositories enabled through subscription-manager",
+ ),
+ (
+ ["repo-1", "repo-2"],
+ ("repo-1, repo-2", 1),
+ True,
+ ["repo-1", "repo-2"],
+ "Repos were not possible to enable through subscription-manager:\nrepo-1, repo-2",
+ ),
+ (
+ ["rhel-8-for-x86_64-baseos-eus-rpms", "rhel-8-for-x86_64-appstream-eus-rpms"],
+ ("repo-1, repo-2", 0),
+ False,
+ ["rhel-8-for-x86_64-baseos-eus-rpms", "rhel-8-for-x86_64-appstream-eus-rpms"],
+ "Repositories enabled through subscription-manager",
+ ),
+ ),
+)
+def test_enable_repos_toolopts_enablerepo(
+ toolopts_enablerepo,
+ subprocess,
+ should_raise,
+ expected,
+ expected_message,
+ tool_opts,
+ monkeypatch,
+ caplog,
+):
+ cmd_mock = ["subscription-manager", "repos"]
+ for repo in toolopts_enablerepo:
+ cmd_mock.append("--enable=%s" % repo)
+
+ run_subprocess_mock = mock.Mock(
+ side_effect=unit_tests.run_subprocess_side_effect(
+ (cmd_mock, subprocess),
+ )
+ )
+ monkeypatch.setattr(
+ utils,
+ "run_subprocess",
+ value=run_subprocess_mock,
+ )
+ tool_opts.enablerepo = toolopts_enablerepo
+ # monkeypatch.setattr(tool_opts, "enablerepo", toolopts_enablerepo)
+
+ if should_raise:
+ with pytest.raises(SystemExit):
+ subscription.enable_repos(rhel_repoids=None)
+ else:
+ subscription.enable_repos(rhel_repoids=None)
+ assert system_info.submgr_enabled_repos == expected
+
+ assert expected_message in caplog.records[-1].message
+ assert run_subprocess_mock.call_count == 1
+
+
+@pytest.mark.parametrize(
+ ("subprocess", "expected"),
+ (
+ (("output", 0), "RHEL repositories locked"),
+ (("output", 1), "Locking RHEL repositories failed"),
+ ),
+)
+@centos8
+def test_lock_releasever_in_rhel_repositories(pretend_os, subprocess, expected, monkeypatch, caplog):
+ cmd = ["subscription-manager", "release", "--set=%s" % system_info.releasever]
+ run_subprocess_mock = mock.Mock(
+ side_effect=unit_tests.run_subprocess_side_effect(
+ (cmd, subprocess),
+ )
+ )
+ monkeypatch.setattr(
+ utils,
+ "run_subprocess",
+ value=run_subprocess_mock,
+ )
+ subscription.lock_releasever_in_rhel_repositories()
+
+ assert expected in caplog.records[-1].message
+ assert run_subprocess_mock.call_count == 1
+
+
+@centos7
+def test_lock_releasever_in_rhel_repositories_not_eus(pretend_os, caplog):
+ subscription.lock_releasever_in_rhel_repositories()
+ assert "Skipping locking RHEL repositories to a specific EUS minor version." in caplog.records[-1].message
diff --git a/convert2rhel/unit_tests/systeminfo_test.py b/convert2rhel/unit_tests/systeminfo_test.py
index 0d27e7d344..1159a61e7b 100644
--- a/convert2rhel/unit_tests/systeminfo_test.py
+++ b/convert2rhel/unit_tests/systeminfo_test.py
@@ -19,6 +19,7 @@
import logging
import os
import shutil
+import socket
import sys
import unittest
@@ -162,10 +163,9 @@ def test_modified_rpm_files_diff_with_differences_after_conversion(self):
@unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked(("rpmva\n", 0)))
def test_generate_rpm_va(self):
# TODO: move class from unittest to pytest and use global tool_opts fixture
- tool_opts.no_rpm_va = False
# Check that rpm -Va is executed (default) and stored into the specific file.
+ tool_opts.no_rpm_va = False
system_info.generate_rpm_va()
-
self.assertTrue(utils.run_subprocess.called > 0)
self.assertEqual(utils.run_subprocess.used_args[0][0], ["rpm", "-Va"])
self.assertTrue(os.path.isfile(self.rpmva_output_file))
@@ -225,24 +225,28 @@ def test_get_release_ver(pretend_os):
"releasever_val",
"self_name",
"self_version",
+ "has_internet",
"exception",
),
(
# good cases
# if releasever set in config - it takes precedence
- ("not_existing_release_ver_set_in_config", None, None, None),
+ ("not_existing_release_ver_set_in_config", None, None, True, None),
# Good cases which matches supported pathes
- ("", "CentOS Linux", systeminfo.Version(8, 4), None),
- ("", "Oracle Linux Server", systeminfo.Version(8, 4), None),
+ ("", "CentOS Linux", systeminfo.Version(8, 4), True, None),
+ ("", "Oracle Linux Server", systeminfo.Version(8, 4), True, None),
# bad cases
- ("", "NextCool Linux", systeminfo.Version(8, 4), SystemExit),
- ("", "CentOS Linux", systeminfo.Version(8, 10000), SystemExit),
+ ("", "NextCool Linux", systeminfo.Version(8, 4), False, SystemExit),
+ ("", "CentOS Linux", systeminfo.Version(8, 10000), False, SystemExit),
),
)
# need to pretend centos8 in order to system info were resolved at module init
@centos8
-def test_get_release_ver_other(pretend_os, monkeypatch, releasever_val, self_name, self_version, exception):
+def test_get_release_ver_other(
+ pretend_os, monkeypatch, releasever_val, self_name, self_version, has_internet, exception
+):
monkeypatch.setattr(systeminfo.SystemInfo, "_get_cfg_opt", mock.Mock(return_value=releasever_val))
+ monkeypatch.setattr(systeminfo.SystemInfo, "_check_internet_access", mock.Mock(return_value=has_internet))
if self_name:
monkeypatch.setattr(systeminfo.SystemInfo, "_get_system_name", mock.Mock(return_value=self_name))
if self_version:
@@ -255,3 +259,38 @@ def test_get_release_ver_other(pretend_os, monkeypatch, releasever_val, self_nam
system_info.resolve_system_info()
if releasever_val:
assert system_info.releasever == releasever_val
+ if has_internet:
+ assert system_info.has_internet_access == has_internet
+
+
+@pytest.mark.parametrize(
+ ("side_effect", "expected"),
+ (
+ (None, True),
+ (socket.error, False),
+ ),
+)
+def test_check_internet_access(side_effect, expected, monkeypatch):
+ monkeypatch.setattr(systeminfo.socket.socket, "connect", mock.Mock(side_effect=side_effect))
+ # Have to initialize the logger since we are not constructing the
+ # system_info object properly i.e: we are not calling `resolve_system_info()`
+ system_info.logger = logging.getLogger(__name__)
+
+ assert system_info._check_internet_access() == expected
+
+
+@pytest.mark.parametrize(
+ ("releasever", "expected"),
+ (
+ ("7.9", False),
+ ("8.4", True),
+ ("8.5", False),
+ ("8.6", False),
+ ("8.7", False),
+ ("8.8", False),
+ ("8.9", False),
+ ),
+)
+def test_corresponds_to_rhel_eus_release(releasever, expected):
+ system_info.releasever = releasever
+ assert system_info.corresponds_to_rhel_eus_release() == expected
diff --git a/convert2rhel/unit_tests/utils_test.py b/convert2rhel/unit_tests/utils_test.py
index ab2b7fa8ed..f4152a962e 100644
--- a/convert2rhel/unit_tests/utils_test.py
+++ b/convert2rhel/unit_tests/utils_test.py
@@ -34,8 +34,7 @@
from collections import namedtuple
-from convert2rhel import unit_tests # Imports unit_tests/__init__.py
-from convert2rhel import utils
+from convert2rhel import unit_tests, utils # Imports unit_tests/__init__.py
from convert2rhel.systeminfo import system_info
from convert2rhel.unit_tests import is_rpm_based_os
@@ -83,78 +82,6 @@ def test_require_root_is_not_root(self):
def test_require_root_is_root(self):
self.assertEqual(utils.require_root(), None)
- def test_track_installed_pkg(self):
- control = utils.ChangedRPMPackagesController()
- pkgs = ["pkg1", "pkg2", "pkg3"]
- for pkg in pkgs:
- control.track_installed_pkg(pkg)
- self.assertEqual(control.installed_pkgs, pkgs)
-
- @unit_tests.mock(utils.RestorablePackage, "backup", DummyFuncMocked())
- def test_backup_and_track_removed_pkg(self):
- control = utils.ChangedRPMPackagesController()
- pkgs = ["pkg1", "pkg2", "pkg3"]
- for pkg in pkgs:
- control.backup_and_track_removed_pkg(pkg)
- self.assertEqual(utils.RestorablePackage.backup.called, len(pkgs))
- self.assertEqual(len(control.removed_pkgs), len(pkgs))
-
- @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
- def test_remove_pkgs_with_empty_list(self):
- utils.remove_pkgs([])
- self.assertEqual(utils.run_subprocess.called, 0)
-
- @unit_tests.mock(utils.ChangedRPMPackagesController, "backup_and_track_removed_pkg", DummyFuncMocked())
- @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
- def test_remove_pkgs_without_backup(self):
- pkgs = ["pkg1", "pkg2", "pkg3"]
- utils.remove_pkgs(pkgs, False)
- self.assertEqual(utils.ChangedRPMPackagesController.backup_and_track_removed_pkg.called, 0)
-
- self.assertEqual(utils.run_subprocess.called, len(pkgs))
-
- rpm_remove_cmd = ["rpm", "-e", "--nodeps"]
- for cmd, pkg in zip(utils.run_subprocess.cmds, pkgs):
- self.assertEqual(rpm_remove_cmd + [pkg], cmd)
-
- @unit_tests.mock(utils.ChangedRPMPackagesController, "backup_and_track_removed_pkg", DummyFuncMocked())
- @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
- def test_remove_pkgs_with_backup(self):
- pkgs = ["pkg1", "pkg2", "pkg3"]
- utils.remove_pkgs(pkgs)
- self.assertEqual(utils.ChangedRPMPackagesController.backup_and_track_removed_pkg.called, len(pkgs))
-
- self.assertEqual(utils.run_subprocess.called, len(pkgs))
-
- rpm_remove_cmd = ["rpm", "-e", "--nodeps"]
- for cmd, pkg in zip(utils.run_subprocess.cmds, pkgs):
- self.assertEqual(rpm_remove_cmd + [pkg], cmd)
-
- @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
- def test_install_local_rpms_with_empty_list(self):
- utils.install_local_rpms([])
- self.assertEqual(utils.run_subprocess.called, 0)
-
- @unit_tests.mock(utils.ChangedRPMPackagesController, "track_installed_pkg", DummyFuncMocked())
- @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
- def test_install_local_rpms_without_replace(self):
- pkgs = ["pkg1", "pkg2", "pkg3"]
- utils.install_local_rpms(pkgs)
- self.assertEqual(utils.ChangedRPMPackagesController.track_installed_pkg.called, len(pkgs))
-
- self.assertEqual(utils.run_subprocess.called, 1)
- self.assertEqual(["rpm", "-i", "pkg1", "pkg2", "pkg3"], utils.run_subprocess.cmd)
-
- @unit_tests.mock(utils.ChangedRPMPackagesController, "track_installed_pkg", DummyFuncMocked())
- @unit_tests.mock(utils, "run_subprocess", RunSubprocessMocked())
- def test_install_local_rpms_with_replace(self):
- pkgs = ["pkg1", "pkg2", "pkg3"]
- utils.install_local_rpms(pkgs, replace=True)
- self.assertEqual(utils.ChangedRPMPackagesController.track_installed_pkg.called, len(pkgs))
-
- self.assertEqual(utils.run_subprocess.called, 1)
- self.assertEqual(["rpm", "-i", "--replacepkgs", "pkg1", "pkg2", "pkg3"], utils.run_subprocess.cmd)
-
def test_run_subprocess(self):
output, code = utils.run_subprocess(["echo", "foobar"])
@@ -179,17 +106,30 @@ def test_run_subprocess(self):
]
@unit_tests.mock(
- utils, "download_pkg", lambda pkg, dest, reposdir, enable_repos, disable_repos, set_releasever: "/filepath/"
+ utils,
+ "download_pkg",
+ lambda pkg, dest, reposdir, enable_repos, disable_repos, set_releasever: "/filepath/",
)
def test_download_pkgs(self):
- paths = utils.download_pkgs(["pkg1", "pkg2"], "/dest/", "/reposdir/", ["repo1"], ["repo2"], False)
+ paths = utils.download_pkgs(
+ ["pkg1", "pkg2"],
+ "/dest/",
+ "/reposdir/",
+ ["repo1"],
+ ["repo2"],
+ False,
+ )
self.assertEqual(paths, ["/filepath/", "/filepath/"])
@unit_tests.mock(system_info, "version", namedtuple("Version", ["major", "minor"])(8, 0))
@unit_tests.mock(system_info, "releasever", "8")
@unit_tests.mock(utils, "run_cmd_in_pty", RunSubprocessMocked(ret_code=0))
- @unit_tests.mock(utils, "get_rpm_path_from_yumdownloader_output", lambda x, y, z: "/path/test.rpm")
+ @unit_tests.mock(
+ utils,
+ "get_rpm_path_from_yumdownloader_output",
+ lambda x, y, z: "/path/test.rpm",
+ )
def test_download_pkg_success_with_all_params(self):
dest = "/test dir/"
reposdir = "/my repofiles/"
@@ -416,11 +356,36 @@ def test_prompt_user(question, is_password, response, monkeypatch):
("5.14.15-300.fc35", ("0", "5.14.15", "300.fc35")),
("0.17-9.fc35", ("0", "0.17", "9.fc35")),
("2.34.1-2.fc35", ("0", "2.34.1", "2.fc35")),
- ("0.9.1-2.20210420git36391559.fc35", ("0", "0.9.1", "2.20210420git36391559.fc35")),
+ (
+ "0.9.1-2.20210420git36391559.fc35",
+ ("0", "0.9.1", "2.20210420git36391559.fc35"),
+ ),
("2:8.2.3568-1.fc35", ("2", "8.2.3568", "1.fc35")),
- ("4.6~pre16262021g84ef6bd9-3.fc35", ("0", "4.6~pre16262021g84ef6bd9", "3.fc35")),
+ (
+ "4.6~pre16262021g84ef6bd9-3.fc35",
+ ("0", "4.6~pre16262021g84ef6bd9", "3.fc35"),
+ ),
),
)
def test_string_to_version(string_version, nevra):
nevra_version = utils.string_to_version(string_version)
assert nevra_version == nevra
+
+
+@pytest.mark.parametrize(
+ ("path_exists", "list_dir", "expected"),
+ (
+ (True, ["dir-1", "dir-2"], 0),
+ (True, [], 2),
+ (False, [], 0),
+ (False, ["dir-1", "dir-2"], 0),
+ ),
+)
+def test_remove_orphan_folders(path_exists, list_dir, expected, tmpdir, monkeypatch):
+ os_remove_mock = mock.Mock()
+ monkeypatch.setattr(os.path, "exists", value=lambda path: path_exists)
+ monkeypatch.setattr(os, "listdir", value=lambda path: list_dir)
+ monkeypatch.setattr(os, "rmdir", value=os_remove_mock)
+
+ utils.remove_orphan_folders()
+ assert os_remove_mock.call_count == expected
diff --git a/convert2rhel/utils.py b/convert2rhel/utils.py
index fe0ee16720..5743767f1b 100644
--- a/convert2rhel/utils.py
+++ b/convert2rhel/utils.py
@@ -57,6 +57,7 @@ class Color(object):
def get_executable_name():
"""Get name of the executable file passed to the python interpreter."""
+
return os.path.basename(inspect.stack()[-1][1])
@@ -344,127 +345,6 @@ def __getitem__(self, item):
return super(DictWListValues, self).__getitem__(item)
-class ChangedRPMPackagesController(object):
- """Keep control of installed/removed RPM pkgs for backup/restore."""
-
- def __init__(self):
- self.installed_pkgs = []
- self.removed_pkgs = []
-
- def track_installed_pkg(self, pkg):
- """Add a installed RPM pkg to the list of installed pkgs."""
- self.installed_pkgs.append(pkg)
-
- def track_installed_pkgs(self, pkgs):
- """Track packages installed before the PONR to be able to remove them later (roll them back) if needed."""
- self.installed_pkgs += pkgs
-
- def backup_and_track_removed_pkg(self, pkg):
- """Add a removed RPM pkg to the list of removed pkgs."""
- restorable_pkg = RestorablePackage(pkg)
- restorable_pkg.backup()
- self.removed_pkgs.append(restorable_pkg)
-
- def _remove_installed_pkgs(self):
- """For each package installed during conversion remove it."""
- loggerinst.task("Rollback: Removing installed packages")
- remove_pkgs(self.installed_pkgs, backup=False, critical=False)
-
- def _install_removed_pkgs(self):
- """For each package removed during conversion install it."""
- loggerinst.task("Rollback: Installing removed packages")
- pkgs_to_install = []
- for restorable_pkg in self.removed_pkgs:
- if restorable_pkg.path is None:
- loggerinst.warning("Couldn't find a backup for %s package." % restorable_pkg.name)
- continue
- pkgs_to_install.append(restorable_pkg.path)
-
- install_local_rpms(pkgs_to_install, replace=True, critical=False)
-
- def restore_pkgs(self):
- """Restore system to the original state."""
- self._remove_installed_pkgs()
- remove_orphan_folders()
- self._install_removed_pkgs()
-
-
-def remove_orphan_folders():
- """Even after removing redhat-release-* package, some of its folders are
- still present, are empty, and that blocks us from installing centos-release
- pkg back. So, by now, we are removing them manually.
- """
- rh_release_paths = [
- "/usr/share/redhat-release",
- "/usr/share/doc/redhat-release",
- ]
-
- def is_dir_empty(path):
- return not os.listdir(path)
-
- for path in rh_release_paths:
- if os.path.exists(path) and is_dir_empty(path):
- os.rmdir(path)
-
-
-def remove_pkgs(pkgs_to_remove, backup=True, critical=True):
- """Remove packages not heeding to their dependencies."""
-
- if backup:
- # Some packages, when removed, will also remove repo files, making it
- # impossible to access the repositories to download a backup. For this
- # reason we first backup all packages and only after that we remove
- for nvra in pkgs_to_remove:
- changed_pkgs_control.backup_and_track_removed_pkg(nvra)
-
- if not pkgs_to_remove:
- loggerinst.info("No package to remove")
- return
-
- for nvra in pkgs_to_remove:
- loggerinst.info("Removing package: %s" % nvra)
- _, ret_code = run_subprocess(["rpm", "-e", "--nodeps", nvra])
- if ret_code != 0:
- if critical:
- loggerinst.critical("Error: Couldn't remove %s." % nvra)
- else:
- loggerinst.warning("Couldn't remove %s." % nvra)
-
-
-def install_local_rpms(pkgs_to_install, replace=False, critical=True):
- """Install packages locally available."""
-
- if not pkgs_to_install:
- loggerinst.info("No package to install")
- return False
-
- cmd_param = ["rpm", "-i"]
- if replace:
- cmd_param.append("--replacepkgs")
-
- loggerinst.info("Installing packages:")
- for pkg in pkgs_to_install:
- loggerinst.info("\t%s" % pkg)
-
- cmd = cmd_param + pkgs_to_install
- output, ret_code = run_subprocess(cmd, print_output=False)
- if ret_code != 0:
- pkgs_as_str = " ".join(pkgs_to_install)
- loggerinst.debug(output.strip())
- if critical:
- loggerinst.critical("Error: Couldn't install %s packages." % pkgs_as_str)
- return False
-
- loggerinst.warning("Couldn't install %s packages." % pkgs_as_str)
- return False
-
- for path in pkgs_to_install:
- nvra, _ = os.path.splitext(os.path.basename(path))
- changed_pkgs_control.track_installed_pkg(nvra)
-
- return True
-
-
def download_pkgs(
pkgs,
dest=TMP_DIR,
@@ -579,58 +459,6 @@ def get_rpm_path_from_yumdownloader_output(cmd, output, dest):
return path
-class RestorableFile(object):
- def __init__(self, filepath):
- self.filepath = filepath
-
- def backup(self):
- """Save current version of a file"""
- loggerinst.info("Backing up %s." % self.filepath)
- if os.path.isfile(self.filepath):
- try:
- loggerinst.debug("Copying %s to %s." % (self.filepath, BACKUP_DIR))
- shutil.copy2(self.filepath, BACKUP_DIR)
- except (OSError, IOError) as err:
- # IOError for py2 and OSError for py3
- loggerinst.critical("Error(%s): %s" % (err.errno, err.strerror))
- else:
- loggerinst.info("Can't find %s.", self.filepath)
-
- def restore(self):
- """Restore a previously backed up file"""
- backup_filepath = os.path.join(BACKUP_DIR, os.path.basename(self.filepath))
- loggerinst.task("Rollback: Restoring %s from backup" % self.filepath)
-
- if not os.path.isfile(backup_filepath):
- loggerinst.warning("%s hasn't been backed up" % self.filepath)
- return
- try:
- shutil.copy2(backup_filepath, self.filepath)
- except (OSError, IOError) as err:
- # Do not call 'critical' which would halt the program. We are in
- # a rollback phase now and we want to rollback as much as possible.
- # IOError for py2 and OSError for py3
- loggerinst.warning("Error(%s): %s" % (err.errno, err.strerror))
- return
- loggerinst.info("File %s restored" % self.filepath)
-
-
-class RestorablePackage(object):
- def __init__(self, pkgname):
- self.name = pkgname
- self.path = None
-
- def backup(self):
- """Save version of RPM package"""
- loggerinst.info("Backing up %s" % self.name)
- if os.path.isdir(BACKUP_DIR):
- # When backing up the packages, the original system repofiles are still available and for them we can't
- # use the releasever for RHEL repositories
- self.path = download_pkg(self.name, dest=BACKUP_DIR, set_releasever=False)
- else:
- loggerinst.warning("Can't access %s" % TMP_DIR)
-
-
def get_package_name_from_rpm(rpm_path):
"""Return name of a package that is represented by a locally stored rpm file."""
hdr = get_rpm_header(rpm_path)
@@ -678,4 +506,19 @@ def string_to_version(verstring):
return (epoch, version, release)
-changed_pkgs_control = ChangedRPMPackagesController() # pylint: disable=C0103
+def remove_orphan_folders():
+ """Even after removing redhat-release-* package, some of its folders are
+ still present, are empty, and that blocks us from installing centos-release
+ pkg back. So, for now, we are removing them manually.
+ """
+ rh_release_paths = [
+ "/usr/share/redhat-release",
+ "/usr/share/doc/redhat-release",
+ ]
+
+ def is_dir_empty(path):
+ return not os.listdir(path)
+
+ for path in rh_release_paths:
+ if os.path.exists(path) and is_dir_empty(path):
+ os.rmdir(path)
diff --git a/plans/main.fmf b/plans/main.fmf
index 5cec384757..7f649e6328 100644
--- a/plans/main.fmf
+++ b/plans/main.fmf
@@ -14,5 +14,13 @@ prepare:
copr: '@oamg/convert2rhel'
package: convert2rhel
missing: fail
+
+ # We need to remove all the repositories that were used to install c2r package.
+ # The updated packages check may find that installed c2r is not latest and it then
+ # ask for one more interactive prompt to continue. This could be incosistent in some tests
+ # that are doing the interactive run of c2r.
+ - name: remove all copr repositories
+ how: shell
+ script: grep -l "copr:copr.fedorainfracloud.org:group_oamg:convert2rhel" /etc/yum.repos.d/* | xargs rm
environment-file:
- https://gitlab.cee.redhat.com/oamg/convert2rhel/convert2rhel-secrets/-/raw/main/.env
diff --git a/plans/tier1.fmf b/plans/tier1.fmf
index e641b57e3e..38bfbae845 100644
--- a/plans/tier1.fmf
+++ b/plans/tier1.fmf
@@ -191,7 +191,7 @@ discover+:
- name: allow access to Satellite only
how: shell
script: pytest -svv tests/integration/tier1/convert-offline-systems/prepare_system.py
- - name: run offline conversion
+ - name: run offline conversion using the satellite
how: shell
script: pytest -svv tests/integration/tier1/convert-offline-systems/run_conversion.py
- name: reboot after conversion
@@ -199,6 +199,13 @@ discover+:
playbook: tests/ansible_collections/roles/reboot/main.yml
/system_up_to_date:
+ # On Oracle Linux 8.4 we do not have minor version repositories so we skip the check for up-to-date system.
+ # The other distributions (including latest Oracle Linux 8 ) have all the necessary repositories
+ # to make the check possible.
+ adjust:
+ enabled: false
+ when: >
+ distro == oraclelinux-8.4
discover+:
test: checks-after-conversion
prepare+:
@@ -238,3 +245,19 @@ discover+:
- name: reboot after conversion
how: ansible
playbook: tests/ansible_collections/roles/reboot/main.yml
+
+/satellite_non_eus_repos:
+ adjust:
+ enabled: false
+ when: >
+ distro != centos-8.4 and
+ distro != oraclelinux-8.4
+ discover+:
+ test: checks-after-conversion
+ prepare+:
+ - name: main conversion preparation
+ how: shell
+ script: pytest -svv tests/integration/tier1/satellite_non_eus_repos/satellite_non_eus_repos.py
+ - name: reboot after conversion
+ how: ansible
+ playbook: tests/ansible_collections/roles/reboot/main.yml
diff --git a/tests/ansible_collections/main.yml b/tests/ansible_collections/main.yml
index c344c64380..66d55b6b3b 100644
--- a/tests/ansible_collections/main.yml
+++ b/tests/ansible_collections/main.yml
@@ -2,6 +2,9 @@
- hosts: all
roles:
+ - role: hardcode-minor-version-repos
+ when: ansible_facts['distribution_version'] == "8.4" and ansible_facts['distribution'] == "CentOS"
+
- role: update-system
- role: oracle-linux-specific
diff --git a/tests/ansible_collections/roles/add-custom-repos/main.yml b/tests/ansible_collections/roles/add-custom-repos/main.yml
index ae3d502a01..8fbb5274ea 100644
--- a/tests/ansible_collections/roles/add-custom-repos/main.yml
+++ b/tests/ansible_collections/roles/add-custom-repos/main.yml
@@ -4,5 +4,9 @@
become: false
- include: rhel7-repos.yml
when: ansible_facts['distribution_major_version'] == "7"
+ # When Oracle Linux 8.7 is released, the "8.6" needs to change to "8.7" and the
+ # "8.6" is to be moved to the condition below related to enabling RHEL 8 EUS repos
- include: rhel8-repos.yml
- when: ansible_facts['distribution_major_version'] == "8"
+ when: ansible_facts['distribution_version'] == "8.5" or ansible_facts['distribution_version'] == "8.6"
+- include: rhel8-eus-repos.yml
+ when: ansible_facts['distribution_version'] == "8.4"
diff --git a/tests/ansible_collections/roles/add-custom-repos/rhel8-eus-repos.yml b/tests/ansible_collections/roles/add-custom-repos/rhel8-eus-repos.yml
new file mode 100644
index 0000000000..ae552d84cd
--- /dev/null
+++ b/tests/ansible_collections/roles/add-custom-repos/rhel8-eus-repos.yml
@@ -0,0 +1,19 @@
+- hosts: all
+ tasks:
+ - name: Add rhel8 baseos eus repo
+ yum_repository:
+ name: rhel-8-for-x86_64-baseos-eus-rpms
+ description: RHEL 8 BaseOS for $basearch
+ baseurl: http://rhsm-pulp.corp.redhat.com/content/eus/rhel8/$releasever/$basearch/baseos/os/
+ gpgcheck: no
+ enabled: no
+ file: rhel8-eus
+
+ - name: Add rhel8 appstream eus repo
+ yum_repository:
+ name: rhel-8-for-x86_64-appstream-eus-rpms
+ description: RHEL 8 AppStream for $basearch
+ baseurl: http://rhsm-pulp.corp.redhat.com/content/eus/rhel8/$releasever/$basearch/appstream/os/
+ gpgcheck: no
+ enabled: no
+ file: rhel8-eus
diff --git a/tests/ansible_collections/roles/hardcode-minor-version-repos/tasks/centos-repos.yml b/tests/ansible_collections/roles/hardcode-minor-version-repos/tasks/centos-repos.yml
new file mode 100644
index 0000000000..cc76b52533
--- /dev/null
+++ b/tests/ansible_collections/roles/hardcode-minor-version-repos/tasks/centos-repos.yml
@@ -0,0 +1,32 @@
+- name: Overwrite AppStream repository (CentOS 8.4)
+ yum_repository:
+ name: appstream
+ description: AppStream repo
+ baseurl: https://vault.centos.org/$contentdir/8.4.2105/AppStream/$basearch/os/
+ state: present
+ gpgcheck: yes
+ enabled: yes
+ gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+ file: CentOS-Linux-AppStream
+
+- name: Overwrite BaseOS repository (CentOS 8.4)
+ yum_repository:
+ name: baseos
+ description: BaseOS repo
+ baseurl: https://vault.centos.org/$contentdir/8.4.2105/BaseOS/$basearch/os/
+ state: present
+ gpgcheck: yes
+ enabled: yes
+ gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+ file: CentOS-Linux-BaseOS
+
+- name: Overwrite Extras repository (CentOS 8.4)
+ yum_repository:
+ name: extras
+ description: Extras repo
+ baseurl: https://vault.centos.org/$contentdir/8.4.2105/extras/$basearch/os/
+ state: present
+ gpgcheck: yes
+ enabled: yes
+ gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+ file: CentOS-Linux-Extras
diff --git a/tests/ansible_collections/roles/hardcode-minor-version-repos/tasks/main.yml b/tests/ansible_collections/roles/hardcode-minor-version-repos/tasks/main.yml
new file mode 100644
index 0000000000..79f63efc9b
--- /dev/null
+++ b/tests/ansible_collections/roles/hardcode-minor-version-repos/tasks/main.yml
@@ -0,0 +1,2 @@
+---
+- include: centos-repos.yml
diff --git a/tests/ansible_collections/roles/install-testing-deps/tasks/main.yml b/tests/ansible_collections/roles/install-testing-deps/tasks/main.yml
index 96e7fe6237..5a4d56c899 100644
--- a/tests/ansible_collections/roles/install-testing-deps/tasks/main.yml
+++ b/tests/ansible_collections/roles/install-testing-deps/tasks/main.yml
@@ -3,9 +3,9 @@
yum:
# gcc and python3-devel are needed for psutil
name:
- - "python3"
- - "gcc"
- - "python3-devel"
+ - python3
+ - gcc
+ - python3-devel
state: present
- name: Install pip if not present
diff --git a/tests/ansible_collections/roles/update-system/tasks/main.yml b/tests/ansible_collections/roles/update-system/tasks/main.yml
index b954679504..f99ae08386 100644
--- a/tests/ansible_collections/roles/update-system/tasks/main.yml
+++ b/tests/ansible_collections/roles/update-system/tasks/main.yml
@@ -1,2 +1,7 @@
---
+# We can't update Oracle Linux 8.4 to the latest 8.4 packages because there are no public Oracle Linux 8.4 repositories available.
+# The CentOS Linux 8.4 can be updated using this role because the repositories on the system image has been
+# tweaked to point to the CentOS Linux 8.4 repositories in the Vault.
- include: update-system.yml
+ when:
+ - not (ansible_facts['distribution_version'] == "8.4" and ansible_facts['distribution'] == "OracleLinux")
diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py
index c6f5d60397..690093f2a9 100644
--- a/tests/integration/conftest.py
+++ b/tests/integration/conftest.py
@@ -87,7 +87,7 @@ def convert2rhel(shell):
def factory(
options: str,
timeout: int = 60 * 60,
- unregister: bool = True,
+ unregister: bool = False,
) -> ContextManager[pexpect.spawn]:
c2r_runtime = pexpect.spawn(
f"convert2rhel {options}",
diff --git a/tests/integration/tier0/backup-release/test_backup_release.py b/tests/integration/tier0/backup-release/test_backup_release.py
index e1ee4d7c81..b7b3d2127c 100644
--- a/tests/integration/tier0/backup-release/test_backup_release.py
+++ b/tests/integration/tier0/backup-release/test_backup_release.py
@@ -4,6 +4,9 @@
from envparse import env
+system = platform.platform()
+
+
def test_backup_os_release_no_envar(shell, convert2rhel):
"""
In this scenario there is no variable `CONVERT2RHEL_UNSUPPORTED_INCOMPLETE_ROLLBACK` set.
@@ -22,7 +25,13 @@ def test_backup_os_release_no_envar(shell, convert2rhel):
assert shell("rpm -i {}".format(pkg_dst)).returncode == 0
# Move all repos to other location, so it is not being used
- assert shell("mkdir /tmp/s_backup && mv /etc/yum.repos.d/* /tmp/s_backup/").returncode == 0
+ assert shell("mkdir /tmp/s_backup").returncode == 0
+ assert shell("mv /etc/yum.repos.d/* /tmp/s_backup/").returncode == 0
+
+ # EUS version use hardoced repos from c2r as well
+ if "centos-8" in system or "oracle-8.4" in system:
+ assert shell("mkdir /tmp/s_backup_eus").returncode == 0
+ assert shell("mv /usr/share/convert2rhel/repos/* /tmp/s_backup_eus/").returncode == 0
# Since we are moving all repos away, we need to bypass kernel check
os.environ["CONVERT2RHEL_UNSUPPORTED_SKIP_KERNEL_CURRENCY_CHECK"] = "1"
@@ -54,27 +63,25 @@ def test_backup_os_release_with_envar(shell, convert2rhel):
os.environ["CONVERT2RHEL_UNSUPPORTED_INCOMPLETE_ROLLBACK"] = "1"
with convert2rhel(
- ("--no-rpm-va -k {} -o {} --debug --keep-rhsm").format(
+ ("-y --no-rpm-va -k {} -o {} --debug --keep-rhsm").format(
env.str("SATELLITE_KEY"),
env.str("SATELLITE_ORG"),
),
) as c2r:
- c2r.expect("Continue with the system conversion?")
- c2r.sendline("y")
- c2r.expect("Continue with the system conversion?")
- c2r.sendline("y")
- # On OracleLinux8 there is one question less than on other distros
- if "oracle-8" not in platform.platform():
- c2r.expect("Continue with the system conversion?")
- c2r.sendline("y")
- c2r.expect("The tool allows rollback of any action until this point.")
- c2r.sendline("n")
+ c2r.expect(
+ "'CONVERT2RHEL_UNSUPPORTED_INCOMPLETE_ROLLBACK' environment variable detected, continuing conversion."
+ )
+ c2r.send(chr(3))
+ c2r.sendcontrol("d")
assert shell("find /etc/os-release").returncode == 0
- # Restore repos
+ # Return repositories to their original location
assert shell("mv /tmp/s_backup/* /etc/yum.repos.d/").returncode == 0
+ if "centos-8" in system or "oracle-8.4" in system:
+ assert shell("mv /tmp/s_backup_eus/* /usr/share/convert2rhel/repos/").returncode == 0
+
# Clean up
del os.environ["CONVERT2RHEL_UNSUPPORTED_INCOMPLETE_ROLLBACK"]
del os.environ["CONVERT2RHEL_UNSUPPORTED_SKIP_KERNEL_CURRENCY_CHECK"]
diff --git a/tests/integration/tier0/check-custom-repo/test_custom_repos.py b/tests/integration/tier0/check-custom-repo/test_custom_repos.py
index 80718c6192..d50e76671b 100644
--- a/tests/integration/tier0/check-custom-repo/test_custom_repos.py
+++ b/tests/integration/tier0/check-custom-repo/test_custom_repos.py
@@ -34,7 +34,14 @@ def test_good_convertion_without_rhsm(shell, convert2rhel):
if system_version.major == 7:
enable_repo_opt = "--enablerepo rhel-7-server-rpms --enablerepo rhel-7-server-optional-rpms --enablerepo rhel-7-server-extras-rpms"
elif system_version.major == 8:
- enable_repo_opt = "--enablerepo rhel-8-for-x86_64-baseos-rpms --enablerepo rhel-8-for-x86_64-appstream-rpms"
+ if system_version.minor != 4:
+ enable_repo_opt = (
+ "--enablerepo rhel-8-for-x86_64-baseos-rpms --enablerepo rhel-8-for-x86_64-appstream-rpms"
+ )
+ elif system_version.minor == 4:
+ enable_repo_opt = (
+ "--enablerepo rhel-8-for-x86_64-baseos-eus-rpms --enablerepo rhel-8-for-x86_64-appstream-eus-rpms"
+ )
with convert2rhel("-y --no-rpm-va --disable-submgr {} --debug".format(enable_repo_opt)) as c2r:
c2r.expect("The repositories passed through the --enablerepo option are all accessible.")
diff --git a/tests/integration/tier0/check-user-response/test_user_response.py b/tests/integration/tier0/check-user-response/test_user_response.py
index 2075edcf97..c36494a657 100644
--- a/tests/integration/tier0/check-user-response/test_user_response.py
+++ b/tests/integration/tier0/check-user-response/test_user_response.py
@@ -4,11 +4,7 @@
def test_check_user_response_user_and_password(convert2rhel):
# Run c2r registration with no username and password provided
# check for user prompt enforcing input, then continue with registration
- with convert2rhel(
- "-y --no-rpm-va --serverurl {}".format(
- env.str("RHSM_SERVER_URL"),
- )
- ) as c2r:
+ with convert2rhel("-y --no-rpm-va --serverurl {}".format(env.str("RHSM_SERVER_URL")), unregister=True) as c2r:
c2r.expect_exact(" ... activation key not found, username and password required")
c2r.expect_exact("Username")
c2r.sendline()
@@ -39,7 +35,8 @@ def test_check_user_response_organization(convert2rhel):
"-y --no-rpm-va --serverurl {} -k {}".format(
env.str("RHSM_SERVER_URL"),
env.str("RHSM_KEY"),
- )
+ ),
+ unregister=True,
) as c2r:
c2r.expect_exact("activation key detected")
c2r.expect_exact("Organization: ")
@@ -60,7 +57,8 @@ def test_auto_attach_pool_submgr(convert2rhel):
env.str("RHSM_SERVER_URL"),
env.str("RHSM_SINGLE_SUB_USERNAME"),
env.str("RHSM_SINGLE_SUB_PASSWORD"),
- )
+ ),
+ unregister=True,
) as c2r:
c2r.expect(
f"{single_pool_id} is the only subscription available, it will automatically be selected for the conversion."
diff --git a/tests/integration/tier0/inhibit-if-kmods-is-not-supported/test_kmods_not_supported.py b/tests/integration/tier0/inhibit-if-kmods-is-not-supported/test_kmods_not_supported.py
index ec7ed52f4c..568106934d 100644
--- a/tests/integration/tier0/inhibit-if-kmods-is-not-supported/test_kmods_not_supported.py
+++ b/tests/integration/tier0/inhibit-if-kmods-is-not-supported/test_kmods_not_supported.py
@@ -39,6 +39,14 @@ def test_inhibit_if_custom_module_loaded(insert_custom_kmod, convert2rhel):
def test_do_not_inhibit_if_module_is_not_loaded(shell, convert2rhel):
assert shell("modprobe -r -v bonding").returncode == 0
+
+ system_version = platform.platform()
+ if "oracle-7" in system_version or "centos-7" in system_version:
+ prompt_amount = 3
+ elif "oracle-8" in system_version:
+ prompt_amount = 2
+ elif "centos-8" in system_version:
+ prompt_amount = 3
# If custom module is not loaded the conversion is not inhibited.
with convert2rhel(
("--no-rpm-va --serverurl {} --username {} --password {} --pool {} --debug").format(
@@ -48,19 +56,15 @@ def test_do_not_inhibit_if_module_is_not_loaded(shell, convert2rhel):
env.str("RHSM_POOL"),
)
) as c2r:
- c2r.expect("Continue with the system conversion?")
- c2r.sendline("y")
- c2r.expect("Continue with the system conversion?")
- c2r.sendline("y")
- c2r.expect("Continue with the system conversion?")
- c2r.sendline("y")
- if "oracle-8" not in platform.platform():
+ while prompt_amount > 0:
c2r.expect("Continue with the system conversion?")
c2r.sendline("y")
+ prompt_amount -= 1
+
assert c2r.expect("Kernel modules are compatible.") == 0
c2r.expect("Continue with the system conversion?")
c2r.sendline("n")
- assert c2r.exitstatus != 0
+ assert c2r.exitstatus != 0
def test_tainted_kernel_inhibitor(shell, convert2rhel):
diff --git a/tests/integration/tier0/test-check-rollback-handling/test_check_rollback_handling.py b/tests/integration/tier0/test-check-rollback-handling/test_check_rollback_handling.py
index 7db88a683d..ecbb82de3b 100644
--- a/tests/integration/tier0/test-check-rollback-handling/test_check_rollback_handling.py
+++ b/tests/integration/tier0/test-check-rollback-handling/test_check_rollback_handling.py
@@ -5,7 +5,7 @@
booted_os = platform.platform()
OL_7_PKGS = ["oracle-release-el7", "usermode", "rhn-setup", "oracle-logos"]
-OL_8_PKGS = ["oracle-release-el8", "usermode", "rhn-setup", "oracle-logos"]
+OL_8_PKGS = ["oraclelinux-release-el8", "usermode", "rhn-setup", "oracle-logos"]
COS_7_PKGS = ["centos-release", "usermode", "rhn-setup", "python-syspurpose", "centos-logos"]
COS_8_PKGS = ["centos-linux-release", "usermode", "rhn-setup", "python3-syspurpose", "centos-logos"]
# The packages 'python-syspurpose' and 'python3-syspurpose' were removed in Oracle Linux 7.9
@@ -66,6 +66,12 @@ def test_proper_rhsm_clean_up(shell, convert2rhel):
# Primary issue - checking for usermode, rhn-setup and os-release.
# It also checks that the system has been successfully unregistered.
install_pkg(shell)
+ if "oracle-7" in booted_os or "centos-7" in booted_os:
+ prompt_amount = 3
+ elif "oracle-8" in booted_os:
+ prompt_amount = 3
+ elif "centos-8" in booted_os:
+ prompt_amount = 3
with convert2rhel(
("--serverurl {} --username {} --password {} --pool {} --debug --no-rpm-va").format(
@@ -75,14 +81,10 @@ def test_proper_rhsm_clean_up(shell, convert2rhel):
env.str("RHSM_POOL"),
)
) as c2r:
- c2r.expect("Continue with the system conversion?")
- c2r.sendline("y")
- c2r.expect("Continue with the system conversion?")
- c2r.sendline("y")
- c2r.expect("Continue with the system conversion?")
- c2r.sendline("y")
- c2r.expect("Continue with the system conversion?")
- c2r.sendline("y")
+ while prompt_amount > 0:
+ c2r.expect("Continue with the system conversion?")
+ c2r.sendline("y")
+ prompt_amount -= 1
c2r.expect("The tool allows rollback of any action until this point.")
c2r.sendline("n")
c2r.expect("Calling command 'subscription-manager unregister'")
diff --git a/tests/integration/tier1/changed-yum-conf/test_patch_yum_conf.py b/tests/integration/tier1/changed-yum-conf/test_patch_yum_conf.py
index 00c324ecf6..b70a725d8d 100644
--- a/tests/integration/tier1/changed-yum-conf/test_patch_yum_conf.py
+++ b/tests/integration/tier1/changed-yum-conf/test_patch_yum_conf.py
@@ -21,5 +21,5 @@ def test_yum_patch(convert2rhel, shell):
c2r.expect("/etc/yum.conf patched.")
assert c2r.exitstatus == 0
- # When testing fedora build which is not latest this would break the test on dest distro
- assert shell("yum update -y -x convert2rhel").returncode == 0
+ # The tsflags will prevent updating the RHEL-8.5 versions to RHEL-8.6
+ assert shell("yum update -y -x convert2rhel --setopt tsflags=test").returncode == 0
diff --git a/tests/integration/tier1/checks-after-conversion/test_enabled_repositories.py b/tests/integration/tier1/checks-after-conversion/test_enabled_repositories.py
new file mode 100644
index 0000000000..8fdf424d49
--- /dev/null
+++ b/tests/integration/tier1/checks-after-conversion/test_enabled_repositories.py
@@ -0,0 +1,28 @@
+import platform
+
+from os.path import exists
+
+
+def test_enabled_repositories(shell):
+ """Testing, if the EUS repostitories are enabled after conversion"""
+ system_version = platform.platform()
+ enabled_repos = shell("yum repolist").output
+
+ # Once we will decide to use EUS 8.6 we have to add them here as well
+ try:
+ if "redhat-8.4" in system_version:
+ # Handle the special test case scenario where we do not use the premium account with EUS repositories
+ if exists("/non_eus_repos_used"):
+ assert "rhel-8-for-x86_64-baseos-rpms" in enabled_repos
+ assert "rhel-8-for-x86_64-appstream-rpms" in enabled_repos
+ else:
+ assert "rhel-8-for-x86_64-appstream-eus-rpms" in enabled_repos
+ assert "rhel-8-for-x86_64-baseos-eus-rpms" in enabled_repos
+ elif "redhat-8.5" in system_version or "redhat-8.6" in system_version:
+ assert "rhel-8-for-x86_64-baseos-rpms" in enabled_repos
+ assert "rhel-8-for-x86_64-appstream-rpms" in enabled_repos
+ elif "redhat-7.9" in system_version:
+ assert "rhel-7-server-rpms/7Server/x86_64" in enabled_repos
+ finally:
+ # We need to unregister the system after the conversion
+ shell("subscription-manager unregister")
diff --git a/tests/integration/tier1/checks-after-conversion/test_release_version.py b/tests/integration/tier1/checks-after-conversion/test_release_version.py
index fbe7068316..58ee62faee 100644
--- a/tests/integration/tier1/checks-after-conversion/test_release_version.py
+++ b/tests/integration/tier1/checks-after-conversion/test_release_version.py
@@ -1,3 +1,32 @@
+import json
+
+
def test_basic_conversion(shell):
os_release = shell("cat /etc/os-release").output
assert "Red Hat Enterprise Linux" in os_release
+
+
+def test_correct_distro():
+ """ "
+ Check that we landed on the correct version
+ """
+ with open("/etc/migration-results") as json_file:
+ json_data = json.load(json_file)
+ source_distro = json_data["activities"][0]["source_os"]
+
+ with open("/etc/system-release", "r") as sys_release:
+ destination_distro = sys_release.read()
+
+ if "Red Hat Enterprise Linux Server release 7.9 (Maipo)" in destination_distro:
+ assert (
+ source_distro == "CentOS Linux release 7.9.2009 (Core)"
+ or source_distro == "Oracle Linux Server release 7.9"
+ )
+ elif "Red Hat Enterprise Linux release 8.4 (Ootpa)" in destination_distro:
+ assert source_distro == "CentOS Linux release 8.4.2105" or source_distro == "Oracle Linux Server release 8.4"
+ elif "Red Hat Enterprise Linux release 8.5 (Ootpa)" in destination_distro:
+ assert source_distro == "CentOS Linux release 8.5.2111"
+ elif "Red Hat Enterprise Linux release 8.6 (Ootpa)" in destination_distro:
+ assert source_distro == "Oracle Linux Server release 8.6"
+ else:
+ assert False, "Unknown destination distro"
diff --git a/tests/integration/tier1/convert-offline-systems/prepare_system.py b/tests/integration/tier1/convert-offline-systems/prepare_system.py
index 5a904721e3..0758aa8dbc 100644
--- a/tests/integration/tier1/convert-offline-systems/prepare_system.py
+++ b/tests/integration/tier1/convert-offline-systems/prepare_system.py
@@ -1,3 +1,4 @@
+import os
import re
import socket
@@ -34,7 +35,7 @@ def configure_connection():
def test_prepare_system(shell):
- assert shell("yum install dnsmasq wget -y").returncode == 0
+ assert shell("yum install dnsmasq wget iptables -y").returncode == 0
# Install katello package
pkg_url = "https://dogfood.sat.engineering.redhat.com/pub/katello-ca-consumer-latest.noarch.rpm"
@@ -46,4 +47,10 @@ def test_prepare_system(shell):
configure_connection()
+ # c2r checks the internet connectivity against the 8.8.8.8 DNS server
+ # pinging specific IP address is still possible so we need to block this as well
+ assert shell("iptables -I OUTPUT -d 8.8.8.8 -j DROP").returncode == 0
+
assert shell("systemctl enable dnsmasq && systemctl restart dnsmasq").returncode == 0
+
+ os.environ["CONVERT2RHEL_UNSUPPORTED_INCOMPLETE_ROLLBACK"] = "1"
diff --git a/tests/integration/tier1/convert-offline-systems/run_conversion.py b/tests/integration/tier1/convert-offline-systems/run_conversion.py
index c7286ca12e..dc45c115c1 100644
--- a/tests/integration/tier1/convert-offline-systems/run_conversion.py
+++ b/tests/integration/tier1/convert-offline-systems/run_conversion.py
@@ -4,20 +4,27 @@
from envparse import env
-def test_convert_offline_systems(shell, convert2rhel):
+def test_convert_offline_systems(convert2rhel):
"""Test converting systems not connected to the Internet but requiring sub-mgr (e.g. managed by Satellite)."""
- # The CentOS8 Extras repo url is unreachable due to offline system setup.
- # The repoquery returns an error, thus we need to disable this repository.
- if "centos-8" in platform.platform():
- shell("yum-config-manager --disable extras --disable epel-modular")
-
os.environ["CONVERT2RHEL_UNSUPPORTED_INCOMPLETE_ROLLBACK"] = "1"
- with convert2rhel(
- ("-y --no-rpm-va -k {} -o {} --keep-rhsm --debug").format(
- env.str("SATELLITE_KEY"),
- env.str("SATELLITE_ORG"),
- )
- ) as c2r:
- c2r.expect("Conversion successful!")
- assert c2r.exitstatus == 0
+ source_distro = platform.platform()
+
+ if "centos-8.4" in source_distro or "oracle-8.4" in source_distro:
+ with convert2rhel(
+ ("-y --no-rpm-va -k {} -o {} --keep-rhsm --debug").format(
+ env.str("SATELLITE_KEY_EUS"),
+ env.str("SATELLITE_ORG"),
+ )
+ ) as c2r:
+ pass
+ assert c2r.exitstatus == 0
+ else:
+ with convert2rhel(
+ ("-y --no-rpm-va -k {} -o {} --keep-rhsm --debug").format(
+ env.str("SATELLITE_KEY"),
+ env.str("SATELLITE_ORG"),
+ )
+ ) as c2r:
+ pass
+ assert c2r.exitstatus == 0
diff --git a/tests/integration/tier1/method/custom_repos.py b/tests/integration/tier1/method/custom_repos.py
index 841f125d09..5d59bfc562 100644
--- a/tests/integration/tier1/method/custom_repos.py
+++ b/tests/integration/tier1/method/custom_repos.py
@@ -28,9 +28,28 @@ def test_run_conversion_using_custom_repos(shell, convert2rhel):
if system_version.major == 7:
enable_repo_opt = "--enablerepo rhel-7-server-rpms --enablerepo rhel-7-server-optional-rpms --enablerepo rhel-7-server-extras-rpms"
elif system_version.major == 8:
- enable_repo_opt = "--enablerepo rhel-8-for-x86_64-baseos-rpms --enablerepo rhel-8-for-x86_64-appstream-rpms"
+ if system_version.minor != 4:
+ enable_repo_opt = (
+ "--enablerepo rhel-8-for-x86_64-baseos-rpms --enablerepo rhel-8-for-x86_64-appstream-rpms"
+ )
+ # for the future releases we will have to enable this also for the 8.6 versions
+ elif system_version.minor == 4:
+ enable_repo_opt = (
+ "--enablerepo rhel-8-for-x86_64-baseos-eus-rpms --enablerepo rhel-8-for-x86_64-appstream-eus-rpms"
+ )
with convert2rhel("-y --no-rpm-va --disable-submgr {} --debug".format(enable_repo_opt)) as c2r:
c2r.expect("Conversion successful!")
-
assert c2r.exitstatus == 0
+
+ # after the conversion using custom repostitories it is expected to enable repos by yourself
+ if system_version.major == 7:
+ enable_repo_opt = (
+ "--enable rhel-7-server-rpms --enable rhel-7-server-optional-rpms --enable rhel-7-server-extras-rpms"
+ )
+ elif system_version.major == 8:
+ if system_version.minor != 4:
+ enable_repo_opt = "--enable rhel-8-for-x86_64-baseos-rpms --enable rhel-8-for-x86_64-appstream-rpms"
+ elif system_version.minor == 4:
+ enable_repo_opt = "--enable rhel-8-for-x86_64-baseos-eus-rpms --enable rhel-8-for-x86_64-appstream-eus-rpms"
+ shell("yum-config-manager {}".format(enable_repo_opt))
diff --git a/tests/integration/tier1/method/satellite.py b/tests/integration/tier1/method/satellite.py
index 1895bc25de..f7176ce842 100644
--- a/tests/integration/tier1/method/satellite.py
+++ b/tests/integration/tier1/method/satellite.py
@@ -1,3 +1,5 @@
+import platform
+
from envparse import env
@@ -12,11 +14,23 @@ def test_satellite_conversion(shell, convert2rhel):
pkg_dst = "/usr/share/convert2rhel/subscription-manager/katello-ca-consumer-latest.noarch.rpm"
assert shell("wget --no-check-certificate --output-document {} {}".format(pkg_dst, pkg_url)).returncode == 0
- with convert2rhel(
- ("-y --no-rpm-va -k {} -o {} --debug").format(
- env.str("SATELLITE_KEY"),
- env.str("SATELLITE_ORG"),
- )
- ) as c2r:
- pass
- assert c2r.exitstatus == 0
+ source_distro = platform.platform()
+
+ if "centos-8.4" in source_distro or "oracle-8.4" in source_distro:
+ with convert2rhel(
+ ("-y --no-rpm-va -k {} -o {} --debug").format(
+ env.str("SATELLITE_KEY_EUS"),
+ env.str("SATELLITE_ORG"),
+ )
+ ) as c2r:
+ pass
+ assert c2r.exitstatus == 0
+ else:
+ with convert2rhel(
+ ("-y --no-rpm-va -k {} -o {} --debug").format(
+ env.str("SATELLITE_KEY"),
+ env.str("SATELLITE_ORG"),
+ )
+ ) as c2r:
+ pass
+ assert c2r.exitstatus == 0
diff --git a/tests/integration/tier1/one-kernel-scenario/run_conversion.py b/tests/integration/tier1/one-kernel-scenario/run_conversion.py
index d25a17522b..fdf31a8088 100644
--- a/tests/integration/tier1/one-kernel-scenario/run_conversion.py
+++ b/tests/integration/tier1/one-kernel-scenario/run_conversion.py
@@ -36,4 +36,14 @@ def test_run_conversion_using_custom_repos(shell, convert2rhel):
assert c2r.exitstatus == 0
+ # replace url in yum.repos.d rhel repo to the original one
+ original_url = "baseurl = http://rhsm-pulp.corp.redhat.com/content/dist/rhel/server/7/\$releasever/\$basearch/os/"
+ new_url = "baseurl=http://rhsm-pulp.corp.redhat.com/content/dist/rhel/server/7/7.9/x86_64/os/"
+ shell('sed -i "s+{}+{}+g" /etc/yum.repos.d/rhel7.repo'.format(new_url, original_url))
+
+ enable_repo_opt = (
+ "--enable rhel-7-server-rpms --enable rhel-7-server-optional-rpms --enable rhel-7-server-extras-rpms"
+ )
+ shell("yum-config-manager {}".format(enable_repo_opt))
+
assert shell("yum install -y python3 --enablerepo=*").returncode == 0
diff --git a/tests/integration/tier1/remove-all-submgr-pkgs/test_no_submgr_pkg_installed.py b/tests/integration/tier1/remove-all-submgr-pkgs/test_no_submgr_pkg_installed.py
index b2c907747e..cd53bd143d 100644
--- a/tests/integration/tier1/remove-all-submgr-pkgs/test_no_submgr_pkg_installed.py
+++ b/tests/integration/tier1/remove-all-submgr-pkgs/test_no_submgr_pkg_installed.py
@@ -10,6 +10,13 @@ def test_no_sub_manager_installed(shell, convert2rhel):
"""
assert shell("yum remove -y subscription-manager").returncode == 0
+ system_version = platform.platform()
+ if "oracle-7" in system_version or "centos-7" in system_version:
+ prompt_amount = 2
+ elif "oracle-8" in system_version:
+ prompt_amount = 1
+ elif "centos-8" in system_version:
+ prompt_amount = 2
with convert2rhel(
("--no-rpm-va --serverurl {} --username {} --password {} --pool {} --debug").format(
@@ -19,18 +26,12 @@ def test_no_sub_manager_installed(shell, convert2rhel):
env.str("RHSM_POOL"),
)
) as c2r:
- c2r.expect("Continue with the system conversion?")
- c2r.sendline("y")
- c2r.expect("Continue with the system conversion?")
- c2r.sendline("y")
- # On OracleLinux8 there is one question less than on other distros
- if "oracle-8" not in platform.platform():
+ while prompt_amount > 0:
c2r.expect("Continue with the system conversion?")
c2r.sendline("y")
+ prompt_amount -= 1
assert c2r.expect("The subscription-manager package is not installed.") == 0
assert c2r.expect("No packages related to subscription-manager installed.") == 0
c2r.expect("Continue with the system conversion?")
- c2r.sendline("y")
- c2r.expect("The tool allows rollback of any action until this point.")
c2r.sendline("n")
diff --git a/tests/integration/tier1/satellite_non_eus_repos/main.fmf b/tests/integration/tier1/satellite_non_eus_repos/main.fmf
new file mode 100644
index 0000000000..666213048a
--- /dev/null
+++ b/tests/integration/tier1/satellite_non_eus_repos/main.fmf
@@ -0,0 +1,6 @@
+summary: test using satellite with non eus account for the EUS distro
+
+tier: 1
+
+test: |
+ pytest -svv
diff --git a/tests/integration/tier1/satellite_non_eus_repos/satellite_non_eus_repos.py b/tests/integration/tier1/satellite_non_eus_repos/satellite_non_eus_repos.py
new file mode 100644
index 0000000000..77e73fc5b2
--- /dev/null
+++ b/tests/integration/tier1/satellite_non_eus_repos/satellite_non_eus_repos.py
@@ -0,0 +1,31 @@
+from envparse import env
+
+
+def test_missing_os_release(shell, convert2rhel):
+ """
+ This test case verify that it's possible to do full conversion when /etc/os-release
+ file is not present on the system.
+ """
+
+ # Mark the system so the check for the enabled repos after the conversion handles this special case
+ assert shell("touch /non_eus_repos_used").returncode == 0
+
+ # Remove subscription manager if installed
+ assert shell("yum remove subscription-manager -y").returncode == 0
+
+ assert shell("yum install wget -y").returncode == 0
+
+ # Install katello package
+ pkg_url = "https://dogfood.sat.engineering.redhat.com/pub/katello-ca-consumer-latest.noarch.rpm"
+ pkg_dst = "/usr/share/convert2rhel/subscription-manager/katello-ca-consumer-latest.noarch.rpm"
+ assert shell("wget --no-check-certificate --output-document {} {}".format(pkg_dst, pkg_url)).returncode == 0
+
+ with convert2rhel(
+ ("-y --no-rpm-va -k {} -o {} --debug").format(
+ env.str("SATELLITE_KEY"),
+ env.str("SATELLITE_ORG"),
+ )
+ ) as c2r:
+ c2r.expect("WARNING - rhel-8-for-x86_64-baseos-eus-rpms repository is not available")
+ c2r.expect("WARNING - rhel-8-for-x86_64-appstream-eus-rpms repository is not available")
+ assert c2r.exitstatus == 0
diff --git a/tests/integration/tier1/system-up-to-date/install_non_latest_kernel.py b/tests/integration/tier1/system-up-to-date/install_non_latest_kernel.py
index b95ef8c630..8fe046e0d4 100644
--- a/tests/integration/tier1/system-up-to-date/install_non_latest_kernel.py
+++ b/tests/integration/tier1/system-up-to-date/install_non_latest_kernel.py
@@ -1,13 +1,28 @@
import platform
+system_version = platform.platform()
+
+
+def handle_centos8(shell):
+ """
+ Install non latest kernel for each version that is available in the repository.
+ """
+
+ if "centos-8.4" in system_version:
+ assert shell("yum install kernel-4.18.0-305.3.1.el8 -y").returncode == 0
+ shell("grub2-set-default 'CentOS Linux (4.18.0-305.3.1.el8.x86_64) 8'")
+ elif "centos-8.5" in system_version:
+ assert shell("yum install kernel-4.18.0-348.el8 -y").returncode == 0
+ shell("grub2-set-default 'CentOS Stream (4.18.0-348.el8.x86_64) 8'")
+
+
def test_install_one_kernel(shell):
"""
Install specific kernel version and configure
the system to boot to it. The kernel version is not the
latest one available in repositories.
"""
- system_version = platform.platform()
# Set default kernel
if "centos-7" in system_version:
@@ -17,8 +32,8 @@ def test_install_one_kernel(shell):
assert shell("yum install kernel-3.10.0-1160.el7.x86_64 -y").returncode == 0
shell("grub2-set-default 'Oracle Linux Server 7.9, with Linux 3.10.0-1160.el7.x86_64'")
elif "centos-8" in system_version:
- assert shell("yum install kernel-4.18.0-240.22.1.el8_3 -y").returncode == 0
- shell("grub2-set-default 'CentOS Linux (4.18.0-240.22.1.el8_3.x86_64) 8'")
+ handle_centos8(shell)
+ # Test is being run only for the latest released oracle-linux
elif "oracle-8" in system_version:
- assert shell("yum install kernel-4.18.0-240.22.1.el8_3 -y").returncode == 0
- shell("grub2-set-default 'Oracle Linux Server (4.18.0-240.22.1.el8_3.x86_64) 8.3'")
+ assert shell("yum install kernel-4.18.0-80.el8.x86_64 -y").returncode == 0
+ shell("grub2-set-default 'Oracle Linux Server (4.18.0-80.el8.x86_64) 8.0'")
diff --git a/tests/integration/tier1/system-up-to-date/test_non_latest_kernel_inhibitor.py b/tests/integration/tier1/system-up-to-date/test_non_latest_kernel_inhibitor.py
index f1641277e9..e1bb92b0ec 100644
--- a/tests/integration/tier1/system-up-to-date/test_non_latest_kernel_inhibitor.py
+++ b/tests/integration/tier1/system-up-to-date/test_non_latest_kernel_inhibitor.py
@@ -39,8 +39,19 @@ def test_non_latest_kernel(shell, convert2rhel):
env.str("RHSM_POOL"),
)
) as c2r:
- c2r.expect("The current kernel version loaded is different from the latest version in your repos.")
+ if "centos-7" in system_version or "oracle-7" in system_version:
+ c2r.expect(
+ "The version of the loaded kernel is different from the latest version on the enabled system repositories."
+ )
+ elif "oracle-8" in system_version:
+ c2r.expect(
+ "The version of the loaded kernel is different from the latest version on the enabled system repositories."
+ )
+ else:
+ c2r.expect(
+ "The version of the loaded kernel is different from the latest version on repositories defined in the"
+ )
assert c2r.exitstatus != 0
- # Clean up, reboot is required after this
+ # Clean up, reboot is required after setting the newest kernel
set_latest_kernel(shell)
diff --git a/tests/integration/tier1/system-up-to-date/test_system_up_to_date.py b/tests/integration/tier1/system-up-to-date/test_system_up_to_date.py
index 6b9ef1a0e8..34c701f65b 100644
--- a/tests/integration/tier1/system-up-to-date/test_system_up_to_date.py
+++ b/tests/integration/tier1/system-up-to-date/test_system_up_to_date.py
@@ -13,10 +13,18 @@ def test_skip_kernel_check(shell, convert2rhel):
the kernel check inhibitor. One of the way to allow this is to not have
any kernel packages present in repos.
"""
- shell("mkdir /tmp/my_tmp; mv /etc/yum.repos.d/* /tmp/my_tmp")
+
+ # Move all repos to other location, so it is not being used
+ assert shell("mkdir /tmp/s_backup")
+ assert shell("mv /etc/yum.repos.d/* /tmp/s_backup/").returncode == 0
+
+ # EUS version use hardoced repos from c2r as well
+ if "centos-8" in system_version:
+ assert shell("mkdir /tmp/s_backup_eus")
+ assert shell("mv /usr/share/convert2rhel/repos/* /tmp/s_backup_eus/").returncode == 0
with convert2rhel(
- ("--no-rpm-va --serverurl {} --username {} --password {} --pool {} --debug").format(
+ ("-y --no-rpm-va --serverurl {} --username {} --password {} --pool {} --debug").format(
env.str("RHSM_SERVER_URL"),
env.str("RHSM_USERNAME"),
env.str("RHSM_PASSWORD"),
@@ -25,7 +33,7 @@ def test_skip_kernel_check(shell, convert2rhel):
) as c2r:
if "centos-7" in system_version or "oracle-7" in system_version:
c2r.expect("Could not find any kernel from repositories to compare against the loaded kernel.")
- elif "centos-8" in system_version or "oracle-8" in system_version:
+ else:
c2r.expect("Could not find any kernel-core from repositories to compare against the loaded kernel.")
assert c2r.exitstatus != 0
@@ -44,7 +52,9 @@ def test_skip_kernel_check(shell, convert2rhel):
assert c2r.exitstatus != 0
# Clean up
- shell("mv /tmp/my_tmp/* /etc/yum.repos.d/")
+ if "centos-8" in system_version in system_version:
+ assert shell("mv /tmp/s_backup_eus/* /usr/share/convert2rhel/repos/").returncode == 0
+ assert shell("mv /tmp/s_backup/* /etc/yum.repos.d/").returncode == 0
def test_system_not_updated(shell, convert2rhel):
diff --git a/tests/integration/tier1/yum-distro-sync/test_yum_distro_sync.py b/tests/integration/tier1/yum-distro-sync/test_yum_distro_sync.py
index 98b479c751..974d393c9a 100644
--- a/tests/integration/tier1/yum-distro-sync/test_yum_distro_sync.py
+++ b/tests/integration/tier1/yum-distro-sync/test_yum_distro_sync.py
@@ -27,8 +27,7 @@ def test_yum_distro_sync(convert2rhel, shell):
env.str("RHSM_USERNAME"),
env.str("RHSM_PASSWORD"),
env.str("RHSM_POOL"),
- ),
- unregister=False,
+ )
) as c2r:
c2r.expect("Conversion successful!")
assert c2r.exitstatus == 0
@@ -40,8 +39,6 @@ def test_yum_distro_sync(convert2rhel, shell):
out = shell("yum distro-sync cpaste")
assert condition_test(out.output, out.returncode)
- shell("subscription-manager unregister")
-
def condition_test(output, ret_code):
"""__THE SAME__ conditions as in convert2rhel/pkghandler.py are. Just small change -