forked from rpms/leapp-repository
		
	
		
			
				
	
	
		
			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
 | |
| 
 |