From 3356c045fe2982f3a26b26b46258398b490a6d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Matu=C5=A1ka?= Date: Thu, 17 Jul 2025 14:33:55 +0200 Subject: [PATCH 66/66] Inhibit upgrade on systems with cgroupsv1 on 9to10 (#1392) * Inhibit upgrade on systems with cgroupsv1 on 9to10 cgroups-v1 were deprecated in RHEL 9 and are unsupported in RHEL 10. The option to switch to cgroups-v1 is ignored. Users have to migrate to cgroups-v2 in order to upgrade. Both legacy and hybrid modes are unsupported. Only unified hierarchy (cgroups-v2) is supported. More info on how the modes are switched is at: https://www.freedesktop.org/software/systemd/man/247/systemd.html#systemd.unified_cgroup_hierarchy and https://www.freedesktop.org/software/systemd/man/247/systemd.html#systemd.legacy_systemd_cgroup_controller. Jira: RHEL-81212 --- .../actors/inhibitcgroupsv1/actor.py | 23 ++++++ .../libraries/inhibitcgroupsv1.py | 56 ++++++++++++++ .../tests/test_inhibitcgroupsv1.py | 74 +++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 repos/system_upgrade/el9toel10/actors/inhibitcgroupsv1/actor.py create mode 100644 repos/system_upgrade/el9toel10/actors/inhibitcgroupsv1/libraries/inhibitcgroupsv1.py create mode 100644 repos/system_upgrade/el9toel10/actors/inhibitcgroupsv1/tests/test_inhibitcgroupsv1.py diff --git a/repos/system_upgrade/el9toel10/actors/inhibitcgroupsv1/actor.py b/repos/system_upgrade/el9toel10/actors/inhibitcgroupsv1/actor.py new file mode 100644 index 00000000..7a3e4be4 --- /dev/null +++ b/repos/system_upgrade/el9toel10/actors/inhibitcgroupsv1/actor.py @@ -0,0 +1,23 @@ +from leapp.actors import Actor +from leapp.libraries.actor import inhibitcgroupsv1 +from leapp.models import KernelCmdline +from leapp.reporting import Report +from leapp.tags import ChecksPhaseTag, IPUWorkflowTag + + +class InhibitCgroupsv1(Actor): + """ + Inhibit upgrade if cgroups-v1 are enabled + + Support for cgroups-v1 was deprecated in RHEL 9 and removed in RHEL 10. + Both legacy and hybrid modes are unsupported, only the unified cgroup + hierarchy (cgroups-v2) is supported. + """ + + name = "inhibit_cgroupsv1" + consumes = (KernelCmdline,) + produces = (Report,) + tags = (ChecksPhaseTag, IPUWorkflowTag) + + def process(self): + inhibitcgroupsv1.process() diff --git a/repos/system_upgrade/el9toel10/actors/inhibitcgroupsv1/libraries/inhibitcgroupsv1.py b/repos/system_upgrade/el9toel10/actors/inhibitcgroupsv1/libraries/inhibitcgroupsv1.py new file mode 100644 index 00000000..6c891f22 --- /dev/null +++ b/repos/system_upgrade/el9toel10/actors/inhibitcgroupsv1/libraries/inhibitcgroupsv1.py @@ -0,0 +1,56 @@ +from leapp import reporting +from leapp.exceptions import StopActorExecutionError +from leapp.libraries.stdlib import api +from leapp.models import KernelCmdline + + +def process(): + kernel_cmdline = next(api.consume(KernelCmdline), None) + if not kernel_cmdline: + # really unlikely + raise StopActorExecutionError("Did not receive any KernelCmdline messages.") + + unified_hierarchy = True # default since RHEL 9 + legacy_controller_present = False + for param in kernel_cmdline.parameters: + if param.key == "systemd.unified_cgroup_hierarchy": + if param.value is not None and param.value.lower() in ("0", "false", "no"): + unified_hierarchy = False + if param.key == "systemd.legacy_systemd_cgroup_controller": + # no matter the value, it should be removed + # it has no effect when unified hierarchy is enabled + legacy_controller_present = True + + if unified_hierarchy: + api.current_logger().debug("cgroups-v2 already in use, nothing to do, skipping.") + return + + remediation_cmd_args = ["systemd.unified_cgroup_hierarchy"] + if legacy_controller_present: + remediation_cmd_args.append('systemd.legacy_systemd_cgroup_controller') + + summary = ( + "Leapp detected cgroups-v1 is enabled on the system." + " The support of cgroups-v1 was deprecated in RHEL 9 and is removed in RHEL 10." + " Software requiring cgroups-v1 might not work correctly or at all on RHEL 10." + ) + reporting.create_report( + [ + reporting.Title("cgroups-v1 enabled on the system"), + reporting.Summary(summary), + reporting.Severity(reporting.Severity.HIGH), + reporting.Groups([reporting.Groups.INHIBITOR, reporting.Groups.KERNEL]), + reporting.RelatedResource("package", "systemd"), + reporting.Remediation( + hint="Make sure no third party software requires cgroups-v1 and switch to cgroups-v2.", + # remove the args from commandline, the defaults are the desired values + commands=[ + [ + "grubby", + "--update-kernel=ALL", + '--remove-args="{}"'.format(",".join(remediation_cmd_args)), + ], + ], + ), + ] + ) diff --git a/repos/system_upgrade/el9toel10/actors/inhibitcgroupsv1/tests/test_inhibitcgroupsv1.py b/repos/system_upgrade/el9toel10/actors/inhibitcgroupsv1/tests/test_inhibitcgroupsv1.py new file mode 100644 index 00000000..9b3ec96f --- /dev/null +++ b/repos/system_upgrade/el9toel10/actors/inhibitcgroupsv1/tests/test_inhibitcgroupsv1.py @@ -0,0 +1,74 @@ +import pytest + +from leapp import reporting +from leapp.libraries.actor import inhibitcgroupsv1 +from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked +from leapp.libraries.stdlib import api +from leapp.models import KernelCmdline, KernelCmdlineArg + + +@pytest.mark.parametrize( + "cmdline_params", ( + ([KernelCmdlineArg(key="systemd.unified_cgroup_hierarchy", value="0")]), + ([KernelCmdlineArg(key="systemd.unified_cgroup_hierarchy", value="false")]), + ([KernelCmdlineArg(key="systemd.unified_cgroup_hierarchy", value="False")]), + ([KernelCmdlineArg(key="systemd.unified_cgroup_hierarchy", value="no")]), + ( + [ + KernelCmdlineArg(key="systemd.unified_cgroup_hierarchy", value="0"), + KernelCmdlineArg(key="systemd.legacy_systemd_cgroup_controller", value="0"), + ] + ), ( + [ + KernelCmdlineArg(key="systemd.unified_cgroup_hierarchy", value="0"), + KernelCmdlineArg(key="systemd.legacy_systemd_cgroup_controller", value="1"), + ] + ) + ) +) +def test_inhibit_should_inhibit(monkeypatch, cmdline_params): + curr_actor_mocked = CurrentActorMocked(msgs=[KernelCmdline(parameters=cmdline_params)]) + monkeypatch.setattr(api, "current_actor", curr_actor_mocked) + monkeypatch.setattr(reporting, "create_report", create_report_mocked()) + + inhibitcgroupsv1.process() + + assert reporting.create_report.called == 1 + report = reporting.create_report.reports[0] + assert "cgroups-v1" in report["title"] + assert reporting.Groups.INHIBITOR in report["groups"] + + command = [r for r in report["detail"]["remediations"] if r["type"] == "command"][0] + assert "systemd.unified_cgroup_hierarchy" in command['context'][2] + if len(cmdline_params) == 2: + assert "systemd.legacy_systemd_cgroup_controller" in command['context'][2] + + +@pytest.mark.parametrize( + "cmdline_params", ( + ([KernelCmdlineArg(key="systemd.unified_cgroup_hierarchy", value="1")]), + ([KernelCmdlineArg(key="systemd.unified_cgroup_hierarchy", value="true")]), + ([KernelCmdlineArg(key="systemd.unified_cgroup_hierarchy", value="True")]), + ([KernelCmdlineArg(key="systemd.unified_cgroup_hierarchy", value="yes")]), + ([KernelCmdlineArg(key="systemd.unified_cgroup_hierarchy", value=None)]), + ( + [ + KernelCmdlineArg(key="systemd.unified_cgroup_hierarchy", value="1"), + KernelCmdlineArg(key="systemd.legacy_systemd_cgroup_controller", value="1"), + ] + ), ( + [ + KernelCmdlineArg(key="systemd.unified_cgroup_hierarchy", value="1"), + KernelCmdlineArg(key="systemd.legacy_systemd_cgroup_controller", value="0"), + ] + ), + ) +) +def test_inhibit_should_not_inhibit(monkeypatch, cmdline_params): + curr_actor_mocked = CurrentActorMocked(msgs=[KernelCmdline(parameters=cmdline_params)]) + monkeypatch.setattr(api, "current_actor", curr_actor_mocked) + monkeypatch.setattr(reporting, "create_report", create_report_mocked()) + + inhibitcgroupsv1.process() + + assert not reporting.create_report.called -- 2.50.1