leapp-repository/SOURCES/0040-Fix-parsing-of-the-kernel-cmdline.patch
2025-06-24 11:34:57 +00:00

167 lines
6.3 KiB
Diff

From 2646484407bef15688fb4838c2f61d06f2098f81 Mon Sep 17 00:00:00 2001
From: Petr Stodulka <pstodulk@redhat.com>
Date: Wed, 30 Apr 2025 12:54:22 +0200
Subject: [PATCH 40/43] Fix parsing of the kernel cmdline
Original parsing has been splitting string tokens by "=" without a
limit, means that e.g.
root=UUID=some-id
has been split to
(root, UUID, some-id)
and and stored just "root" and "UUID" strings in the parsed msg,
instead of "root" and "UUID=some-id".
So split the key=value just based on the first occurence of "="
instead.
JIRA: RHELMISC-12490
Co-Authored-By: Karolina Kula <kkula@redhat.com>
---
.../common/actors/scankernelcmdline/actor.py | 16 ++---
.../libraries/scankernelcmdline.py | 23 +++++++
.../tests/test_scankernelcmdline.py | 67 +++++++++++++++++++
3 files changed, 94 insertions(+), 12 deletions(-)
create mode 100644 repos/system_upgrade/common/actors/scankernelcmdline/libraries/scankernelcmdline.py
create mode 100644 repos/system_upgrade/common/actors/scankernelcmdline/tests/test_scankernelcmdline.py
diff --git a/repos/system_upgrade/common/actors/scankernelcmdline/actor.py b/repos/system_upgrade/common/actors/scankernelcmdline/actor.py
index 9f8fef30..2f1a5ae2 100644
--- a/repos/system_upgrade/common/actors/scankernelcmdline/actor.py
+++ b/repos/system_upgrade/common/actors/scankernelcmdline/actor.py
@@ -1,12 +1,12 @@
from leapp.actors import Actor
-from leapp.libraries.stdlib import run
-from leapp.models import KernelCmdline, KernelCmdlineArg
+from leapp.libraries.actor import scankernelcmdline
+from leapp.models import KernelCmdline
from leapp.tags import FactsPhaseTag, IPUWorkflowTag
class ScanKernelCmdline(Actor):
"""
- No documentation has been provided for the scan_kernel_cmdline actor.
+ Scan the kernel command line of the booted system.
"""
name = 'scan_kernel_cmdline'
@@ -15,12 +15,4 @@ class ScanKernelCmdline(Actor):
tags = (FactsPhaseTag, IPUWorkflowTag)
def process(self):
- cmdline = run(['cat', '/proc/cmdline'])['stdout'].strip()
- parameters = []
- for parameter in cmdline.split(' '):
- if '=' in parameter:
- kv = parameter.split('=')
- parameters.append(KernelCmdlineArg(key=kv[0], value=kv[1]))
- else:
- parameters.append(KernelCmdlineArg(key=parameter))
- self.produce(KernelCmdline(parameters=parameters))
+ scankernelcmdline.parse_cmdline_input()
diff --git a/repos/system_upgrade/common/actors/scankernelcmdline/libraries/scankernelcmdline.py b/repos/system_upgrade/common/actors/scankernelcmdline/libraries/scankernelcmdline.py
new file mode 100644
index 00000000..9cffa70e
--- /dev/null
+++ b/repos/system_upgrade/common/actors/scankernelcmdline/libraries/scankernelcmdline.py
@@ -0,0 +1,23 @@
+from leapp.libraries.stdlib import api, CalledProcessError, run
+from leapp.models import KernelCmdline, KernelCmdlineArg
+
+
+def get_cmdline_input():
+ try:
+ cmdline_input = run(['cat', '/proc/cmdline'])['stdout'].strip()
+ return cmdline_input
+ except (OSError, CalledProcessError):
+ api.current_logger().debug('Executing `cat /proc/cmdline` failed', exc_info=True)
+ return ''
+
+
+def parse_cmdline_input():
+ cmdline = get_cmdline_input()
+ parameters = []
+ for parameter in cmdline.split(' '):
+ if '=' in parameter:
+ kv = parameter.split('=', 1)
+ parameters.append(KernelCmdlineArg(key=kv[0], value=kv[1]))
+ else:
+ parameters.append(KernelCmdlineArg(key=parameter))
+ api.produce(KernelCmdline(parameters=parameters))
diff --git a/repos/system_upgrade/common/actors/scankernelcmdline/tests/test_scankernelcmdline.py b/repos/system_upgrade/common/actors/scankernelcmdline/tests/test_scankernelcmdline.py
new file mode 100644
index 00000000..ff79054f
--- /dev/null
+++ b/repos/system_upgrade/common/actors/scankernelcmdline/tests/test_scankernelcmdline.py
@@ -0,0 +1,67 @@
+import pytest
+
+from leapp.libraries.actor import scankernelcmdline
+from leapp.libraries.common.testutils import CurrentActorMocked, produce_mocked
+from leapp.libraries.stdlib import api, CalledProcessError
+from leapp.models import KernelCmdline, KernelCmdlineArg
+
+
+def mock_cmd_output():
+ expected_cmd_output = (
+ 'BOOT_IMAGE=(hd0,msdos1)/vmlinuz-xxx root=UUID=some_uid ro console=tty0'
+ ' console=ttyS0,115200 rd_NO_PLYMOUTH biosdevname=0 net.ifnames=0 crashkernel=auto'
+ )
+ return expected_cmd_output
+
+
+def test_cmdline_output(monkeypatch):
+
+ monkeypatch.setattr(scankernelcmdline, 'get_cmdline_input', mock_cmd_output)
+ current_actor = CurrentActorMocked(src_ver='8.10', dst_ver='9.6')
+ monkeypatch.setattr(api, 'current_actor', current_actor)
+ monkeypatch.setattr(api, 'produce', produce_mocked())
+
+ scankernelcmdline.parse_cmdline_input()
+
+ expected_params = [KernelCmdlineArg(key=k, value=v) for k, v in [
+ ('BOOT_IMAGE', '(hd0,msdos1)/vmlinuz-xxx'),
+ ('root', 'UUID=some_uid'),
+ ('ro', None),
+ ('console', 'tty0'),
+ ('console', 'ttyS0,115200'),
+ ('rd_NO_PLYMOUTH', None),
+ ('biosdevname', '0'),
+ ('net.ifnames', '0'),
+ ('crashkernel', 'auto')]]
+
+ expected_output_msg = KernelCmdline(parameters=expected_params)
+ assert api.produce.model_instances
+ assert expected_output_msg == api.produce.model_instances[0]
+
+
+def test_cmdline_content(monkeypatch):
+
+ def run_mocked(cmd, **kwargs):
+ assert cmd == ['cat', '/proc/cmdline']
+ output = mock_cmd_output()
+ return {'stdout': output}
+
+ monkeypatch.setattr(scankernelcmdline, 'run', run_mocked)
+ cmd_output = scankernelcmdline.get_cmdline_input()
+ expected_cmd_output = mock_cmd_output()
+
+ assert cmd_output == expected_cmd_output
+
+
+@pytest.mark.parametrize('is_os_error', [True, False])
+def test_cmdline_run_failed(monkeypatch, is_os_error):
+
+ def run_mocked_error(cmd, **kwargs):
+ assert cmd == ['cat', '/proc/cmdline']
+ if is_os_error:
+ raise OSError('OSError raised')
+ raise CalledProcessError("CalledProcessError raised", cmd, "result")
+
+ monkeypatch.setattr(scankernelcmdline, 'run', run_mocked_error)
+ cmd_output = scankernelcmdline.get_cmdline_input()
+ assert cmd_output == ''
--
2.49.0