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