Skip to content

Commit c2c96af

Browse files
matejmatuskapirat89
authored andcommitted
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
1 parent b997e4e commit c2c96af

File tree

2 files changed

+116
-11
lines changed

2 files changed

+116
-11
lines changed

repos/system_upgrade/common/actors/kernelcmdlineconfig/libraries/kernelcmdlineconfig.py

+69-10
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,55 @@ def _extract_grubby_value(record):
109109
return matches.group(2)
110110

111111

112+
def report_multple_entries_for_default_kernel():
113+
if use_cmdline_file():
114+
report_hint = (
115+
'After the system has been rebooted into the new version of RHEL,'
116+
' check that configured default kernel cmdline arguments in /etc/kernel/cmdline '
117+
' are correct. In case that different arguments are expected, update the file as needed.'
118+
)
119+
else:
120+
report_hint = (
121+
'After the system has been rebooted into the new version of RHEL,'
122+
' check that configured default kernel cmdline arguments are set as expected, using'
123+
' the `grub2-editenv list` command. '
124+
' If different default arguments are expected, update them using grub2-editenv.\n'
125+
' For example, consider that current booted kernel has correct kernel cmdline'
126+
' arguments and /proc/cmdline contains:\n\n'
127+
' BOOT_IMAGE=(hd0,msdos1)/vmlinuz-4.18.0-425.3.1.el8.x86_64'
128+
' root=/dev/mapper/rhel_ibm--root ro console=tty0'
129+
' console=ttyS0,115200 rd_NO_PLYMOUTH\n\n'
130+
' then run the following grub2-editenv command:\n\n'
131+
' # grub2-editenv - set "kernelopts=root=/dev/mapper/rhel_ibm--root'
132+
' ro console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH"'
133+
)
134+
135+
reporting.create_report([
136+
reporting.Title('Ensure that expected default kernel cmdline arguments are set'),
137+
reporting.Summary(
138+
'During the upgrade we needed to modify the kernel command line arguments.'
139+
' However, multiple bootloader entries with different arguments were found for the default'
140+
' kernel (perhaps MAKEDEBUG=yes is set in /etc/sysconfig/kernel).'
141+
' Leapp used the arguments from the first found entry of the target kernel'
142+
' and set it as the new default kernel cmdline arguments for kernels installed in the future.'
143+
),
144+
reporting.Remediation(hint=report_hint),
145+
reporting.Severity(reporting.Severity.HIGH),
146+
reporting.Groups([
147+
reporting.Groups.BOOT,
148+
reporting.Groups.KERNEL,
149+
reporting.Groups.POST,
150+
]),
151+
reporting.RelatedResource('file', '/etc/kernel/cmdline'),
152+
])
153+
154+
112155
def retrieve_args_for_default_kernel(kernel_info):
113156
# Copy the args for the default kernel to all kernels.
114157
kernel_args = None
115158
kernel_root = None
159+
detected_multiple_entries = False
160+
116161
cmd = ['grubby', '--info', kernel_info.kernel_img_path]
117162
output = stdlib.run(cmd, split=False)
118163
for record in output['stdout'].splitlines():
@@ -122,26 +167,40 @@ def retrieve_args_for_default_kernel(kernel_info):
122167
temp_kernel_args = _extract_grubby_value(record)
123168

124169
if kernel_args:
125-
api.current_logger().warning('Grubby output is malformed:'
126-
' `args=` is listed more than once.')
127170
if kernel_args != temp_kernel_args:
128-
raise ReadOfKernelArgsError('Grubby listed `args=` multiple'
129-
' times with different values.')
130-
kernel_args = _extract_grubby_value(record)
171+
api.current_logger().warning(
172+
'Grubby output listed `args=` multiple times with different values,'
173+
' continuing with the first result'
174+
)
175+
detected_multiple_entries = True
176+
else:
177+
api.current_logger().warning('Grubby output listed `args=` more than once')
178+
else:
179+
kernel_args = temp_kernel_args
131180
elif record.startswith('root='):
132-
api.current_logger().warning('Grubby output is malformed:'
133-
' `root=` is listed more than once.')
181+
temp_kernel_root = _extract_grubby_value(record)
182+
134183
if kernel_root:
135-
raise ReadOfKernelArgsError('Grubby listed `root=` multiple'
136-
' times with different values')
137-
kernel_root = _extract_grubby_value(record)
184+
if kernel_root != temp_kernel_root:
185+
api.current_logger().warning(
186+
'Grubby output listed `root=` multiple times with different values,'
187+
' continuing with the first result'
188+
)
189+
detected_multiple_entries = True
190+
else:
191+
api.current_logger().warning('Grubby output listed `root=` more than once')
192+
else:
193+
kernel_root = temp_kernel_root
138194

