From 1c4d6661c193d96be4f99c7c6a0ef2bc8b5232ff Mon Sep 17 00:00:00 2001 From: Preston Watson Date: Fri, 31 May 2024 16:46:09 -0400 Subject: [PATCH 01/17] [RHELC-1329] Port pkghandler.preserve_only_rhel_kernel() to Action framework --- .../conversion/preserve_only_rhel_kernel.py | 207 ++++++++++++++++++ convert2rhel/main.py | 4 +- convert2rhel/pkghandler.py | 124 ----------- 3 files changed, 209 insertions(+), 126 deletions(-) create mode 100644 convert2rhel/actions/conversion/preserve_only_rhel_kernel.py diff --git a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py new file mode 100644 index 0000000000..965f8eb238 --- /dev/null +++ b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py @@ -0,0 +1,207 @@ +# Copyright(C) 2024 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 . + +__metaclass__ = type + +import glob +import logging +import os +import re + +from convert2rhel import actions, exceptions, pkghandler, pkgmanager, utils +from convert2rhel.systeminfo import system_info + + +loggerinst = logging.getLogger(__name__) + +# create classes for installing, removing non rhel kernels, install additional rhel kernel pkgs and update rhel kernel if needed +class InstallRhelKernel(actions.Action): + id = "INSTALL_RHEL_KERNEL" + + def run(self): + """Install and update the RHEL kernel.""" + super(InstallRhelKernel, self).run() + loggerinst.info("Installing RHEL kernel ...") + output, ret_code = pkgmanager.call_yum_cmd(command="install", args=["kernel"]) + kernel_update_needed = False + + if ret_code != 0: + self.set_result( + level="ERROR", + id="FAILED_TO_INSTALL_RHEL_KERNEL", + title="Failed to install RHEL kernel", + description="There was an error while attempting to install the RHEL kernel from yum.", + remediations="Please check that you can access the repositories that provide the RHEL kernel.", + ) + + # Check if kernel with same version is already installed. + # Example output from yum and dnf: + # "Package kernel-4.18.0-193.el8.x86_64 is already installed." + already_installed = re.search(r" (.*?)(?: is)? already installed", output, re.MULTILINE) + if already_installed: + rhel_kernel_nevra = already_installed.group(1) + non_rhel_kernels = pkghandler.get_installed_pkgs_w_different_fingerprint( + system_info.fingerprints_rhel, "kernel" + ) + for non_rhel_kernel in non_rhel_kernels: + # We're comparing to NEVRA since that's what yum/dnf prints out + if rhel_kernel_nevra == pkghandler.get_pkg_nevra(non_rhel_kernel): + # If the installed kernel is from a third party (non-RHEL) and has the same NEVRA as the one available + # from RHEL repos, it's necessary to install an older version RHEL kernel and the third party one will + # be removed later in the conversion process. It's because yum/dnf is unable to reinstall a kernel. + + loggerinst.info( + "\nConflict of kernels: One of the installed kernels" + " has the same version as the latest RHEL kernel." + ) + self.add_message( + level="INFO", + id="CONFLICT_OF_KERNELS", + description="Conflict of kernels: One of the installed kernels" + " has the same version as the latest RHEL kernel.", + ) + pkghandler.handle_no_newer_rhel_kernel_available() + kernel_update_needed = True + if kernel_update_needed: + pkghandler.update_rhel_kernel() + + +class VerifyRhelKernelInstalled(actions.Action): + id = "VERIFY_RHEL_KERNEL_INSTALLED" + + def run(self): + """Verify that the RHEL kernel has been successfully installed and raise an ERROR if not""" + loggerinst.info("Verifying that RHEL kernel has been installed") + if not pkghandler.is_rhel_kernel_installed(): + self.set_result( + level="ERROR", + id="NO_RHEL_KERNEL_INSTALLED", + title="No RHEL kernel installed", + description="There is no RHEL kernel installed on the system.", + remediations="Verify that the repository used for installing kernel contains RHEL packages.", + ) + else: + loggerinst.info("RHEL kernel has been installed.") + self.add_message( + level="INFO", + id="RHEL_KERNEL_INSTALLED", + title="RHEL kernel installed", + description="The RHEL kernel has been installed successfully.", + ) + + +class FixInvalidGrub2Entries(actions.Action): + id = "FIX_INVALID_GRUB2_ENTRIES" + + def run(self): + """ + On systems derived from RHEL 8 and later, /etc/machine-id is being used to identify grub2 boot loader entries per + the Boot Loader Specification. + However, at the time of executing convert2rhel, the current machine-id can be different from the machine-id from the + time when the kernels were installed. If that happens: + - convert2rhel installs the RHEL kernel, but it's not set as default + - convert2rhel removes the original OS kernels, but for these the boot entries are not removed + The solution handled by this function is to remove the non-functioning boot entries upon the removal of the original + OS kernels, and set the RHEL kernel as default. + """ + if system_info.version.major < 8 or system_info.arch == "s390x": + # Applicable only on systems derived from RHEL 8 and later, and systems using GRUB2 (s390x uses zipl) + return + + loggerinst.info("Fixing GRUB boot loader entries.") + + machine_id = utils.get_file_content("/etc/machine-id") + boot_entries = glob.glob("/boot/loader/entries/*.conf") + for entry in boot_entries: + # The boot loader entries in /boot/loader/entries/-.conf + if machine_id.strip() not in os.path.basename(entry): + loggerinst.debug("Removing boot entry %s" % entry) + os.remove(entry) + + # Removing a boot entry that used to be the default makes grubby to choose a different entry as default, but we will + # call grub --set-default to set the new default on all the proper places, e.g. for grub2-editenv + output, ret_code = utils.run_subprocess(["/usr/sbin/grubby", "--default-kernel"], print_output=False) + if ret_code: + # Not setting the default entry shouldn't be a deal breaker and the reason to stop the conversions, grub should + # pick one entry in any case. + loggerinst.warning("Couldn't get the default GRUB2 boot loader entry:\n%s" % output) + self.add_message( + level="WARNING", + id="UNABLE_TO_GET_GRUB2_BOOT_LOADER_ENTRY", + title="Unable to get the GRUB2 boot loader entry", + description="Couldn't get the default GRUB2 boot loader entry:\n%s" % output, + ) + return + loggerinst.debug("Setting RHEL kernel %s as the default boot loader entry." % output.strip()) + output, ret_code = utils.run_subprocess(["/usr/sbin/grubby", "--set-default", output.strip()]) + if ret_code: + loggerinst.warning("Couldn't set the default GRUB2 boot loader entry:\n%s" % output) + self.add_message( + level="WARNING", + id="UNABLE_TO_SET_GRUB2_BOOT_LOADER_ENTRY", + title="Unable to set the GRUB2 boot loader entry", + description="Couldn't set the default GRUB2 boot loader entry:\n%s" % output, + ) + + +class FixDefaultKernel(actions.Action): + id = "FIX_DEFAULT_KERNEL" + + def run(self): + """ + Systems converted from Oracle Linux or CentOS Linux may have leftover kernel-uek or kernel-plus in + /etc/sysconfig/kernel as DEFAULTKERNEL. + This function fixes that by replacing the DEFAULTKERNEL setting from kernel-uek or kernel-plus to kernel for + RHEL7 and kernel-core for RHEL8. + """ + super(FixDefaultKernel, self).run() + + loggerinst = logging.getLogger(__name__) + + loggerinst.info("Checking for incorrect boot kernel") + kernel_sys_cfg = utils.get_file_content("/etc/sysconfig/kernel") + + possible_kernels = ["kernel-uek", "kernel-plus"] + kernel_to_change = next( + iter(kernel for kernel in possible_kernels if kernel in kernel_sys_cfg), + None, + ) + if kernel_to_change: + loggerinst.warning("Detected leftover boot kernel, changing to RHEL kernel") + self.add_message( + level="WARNING", + id="LEFTOVER_BOOT_KERNEL_DETECTED", + title="Leftover boot kernel detected", + description="Detected leftover boot kernel, changing to RHEL kernel", + ) + # need to change to "kernel" in rhel7 and "kernel-core" in rhel8 + new_kernel_str = "DEFAULTKERNEL=" + ("kernel" if system_info.version.major == 7 else "kernel-core") + + kernel_sys_cfg = kernel_sys_cfg.replace("DEFAULTKERNEL=" + kernel_to_change, new_kernel_str) + utils.store_content_to_file("/etc/sysconfig/kernel", kernel_sys_cfg) + loggerinst.info("Boot kernel %s was changed to %s" % (kernel_to_change, new_kernel_str)) + else: + loggerinst.debug("Boot kernel validated.") + + +class KernelPkgsInstall(actions.Action): + id = "KERNEL_PACKAGES_INSTALLATION" + + def run(self): + """Install kernel packages and remove non-RHEL kernels.""" + + kernel_pkgs_to_install = pkghandler.remove_non_rhel_kernels() + if kernel_pkgs_to_install: + pkghandler.install_additional_rhel_kernel_pkgs(kernel_pkgs_to_install) diff --git a/convert2rhel/main.py b/convert2rhel/main.py index f9e59268db..ea79cff2c7 100644 --- a/convert2rhel/main.py +++ b/convert2rhel/main.py @@ -394,8 +394,8 @@ def post_ponr_changes(): def post_ponr_conversion(): """Perform main steps for system conversion.""" - loggerinst.task("Convert: Prepare kernel") - pkghandler.preserve_only_rhel_kernel() + # loggerinst.task("Convert: Prepare kernel") + # pkghandler.preserve_only_rhel_kernel() loggerinst.task("Convert: List remaining non-Red Hat packages") pkghandler.list_non_red_hat_pkgs_left() loggerinst.task("Convert: Configure the bootloader") diff --git a/convert2rhel/pkghandler.py b/convert2rhel/pkghandler.py index 51c361288d..86efef140b 100644 --- a/convert2rhel/pkghandler.py +++ b/convert2rhel/pkghandler.py @@ -616,52 +616,6 @@ def install_gpg_keys(): loggerinst.info("GPG key %s imported successfuly.", gpg_key) -def preserve_only_rhel_kernel(): - kernel_update_needed = install_rhel_kernel() - verify_rhel_kernel_installed() - - kernel_pkgs_to_install = remove_non_rhel_kernels() - fix_invalid_grub2_entries() - fix_default_kernel() - - if kernel_pkgs_to_install: - install_additional_rhel_kernel_pkgs(kernel_pkgs_to_install) - if kernel_update_needed: - update_rhel_kernel() - - -def install_rhel_kernel(): - """Return boolean indicating whether it's needed to update the kernel - later on. - """ - loggerinst.info("Installing RHEL kernel ...") - output, ret_code = pkgmanager.call_yum_cmd(command="install", args=["kernel"]) - - if ret_code != 0: - loggerinst.critical("Error occured while attempting to install the RHEL kernel") - - # Check if kernel with same version is already installed. - # Example output from yum and dnf: - # "Package kernel-4.18.0-193.el8.x86_64 is already installed." - already_installed = re.search(r" (.*?)(?: is)? already installed", output, re.MULTILINE) - if already_installed: - rhel_kernel_nevra = already_installed.group(1) - non_rhel_kernels = get_installed_pkgs_w_different_fingerprint(system_info.fingerprints_rhel, "kernel") - for non_rhel_kernel in non_rhel_kernels: - # We're comparing to NEVRA since that's what yum/dnf prints out - if rhel_kernel_nevra == get_pkg_nevra(non_rhel_kernel): - # If the installed kernel is from a third party (non-RHEL) and has the same NEVRA as the one available - # from RHEL repos, it's necessary to install an older version RHEL kernel and the third party one will - # be removed later in the conversion process. It's because yum/dnf is unable to reinstall a kernel. - loggerinst.info( - "\nConflict of kernels: One of the installed kernels" - " has the same version as the latest RHEL kernel." - ) - handle_no_newer_rhel_kernel_available() - return True - return False - - def handle_no_newer_rhel_kernel_available(): """Handle cases when the installed third party (non-RHEL) kernel has the same version as (or newer than) the RHEL one available in the RHEL repo(s). @@ -747,16 +701,6 @@ def replace_non_rhel_installed_kernel(version): loggerinst.info("\nRHEL %s installed.\n" % pkg) -def verify_rhel_kernel_installed(): - loggerinst.info("Verifying that RHEL kernel has been installed") - if not is_rhel_kernel_installed(): - loggerinst.critical( - "No RHEL kernel installed. Verify that the repository used for installing kernel contains RHEL packages." - ) - else: - loggerinst.info("RHEL kernel has been installed.") - - def is_rhel_kernel_installed(): installed_rhel_kernels = get_installed_pkgs_by_fingerprint(system_info.fingerprints_rhel, name="kernel") return len(installed_rhel_kernels) > 0 @@ -776,74 +720,6 @@ def remove_non_rhel_kernels(): return non_rhel_kernels -def fix_default_kernel(): - """ - Systems converted from Oracle Linux or CentOS Linux may have leftover kernel-uek or kernel-plus in - /etc/sysconfig/kernel as DEFAULTKERNEL. - This function fixes that by replacing the DEFAULTKERNEL setting from kernel-uek or kernel-plus to kernel for - RHEL7 and kernel-core for RHEL8 - """ - loggerinst = logging.getLogger(__name__) - - loggerinst.info("Checking for incorrect boot kernel") - kernel_sys_cfg = utils.get_file_content("/etc/sysconfig/kernel") - - possible_kernels = ["kernel-uek", "kernel-plus"] - kernel_to_change = next( - iter(kernel for kernel in possible_kernels if kernel in kernel_sys_cfg), - None, - ) - if kernel_to_change: - loggerinst.warning("Detected leftover boot kernel, changing to RHEL kernel") - # need to change to "kernel" in rhel7 and "kernel-core" in rhel8 - new_kernel_str = "DEFAULTKERNEL=" + ("kernel" if system_info.version.major == 7 else "kernel-core") - - kernel_sys_cfg = kernel_sys_cfg.replace("DEFAULTKERNEL=" + kernel_to_change, new_kernel_str) - utils.store_content_to_file("/etc/sysconfig/kernel", kernel_sys_cfg) - loggerinst.info("Boot kernel %s was changed to %s" % (kernel_to_change, new_kernel_str)) - else: - loggerinst.debug("Boot kernel validated.") - - -def fix_invalid_grub2_entries(): - """ - On systems derived from RHEL 8 and later, /etc/machine-id is being used to identify grub2 boot loader entries per - the Boot Loader Specification. - However, at the time of executing convert2rhel, the current machine-id can be different from the machine-id from the - time when the kernels were installed. If that happens: - - convert2rhel installs the RHEL kernel, but it's not set as default - - convert2rhel removes the original OS kernels, but for these the boot entries are not removed - The solution handled by this function is to remove the non-functioning boot entries upon the removal of the original - OS kernels, and set the RHEL kernel as default. - """ - if system_info.version.major < 8 or system_info.arch == "s390x": - # Applicable only on systems derived from RHEL 8 and later, and systems using GRUB2 (s390x uses zipl) - return - - loggerinst.info("Fixing GRUB boot loader entries.") - - machine_id = utils.get_file_content("/etc/machine-id") - boot_entries = glob.glob("/boot/loader/entries/*.conf") - for entry in boot_entries: - # The boot loader entries in /boot/loader/entries/-.conf - if machine_id.strip() not in os.path.basename(entry): - loggerinst.debug("Removing boot entry %s" % entry) - os.remove(entry) - - # Removing a boot entry that used to be the default makes grubby to choose a different entry as default, but we will - # call grub --set-default to set the new default on all the proper places, e.g. for grub2-editenv - output, ret_code = utils.run_subprocess(["/usr/sbin/grubby", "--default-kernel"], print_output=False) - if ret_code: - # Not setting the default entry shouldn't be a deal breaker and the reason to stop the conversions, grub should - # pick one entry in any case. - loggerinst.warning("Couldn't get the default GRUB2 boot loader entry:\n%s" % output) - return - loggerinst.debug("Setting RHEL kernel %s as the default boot loader entry." % output.strip()) - output, ret_code = utils.run_subprocess(["/usr/sbin/grubby", "--set-default", output.strip()]) - if ret_code: - loggerinst.warning("Couldn't set the default GRUB2 boot loader entry:\n%s" % output) - - def install_additional_rhel_kernel_pkgs(additional_pkgs): """Convert2rhel removes all non-RHEL kernel packages, including kernel-tools, kernel-headers, etc. This function tries to install back all of these from RHEL repositories. From 066db73a4d65a25b2521f32cdbbb1d84633d9e80 Mon Sep 17 00:00:00 2001 From: Preston Watson Date: Wed, 5 Jun 2024 09:30:40 -0400 Subject: [PATCH 02/17] Apply suggestions from code review Co-authored-by: Rodolfo Olivieri --- .../conversion/preserve_only_rhel_kernel.py | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py index 965f8eb238..8ee9a1c3ac 100644 --- a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py +++ b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py @@ -45,6 +45,7 @@ def run(self): description="There was an error while attempting to install the RHEL kernel from yum.", remediations="Please check that you can access the repositories that provide the RHEL kernel.", ) + return # Check if kernel with same version is already installed. # Example output from yum and dnf: @@ -92,14 +93,14 @@ def run(self): description="There is no RHEL kernel installed on the system.", remediations="Verify that the repository used for installing kernel contains RHEL packages.", ) - else: - loggerinst.info("RHEL kernel has been installed.") - self.add_message( - level="INFO", - id="RHEL_KERNEL_INSTALLED", - title="RHEL kernel installed", - description="The RHEL kernel has been installed successfully.", - ) + return + loggerinst.info("RHEL kernel has been installed.") + self.add_message( + level="INFO", + id="RHEL_KERNEL_INSTALLED", + title="RHEL kernel installed", + description="The RHEL kernel has been installed successfully.", + ) class FixInvalidGrub2Entries(actions.Action): @@ -116,17 +117,17 @@ def run(self): The solution handled by this function is to remove the non-functioning boot entries upon the removal of the original OS kernels, and set the RHEL kernel as default. """ - if system_info.version.major < 8 or system_info.arch == "s390x": + if system_info.version.major < 8: # Applicable only on systems derived from RHEL 8 and later, and systems using GRUB2 (s390x uses zipl) return loggerinst.info("Fixing GRUB boot loader entries.") - machine_id = utils.get_file_content("/etc/machine-id") + machine_id = utils.get_file_content("/etc/machine-id").strip() boot_entries = glob.glob("/boot/loader/entries/*.conf") for entry in boot_entries: # The boot loader entries in /boot/loader/entries/-.conf - if machine_id.strip() not in os.path.basename(entry): + if machine_id not in os.path.basename(entry): loggerinst.debug("Removing boot entry %s" % entry) os.remove(entry) From 8a01104c109e969992315f756fc6a1f9ad736e01 Mon Sep 17 00:00:00 2001 From: Preston Watson Date: Wed, 5 Jun 2024 10:27:46 -0400 Subject: [PATCH 03/17] Code review suggestions --- .../conversion/preserve_only_rhel_kernel.py | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py index 8ee9a1c3ac..e9b1372ef7 100644 --- a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py +++ b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py @@ -20,19 +20,21 @@ import os import re -from convert2rhel import actions, exceptions, pkghandler, pkgmanager, utils +from convert2rhel import actions, pkghandler, pkgmanager, utils from convert2rhel.systeminfo import system_info loggerinst = logging.getLogger(__name__) -# create classes for installing, removing non rhel kernels, install additional rhel kernel pkgs and update rhel kernel if needed + class InstallRhelKernel(actions.Action): id = "INSTALL_RHEL_KERNEL" + dependencies = ("CONVERT_SYSTEM_PACKAGES",) def run(self): """Install and update the RHEL kernel.""" super(InstallRhelKernel, self).run() + loggerinst.info("Installing RHEL kernel ...") output, ret_code = pkgmanager.call_yum_cmd(command="install", args=["kernel"]) kernel_update_needed = False @@ -62,17 +64,12 @@ def run(self): # If the installed kernel is from a third party (non-RHEL) and has the same NEVRA as the one available # from RHEL repos, it's necessary to install an older version RHEL kernel and the third party one will # be removed later in the conversion process. It's because yum/dnf is unable to reinstall a kernel. - - loggerinst.info( - "\nConflict of kernels: One of the installed kernels" + info_message = ( + "Conflict of kernels: One of the installed kernels" " has the same version as the latest RHEL kernel." ) - self.add_message( - level="INFO", - id="CONFLICT_OF_KERNELS", - description="Conflict of kernels: One of the installed kernels" - " has the same version as the latest RHEL kernel.", - ) + loggerinst.info("\n%s" % info_message) + self.add_message(level="INFO", id="CONFLICT_OF_KERNELS", description=info_message) pkghandler.handle_no_newer_rhel_kernel_available() kernel_update_needed = True if kernel_update_needed: @@ -81,9 +78,12 @@ def run(self): class VerifyRhelKernelInstalled(actions.Action): id = "VERIFY_RHEL_KERNEL_INSTALLED" + dependencies = ("INSTALL_RHEL_KERNEL",) def run(self): """Verify that the RHEL kernel has been successfully installed and raise an ERROR if not""" + super(VerifyRhelKernelInstalled, self).run() + loggerinst.info("Verifying that RHEL kernel has been installed") if not pkghandler.is_rhel_kernel_installed(): self.set_result( @@ -94,17 +94,19 @@ def run(self): remediations="Verify that the repository used for installing kernel contains RHEL packages.", ) return - loggerinst.info("RHEL kernel has been installed.") - self.add_message( - level="INFO", - id="RHEL_KERNEL_INSTALLED", - title="RHEL kernel installed", - description="The RHEL kernel has been installed successfully.", - ) + + loggerinst.info("RHEL kernel has been installed.") + self.add_message( + level="INFO", + id="RHEL_KERNEL_INSTALLED", + title="RHEL kernel installed", + description="The RHEL kernel has been installed successfully.", + ) class FixInvalidGrub2Entries(actions.Action): id = "FIX_INVALID_GRUB2_ENTRIES" + dependencies = ("KERNEL_PACKAGES_INSTALLATION",) def run(self): """ @@ -117,6 +119,8 @@ def run(self): The solution handled by this function is to remove the non-functioning boot entries upon the removal of the original OS kernels, and set the RHEL kernel as default. """ + super(FixInvalidGrub2Entries, self).run() + if system_info.version.major < 8: # Applicable only on systems derived from RHEL 8 and later, and systems using GRUB2 (s390x uses zipl) return @@ -159,6 +163,7 @@ def run(self): class FixDefaultKernel(actions.Action): id = "FIX_DEFAULT_KERNEL" + dependencies = ("FIX_INVALID_GRUB2_ENTRIES",) def run(self): """ @@ -199,9 +204,11 @@ def run(self): class KernelPkgsInstall(actions.Action): id = "KERNEL_PACKAGES_INSTALLATION" + dependencies = ("VERIFY_RHEL_KERNEL_INSTALLED",) def run(self): """Install kernel packages and remove non-RHEL kernels.""" + super(KernelPkgsInstall, self).run() kernel_pkgs_to_install = pkghandler.remove_non_rhel_kernels() if kernel_pkgs_to_install: From 327eb5fafaca93c8d4b17fd7ec0840999e1004b2 Mon Sep 17 00:00:00 2001 From: Preston Watson Date: Wed, 12 Jun 2024 09:39:29 -0400 Subject: [PATCH 04/17] Unit tests --- .../conversion/preserve_only_rhel_kernel.py | 9 +- .../preserve_only_rhel_kernel_test.py | 99 +++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py diff --git a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py index e9b1372ef7..ab8ca8f5ac 100644 --- a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py +++ b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py @@ -53,11 +53,13 @@ def run(self): # Example output from yum and dnf: # "Package kernel-4.18.0-193.el8.x86_64 is already installed." already_installed = re.search(r" (.*?)(?: is)? already installed", output, re.MULTILINE) + print("1") if already_installed: rhel_kernel_nevra = already_installed.group(1) non_rhel_kernels = pkghandler.get_installed_pkgs_w_different_fingerprint( system_info.fingerprints_rhel, "kernel" ) + print("2") for non_rhel_kernel in non_rhel_kernels: # We're comparing to NEVRA since that's what yum/dnf prints out if rhel_kernel_nevra == pkghandler.get_pkg_nevra(non_rhel_kernel): @@ -69,10 +71,15 @@ def run(self): " has the same version as the latest RHEL kernel." ) loggerinst.info("\n%s" % info_message) - self.add_message(level="INFO", id="CONFLICT_OF_KERNELS", description=info_message) + self.add_message( + level="INFO", id="CONFLICT_OF_KERNELS", title="Conflict of kernels", description=info_message + ) pkghandler.handle_no_newer_rhel_kernel_available() kernel_update_needed = True + print("3") + if kernel_update_needed: + print("4") pkghandler.update_rhel_kernel() diff --git a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py new file mode 100644 index 0000000000..ab0d40cc4c --- /dev/null +++ b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py @@ -0,0 +1,99 @@ +# Copyright(C) 2024 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 . + +__metaclass__ = type +import pytest +import six + +from convert2rhel import exceptions, pkghandler, unit_tests, utils +from convert2rhel.actions import STATUS_CODE +from convert2rhel.actions.conversion import preserve_only_rhel_kernel +from convert2rhel.unit_tests import ( + GetInstalledPkgsByFingerprintMocked, + GetInstalledPkgsWDifferentFingerprintMocked, + RunSubprocessMocked, +) +from convert2rhel.unit_tests.conftest import all_systems, centos7, centos8 + + +six.add_move(six.MovedModule("mock", "mock", "unittest.mock")) +from six.moves import mock + + +@pytest.fixture +def install_rhel_kernel_instance(): + return preserve_only_rhel_kernel.InstallRhelKernel() + + +@pytest.fixture +def verify_rhel_kernel_installed_instance(): + return preserve_only_rhel_kernel.VerifyRhelKernelInstalled() + + +@pytest.fixture +def fix_invalid_grub2_entries_instance(): + return preserve_only_rhel_kernel.FixInvalidGrub2Entries() + + +@pytest.fixture +def fix_default_kernel_instance(): + return preserve_only_rhel_kernel.FixDefaultKernel() + + +@pytest.fixture +def kernel_packages_install_instance(): + return preserve_only_rhel_kernel.KernelPkgsInstall() + + +@pytest.mark.parametrize( + ( + "subprocess_output", + "is_only_rhel_kernel", + "expected", + ), + ( + ("Package kernel-3.10.0-1127.19.1.el7.x86_64 already installed and latest version", True, False), + ("Package kernel-3.10.0-1127.19.1.el7.x86_64 already installed and latest version", False, True), + ("Installed:\nkernel", False, False), + ), + ids=( + "Kernels collide and installed is already RHEL. Do not update.", + "Kernels collide and installed is not RHEL and older. Update.", + "Kernels do not collide. Install RHEL kernel and do not update.", + ), +) +@centos7 +def test_install_rhel_kernel( + subprocess_output, is_only_rhel_kernel, expected, pretend_os, install_rhel_kernel_instance, monkeypatch +): + update_rhel_kernel_mock = mock.Mock() + + monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked(return_string=subprocess_output)) + monkeypatch.setattr(pkghandler, "handle_no_newer_rhel_kernel_available", mock.Mock()) + monkeypatch.setattr(pkghandler, "update_rhel_kernel", value=update_rhel_kernel_mock) + + if is_only_rhel_kernel: + pkg_selection = "empty" + else: + pkg_selection = "kernels" + + monkeypatch.setattr( + pkghandler, + "get_installed_pkgs_w_different_fingerprint", + GetInstalledPkgsWDifferentFingerprintMocked(pkg_selection=pkg_selection), + ) + install_rhel_kernel_instance.run() + if expected: + assert update_rhel_kernel_mock.assert_called_once() From f3bf636f0f35200416e0ebc631e2ba0af2c99473 Mon Sep 17 00:00:00 2001 From: Preston Watson Date: Tue, 18 Jun 2024 09:28:24 -0400 Subject: [PATCH 05/17] Updated unit tests --- .../conversion/preserve_only_rhel_kernel.py | 4 - .../preserve_only_rhel_kernel_test.py | 338 +++++++++++++++++- convert2rhel/unit_tests/main_test.py | 3 - convert2rhel/unit_tests/pkghandler_test.py | 218 ----------- 4 files changed, 335 insertions(+), 228 deletions(-) diff --git a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py index ab8ca8f5ac..b2ef7d87c3 100644 --- a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py +++ b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py @@ -53,13 +53,11 @@ def run(self): # Example output from yum and dnf: # "Package kernel-4.18.0-193.el8.x86_64 is already installed." already_installed = re.search(r" (.*?)(?: is)? already installed", output, re.MULTILINE) - print("1") if already_installed: rhel_kernel_nevra = already_installed.group(1) non_rhel_kernels = pkghandler.get_installed_pkgs_w_different_fingerprint( system_info.fingerprints_rhel, "kernel" ) - print("2") for non_rhel_kernel in non_rhel_kernels: # We're comparing to NEVRA since that's what yum/dnf prints out if rhel_kernel_nevra == pkghandler.get_pkg_nevra(non_rhel_kernel): @@ -76,10 +74,8 @@ def run(self): ) pkghandler.handle_no_newer_rhel_kernel_available() kernel_update_needed = True - print("3") if kernel_update_needed: - print("4") pkghandler.update_rhel_kernel() diff --git a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py index ab0d40cc4c..0d71d8d4db 100644 --- a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py +++ b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py @@ -14,16 +14,22 @@ # along with this program. If not, see . __metaclass__ = type +import glob +import os +import re + import pytest import six -from convert2rhel import exceptions, pkghandler, unit_tests, utils +from convert2rhel import actions, exceptions, pkghandler, unit_tests, utils from convert2rhel.actions import STATUS_CODE from convert2rhel.actions.conversion import preserve_only_rhel_kernel +from convert2rhel.systeminfo import Version, system_info from convert2rhel.unit_tests import ( GetInstalledPkgsByFingerprintMocked, GetInstalledPkgsWDifferentFingerprintMocked, RunSubprocessMocked, + StoreContentToFileMocked, ) from convert2rhel.unit_tests.conftest import all_systems, centos7, centos8 @@ -80,7 +86,7 @@ def test_install_rhel_kernel( ): update_rhel_kernel_mock = mock.Mock() - monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked(return_string=subprocess_output)) + monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked(return_string=subprocess_output, return_code=0)) monkeypatch.setattr(pkghandler, "handle_no_newer_rhel_kernel_available", mock.Mock()) monkeypatch.setattr(pkghandler, "update_rhel_kernel", value=update_rhel_kernel_mock) @@ -96,4 +102,330 @@ def test_install_rhel_kernel( ) install_rhel_kernel_instance.run() if expected: - assert update_rhel_kernel_mock.assert_called_once() + update_rhel_kernel_mock.assert_called_once() + + +@pytest.mark.parametrize( + ("subprocess_output",), + ( + ("Package kernel-2.6.32-754.33.1.el7.x86_64 already installed and latest version",), + ("Package kernel-4.18.0-193.el8.x86_64 is already installed.",), + ), +) +@centos7 +def test_install_rhel_kernel_already_installed_regexp( + subprocess_output, pretend_os, monkeypatch, install_rhel_kernel_instance +): + monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked(return_string=subprocess_output)) + monkeypatch.setattr( + pkghandler, + "get_installed_pkgs_w_different_fingerprint", + GetInstalledPkgsWDifferentFingerprintMocked(pkg_selection="kernels"), + ) + + install_rhel_kernel_instance.run() + + assert pkghandler.get_installed_pkgs_w_different_fingerprint.call_count == 1 + + +@centos7 +def test_install_rhel_kernel_error(pretend_os, install_rhel_kernel_instance, monkeypatch): + + monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked(return_code=1)) + install_rhel_kernel_instance.run() + unit_tests.assert_actions_result( + install_rhel_kernel_instance, + level="ERROR", + id="FAILED_TO_INSTALL_RHEL_KERNEL", + title="Failed to install RHEL kernel", + description="There was an error while attempting to install the RHEL kernel from yum.", + remediations="Please check that you can access the repositories that provide the RHEL kernel.", + ) + + +@centos7 +def test_install_rhel_kernel_info_msg(pretend_os, install_rhel_kernel_instance, monkeypatch): + subprocess_output = "Package kernel-3.10.0-1127.19.1.el7.x86_64 already installed and latest version" + monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked(return_string=subprocess_output)) + monkeypatch.setattr(pkghandler, "handle_no_newer_rhel_kernel_available", mock.Mock()) + monkeypatch.setattr( + pkghandler, + "get_installed_pkgs_w_different_fingerprint", + GetInstalledPkgsWDifferentFingerprintMocked(pkg_selection="kernels"), + ) + install_rhel_kernel_instance.run() + expected = set( + ( + actions.ActionMessage( + level="INFO", + id="CONFLICT_OF_KERNELS", + title="Conflict of kernels", + description="Conflict of kernels: One of the installed kernels has the same version as the latest RHEL kernel.", + diagnosis=None, + remediations=None, + ), + ) + ) + assert expected.issuperset(install_rhel_kernel_instance.messages) + assert expected.issubset(install_rhel_kernel_instance.messages) + + +@pytest.mark.parametrize( + ("kernel_pkgs_to_install",), + ( + (["example_pkg"],), + ([],), + ), +) +def test_kernel_pkgs_install(monkeypatch, kernel_packages_install_instance, kernel_pkgs_to_install): + install_additional_rhel_kernel_pkgs_mock = mock.Mock() + monkeypatch.setattr( + pkghandler, "install_additional_rhel_kernel_pkgs", value=install_additional_rhel_kernel_pkgs_mock + ) + monkeypatch.setattr(pkghandler, "remove_non_rhel_kernels", mock.Mock(return_value=kernel_pkgs_to_install)) + + kernel_packages_install_instance.run() + if kernel_pkgs_to_install: + install_additional_rhel_kernel_pkgs_mock.assert_called_once() + + +class TestVerifyRHELKernelInstalled: + def test_verify_rhel_kernel_installed(self, monkeypatch, verify_rhel_kernel_installed_instance): + monkeypatch.setattr(pkghandler, "is_rhel_kernel_installed", lambda: True) + + verify_rhel_kernel_installed_instance.run() + expected = set( + ( + actions.ActionMessage( + level="INFO", + id="RHEL_KERNEL_INSTALLED", + title="RHEL kernel installed", + description="The RHEL kernel has been installed successfully.", + diagnosis=None, + remediations=None, + ), + ) + ) + assert expected.issuperset(verify_rhel_kernel_installed_instance.messages) + assert expected.issubset(verify_rhel_kernel_installed_instance.messages) + + def test_verify_rhel_kernel_installed_not_installed(self, monkeypatch, verify_rhel_kernel_installed_instance): + monkeypatch.setattr(pkghandler, "is_rhel_kernel_installed", lambda: False) + + verify_rhel_kernel_installed_instance.run() + unit_tests.assert_actions_result( + verify_rhel_kernel_installed_instance, + level="ERROR", + id="NO_RHEL_KERNEL_INSTALLED", + title="No RHEL kernel installed", + description="There is no RHEL kernel installed on the system.", + remediations="Verify that the repository used for installing kernel contains RHEL packages.", + ) + + +class TestFixInvalidGrub2Entries: + def test_fix_invalid_grub2_entries(self, caplog, monkeypatch, fix_invalid_grub2_entries_instance): + monkeypatch.setattr(system_info, "version", Version(8, 0)) + monkeypatch.setattr(system_info, "arch", "x86_64") + monkeypatch.setattr( + utils, + "get_file_content", + lambda x: "1b11755afe1341d7a86383ca4944c324\n", + ) + monkeypatch.setattr( + glob, + "glob", + lambda x: [ + "/boot/loader/entries/1b11755afe1341d7a86383ca4944c324-0-rescue.conf", + "/boot/loader/entries/1b11755afe1341d7a86383ca4944c324-4.18.0-193.28.1.el8_2.x86_64.conf", + "/boot/loader/entries/b5aebfb91bff486bb9d44ba85e4ae683-0-rescue.conf", + "/boot/loader/entries/b5aebfb91bff486bb9d44ba85e4ae683-4.18.0-193.el8.x86_64.conf", + "/boot/loader/entries/b5aebfb91bff486bb9d44ba85e4ae683-5.4.17-2011.7.4.el8uek.x86_64.conf", + ], + ) + monkeypatch.setattr(os, "remove", mock.Mock()) + monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked()) + + fix_invalid_grub2_entries_instance.run() + + assert os.remove.call_count == 3 + assert utils.run_subprocess.call_count == 2 + + @pytest.mark.parametrize( + ("return_code_1", "return_code_2", "expected"), + ( + ( + 1, + 0, + set( + ( + actions.ActionMessage( + level="WARNING", + id="UNABLE_TO_GET_GRUB2_BOOT_LOADER_ENTRY", + title="Unable to get the GRUB2 boot loader entry", + description="Couldn't get the default GRUB2 boot loader entry:\nboot loader", + diagnosis=None, + remediations=None, + ), + ) + ), + ), + ( + 0, + 1, + set( + ( + actions.ActionMessage( + level="WARNING", + id="UNABLE_TO_SET_GRUB2_BOOT_LOADER_ENTRY", + title="Unable to set the GRUB2 boot loader entry", + description="Couldn't set the default GRUB2 boot loader entry:\ngrep: /boot/grub2/grubenv: Permission denied\nThe param boot loader is incorrect\n", + diagnosis=None, + remediations=None, + ), + ) + ), + ), + ), + ) + def test_fix_invalid_grub2_entries_messages( + self, monkeypatch, fix_invalid_grub2_entries_instance, return_code_1, return_code_2, expected + ): + monkeypatch.setattr(os, "remove", mock.Mock()) + monkeypatch.setattr( + glob, + "glob", + lambda x: [ + "/boot/loader/entries/1b11755afe1341d7a86383ca4944c324-0-rescue.conf", + "/boot/loader/entries/1b11755afe1341d7a86383ca4944c324-4.18.0-193.28.1.el8_2.x86_64.conf", + "/boot/loader/entries/b5aebfb91bff486bb9d44ba85e4ae683-0-rescue.conf", + "/boot/loader/entries/b5aebfb91bff486bb9d44ba85e4ae683-4.18.0-193.el8.x86_64.conf", + "/boot/loader/entries/b5aebfb91bff486bb9d44ba85e4ae683-5.4.17-2011.7.4.el8uek.x86_64.conf", + ], + ) + monkeypatch.setattr(system_info, "version", Version(8, 0)) + monkeypatch.setattr(system_info, "arch", "x86_64") + monkeypatch.setattr( + utils, + "get_file_content", + lambda x: "1b11755afe1341d7a86383ca4944c324\n", + ) + run_subprocess_mocked = RunSubprocessMocked( + side_effect=unit_tests.run_subprocess_side_effect( + ( + ( + "/usr/sbin/grubby", + "--default-kernel", + ), + ( + "boot loader", + return_code_1, + ), + ), + ( + "/usr/sbin/grubby", + "--set-default", + ), + ( + "boot loader", + return_code_2, + ), + ), + ) + + monkeypatch.setattr( + utils, + "run_subprocess", + value=run_subprocess_mocked, + ) + + fix_invalid_grub2_entries_instance.run() + assert expected.issuperset(fix_invalid_grub2_entries_instance.messages) + assert expected.issubset(fix_invalid_grub2_entries_instance.messages) + + +class TestFixDefaultKernel: + @pytest.mark.parametrize( + ("system_name", "version", "old_kernel", "new_kernel", "not_default_kernels"), + ( + ( + "Oracle Linux Server release 7.9", + Version(7, 9), + "kernel-uek", + "kernel", + ("kernel-uek", "kernel-core"), + ), + ( + "Oracle Linux Server release 8.1", + Version(8, 1), + "kernel-uek", + "kernel-core", + ("kernel-uek", "kernel"), + ), + ( + "CentOS Plus Linux Server release 7.9", + Version(7, 9), + "kernel-plus", + "kernel", + ("kernel-plus",), + ), + ), + ) + def test_fix_default_kernel_converting_success( + self, + system_name, + version, + old_kernel, + new_kernel, + not_default_kernels, + caplog, + monkeypatch, + fix_default_kernel_instance, + ): + monkeypatch.setattr(system_info, "name", system_name) + monkeypatch.setattr(system_info, "arch", "x86_64") + monkeypatch.setattr(system_info, "version", version) + monkeypatch.setattr( + utils, + "get_file_content", + lambda _: "UPDATEDEFAULT=yes\nDEFAULTKERNEL=%s\n" % old_kernel, + ) + monkeypatch.setattr(utils, "store_content_to_file", StoreContentToFileMocked()) + + fix_default_kernel_instance.run() + + warning_msgs = [r for r in caplog.records if r.levelname == "WARNING"] + assert warning_msgs + assert "Detected leftover boot kernel, changing to RHEL kernel" in warning_msgs[-1].message + + (filename, content), _dummy = utils.store_content_to_file.call_args + kernel_file_lines = content.splitlines() + + assert "/etc/sysconfig/kernel" == filename + assert "DEFAULTKERNEL=%s" % new_kernel in kernel_file_lines + + for kernel_name in not_default_kernels: + assert "DEFAULTKERNEL=%s" % kernel_name not in kernel_file_lines + + def test_fix_default_kernel_with_no_incorrect_kernel(self, caplog, monkeypatch, fix_default_kernel_instance): + monkeypatch.setattr(system_info, "name", "CentOS Plus Linux Server release 7.9") + monkeypatch.setattr(system_info, "arch", "x86_64") + monkeypatch.setattr(system_info, "version", Version(7, 9)) + monkeypatch.setattr( + utils, + "get_file_content", + lambda _: "UPDATEDEFAULT=yes\nDEFAULTKERNEL=kernel\n", + ) + monkeypatch.setattr(utils, "store_content_to_file", StoreContentToFileMocked()) + + fix_default_kernel_instance.run() + + info_records = [m for m in caplog.records if m.levelname == "INFO"] + warning_records = [m for m in caplog.records if m.levelname == "WARNING"] + debug_records = [m for m in caplog.records if m.levelname == "DEBUG"] + + assert not warning_records + assert any("Boot kernel validated." in r.message for r in debug_records) + + for record in info_records: + assert not re.search("Boot kernel [^ ]\\+ was changed to [^ ]\\+", record.message) diff --git a/convert2rhel/unit_tests/main_test.py b/convert2rhel/unit_tests/main_test.py index 8a356abf4e..541acbc15a 100644 --- a/convert2rhel/unit_tests/main_test.py +++ b/convert2rhel/unit_tests/main_test.py @@ -207,13 +207,11 @@ def test_show_eula_nonexisting_file(self, caplog, monkeypatch, tmpdir): def test_post_ponr_conversion(monkeypatch): - perserve_only_rhel_kernel_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() - monkeypatch.setattr(pkghandler, "preserve_only_rhel_kernel", perserve_only_rhel_kernel_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) @@ -221,7 +219,6 @@ def test_post_ponr_conversion(monkeypatch): main.post_ponr_conversion() - assert perserve_only_rhel_kernel_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 diff --git a/convert2rhel/unit_tests/pkghandler_test.py b/convert2rhel/unit_tests/pkghandler_test.py index e127851ddb..8556f8c7f9 100644 --- a/convert2rhel/unit_tests/pkghandler_test.py +++ b/convert2rhel/unit_tests/pkghandler_test.py @@ -231,29 +231,6 @@ def test_get_rpm_header_failure(self, monkeypatch): pkghandler.get_rpm_header(unknown_pkg) -class TestPreserveOnlyRHELKernel: - @centos7 - def test_preserve_only_rhel_kernel(self, pretend_os, monkeypatch): - monkeypatch.setattr(pkghandler, "install_rhel_kernel", lambda: True) - monkeypatch.setattr(pkghandler, "fix_invalid_grub2_entries", lambda: None) - monkeypatch.setattr(pkghandler, "remove_non_rhel_kernels", mock.Mock(return_value=[])) - monkeypatch.setattr(pkghandler, "install_gpg_keys", mock.Mock()) - monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked()) - monkeypatch.setattr( - pkghandler, - "get_installed_pkgs_by_fingerprint", - GetInstalledPkgsByFingerprintMocked(return_value=[create_pkg_information(name="kernel")]), - ) - monkeypatch.setattr(system_info, "name", "CentOS7") - monkeypatch.setattr(system_info, "arch", "x86_64") - monkeypatch.setattr(utils, "store_content_to_file", StoreContentToFileMocked()) - - pkghandler.preserve_only_rhel_kernel() - - assert utils.run_subprocess.cmd == ["yum", "update", "-y", "--releasever=7Server", "kernel"] - assert pkghandler.get_installed_pkgs_by_fingerprint.call_count == 1 - - class TestGetKernelAvailability: @pytest.mark.parametrize( ("subprocess_output", "expected_installed", "expected_available"), @@ -385,19 +362,6 @@ def test_get_kernel(self): assert kernel_version == ["4.7.4-200.fc24", "4.7.4-200.fc24"] -class TestVerifyRHELKernelInstalled: - def test_verify_rhel_kernel_installed(self, monkeypatch): - monkeypatch.setattr(pkghandler, "is_rhel_kernel_installed", lambda: True) - - pkghandler.verify_rhel_kernel_installed() - - def test_verify_rhel_kernel_installed_not_installed(self, monkeypatch): - monkeypatch.setattr(pkghandler, "is_rhel_kernel_installed", lambda: False) - - with pytest.raises(SystemExit): - pkghandler.verify_rhel_kernel_installed() - - class TestIsRHELKernelInstalled: def test_is_rhel_kernel_installed_no(self, monkeypatch): monkeypatch.setattr(pkghandler, "get_installed_pkgs_by_fingerprint", lambda x, name: []) @@ -414,129 +378,6 @@ def test_is_rhel_kernel_installed_yes(self, monkeypatch): assert pkghandler.is_rhel_kernel_installed() -class TestFixInvalidGrub2Entries: - @pytest.mark.parametrize( - ("version", "arch"), - ( - (Version(7, 0), "x86_64"), - (Version(8, 0), "s390x"), - ), - ) - def test_fix_invalid_grub2_entries_not_applicable(self, version, arch, caplog, monkeypatch): - monkeypatch.setattr(system_info, "version", version) - monkeypatch.setattr(system_info, "arch", arch) - - pkghandler.fix_invalid_grub2_entries() - - assert not [r for r in caplog.records if r.levelname != "DEBUG"] - - def test_fix_invalid_grub2_entries(self, caplog, monkeypatch): - monkeypatch.setattr(system_info, "version", Version(8, 0)) - monkeypatch.setattr(system_info, "arch", "x86_64") - monkeypatch.setattr( - utils, - "get_file_content", - lambda x: "1b11755afe1341d7a86383ca4944c324\n", - ) - monkeypatch.setattr( - glob, - "glob", - lambda x: [ - "/boot/loader/entries/1b11755afe1341d7a86383ca4944c324-0-rescue.conf", - "/boot/loader/entries/1b11755afe1341d7a86383ca4944c324-4.18.0-193.28.1.el8_2.x86_64.conf", - "/boot/loader/entries/b5aebfb91bff486bb9d44ba85e4ae683-0-rescue.conf", - "/boot/loader/entries/b5aebfb91bff486bb9d44ba85e4ae683-4.18.0-193.el8.x86_64.conf", - "/boot/loader/entries/b5aebfb91bff486bb9d44ba85e4ae683-5.4.17-2011.7.4.el8uek.x86_64.conf", - ], - ) - monkeypatch.setattr(os, "remove", mock.Mock()) - monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked()) - - pkghandler.fix_invalid_grub2_entries() - - assert os.remove.call_count == 3 - assert utils.run_subprocess.call_count == 2 - - -class TestFixDefaultKernel: - @pytest.mark.parametrize( - ("system_name", "version", "old_kernel", "new_kernel", "not_default_kernels"), - ( - ( - "Oracle Linux Server release 7.9", - Version(7, 9), - "kernel-uek", - "kernel", - ("kernel-uek", "kernel-core"), - ), - ( - "Oracle Linux Server release 8.1", - Version(8, 1), - "kernel-uek", - "kernel-core", - ("kernel-uek", "kernel"), - ), - ( - "CentOS Plus Linux Server release 7.9", - Version(7, 9), - "kernel-plus", - "kernel", - ("kernel-plus",), - ), - ), - ) - def test_fix_default_kernel_converting_success( - self, system_name, version, old_kernel, new_kernel, not_default_kernels, caplog, monkeypatch - ): - monkeypatch.setattr(system_info, "name", system_name) - monkeypatch.setattr(system_info, "arch", "x86_64") - monkeypatch.setattr(system_info, "version", version) - monkeypatch.setattr( - utils, - "get_file_content", - lambda _: "UPDATEDEFAULT=yes\nDEFAULTKERNEL=%s\n" % old_kernel, - ) - monkeypatch.setattr(utils, "store_content_to_file", StoreContentToFileMocked()) - - pkghandler.fix_default_kernel() - - warning_msgs = [r for r in caplog.records if r.levelname == "WARNING"] - assert warning_msgs - assert "Detected leftover boot kernel, changing to RHEL kernel" in warning_msgs[-1].message - - (filename, content), _dummy = utils.store_content_to_file.call_args - kernel_file_lines = content.splitlines() - - assert "/etc/sysconfig/kernel" == filename - assert "DEFAULTKERNEL=%s" % new_kernel in kernel_file_lines - - for kernel_name in not_default_kernels: - assert "DEFAULTKERNEL=%s" % kernel_name not in kernel_file_lines - - def test_fix_default_kernel_with_no_incorrect_kernel(self, caplog, monkeypatch): - monkeypatch.setattr(system_info, "name", "CentOS Plus Linux Server release 7.9") - monkeypatch.setattr(system_info, "arch", "x86_64") - monkeypatch.setattr(system_info, "version", Version(7, 9)) - monkeypatch.setattr( - utils, - "get_file_content", - lambda _: "UPDATEDEFAULT=yes\nDEFAULTKERNEL=kernel\n", - ) - monkeypatch.setattr(utils, "store_content_to_file", StoreContentToFileMocked()) - - pkghandler.fix_default_kernel() - - info_records = [m for m in caplog.records if m.levelname == "INFO"] - warning_records = [m for m in caplog.records if m.levelname == "WARNING"] - debug_records = [m for m in caplog.records if m.levelname == "DEBUG"] - - assert not warning_records - assert any("Boot kernel validated." in r.message for r in debug_records) - - for record in info_records: - assert not re.search("Boot kernel [^ ]\\+ was changed to [^ ]\\+", record.message) - - @pytest.mark.parametrize( ("version1", "version2", "expected"), ( @@ -1669,65 +1510,6 @@ def test_list_non_red_hat_pkgs_left(monkeypatch): assert pkghandler.format_pkg_info.call_args[0][0][0].nevra.name == "pkg2" -@pytest.mark.parametrize( - ( - "subprocess_output", - "is_only_rhel_kernel", - "expected", - ), - ( - ("Package kernel-3.10.0-1127.19.1.el7.x86_64 already installed and latest version", True, False), - ("Package kernel-3.10.0-1127.19.1.el7.x86_64 already installed and latest version", False, True), - ("Installed:\nkernel", False, False), - ), - ids=( - "Kernels collide and installed is already RHEL. Do not update.", - "Kernels collide and installed is not RHEL and older. Update.", - "Kernels do not collide. Install RHEL kernel and do not update.", - ), -) -@centos7 -def test_install_rhel_kernel(subprocess_output, is_only_rhel_kernel, expected, pretend_os, monkeypatch): - monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked(return_string=subprocess_output)) - monkeypatch.setattr(pkghandler, "handle_no_newer_rhel_kernel_available", mock.Mock()) - - if is_only_rhel_kernel: - pkg_selection = "empty" - else: - pkg_selection = "kernels" - - monkeypatch.setattr( - pkghandler, - "get_installed_pkgs_w_different_fingerprint", - GetInstalledPkgsWDifferentFingerprintMocked(pkg_selection=pkg_selection), - ) - - update_kernel = pkghandler.install_rhel_kernel() - - assert update_kernel is expected - - -@pytest.mark.parametrize( - ("subprocess_output",), - ( - ("Package kernel-2.6.32-754.33.1.el7.x86_64 already installed and latest version",), - ("Package kernel-4.18.0-193.el8.x86_64 is already installed.",), - ), -) -@centos7 -def test_install_rhel_kernel_already_installed_regexp(subprocess_output, pretend_os, monkeypatch): - monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked(return_string=subprocess_output)) - monkeypatch.setattr( - pkghandler, - "get_installed_pkgs_w_different_fingerprint", - GetInstalledPkgsWDifferentFingerprintMocked(pkg_selection="kernels"), - ) - - pkghandler.install_rhel_kernel() - - assert pkghandler.get_installed_pkgs_w_different_fingerprint.call_count == 1 - - def test_remove_non_rhel_kernels(monkeypatch): monkeypatch.setattr( pkghandler, From 4e7817857d3d5d13cc67d54ab6e5f5f728e7453e Mon Sep 17 00:00:00 2001 From: Preston Watson Date: Tue, 2 Jul 2024 15:09:46 -0400 Subject: [PATCH 06/17] Apply suggestions from code review Co-authored-by: Rodolfo Olivieri --- .../actions/conversion/preserve_only_rhel_kernel_test.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py index 0d71d8d4db..d681ddb80d 100644 --- a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py +++ b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py @@ -21,17 +21,15 @@ import pytest import six -from convert2rhel import actions, exceptions, pkghandler, unit_tests, utils -from convert2rhel.actions import STATUS_CODE +from convert2rhel import actions, pkghandler, unit_tests, utils from convert2rhel.actions.conversion import preserve_only_rhel_kernel from convert2rhel.systeminfo import Version, system_info from convert2rhel.unit_tests import ( - GetInstalledPkgsByFingerprintMocked, GetInstalledPkgsWDifferentFingerprintMocked, RunSubprocessMocked, StoreContentToFileMocked, ) -from convert2rhel.unit_tests.conftest import all_systems, centos7, centos8 +from convert2rhel.unit_tests.conftest import centos7 six.add_move(six.MovedModule("mock", "mock", "unittest.mock")) From bd3126b3db8b64ac51e0d01e1e9efac204d06617 Mon Sep 17 00:00:00 2001 From: Preston Watson Date: Wed, 3 Jul 2024 10:12:15 -0400 Subject: [PATCH 07/17] Update title --- convert2rhel/actions/conversion/preserve_only_rhel_kernel.py | 5 ++++- .../actions/conversion/preserve_only_rhel_kernel_test.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py index b2ef7d87c3..a34293618b 100644 --- a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py +++ b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py @@ -70,7 +70,10 @@ def run(self): ) loggerinst.info("\n%s" % info_message) self.add_message( - level="INFO", id="CONFLICT_OF_KERNELS", title="Conflict of kernels", description=info_message + level="INFO", + id="CONFLICT_OF_KERNELS", + title="Conflict of installed kernel versions", + description=info_message, ) pkghandler.handle_no_newer_rhel_kernel_available() kernel_update_needed = True diff --git a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py index d681ddb80d..34e136d6c4 100644 --- a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py +++ b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py @@ -157,7 +157,7 @@ def test_install_rhel_kernel_info_msg(pretend_os, install_rhel_kernel_instance, actions.ActionMessage( level="INFO", id="CONFLICT_OF_KERNELS", - title="Conflict of kernels", + title="Conflict of installed kernel versions", description="Conflict of kernels: One of the installed kernels has the same version as the latest RHEL kernel.", diagnosis=None, remediations=None, From bd8a4ad1da012fba750c9c9a81c9b1d2e106b669 Mon Sep 17 00:00:00 2001 From: Preston Watson Date: Wed, 3 Jul 2024 16:15:14 -0400 Subject: [PATCH 08/17] Fix unit tests --- .../preserve_only_rhel_kernel_test.py | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py index 34e136d6c4..db08828d8a 100644 --- a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py +++ b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py @@ -261,7 +261,7 @@ def test_fix_invalid_grub2_entries(self, caplog, monkeypatch, fix_invalid_grub2_ level="WARNING", id="UNABLE_TO_GET_GRUB2_BOOT_LOADER_ENTRY", title="Unable to get the GRUB2 boot loader entry", - description="Couldn't get the default GRUB2 boot loader entry:\nboot loader", + description="Couldn't get the default GRUB2 boot loader entry:\nbootloader", diagnosis=None, remediations=None, ), @@ -277,7 +277,7 @@ def test_fix_invalid_grub2_entries(self, caplog, monkeypatch, fix_invalid_grub2_ level="WARNING", id="UNABLE_TO_SET_GRUB2_BOOT_LOADER_ENTRY", title="Unable to set the GRUB2 boot loader entry", - description="Couldn't set the default GRUB2 boot loader entry:\ngrep: /boot/grub2/grubenv: Permission denied\nThe param boot loader is incorrect\n", + description="Couldn't set the default GRUB2 boot loader entry:\nbootloader", diagnosis=None, remediations=None, ), @@ -316,17 +316,20 @@ def test_fix_invalid_grub2_entries_messages( "--default-kernel", ), ( - "boot loader", + "bootloader", return_code_1, ), ), ( - "/usr/sbin/grubby", - "--set-default", - ), - ( - "boot loader", - return_code_2, + ( + "/usr/sbin/grubby", + "--set-default", + "bootloader", + ), + ( + "bootloader", + return_code_2, + ), ), ), ) @@ -338,6 +341,8 @@ def test_fix_invalid_grub2_entries_messages( ) fix_invalid_grub2_entries_instance.run() + print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + print(fix_invalid_grub2_entries_instance.messages) assert expected.issuperset(fix_invalid_grub2_entries_instance.messages) assert expected.issubset(fix_invalid_grub2_entries_instance.messages) From e2c5f89fa063ed8e88dc61ab80db6977ef89cb89 Mon Sep 17 00:00:00 2001 From: Preston Watson Date: Mon, 8 Jul 2024 14:17:55 -0400 Subject: [PATCH 09/17] Apply suggestions from code review Co-authored-by: Rodolfo Olivieri --- .../conversion/preserve_only_rhel_kernel_test.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py index db08828d8a..74f55b42d5 100644 --- a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py +++ b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py @@ -22,6 +22,8 @@ import six from convert2rhel import actions, pkghandler, unit_tests, utils +from convert2rhel import actions, pkghandler, unit_tests, utils + from convert2rhel.actions.conversion import preserve_only_rhel_kernel from convert2rhel.systeminfo import Version, system_info from convert2rhel.unit_tests import ( @@ -31,7 +33,6 @@ ) from convert2rhel.unit_tests.conftest import centos7 - six.add_move(six.MovedModule("mock", "mock", "unittest.mock")) from six.moves import mock @@ -88,11 +89,7 @@ def test_install_rhel_kernel( monkeypatch.setattr(pkghandler, "handle_no_newer_rhel_kernel_available", mock.Mock()) monkeypatch.setattr(pkghandler, "update_rhel_kernel", value=update_rhel_kernel_mock) - if is_only_rhel_kernel: - pkg_selection = "empty" - else: - pkg_selection = "kernels" - + pkg_selection = "empty" if is_only_rhel_kernel else "kernels" monkeypatch.setattr( pkghandler, "get_installed_pkgs_w_different_fingerprint", @@ -401,7 +398,7 @@ def test_fix_default_kernel_converting_success( assert warning_msgs assert "Detected leftover boot kernel, changing to RHEL kernel" in warning_msgs[-1].message - (filename, content), _dummy = utils.store_content_to_file.call_args + (filename, content), _ = utils.store_content_to_file.call_args kernel_file_lines = content.splitlines() assert "/etc/sysconfig/kernel" == filename From 6e93da64976fd3a0f57d8ed608e33608f24da78d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 18:18:39 +0000 Subject: [PATCH 10/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../actions/conversion/preserve_only_rhel_kernel_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py index 74f55b42d5..79b087e450 100644 --- a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py +++ b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py @@ -22,8 +22,6 @@ import six from convert2rhel import actions, pkghandler, unit_tests, utils -from convert2rhel import actions, pkghandler, unit_tests, utils - from convert2rhel.actions.conversion import preserve_only_rhel_kernel from convert2rhel.systeminfo import Version, system_info from convert2rhel.unit_tests import ( @@ -33,6 +31,7 @@ ) from convert2rhel.unit_tests.conftest import centos7 + six.add_move(six.MovedModule("mock", "mock", "unittest.mock")) from six.moves import mock From 39971a24ddbf153c01765b76501d97b06810feda Mon Sep 17 00:00:00 2001 From: Preston Watson Date: Mon, 8 Jul 2024 16:14:27 -0400 Subject: [PATCH 11/17] Fix unit tests --- .../conversion/preserve_only_rhel_kernel.py | 39 ++- convert2rhel/pkghandler.py | 35 --- .../preserve_only_rhel_kernel_test.py | 283 ++++++++++-------- convert2rhel/unit_tests/pkghandler_test.py | 53 ---- 4 files changed, 201 insertions(+), 209 deletions(-) diff --git a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py index a34293618b..e57129c2e2 100644 --- a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py +++ b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py @@ -91,7 +91,10 @@ def run(self): super(VerifyRhelKernelInstalled, self).run() loggerinst.info("Verifying that RHEL kernel has been installed") - if not pkghandler.is_rhel_kernel_installed(): + installed_rhel_kernels = pkghandler.get_installed_pkgs_by_fingerprint( + system_info.fingerprints_rhel, name="kernel" + ) + if len(installed_rhel_kernels) <= 0: self.set_result( level="ERROR", id="NO_RHEL_KERNEL_INSTALLED", @@ -216,6 +219,36 @@ def run(self): """Install kernel packages and remove non-RHEL kernels.""" super(KernelPkgsInstall, self).run() - kernel_pkgs_to_install = pkghandler.remove_non_rhel_kernels() + kernel_pkgs_to_install = self.remove_non_rhel_kernels() if kernel_pkgs_to_install: - pkghandler.install_additional_rhel_kernel_pkgs(kernel_pkgs_to_install) + self.install_additional_rhel_kernel_pkgs(kernel_pkgs_to_install) + + def remove_non_rhel_kernels(self): + loggerinst.info("Searching for non-RHEL kernels ...") + non_rhel_kernels = pkghandler.get_installed_pkgs_w_different_fingerprint( + system_info.fingerprints_rhel, "kernel*" + ) + if non_rhel_kernels: + loggerinst.info("Removing non-RHEL kernels\n") + pkghandler.print_pkg_info(non_rhel_kernels) + utils.remove_pkgs( + pkgs_to_remove=[pkghandler.get_pkg_nvra(pkg) for pkg in non_rhel_kernels], + ) + else: + loggerinst.info("None found.") + return non_rhel_kernels + + def install_additional_rhel_kernel_pkgs(self, additional_pkgs): + """Convert2rhel removes all non-RHEL kernel packages, including kernel-tools, kernel-headers, etc. This function + tries to install back all of these from RHEL repositories. + """ + # OL renames some of the kernel packages by adding "-uek" (Unbreakable + # Enterprise Kernel), e.g. kernel-uek-devel instead of kernel-devel. Such + # package names need to be mapped to the RHEL kernel package names to have + # them installed on the converted system. + ol_kernel_ext = "-uek" + pkg_names = [p.nevra.name.replace(ol_kernel_ext, "", 1) for p in additional_pkgs] + for name in set(pkg_names): + if name != "kernel": + loggerinst.info("Installing RHEL %s" % name) + pkgmanager.call_yum_cmd("install", args=[name]) diff --git a/convert2rhel/pkghandler.py b/convert2rhel/pkghandler.py index 86efef140b..bf561e3723 100644 --- a/convert2rhel/pkghandler.py +++ b/convert2rhel/pkghandler.py @@ -701,41 +701,6 @@ def replace_non_rhel_installed_kernel(version): loggerinst.info("\nRHEL %s installed.\n" % pkg) -def is_rhel_kernel_installed(): - installed_rhel_kernels = get_installed_pkgs_by_fingerprint(system_info.fingerprints_rhel, name="kernel") - return len(installed_rhel_kernels) > 0 - - -def remove_non_rhel_kernels(): - loggerinst.info("Searching for non-RHEL kernels ...") - non_rhel_kernels = get_installed_pkgs_w_different_fingerprint(system_info.fingerprints_rhel, "kernel*") - if non_rhel_kernels: - loggerinst.info("Removing non-RHEL kernels\n") - print_pkg_info(non_rhel_kernels) - utils.remove_pkgs( - pkgs_to_remove=[get_pkg_nvra(pkg) for pkg in non_rhel_kernels], - ) - else: - loggerinst.info("None found.") - return non_rhel_kernels - - -def install_additional_rhel_kernel_pkgs(additional_pkgs): - """Convert2rhel removes all non-RHEL kernel packages, including kernel-tools, kernel-headers, etc. This function - tries to install back all of these from RHEL repositories. - """ - # OL renames some of the kernel packages by adding "-uek" (Unbreakable - # Enterprise Kernel), e.g. kernel-uek-devel instead of kernel-devel. Such - # package names need to be mapped to the RHEL kernel package names to have - # them installed on the converted system. - ol_kernel_ext = "-uek" - pkg_names = [p.nevra.name.replace(ol_kernel_ext, "", 1) for p in additional_pkgs] - for name in set(pkg_names): - if name != "kernel": - loggerinst.info("Installing RHEL %s" % name) - pkgmanager.call_yum_cmd("install", args=[name]) - - def update_rhel_kernel(): """In the corner case where the original system kernel version is the same as the latest available RHEL kernel, convert2rhel needs to install older RHEL kernel version first. In this function, RHEL kernel is updated to the diff --git a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py index 79b087e450..d46305a3bf 100644 --- a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py +++ b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py @@ -21,15 +21,20 @@ import pytest import six -from convert2rhel import actions, pkghandler, unit_tests, utils +from convert2rhel import actions, pkghandler, pkgmanager, unit_tests, utils from convert2rhel.actions.conversion import preserve_only_rhel_kernel from convert2rhel.systeminfo import Version, system_info from convert2rhel.unit_tests import ( + CallYumCmdMocked, + FormatPkgInfoMocked, + GetInstalledPkgsByFingerprintMocked, GetInstalledPkgsWDifferentFingerprintMocked, + RemovePkgsMocked, RunSubprocessMocked, StoreContentToFileMocked, + create_pkg_information, ) -from convert2rhel.unit_tests.conftest import centos7 +from convert2rhel.unit_tests.conftest import centos7, centos8 six.add_move(six.MovedModule("mock", "mock", "unittest.mock")) @@ -61,132 +66,177 @@ def kernel_packages_install_instance(): return preserve_only_rhel_kernel.KernelPkgsInstall() -@pytest.mark.parametrize( - ( - "subprocess_output", - "is_only_rhel_kernel", - "expected", - ), - ( - ("Package kernel-3.10.0-1127.19.1.el7.x86_64 already installed and latest version", True, False), - ("Package kernel-3.10.0-1127.19.1.el7.x86_64 already installed and latest version", False, True), - ("Installed:\nkernel", False, False), - ), - ids=( - "Kernels collide and installed is already RHEL. Do not update.", - "Kernels collide and installed is not RHEL and older. Update.", - "Kernels do not collide. Install RHEL kernel and do not update.", - ), -) -@centos7 -def test_install_rhel_kernel( - subprocess_output, is_only_rhel_kernel, expected, pretend_os, install_rhel_kernel_instance, monkeypatch -): - update_rhel_kernel_mock = mock.Mock() - - monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked(return_string=subprocess_output, return_code=0)) - monkeypatch.setattr(pkghandler, "handle_no_newer_rhel_kernel_available", mock.Mock()) - monkeypatch.setattr(pkghandler, "update_rhel_kernel", value=update_rhel_kernel_mock) - - pkg_selection = "empty" if is_only_rhel_kernel else "kernels" - monkeypatch.setattr( - pkghandler, - "get_installed_pkgs_w_different_fingerprint", - GetInstalledPkgsWDifferentFingerprintMocked(pkg_selection=pkg_selection), +class TestInstallRhelKernel: + @pytest.mark.parametrize( + ( + "subprocess_output", + "is_only_rhel_kernel", + "expected", + ), + ( + ("Package kernel-3.10.0-1127.19.1.el7.x86_64 already installed and latest version", True, False), + ("Package kernel-3.10.0-1127.19.1.el7.x86_64 already installed and latest version", False, True), + ("Installed:\nkernel", False, False), + ), + ids=( + "Kernels collide and installed is already RHEL. Do not update.", + "Kernels collide and installed is not RHEL and older. Update.", + "Kernels do not collide. Install RHEL kernel and do not update.", + ), ) - install_rhel_kernel_instance.run() - if expected: - update_rhel_kernel_mock.assert_called_once() + @centos7 + def test_install_rhel_kernel( + self, subprocess_output, is_only_rhel_kernel, expected, pretend_os, install_rhel_kernel_instance, monkeypatch + ): + update_rhel_kernel_mock = mock.Mock() + monkeypatch.setattr( + utils, "run_subprocess", RunSubprocessMocked(return_string=subprocess_output, return_code=0) + ) + monkeypatch.setattr(pkghandler, "handle_no_newer_rhel_kernel_available", mock.Mock()) + monkeypatch.setattr(pkghandler, "update_rhel_kernel", value=update_rhel_kernel_mock) -@pytest.mark.parametrize( - ("subprocess_output",), - ( - ("Package kernel-2.6.32-754.33.1.el7.x86_64 already installed and latest version",), - ("Package kernel-4.18.0-193.el8.x86_64 is already installed.",), - ), -) -@centos7 -def test_install_rhel_kernel_already_installed_regexp( - subprocess_output, pretend_os, monkeypatch, install_rhel_kernel_instance -): - monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked(return_string=subprocess_output)) - monkeypatch.setattr( - pkghandler, - "get_installed_pkgs_w_different_fingerprint", - GetInstalledPkgsWDifferentFingerprintMocked(pkg_selection="kernels"), + pkg_selection = "empty" if is_only_rhel_kernel else "kernels" + monkeypatch.setattr( + pkghandler, + "get_installed_pkgs_w_different_fingerprint", + GetInstalledPkgsWDifferentFingerprintMocked(pkg_selection=pkg_selection), + ) + install_rhel_kernel_instance.run() + if expected: + update_rhel_kernel_mock.assert_called_once() + + @pytest.mark.parametrize( + ("subprocess_output",), + ( + ("Package kernel-2.6.32-754.33.1.el7.x86_64 already installed and latest version",), + ("Package kernel-4.18.0-193.el8.x86_64 is already installed.",), + ), ) + @centos7 + def test_install_rhel_kernel_already_installed_regexp( + self, subprocess_output, pretend_os, monkeypatch, install_rhel_kernel_instance + ): + monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked(return_string=subprocess_output)) + monkeypatch.setattr( + pkghandler, + "get_installed_pkgs_w_different_fingerprint", + GetInstalledPkgsWDifferentFingerprintMocked(pkg_selection="kernels"), + ) - install_rhel_kernel_instance.run() + install_rhel_kernel_instance.run() - assert pkghandler.get_installed_pkgs_w_different_fingerprint.call_count == 1 + assert pkghandler.get_installed_pkgs_w_different_fingerprint.call_count == 1 + @centos7 + def test_install_rhel_kernel_error(self, pretend_os, install_rhel_kernel_instance, monkeypatch): -@centos7 -def test_install_rhel_kernel_error(pretend_os, install_rhel_kernel_instance, monkeypatch): + monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked(return_code=1)) + install_rhel_kernel_instance.run() + unit_tests.assert_actions_result( + install_rhel_kernel_instance, + level="ERROR", + id="FAILED_TO_INSTALL_RHEL_KERNEL", + title="Failed to install RHEL kernel", + description="There was an error while attempting to install the RHEL kernel from yum.", + remediations="Please check that you can access the repositories that provide the RHEL kernel.", + ) - monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked(return_code=1)) - install_rhel_kernel_instance.run() - unit_tests.assert_actions_result( - install_rhel_kernel_instance, - level="ERROR", - id="FAILED_TO_INSTALL_RHEL_KERNEL", - title="Failed to install RHEL kernel", - description="There was an error while attempting to install the RHEL kernel from yum.", - remediations="Please check that you can access the repositories that provide the RHEL kernel.", - ) + @centos7 + def test_install_rhel_kernel_info_msg(self, pretend_os, install_rhel_kernel_instance, monkeypatch): + subprocess_output = "Package kernel-3.10.0-1127.19.1.el7.x86_64 already installed and latest version" + monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked(return_string=subprocess_output)) + monkeypatch.setattr(pkghandler, "handle_no_newer_rhel_kernel_available", mock.Mock()) + monkeypatch.setattr( + pkghandler, + "get_installed_pkgs_w_different_fingerprint", + GetInstalledPkgsWDifferentFingerprintMocked(pkg_selection="kernels"), + ) + install_rhel_kernel_instance.run() + expected = set( + ( + actions.ActionMessage( + level="INFO", + id="CONFLICT_OF_KERNELS", + title="Conflict of installed kernel versions", + description="Conflict of kernels: One of the installed kernels has the same version as the latest RHEL kernel.", + diagnosis=None, + remediations=None, + ), + ) + ) + assert expected.issuperset(install_rhel_kernel_instance.messages) + assert expected.issubset(install_rhel_kernel_instance.messages) -@centos7 -def test_install_rhel_kernel_info_msg(pretend_os, install_rhel_kernel_instance, monkeypatch): - subprocess_output = "Package kernel-3.10.0-1127.19.1.el7.x86_64 already installed and latest version" - monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked(return_string=subprocess_output)) - monkeypatch.setattr(pkghandler, "handle_no_newer_rhel_kernel_available", mock.Mock()) - monkeypatch.setattr( - pkghandler, - "get_installed_pkgs_w_different_fingerprint", - GetInstalledPkgsWDifferentFingerprintMocked(pkg_selection="kernels"), - ) - install_rhel_kernel_instance.run() - expected = set( +class TestKernelPkgsInstall: + @pytest.mark.parametrize( + ("kernel_pkgs_to_install",), ( - actions.ActionMessage( - level="INFO", - id="CONFLICT_OF_KERNELS", - title="Conflict of installed kernel versions", - description="Conflict of kernels: One of the installed kernels has the same version as the latest RHEL kernel.", - diagnosis=None, - remediations=None, - ), - ) + (["example_pkg"],), + ([],), + ), ) - assert expected.issuperset(install_rhel_kernel_instance.messages) - assert expected.issubset(install_rhel_kernel_instance.messages) + def test_kernel_pkgs_install(self, monkeypatch, kernel_packages_install_instance, kernel_pkgs_to_install): + install_additional_rhel_kernel_pkgs_mock = mock.Mock() + monkeypatch.setattr( + preserve_only_rhel_kernel.KernelPkgsInstall, + "install_additional_rhel_kernel_pkgs", + value=install_additional_rhel_kernel_pkgs_mock, + ) + monkeypatch.setattr( + preserve_only_rhel_kernel.KernelPkgsInstall, + "remove_non_rhel_kernels", + mock.Mock(return_value=kernel_pkgs_to_install), + ) + kernel_packages_install_instance.run() + if kernel_pkgs_to_install: + install_additional_rhel_kernel_pkgs_mock.assert_called_once() -@pytest.mark.parametrize( - ("kernel_pkgs_to_install",), - ( - (["example_pkg"],), - ([],), - ), -) -def test_kernel_pkgs_install(monkeypatch, kernel_packages_install_instance, kernel_pkgs_to_install): - install_additional_rhel_kernel_pkgs_mock = mock.Mock() - monkeypatch.setattr( - pkghandler, "install_additional_rhel_kernel_pkgs", value=install_additional_rhel_kernel_pkgs_mock - ) - monkeypatch.setattr(pkghandler, "remove_non_rhel_kernels", mock.Mock(return_value=kernel_pkgs_to_install)) + def test_remove_non_rhel_kernels(self, monkeypatch, kernel_packages_install_instance): + monkeypatch.setattr( + pkghandler, + "get_installed_pkgs_w_different_fingerprint", + GetInstalledPkgsWDifferentFingerprintMocked(pkg_selection="kernels"), + ) + monkeypatch.setattr(pkghandler, "format_pkg_info", FormatPkgInfoMocked()) + monkeypatch.setattr(utils, "remove_pkgs", RemovePkgsMocked()) + + removed_pkgs = kernel_packages_install_instance.remove_non_rhel_kernels() + + assert len(removed_pkgs) == 6 + assert [p.nevra.name for p in removed_pkgs] == [ + "kernel", + "kernel-uek", + "kernel-headers", + "kernel-uek-headers", + "kernel-firmware", + "kernel-uek-firmware", + ] + + def test_install_additional_rhel_kernel_pkgs(self, monkeypatch, kernel_packages_install_instance): + monkeypatch.setattr( + pkghandler, + "get_installed_pkgs_w_different_fingerprint", + GetInstalledPkgsWDifferentFingerprintMocked(pkg_selection="kernels"), + ) + monkeypatch.setattr(pkghandler, "format_pkg_info", FormatPkgInfoMocked()) + monkeypatch.setattr(utils, "remove_pkgs", RemovePkgsMocked()) + monkeypatch.setattr(pkgmanager, "call_yum_cmd", CallYumCmdMocked()) - kernel_packages_install_instance.run() - if kernel_pkgs_to_install: - install_additional_rhel_kernel_pkgs_mock.assert_called_once() + removed_pkgs = kernel_packages_install_instance.remove_non_rhel_kernels() + kernel_packages_install_instance.install_additional_rhel_kernel_pkgs(removed_pkgs) + assert pkgmanager.call_yum_cmd.call_count == 2 class TestVerifyRHELKernelInstalled: def test_verify_rhel_kernel_installed(self, monkeypatch, verify_rhel_kernel_installed_instance): - monkeypatch.setattr(pkghandler, "is_rhel_kernel_installed", lambda: True) - + monkeypatch.setattr( + pkghandler, + "get_installed_pkgs_by_fingerprint", + GetInstalledPkgsByFingerprintMocked(return_value=[create_pkg_information(name="kernel")]), + ) verify_rhel_kernel_installed_instance.run() expected = set( ( @@ -204,7 +254,7 @@ def test_verify_rhel_kernel_installed(self, monkeypatch, verify_rhel_kernel_inst assert expected.issubset(verify_rhel_kernel_installed_instance.messages) def test_verify_rhel_kernel_installed_not_installed(self, monkeypatch, verify_rhel_kernel_installed_instance): - monkeypatch.setattr(pkghandler, "is_rhel_kernel_installed", lambda: False) + monkeypatch.setattr(pkghandler, "get_installed_pkgs_by_fingerprint", mock.Mock(return_value=[])) verify_rhel_kernel_installed_instance.run() unit_tests.assert_actions_result( @@ -245,6 +295,7 @@ def test_fix_invalid_grub2_entries(self, caplog, monkeypatch, fix_invalid_grub2_ assert os.remove.call_count == 3 assert utils.run_subprocess.call_count == 2 + @centos8 @pytest.mark.parametrize( ("return_code_1", "return_code_2", "expected"), ( @@ -283,7 +334,7 @@ def test_fix_invalid_grub2_entries(self, caplog, monkeypatch, fix_invalid_grub2_ ), ) def test_fix_invalid_grub2_entries_messages( - self, monkeypatch, fix_invalid_grub2_entries_instance, return_code_1, return_code_2, expected + self, monkeypatch, fix_invalid_grub2_entries_instance, return_code_1, return_code_2, expected, pretend_os ): monkeypatch.setattr(os, "remove", mock.Mock()) monkeypatch.setattr( @@ -297,8 +348,6 @@ def test_fix_invalid_grub2_entries_messages( "/boot/loader/entries/b5aebfb91bff486bb9d44ba85e4ae683-5.4.17-2011.7.4.el8uek.x86_64.conf", ], ) - monkeypatch.setattr(system_info, "version", Version(8, 0)) - monkeypatch.setattr(system_info, "arch", "x86_64") monkeypatch.setattr( utils, "get_file_content", @@ -337,8 +386,6 @@ def test_fix_invalid_grub2_entries_messages( ) fix_invalid_grub2_entries_instance.run() - print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - print(fix_invalid_grub2_entries_instance.messages) assert expected.issuperset(fix_invalid_grub2_entries_instance.messages) assert expected.issubset(fix_invalid_grub2_entries_instance.messages) @@ -406,10 +453,10 @@ def test_fix_default_kernel_converting_success( for kernel_name in not_default_kernels: assert "DEFAULTKERNEL=%s" % kernel_name not in kernel_file_lines - def test_fix_default_kernel_with_no_incorrect_kernel(self, caplog, monkeypatch, fix_default_kernel_instance): - monkeypatch.setattr(system_info, "name", "CentOS Plus Linux Server release 7.9") - monkeypatch.setattr(system_info, "arch", "x86_64") - monkeypatch.setattr(system_info, "version", Version(7, 9)) + @centos7 + def test_fix_default_kernel_with_no_incorrect_kernel( + self, caplog, monkeypatch, fix_default_kernel_instance, pretend_os + ): monkeypatch.setattr( utils, "get_file_content", diff --git a/convert2rhel/unit_tests/pkghandler_test.py b/convert2rhel/unit_tests/pkghandler_test.py index 8556f8c7f9..a3ef0e3719 100644 --- a/convert2rhel/unit_tests/pkghandler_test.py +++ b/convert2rhel/unit_tests/pkghandler_test.py @@ -362,22 +362,6 @@ def test_get_kernel(self): assert kernel_version == ["4.7.4-200.fc24", "4.7.4-200.fc24"] -class TestIsRHELKernelInstalled: - def test_is_rhel_kernel_installed_no(self, monkeypatch): - monkeypatch.setattr(pkghandler, "get_installed_pkgs_by_fingerprint", lambda x, name: []) - - assert not pkghandler.is_rhel_kernel_installed() - - def test_is_rhel_kernel_installed_yes(self, monkeypatch): - monkeypatch.setattr( - pkghandler, - "get_installed_pkgs_by_fingerprint", - GetInstalledPkgsByFingerprintMocked(return_value=[create_pkg_information(name="kernel")]), - ) - - assert pkghandler.is_rhel_kernel_installed() - - @pytest.mark.parametrize( ("version1", "version2", "expected"), ( @@ -1510,43 +1494,6 @@ def test_list_non_red_hat_pkgs_left(monkeypatch): assert pkghandler.format_pkg_info.call_args[0][0][0].nevra.name == "pkg2" -def test_remove_non_rhel_kernels(monkeypatch): - monkeypatch.setattr( - pkghandler, - "get_installed_pkgs_w_different_fingerprint", - GetInstalledPkgsWDifferentFingerprintMocked(pkg_selection="kernels"), - ) - monkeypatch.setattr(pkghandler, "format_pkg_info", FormatPkgInfoMocked()) - monkeypatch.setattr(utils, "remove_pkgs", RemovePkgsMocked()) - - removed_pkgs = pkghandler.remove_non_rhel_kernels() - - assert len(removed_pkgs) == 6 - assert [p.nevra.name for p in removed_pkgs] == [ - "kernel", - "kernel-uek", - "kernel-headers", - "kernel-uek-headers", - "kernel-firmware", - "kernel-uek-firmware", - ] - - -def test_install_additional_rhel_kernel_pkgs(monkeypatch): - monkeypatch.setattr( - pkghandler, - "get_installed_pkgs_w_different_fingerprint", - GetInstalledPkgsWDifferentFingerprintMocked(pkg_selection="kernels"), - ) - monkeypatch.setattr(pkghandler, "format_pkg_info", FormatPkgInfoMocked()) - monkeypatch.setattr(utils, "remove_pkgs", RemovePkgsMocked()) - monkeypatch.setattr(pkgmanager, "call_yum_cmd", CallYumCmdMocked()) - - removed_pkgs = pkghandler.remove_non_rhel_kernels() - pkghandler.install_additional_rhel_kernel_pkgs(removed_pkgs) - assert pkgmanager.call_yum_cmd.call_count == 2 - - @pytest.mark.parametrize( ("package_name", "subprocess_output", "expected", "expected_command"), ( From b6722ceb6c4340932eb1a35f6ce36a82341bdc49 Mon Sep 17 00:00:00 2001 From: Preston Watson Date: Mon, 5 Aug 2024 09:02:53 -0400 Subject: [PATCH 12/17] Remove preserve_only_rhel_kernel call from main --- convert2rhel/actions/conversion/preserve_only_rhel_kernel.py | 1 + convert2rhel/main.py | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py index e57129c2e2..b7ffcc9ec6 100644 --- a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py +++ b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py @@ -34,6 +34,7 @@ class InstallRhelKernel(actions.Action): def run(self): """Install and update the RHEL kernel.""" super(InstallRhelKernel, self).run() + loggerinst.task("Convert: Prepare kernel") loggerinst.info("Installing RHEL kernel ...") output, ret_code = pkgmanager.call_yum_cmd(command="install", args=["kernel"]) diff --git a/convert2rhel/main.py b/convert2rhel/main.py index ea79cff2c7..a0658e5931 100644 --- a/convert2rhel/main.py +++ b/convert2rhel/main.py @@ -394,8 +394,6 @@ def post_ponr_changes(): def post_ponr_conversion(): """Perform main steps for system conversion.""" - # loggerinst.task("Convert: Prepare kernel") - # pkghandler.preserve_only_rhel_kernel() loggerinst.task("Convert: List remaining non-Red Hat packages") pkghandler.list_non_red_hat_pkgs_left() loggerinst.task("Convert: Configure the bootloader") From 948fb24916e798d549d34504365a35859a2958f0 Mon Sep 17 00:00:00 2001 From: Preston Watson Date: Mon, 5 Aug 2024 11:25:28 -0400 Subject: [PATCH 13/17] Apply suggestions from code review Co-authored-by: Rodolfo Olivieri --- .../conversion/preserve_only_rhel_kernel.py | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py index b7ffcc9ec6..66a623a244 100644 --- a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py +++ b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py @@ -151,23 +151,25 @@ def run(self): if ret_code: # Not setting the default entry shouldn't be a deal breaker and the reason to stop the conversions, grub should # pick one entry in any case. - loggerinst.warning("Couldn't get the default GRUB2 boot loader entry:\n%s" % output) + description = "Couldn't get the default GRUB2 boot loader entry:\n%s" % output + loggerinst.warning(description) self.add_message( level="WARNING", id="UNABLE_TO_GET_GRUB2_BOOT_LOADER_ENTRY", title="Unable to get the GRUB2 boot loader entry", - description="Couldn't get the default GRUB2 boot loader entry:\n%s" % output, + description=description, ) return loggerinst.debug("Setting RHEL kernel %s as the default boot loader entry." % output.strip()) output, ret_code = utils.run_subprocess(["/usr/sbin/grubby", "--set-default", output.strip()]) if ret_code: - loggerinst.warning("Couldn't set the default GRUB2 boot loader entry:\n%s" % output) + description = "Couldn't get the default GRUB2 boot loader entry:\n%s" % output + loggerinst.warning(description) self.add_message( level="WARNING", id="UNABLE_TO_SET_GRUB2_BOOT_LOADER_ENTRY", title="Unable to set the GRUB2 boot loader entry", - description="Couldn't set the default GRUB2 boot loader entry:\n%s" % output, + description=description, ) @@ -195,12 +197,13 @@ def run(self): None, ) if kernel_to_change: - loggerinst.warning("Detected leftover boot kernel, changing to RHEL kernel") + description = "Detected leftover boot kernel, changing to RHEL kernel" + loggerinst.warning(description) self.add_message( level="WARNING", id="LEFTOVER_BOOT_KERNEL_DETECTED", title="Leftover boot kernel detected", - description="Detected leftover boot kernel, changing to RHEL kernel", + description=description, ) # need to change to "kernel" in rhel7 and "kernel-core" in rhel8 new_kernel_str = "DEFAULTKERNEL=" + ("kernel" if system_info.version.major == 7 else "kernel-core") @@ -229,16 +232,16 @@ def remove_non_rhel_kernels(self): non_rhel_kernels = pkghandler.get_installed_pkgs_w_different_fingerprint( system_info.fingerprints_rhel, "kernel*" ) - if non_rhel_kernels: - loggerinst.info("Removing non-RHEL kernels\n") - pkghandler.print_pkg_info(non_rhel_kernels) - utils.remove_pkgs( - pkgs_to_remove=[pkghandler.get_pkg_nvra(pkg) for pkg in non_rhel_kernels], - ) - else: + if not non_rhel_kernels: loggerinst.info("None found.") - return non_rhel_kernels + return + loggerinst.info("Removing non-RHEL kernels\n") + pkghandler.print_pkg_info(non_rhel_kernels) + utils.remove_pkgs( + pkgs_to_remove=[pkghandler.get_pkg_nvra(pkg) for pkg in non_rhel_kernels], + ) + return non_rhel_kernels def install_additional_rhel_kernel_pkgs(self, additional_pkgs): """Convert2rhel removes all non-RHEL kernel packages, including kernel-tools, kernel-headers, etc. This function tries to install back all of these from RHEL repositories. From 58ca086e1b6fa2e3e1c14aa2364e1950d15dd4bf Mon Sep 17 00:00:00 2001 From: Preston Watson Date: Mon, 5 Aug 2024 11:32:48 -0400 Subject: [PATCH 14/17] Update RHEL_KERNEL_INSTALLED info block --- .../actions/conversion/preserve_only_rhel_kernel.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py index 66a623a244..7657af85db 100644 --- a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py +++ b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py @@ -108,9 +108,9 @@ def run(self): loggerinst.info("RHEL kernel has been installed.") self.add_message( level="INFO", - id="RHEL_KERNEL_INSTALLED", - title="RHEL kernel installed", - description="The RHEL kernel has been installed successfully.", + id="RHEL_KERNEL_INSTALL_VERIFIED", + title="RHEL kernel install verified", + description="The RHEL kernel has been verified to be on the system.", ) @@ -238,10 +238,10 @@ def remove_non_rhel_kernels(self): loggerinst.info("Removing non-RHEL kernels\n") pkghandler.print_pkg_info(non_rhel_kernels) - utils.remove_pkgs( - pkgs_to_remove=[pkghandler.get_pkg_nvra(pkg) for pkg in non_rhel_kernels], - ) + pkgs_to_remove = [pkghandler.get_pkg_nvra(pkg) for pkg in non_rhel_kernels] + utils.remove_pkgs(pkgs_to_remove) return non_rhel_kernels + def install_additional_rhel_kernel_pkgs(self, additional_pkgs): """Convert2rhel removes all non-RHEL kernel packages, including kernel-tools, kernel-headers, etc. This function tries to install back all of these from RHEL repositories. From 643f8397ae5579a2f94969f83d25fb18c2330840 Mon Sep 17 00:00:00 2001 From: Preston Watson Date: Mon, 5 Aug 2024 11:39:41 -0400 Subject: [PATCH 15/17] Update info log for kernel install --- convert2rhel/actions/conversion/preserve_only_rhel_kernel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py index 7657af85db..70640c8b38 100644 --- a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py +++ b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py @@ -105,7 +105,7 @@ def run(self): ) return - loggerinst.info("RHEL kernel has been installed.") + loggerinst.info("RHEL kernel has been verified to be on the system.") self.add_message( level="INFO", id="RHEL_KERNEL_INSTALL_VERIFIED", From d29c3a3f33519caef5193a05e62a8d41759eb51c Mon Sep 17 00:00:00 2001 From: Preston Watson Date: Mon, 5 Aug 2024 11:49:21 -0400 Subject: [PATCH 16/17] Fix unit tests --- .../actions/conversion/preserve_only_rhel_kernel.py | 2 +- .../actions/conversion/preserve_only_rhel_kernel_test.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py index 70640c8b38..96e2b891c2 100644 --- a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py +++ b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py @@ -163,7 +163,7 @@ def run(self): loggerinst.debug("Setting RHEL kernel %s as the default boot loader entry." % output.strip()) output, ret_code = utils.run_subprocess(["/usr/sbin/grubby", "--set-default", output.strip()]) if ret_code: - description = "Couldn't get the default GRUB2 boot loader entry:\n%s" % output + description = "Couldn't set the default GRUB2 boot loader entry:\n%s" % output loggerinst.warning(description) self.add_message( level="WARNING", diff --git a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py index d46305a3bf..7d76fef6ef 100644 --- a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py +++ b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py @@ -242,9 +242,9 @@ def test_verify_rhel_kernel_installed(self, monkeypatch, verify_rhel_kernel_inst ( actions.ActionMessage( level="INFO", - id="RHEL_KERNEL_INSTALLED", - title="RHEL kernel installed", - description="The RHEL kernel has been installed successfully.", + id="RHEL_KERNEL_INSTALL_VERIFIED", + title="RHEL kernel install verified", + description="The RHEL kernel has been verified to be on the system.", diagnosis=None, remediations=None, ), From d39ebc4c6526cbd7789e1735b227747de4c1d5b9 Mon Sep 17 00:00:00 2001 From: Preston Watson Date: Tue, 6 Aug 2024 12:03:24 -0400 Subject: [PATCH 17/17] Add unit test for invalid grub2 entries --- .../conversion/preserve_only_rhel_kernel.py | 2 +- .../preserve_only_rhel_kernel_test.py | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py index 96e2b891c2..60add7f5fe 100644 --- a/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py +++ b/convert2rhel/actions/conversion/preserve_only_rhel_kernel.py @@ -234,7 +234,7 @@ def remove_non_rhel_kernels(self): ) if not non_rhel_kernels: loggerinst.info("None found.") - return + return None loggerinst.info("Removing non-RHEL kernels\n") pkghandler.print_pkg_info(non_rhel_kernels) diff --git a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py index 7d76fef6ef..eef2cb1d78 100644 --- a/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py +++ b/convert2rhel/unit_tests/actions/conversion/preserve_only_rhel_kernel_test.py @@ -389,6 +389,55 @@ def test_fix_invalid_grub2_entries_messages( assert expected.issuperset(fix_invalid_grub2_entries_instance.messages) assert expected.issubset(fix_invalid_grub2_entries_instance.messages) + @pytest.mark.parametrize( + ("version", "expected"), + ( + (Version(7, 9), False), + (Version(8, 9), True), + ), + ) + def test_fix_invalid_grub2_entries_execution( + self, monkeypatch, fix_invalid_grub2_entries_instance, caplog, version, expected + ): + + monkeypatch.setattr(system_info, "version", version) + run_subprocess_mocked = RunSubprocessMocked( + side_effect=unit_tests.run_subprocess_side_effect( + ( + ( + "/usr/sbin/grubby", + "--default-kernel", + ), + ( + "bootloader", + 0, + ), + ), + ( + ( + "/usr/sbin/grubby", + "--set-default", + "bootloader", + ), + ( + "bootloader", + 0, + ), + ), + ), + ) + + monkeypatch.setattr( + utils, + "run_subprocess", + value=run_subprocess_mocked, + ) + fix_invalid_grub2_entries_instance.run() + if expected: + assert "Fixing GRUB boot loader" in caplog.text + else: + assert "Fixing GRUB boot loader" not in caplog.text + class TestFixDefaultKernel: @pytest.mark.parametrize(