From 68e286f5d36fc76ce06e8feff2fe418c96f3a9f5 Mon Sep 17 00:00:00 2001 From: Matej Matuska Date: Fri, 29 May 2026 13:33:23 +0200 Subject: [PATCH 086/105] lib/kernel: Fix rt kernel detection on centos The kernel detection function determine_kernel_type_from_uname() didn't take major-only versions as used for CentOS Stream into account and therefore it misidentified rt kernels as "ordinary" on CentOS Stream systems. The function is modified to use matches_version() from the version lib which already handles the versions comparison for CentOS Stream as. Jira: RHEL-161560 --- .../common/libraries/config/version.py | 13 ++++++ .../system_upgrade/common/libraries/kernel.py | 10 ++--- .../common/libraries/tests/test_kernel_lib.py | 43 ++++++++++++++----- 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/repos/system_upgrade/common/libraries/config/version.py b/repos/system_upgrade/common/libraries/config/version.py index 8eb02ef1..faba3e68 100644 --- a/repos/system_upgrade/common/libraries/config/version.py +++ b/repos/system_upgrade/common/libraries/config/version.py @@ -171,6 +171,19 @@ def matches_version(match_list, detected): """ Check if the `detected` version meets the criteria specified in `match_list`. + For CentOS Stream (which natively uses only major versions), the match list + and the detected version are automatically adjusted to ensure intuitive evaluation: + + - If `match_list` contains only major versions, the comparison is restricted + to the major version component: + version.matches_version(['> 8', '<= 9'], '9.5') # True + + - If `match_list` contains major.minor versions but `detected` is a major-only + version, the function resolves the input to its defined "virtual version" + before evaluation: + # e.g., if the virtual version for '9' is defined as '9.5' + version.matches_version(['> 8.10', '<= 9.7'], '9') # True + :param match_list: specification of versions to check against :type match_list: list or tuple of strings in one of the two following forms: ``['>'|'>='|'<'|'<='] .`` form, where elements are ANDed, diff --git a/repos/system_upgrade/common/libraries/kernel.py b/repos/system_upgrade/common/libraries/kernel.py index fc8c1167..0a160e7f 100644 --- a/repos/system_upgrade/common/libraries/kernel.py +++ b/repos/system_upgrade/common/libraries/kernel.py @@ -1,6 +1,7 @@ from collections import namedtuple from leapp.exceptions import StopActorExecutionError +from leapp.libraries.common.config.version import matches_version from leapp.libraries.stdlib import api, CalledProcessError, run KernelPkgInfo = namedtuple('KernelPkgInfo', ('name', 'version', 'release', 'arch', 'nevra')) @@ -14,6 +15,8 @@ class KernelType: REALTIME = 'realtime' +# TODO: rename rhel_version to something distro agnostic in the new function +# when this is deprecated def determine_kernel_type_from_uname(rhel_version, kernel_uname_r): """ Determine kernel type from given kernel release (uname-r). @@ -23,12 +26,7 @@ def determine_kernel_type_from_uname(rhel_version, kernel_uname_r): :returns: Kernel type based on a given uname_r :rtype: KernelType """ - version_fragments = rhel_version.split('.') - major_ver = version_fragments[0] - minor_ver = version_fragments[1] if len(version_fragments) > 1 else '0' - rhel_version = (major_ver, minor_ver) - - if rhel_version <= ('9', '2'): + if matches_version(['<= 9.2'], rhel_version): uname_r_infixes = { '.rt': KernelType.REALTIME } diff --git a/repos/system_upgrade/common/libraries/tests/test_kernel_lib.py b/repos/system_upgrade/common/libraries/tests/test_kernel_lib.py index a6696a3c..1687d0dc 100644 --- a/repos/system_upgrade/common/libraries/tests/test_kernel_lib.py +++ b/repos/system_upgrade/common/libraries/tests/test_kernel_lib.py @@ -5,23 +5,44 @@ import pytest from leapp.exceptions import StopActorExecutionError from leapp.libraries.common import kernel as kernel_lib from leapp.libraries.common.kernel import KernelType +from leapp.libraries.common.testutils import CurrentActorMocked +from leapp.libraries.stdlib import api @pytest.mark.parametrize( - ('rhel_version', 'uname_r', 'expected_kernel_type'), + ('version', 'uname_r', 'expected_kernel_type'), ( - ('7.9', '3.10.0-1160.el7.x86_64', KernelType.ORDINARY), - ('7.9', '3.10.0-1160.rt56.1131.el7.x86_64', KernelType.REALTIME), - ('8.7', '4.18.0-425.3.1.el8.x86_64', KernelType.ORDINARY), - ('8.7', '4.18.0-425.3.1.rt7.213.el8.x86_64', KernelType.REALTIME), - ('9.2', '5.14.0-284.11.1.el9_2.x86_64', KernelType.ORDINARY), - ('9.2', '5.14.0-284.11.1.rt14.296.el9_2.x86_64', KernelType.REALTIME), - ('9.3', '5.14.0-354.el9.x86_64', KernelType.ORDINARY), - ('9.3', '5.14.0-354.el9.x86_64+rt', KernelType.REALTIME), + # (version, virtual_version) + (('7.9', None), '3.10.0-1160.el7.x86_64', KernelType.ORDINARY), + (('7.9', None), '3.10.0-1160.rt56.1131.el7.x86_64', KernelType.REALTIME), + (('8.7', None), '4.18.0-425.3.1.el8.x86_64', KernelType.ORDINARY), + (('8.7', None), '4.18.0-425.3.1.rt7.213.el8.x86_64', KernelType.REALTIME), + (('9.2', None), '5.14.0-284.11.1.el9_2.x86_64', KernelType.ORDINARY), + (('9.2', None), '5.14.0-284.11.1.rt14.296.el9_2.x86_64', KernelType.REALTIME), + (('9.3', None), '5.14.0-354.el9.x86_64', KernelType.ORDINARY), + (('9.3', None), '5.14.0-354.el9.x86_64+rt', KernelType.REALTIME), + # centos + (('8', '8.7'), '4.18.0-425.3.1.el8.x86_64', KernelType.ORDINARY), + (('8', '8.7'), '4.18.0-425.3.1.rt7.213.el8.x86_64', KernelType.REALTIME), + (('9', '9.2'), '5.14.0-284.11.1.el9_2.x86_64', KernelType.ORDINARY), + (('9', '9.2'), '5.14.0-284.11.1.rt14.296.el9_2.x86_64', KernelType.REALTIME), + (('9', '9.3'), '5.14.0-354.el9.x86_64', KernelType.ORDINARY), + (('9', '9.3'), '5.14.0-354.el9.x86_64+rt', KernelType.REALTIME), ) ) -def test_determine_kernel_type_from_uname(rhel_version, uname_r, expected_kernel_type): - kernel_type = kernel_lib.determine_kernel_type_from_uname(rhel_version, uname_r) +def test_determine_kernel_type_from_uname(monkeypatch, version, uname_r, expected_kernel_type): + real_ver, virtual_ver = version + # needed to for lookups of virtual versions in matches_version + actor_mock = CurrentActorMocked( + release_id='centos' if '.' not in real_ver else 'rhel', + src_ver=real_ver, + dst_ver="irrelevant", + virtual_source_version=virtual_ver or real_ver, + virtual_target_version="irrelevant", + ) + monkeypatch.setattr(api, 'current_actor', actor_mock) + + kernel_type = kernel_lib.determine_kernel_type_from_uname(real_ver, uname_r) assert kernel_type == expected_kernel_type -- 2.54.0