139195
if not kernel_args or not kernel_root:
140196
raise ReadOfKernelArgsError(
141197
'Failed to retrieve kernel command line to save for future installed'
142198
' kernels: root={}, args={}'.format(kernel_root, kernel_args)
143199
)
144200

201+
if detected_multiple_entries:
202+
report_multple_entries_for_default_kernel()
203+
145204
return kernel_root, kernel_args
146205

147206

repos/system_upgrade/common/actors/kernelcmdlineconfig/tests/test_kernelcmdlineconfig.py

+47-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44

55
import pytest
66

7+
from leapp import reporting
78
from leapp.exceptions import StopActorExecutionError
89
from leapp.libraries import stdlib
910
from leapp.libraries.actor import kernelcmdlineconfig
1011
from leapp.libraries.common.config import architecture
11-
from leapp.libraries.common.testutils import CurrentActorMocked
12+
from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked
1213
from leapp.libraries.stdlib import api
1314
from leapp.models import InstalledTargetKernelInfo, KernelCmdlineArg, TargetKernelCmdlineArgTasks
1415

@@ -183,6 +184,51 @@ def test_kernelcmdline_config_no_version(monkeypatch):
183184
assert not mocked_run.commands
184185

185186

187+
SECOND_KERNEL_ARGS = (
188+
'ro rootflags=subvol=root'
189+
' resume=/dev/mapper/luks-2c0df999-81ec-4a35-a1f9-b93afee8c6ad'
190+
' rd.luks.uuid=luks-90a6412f-c588-46ca-9118-5aca35943d25'
191+
' rd.luks.uuid=luks-2c0df999-81ec-4a35-a1f9-b93afee8c6ad'
192+
)
193+
SECOND_KERNEL_ROOT = 'UUID=1aa15850-2685-418d-95a6-f7266a2de83b'
194+
195+
196+
@pytest.mark.parametrize(
197+
'second_grubby_output',
198+
(
199+
TEMPLATE_GRUBBY_INFO_OUTPUT.format(SECOND_KERNEL_ARGS, SECOND_KERNEL_ROOT),
200+
TEMPLATE_GRUBBY_INFO_OUTPUT.format(SAMPLE_KERNEL_ARGS, SECOND_KERNEL_ROOT),
201+
TEMPLATE_GRUBBY_INFO_OUTPUT.format(SECOND_KERNEL_ARGS, SAMPLE_KERNEL_ROOT),
202+
)
203+
)
204+
def test_kernelcmdline_config_mutiple_args(monkeypatch, second_grubby_output):
205+
kernel_img_path = '/boot/vmlinuz-X'
206+
kernel_info = InstalledTargetKernelInfo(pkg_nevra=TARGET_KERNEL_NEVRA,
207+
uname_r='',
208+
kernel_img_path=kernel_img_path,
209+
initramfs_path='/boot/initramfs-X')
210+
211+
# For this test, we need to check we get the proper report if grubby --info
212+
# outputs multiple different `root=` or `args=`
213+
# and that the first ones are used
214+
grubby_info_output = "\n".join((SAMPLE_GRUBBY_INFO_OUTPUT, second_grubby_output))
215+
216+
mocked_run = MockedRun(
217+
outputs={" ".join(("grubby", "--info", kernel_img_path)): grubby_info_output,
218+
}
219+
)
220+
monkeypatch.setattr(stdlib, 'run', mocked_run)
221+
monkeypatch.setattr(api, 'current_actor', CurrentActorMocked())
222+
monkeypatch.setattr(reporting, "create_report", create_report_mocked())
223+
224+
root, args = kernelcmdlineconfig.retrieve_args_for_default_kernel(kernel_info)
225+
assert root == SAMPLE_KERNEL_ROOT
226+
assert args == SAMPLE_KERNEL_ARGS
227+
assert reporting.create_report.called == 1
228+
expected_title = 'Ensure that expected default kernel cmdline arguments are set'
229+
assert expected_title in reporting.create_report.report_fields['title']
230+
231+
186232
def test_kernelcmdline_config_malformed_args(monkeypatch):
187233
kernel_img_path = '/boot/vmlinuz-X'
188234
kernel_info = InstalledTargetKernelInfo(pkg_nevra=TARGET_KERNEL_NEVRA,

0 commit comments

Comments
 (0)