From 1aafb7317df1f18934aeafc2222296c037ee2e43 Mon Sep 17 00:00:00 2001 From: Roman Prilipskii Date: Mon, 27 Apr 2026 12:06:10 -0400 Subject: [PATCH 1/4] CLOS-4056: gate CLN-assuming actors on is_cln_configured() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Systems migrated to the no-auth (SWNG) scheme no longer have CLN as a package source. Several CL-specific actors assumed CLN was always active and either crashed on missing files or produced spurious inhibitors. Add cln_detect.is_cln_configured() — True when the CLN plumbing is present and not explicitly disabled (registration file exists + spacewalk plugin installed + plugin enabled). Gate these actors on it: - switch_cln_channel: skip the cln-switch-channel call on no-auth systems. Also downgrade the failed-switch inhibitor to a MEDIUM report, since a failure on a transitional system where CLN plumbing lingers but is no longer usable should not block the upgrade — CL9 packages come from cl-channel / cloudlinux9-baseos instead. - pin_cln_mirror / unpin_cln_mirror: no-op on no-auth systems; also wrap the up2date update in try/except in pin_cln_mirror in case the file was not shipped on the target. - check_rhn_version_override / reset_rhn_version_override: skip on no-auth systems and fall back cleanly when /etc/sysconfig/rhn/up2date is missing. reset_rhn_version_override: also fix a pre-existing bug where rebinding inside the loop did not update config_data, so the reset was silently a no-op. enable_yum_spacewalk_plugin is not touched here — CLOS-3960 has concurrent work on it. --- .../actors/checkrhnversionoverride/actor.py | 52 ++++++++----- .../cloudlinux/actors/pinclnmirror/actor.py | 19 ++++- .../actors/resetrhnversionoverride/actor.py | 29 ++++++-- .../actors/switchclnchannel/actor.py | 29 ++++++-- .../cloudlinux/actors/unpinclnmirror/actor.py | 5 ++ .../cloudlinux/libraries/cln_detect.py | 55 ++++++++++++++ .../libraries/tests/test_cln_detect.py | 74 +++++++++++++++++++ 7 files changed, 229 insertions(+), 34 deletions(-) create mode 100644 repos/system_upgrade/cloudlinux/libraries/cln_detect.py create mode 100644 repos/system_upgrade/cloudlinux/libraries/tests/test_cln_detect.py diff --git a/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py b/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py index 6a21e10b6e..a9786d143e 100644 --- a/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py @@ -1,8 +1,10 @@ from leapp.actors import Actor from leapp import reporting +from leapp.libraries.stdlib import api from leapp.reporting import Report from leapp.tags import ChecksPhaseTag, IPUWorkflowTag from leapp.libraries.common.cllaunch import run_on_cloudlinux +from leapp.libraries.common.cln_detect import is_cln_configured class CheckRhnVersionOverride(Actor): @@ -17,23 +19,35 @@ class CheckRhnVersionOverride(Actor): @run_on_cloudlinux def process(self): + if not is_cln_configured(): + # CLOS-4056: no-auth systems have no CLN config to inspect. + return + up2date_config = '/etc/sysconfig/rhn/up2date' - with open(up2date_config, 'r') as f: - config_data = f.readlines() - for line in config_data: - if line.startswith('versionOverride='): - stripped_line = line.strip().split("=") - versionOverrideValue = stripped_line[1] - # If the version is being overriden to 8, we can continue as is. - if versionOverrideValue not in ['', '8']: - title = 'RHN up2date: versionOverride overwritten by the upgrade' - summary = ("The RHN config file up2date has a set value of the versionOverride option: {}." - " This value will get overwritten by the upgrade process, and reset to an empty" - " value once it's complete.".format(versionOverrideValue)) - reporting.create_report([ - reporting.Title(title), - reporting.Summary(summary), - reporting.Severity(reporting.Severity.MEDIUM), - reporting.Groups([reporting.Groups.OS_FACTS]), - reporting.RelatedResource('file', '/etc/sysconfig/rhn/up2date') - ]) + try: + with open(up2date_config, 'r') as f: + config_data = f.readlines() + except (OSError, IOError): + api.current_logger().info( + "RHN up2date config %s not present; skipping versionOverride check", + up2date_config, + ) + return + + for line in config_data: + if line.startswith('versionOverride='): + stripped_line = line.strip().split("=") + versionOverrideValue = stripped_line[1] + # If the version is being overriden to 8, we can continue as is. + if versionOverrideValue not in ['', '8']: + title = 'RHN up2date: versionOverride overwritten by the upgrade' + summary = ("The RHN config file up2date has a set value of the versionOverride option: {}." + " This value will get overwritten by the upgrade process, and reset to an empty" + " value once it's complete.".format(versionOverrideValue)) + reporting.create_report([ + reporting.Title(title), + reporting.Summary(summary), + reporting.Severity(reporting.Severity.MEDIUM), + reporting.Groups([reporting.Groups.OS_FACTS]), + reporting.RelatedResource('file', '/etc/sysconfig/rhn/up2date') + ]) diff --git a/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py b/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py index bc1686233f..162dbba96d 100644 --- a/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py @@ -4,6 +4,7 @@ from leapp.actors import Actor from leapp.libraries.stdlib import api from leapp.libraries.common.cllaunch import run_on_cloudlinux +from leapp.libraries.common.cln_detect import is_cln_configured from leapp.libraries.common.cln_switch import get_target_userspace_path from leapp.tags import DownloadPhaseTag, IPUWorkflowTag from leapp.libraries.common.config.version import get_target_major_version @@ -25,6 +26,13 @@ class PinClnMirror(Actor): @run_on_cloudlinux def process(self): """Pin CLN mirror""" + if not is_cln_configured(): + # CLOS-4056: no-auth systems don't use CLN mirrors; skip cleanly. + api.current_logger().info( + "CLN is not configured on this system; skipping mirror pinning" + ) + return + target_userspace = get_target_userspace_path() api.current_logger().info("Pin CLN mirror: target userspace=%s", target_userspace) @@ -54,6 +62,11 @@ def process(self): api.current_logger().info("Pin CLN mirror %s in %s", mirror_url, mirrorlist_path) up2date_path = os.path.join(target_userspace, 'etc/sysconfig/rhn/up2date') - with open(up2date_path, 'a+') as file: - file.write('\nmirrorURL[comment]=Set mirror URL to /etc/mirrorlist\nmirrorURL=file:///etc/mirrorlist\n') - api.current_logger().info("Updated up2date_path %s", up2date_path) + try: + with open(up2date_path, 'a+') as file: + file.write('\nmirrorURL[comment]=Set mirror URL to /etc/mirrorlist\nmirrorURL=file:///etc/mirrorlist\n') + api.current_logger().info("Updated up2date_path %s", up2date_path) + except (OSError, IOError) as e: + api.current_logger().info( + "Could not update %s: %s", up2date_path, e, + ) diff --git a/repos/system_upgrade/cloudlinux/actors/resetrhnversionoverride/actor.py b/repos/system_upgrade/cloudlinux/actors/resetrhnversionoverride/actor.py index 21b2164cb0..7b5f5d0f51 100644 --- a/repos/system_upgrade/cloudlinux/actors/resetrhnversionoverride/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/resetrhnversionoverride/actor.py @@ -1,6 +1,8 @@ from leapp.actors import Actor +from leapp.libraries.stdlib import api from leapp.tags import FinalizationPhaseTag, IPUWorkflowTag from leapp.libraries.common.cllaunch import run_on_cloudlinux +from leapp.libraries.common.cln_detect import is_cln_configured class ResetRhnVersionOverride(Actor): @@ -15,11 +17,26 @@ class ResetRhnVersionOverride(Actor): @run_on_cloudlinux def process(self): + if not is_cln_configured(): + # CLOS-4056: no-auth systems have no CLN config to reset. + return + up2date_config = '/etc/sysconfig/rhn/up2date' - with open(up2date_config, 'r') as f: - config_data = f.readlines() - for line in config_data: - if line.startswith('versionOverride='): - line = 'versionOverride=' + try: + with open(up2date_config, 'r') as f: + config_data = f.readlines() + except (OSError, IOError): + api.current_logger().info( + "RHN up2date config %s not present; skipping versionOverride reset", + up2date_config, + ) + return + + new_data = [] + for line in config_data: + if line.startswith('versionOverride='): + new_data.append('versionOverride=\n') + else: + new_data.append(line) with open(up2date_config, 'w') as f: - f.writelines(config_data) + f.writelines(new_data) diff --git a/repos/system_upgrade/cloudlinux/actors/switchclnchannel/actor.py b/repos/system_upgrade/cloudlinux/actors/switchclnchannel/actor.py index 86421856b2..e80f0e8fa6 100644 --- a/repos/system_upgrade/cloudlinux/actors/switchclnchannel/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/switchclnchannel/actor.py @@ -3,7 +3,8 @@ from leapp.tags import FirstBootPhaseTag, IPUWorkflowTag from leapp.libraries.stdlib import CalledProcessError from leapp.libraries.common.cllaunch import run_on_cloudlinux -from leapp.libraries.common.cln_switch import cln_switch, get_target_userspace_path +from leapp.libraries.common.cln_detect import is_cln_configured +from leapp.libraries.common.cln_switch import cln_switch from leapp import reporting from leapp.reporting import Report from leapp.libraries.common.config.version import get_target_major_version @@ -22,9 +23,22 @@ class SwitchClnChannel(Actor): @run_on_cloudlinux def process(self): + if not is_cln_configured(): + # CLOS-4056: No-auth (SWNG) systems have no CLN plumbing. Skipping + # the channel switch here is correct — the system receives CL9 + # packages via cl-channel / cloudlinux9-baseos instead. + api.current_logger().info( + "CLN is not configured on this system; skipping channel switch" + ) + return + try: cln_switch(target=int(get_target_major_version())) except CalledProcessError as e: + # CLOS-4056: Do not inhibit. CLN may be partially configured (legacy + # registration files present but no working registration) on systems + # transitioning to the no-auth scheme, and a failed channel switch + # there is expected — the no-auth repos still serve CL9 packages. reporting.create_report( [ reporting.Title( @@ -33,17 +47,20 @@ def process(self): reporting.Summary( "Command {} failed with exit code {}." " The most probable cause of that is a problem with this system's" - " CloudLinux Network registration.".format(e.command, e.exit_code) + " CloudLinux Network registration. If this system now uses the" + " no-auth (SWNG) repository scheme, this failure is harmless —" + " CL9 packages come from cl-channel / cloudlinux9-baseos instead" + " of CLN.".format(e.command, e.exit_code) ), reporting.Remediation( - hint="Check the state of this system's registration with \'rhn_check\'." - " Attempt to re-register the system with \'rhnreg_ks --force\'." + hint="If you rely on CLN: check registration with 'rhn_check' and" + " re-register with 'rhnreg_ks --force'. If you have migrated to" + " no-auth repos, this message can be ignored." ), - reporting.Severity(reporting.Severity.HIGH), + reporting.Severity(reporting.Severity.MEDIUM), reporting.Groups( [reporting.Groups.OS_FACTS, reporting.Groups.AUTHENTICATION] ), - reporting.Groups([reporting.Groups.INHIBITOR]), ] ) except OSError as e: diff --git a/repos/system_upgrade/cloudlinux/actors/unpinclnmirror/actor.py b/repos/system_upgrade/cloudlinux/actors/unpinclnmirror/actor.py index 8e7ffc93a0..cc2247d91e 100644 --- a/repos/system_upgrade/cloudlinux/actors/unpinclnmirror/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/unpinclnmirror/actor.py @@ -2,6 +2,7 @@ from leapp.actors import Actor from leapp.libraries.common.cllaunch import run_on_cloudlinux +from leapp.libraries.common.cln_detect import is_cln_configured from leapp.libraries.common.cln_switch import get_target_userspace_path from leapp.tags import FirstBootPhaseTag, IPUWorkflowTag @@ -19,6 +20,10 @@ class UnpinClnMirror(Actor): @run_on_cloudlinux def process(self): + if not is_cln_configured(): + # CLOS-4056: pinclnmirror was skipped on no-auth systems, nothing to unpin. + return + target_userspace = get_target_userspace_path() mirrorlist_path = os.path.join(target_userspace, 'etc/mirrorlist') diff --git a/repos/system_upgrade/cloudlinux/libraries/cln_detect.py b/repos/system_upgrade/cloudlinux/libraries/cln_detect.py new file mode 100644 index 0000000000..623f36a71a --- /dev/null +++ b/repos/system_upgrade/cloudlinux/libraries/cln_detect.py @@ -0,0 +1,55 @@ +"""Detection helpers for CLN (CloudLinux Network / Spacewalk) state. + +A system is considered to have CLN *configured* when it has registration +state plus the spacewalk DNF/YUM plugin installed and not explicitly +disabled. Systems that have been migrated to the no-auth (SWNG mirrorlist) +scheme have either: + + - no `/etc/sysconfig/rhn/systemid` (never registered or deregistered), + - no spacewalk plugin installed (rhn-client-tools >= 3.0.1 removes it), or + - the plugin's `enabled = 0` in its config. + +CLOS-4056: several CloudLinux-specific actors were written when CLN was the +only scheme and assume it is always active. They need to gate their +behavior on `is_cln_configured()` so systems on the no-auth scheme pass +through without bogus inhibitors or crashes. +""" + +import os + + +RHN_SYSTEMID = '/etc/sysconfig/rhn/systemid' +SPACEWALK_DNF_CONF = '/etc/dnf/plugins/spacewalk.conf' +SPACEWALK_YUM_CONF = '/etc/yum/pluginconf.d/spacewalk.conf' + + +def _plugin_explicitly_disabled(conf_path): + try: + with open(conf_path) as f: + for line in f: + stripped = line.strip().lower() + if not stripped or stripped.startswith('#') or stripped.startswith('['): + continue + if stripped.startswith('enabled') and '=' in stripped: + value = stripped.split('=', 1)[1].strip() + return value == '0' + except (OSError, IOError): + pass + return False + + +def is_cln_configured(): + """Return True if CLN plumbing is present and not disabled on this system.""" + if not os.path.exists(RHN_SYSTEMID): + return False + + configs = [p for p in (SPACEWALK_DNF_CONF, SPACEWALK_YUM_CONF) if os.path.exists(p)] + if not configs: + return False + + # If any plugin config explicitly disables the plugin, treat as no-auth. + for conf in configs: + if _plugin_explicitly_disabled(conf): + return False + + return True diff --git a/repos/system_upgrade/cloudlinux/libraries/tests/test_cln_detect.py b/repos/system_upgrade/cloudlinux/libraries/tests/test_cln_detect.py new file mode 100644 index 0000000000..ee2bbae411 --- /dev/null +++ b/repos/system_upgrade/cloudlinux/libraries/tests/test_cln_detect.py @@ -0,0 +1,74 @@ +import os + +import pytest + +from leapp.libraries.common import cln_detect + + +@pytest.fixture +def clean_paths(monkeypatch, tmp_path): + """Point cln_detect at a clean tmp dir so each test starts from no state.""" + systemid = tmp_path / "systemid" + dnf_conf = tmp_path / "dnf_spacewalk.conf" + yum_conf = tmp_path / "yum_spacewalk.conf" + monkeypatch.setattr(cln_detect, "RHN_SYSTEMID", str(systemid)) + monkeypatch.setattr(cln_detect, "SPACEWALK_DNF_CONF", str(dnf_conf)) + monkeypatch.setattr(cln_detect, "SPACEWALK_YUM_CONF", str(yum_conf)) + return {"systemid": systemid, "dnf_conf": dnf_conf, "yum_conf": yum_conf} + + +def _touch(path, content=""): + path.write_text(content) + + +def test_no_systemid_means_no_cln(clean_paths): + # Without /etc/sysconfig/rhn/systemid the system is not registered with CLN. + assert cln_detect.is_cln_configured() is False + + +def test_systemid_but_no_plugin_means_no_cln(clean_paths): + _touch(clean_paths["systemid"]) + assert cln_detect.is_cln_configured() is False + + +def test_systemid_and_enabled_dnf_plugin_means_cln(clean_paths): + _touch(clean_paths["systemid"]) + _touch(clean_paths["dnf_conf"], "[main]\nenabled = 1\n") + assert cln_detect.is_cln_configured() is True + + +def test_explicit_disabled_dnf_plugin_means_no_cln(clean_paths): + _touch(clean_paths["systemid"]) + _touch(clean_paths["dnf_conf"], "[main]\nenabled = 0\n") + assert cln_detect.is_cln_configured() is False + + +def test_explicit_disabled_yum_plugin_means_no_cln(clean_paths): + _touch(clean_paths["systemid"]) + _touch(clean_paths["yum_conf"], "[main]\nenabled=0\n") + assert cln_detect.is_cln_configured() is False + + +def test_one_plugin_disabled_one_not_means_no_cln(clean_paths): + # If either plugin config disables it, CLN is not usable. + _touch(clean_paths["systemid"]) + _touch(clean_paths["dnf_conf"], "[main]\nenabled = 1\n") + _touch(clean_paths["yum_conf"], "[main]\nenabled = 0\n") + assert cln_detect.is_cln_configured() is False + + +def test_plugin_conf_without_enabled_key_means_cln(clean_paths): + # A plugin config that doesn't mention `enabled` defaults to enabled upstream, + # so we must treat it as CLN active. + _touch(clean_paths["systemid"]) + _touch(clean_paths["dnf_conf"], "[main]\ntimeout = 120\n") + assert cln_detect.is_cln_configured() is True + + +def test_comments_and_blank_lines_ignored(clean_paths): + _touch(clean_paths["systemid"]) + _touch( + clean_paths["dnf_conf"], + "# some comment\n\n[main]\n# enabled = 0\nenabled = 1\n", + ) + assert cln_detect.is_cln_configured() is True From d7eb9963402bbf02ef41516b3d7d57b5e05539ab Mon Sep 17 00:00:00 2001 From: Roman Prilipskii Date: Mon, 27 Apr 2026 12:06:10 -0400 Subject: [PATCH 2/4] =?UTF-8?q?CLOS-4056:=20clarify=20CLN=20detection=20?= =?UTF-8?q?=E2=80=94=20package=20channel=20vs=20registration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first commit on this branch named the helper is_cln_configured() and the actor comments said things like 'CLN is not configured here'. That conflated two separate concerns and was misleading: CLN registration is still in use on no-auth (SWNG) systems for licensing and inventory — what the no-auth migration changes is only the package channel (the spacewalk DNF plugin no longer delivers packages from a CLN channel). Rename: is_cln_configured() -> is_cln_package_channel_active() so the function name reflects what the actors actually need to gate on, and rewrite its docstring + module header to spell out the package-channel vs registration distinction. Update each of the five actor comments accordingly. The detection logic itself is unchanged — registration state plus a non-disabled spacewalk plugin remains the right heuristic for 'CLN is delivering packages'. Tests updated to match the new name and to phrase scenarios in terms of the channel rather than 'CLN configured'. --- .../actors/checkrhnversionoverride/actor.py | 10 ++-- .../cloudlinux/actors/pinclnmirror/actor.py | 11 ++-- .../actors/resetrhnversionoverride/actor.py | 9 ++-- .../actors/switchclnchannel/actor.py | 22 ++++---- .../cloudlinux/actors/unpinclnmirror/actor.py | 8 +-- .../cloudlinux/libraries/cln_detect.py | 50 +++++++++++++------ .../libraries/tests/test_cln_detect.py | 39 ++++++++------- 7 files changed, 92 insertions(+), 57 deletions(-) diff --git a/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py b/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py index a9786d143e..21a8b3ee13 100644 --- a/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py @@ -4,7 +4,7 @@ from leapp.reporting import Report from leapp.tags import ChecksPhaseTag, IPUWorkflowTag from leapp.libraries.common.cllaunch import run_on_cloudlinux -from leapp.libraries.common.cln_detect import is_cln_configured +from leapp.libraries.common.cln_detect import is_cln_package_channel_active class CheckRhnVersionOverride(Actor): @@ -19,8 +19,12 @@ class CheckRhnVersionOverride(Actor): @run_on_cloudlinux def process(self): - if not is_cln_configured(): - # CLOS-4056: no-auth systems have no CLN config to inspect. + if not is_cln_package_channel_active(): + # CLOS-4056: versionOverride only matters when CLN is delivering + # packages — the upgrade rewrites it to drive channel selection. + # On no-auth (SWNG) systems the package channel is cl-channel, + # not CLN, so there is nothing to inspect or warn about even if + # /etc/sysconfig/rhn/up2date is still present from registration. return up2date_config = '/etc/sysconfig/rhn/up2date' diff --git a/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py b/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py index 162dbba96d..1bdcb42d9e 100644 --- a/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py @@ -4,7 +4,7 @@ from leapp.actors import Actor from leapp.libraries.stdlib import api from leapp.libraries.common.cllaunch import run_on_cloudlinux -from leapp.libraries.common.cln_detect import is_cln_configured +from leapp.libraries.common.cln_detect import is_cln_package_channel_active from leapp.libraries.common.cln_switch import get_target_userspace_path from leapp.tags import DownloadPhaseTag, IPUWorkflowTag from leapp.libraries.common.config.version import get_target_major_version @@ -26,10 +26,13 @@ class PinClnMirror(Actor): @run_on_cloudlinux def process(self): """Pin CLN mirror""" - if not is_cln_configured(): - # CLOS-4056: no-auth systems don't use CLN mirrors; skip cleanly. + if not is_cln_package_channel_active(): + # CLOS-4056: pinning the CLN mirror is only meaningful when CLN + # is delivering packages. On no-auth (SWNG) systems packages come + # from cl-channel via mirrorlist, so there is nothing to pin — + # registration may still be in place but is irrelevant here. api.current_logger().info( - "CLN is not configured on this system; skipping mirror pinning" + "CLN is not the active package channel; skipping mirror pinning" ) return diff --git a/repos/system_upgrade/cloudlinux/actors/resetrhnversionoverride/actor.py b/repos/system_upgrade/cloudlinux/actors/resetrhnversionoverride/actor.py index 7b5f5d0f51..ff446c77a2 100644 --- a/repos/system_upgrade/cloudlinux/actors/resetrhnversionoverride/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/resetrhnversionoverride/actor.py @@ -2,7 +2,7 @@ from leapp.libraries.stdlib import api from leapp.tags import FinalizationPhaseTag, IPUWorkflowTag from leapp.libraries.common.cllaunch import run_on_cloudlinux -from leapp.libraries.common.cln_detect import is_cln_configured +from leapp.libraries.common.cln_detect import is_cln_package_channel_active class ResetRhnVersionOverride(Actor): @@ -17,8 +17,11 @@ class ResetRhnVersionOverride(Actor): @run_on_cloudlinux def process(self): - if not is_cln_configured(): - # CLOS-4056: no-auth systems have no CLN config to reset. + if not is_cln_package_channel_active(): + # CLOS-4056: versionOverride is only set/used by the CLN package + # channel flow. If the system isn't on CLN for packages, leave + # /etc/sysconfig/rhn/up2date alone — registration metadata there + # is not ours to touch. return up2date_config = '/etc/sysconfig/rhn/up2date' diff --git a/repos/system_upgrade/cloudlinux/actors/switchclnchannel/actor.py b/repos/system_upgrade/cloudlinux/actors/switchclnchannel/actor.py index e80f0e8fa6..f7c5675c82 100644 --- a/repos/system_upgrade/cloudlinux/actors/switchclnchannel/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/switchclnchannel/actor.py @@ -3,7 +3,7 @@ from leapp.tags import FirstBootPhaseTag, IPUWorkflowTag from leapp.libraries.stdlib import CalledProcessError from leapp.libraries.common.cllaunch import run_on_cloudlinux -from leapp.libraries.common.cln_detect import is_cln_configured +from leapp.libraries.common.cln_detect import is_cln_package_channel_active from leapp.libraries.common.cln_switch import cln_switch from leapp import reporting from leapp.reporting import Report @@ -23,22 +23,24 @@ class SwitchClnChannel(Actor): @run_on_cloudlinux def process(self): - if not is_cln_configured(): - # CLOS-4056: No-auth (SWNG) systems have no CLN plumbing. Skipping - # the channel switch here is correct — the system receives CL9 - # packages via cl-channel / cloudlinux9-baseos instead. + if not is_cln_package_channel_active(): + # CLOS-4056: CLN is no longer the package channel here (no-auth / + # SWNG mode). Skipping the channel switch is correct — packages + # come from cl-channel / cloudlinux9-baseos instead. The system + # may still be CLN-registered for licensing; that is a separate + # concern this actor does not need to manage. api.current_logger().info( - "CLN is not configured on this system; skipping channel switch" + "CLN is not the active package channel; skipping channel switch" ) return try: cln_switch(target=int(get_target_major_version())) except CalledProcessError as e: - # CLOS-4056: Do not inhibit. CLN may be partially configured (legacy - # registration files present but no working registration) on systems - # transitioning to the no-auth scheme, and a failed channel switch - # there is expected — the no-auth repos still serve CL9 packages. + # CLOS-4056: Do not inhibit. Even on systems that ARE using CLN + # as the package channel, a transient CLN-server reachability + # problem at FirstBoot (DNS/network not up yet) shouldn't block + # the upgrade — the no-auth fallback repos still serve packages. reporting.create_report( [ reporting.Title( diff --git a/repos/system_upgrade/cloudlinux/actors/unpinclnmirror/actor.py b/repos/system_upgrade/cloudlinux/actors/unpinclnmirror/actor.py index cc2247d91e..01ddafadf4 100644 --- a/repos/system_upgrade/cloudlinux/actors/unpinclnmirror/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/unpinclnmirror/actor.py @@ -2,7 +2,7 @@ from leapp.actors import Actor from leapp.libraries.common.cllaunch import run_on_cloudlinux -from leapp.libraries.common.cln_detect import is_cln_configured +from leapp.libraries.common.cln_detect import is_cln_package_channel_active from leapp.libraries.common.cln_switch import get_target_userspace_path from leapp.tags import FirstBootPhaseTag, IPUWorkflowTag @@ -20,8 +20,10 @@ class UnpinClnMirror(Actor): @run_on_cloudlinux def process(self): - if not is_cln_configured(): - # CLOS-4056: pinclnmirror was skipped on no-auth systems, nothing to unpin. + if not is_cln_package_channel_active(): + # CLOS-4056: pinclnmirror skipped its work for the same reason + # (CLN is not the package channel here), so there is nothing + # for us to unpin. return target_userspace = get_target_userspace_path() diff --git a/repos/system_upgrade/cloudlinux/libraries/cln_detect.py b/repos/system_upgrade/cloudlinux/libraries/cln_detect.py index 623f36a71a..f5c6532f87 100644 --- a/repos/system_upgrade/cloudlinux/libraries/cln_detect.py +++ b/repos/system_upgrade/cloudlinux/libraries/cln_detect.py @@ -1,18 +1,27 @@ -"""Detection helpers for CLN (CloudLinux Network / Spacewalk) state. +"""Detection helpers for the CloudLinux Network (CLN) package channel. -A system is considered to have CLN *configured* when it has registration -state plus the spacewalk DNF/YUM plugin installed and not explicitly -disabled. Systems that have been migrated to the no-auth (SWNG mirrorlist) -scheme have either: +CLN has historically combined two concerns: - - no `/etc/sysconfig/rhn/systemid` (never registered or deregistered), - - no spacewalk plugin installed (rhn-client-tools >= 3.0.1 removes it), or - - the plugin's `enabled = 0` in its config. + 1. **Registration / identity** — the system is registered with the CLN + server (`/etc/sysconfig/rhn/systemid`, JWT token), used for licensing + and inventory regardless of how packages are delivered. -CLOS-4056: several CloudLinux-specific actors were written when CLN was the -only scheme and assume it is always active. They need to gate their -behavior on `is_cln_configured()` so systems on the no-auth scheme pass -through without bogus inhibitors or crashes. + 2. **Package delivery** — the system pulls CloudLinux packages through + the spacewalk DNF/YUM plugin against the CLN-side channel + (`cloudlinux-x86_64-server-N`). + +The no-auth (SWNG) transition decouples these. New CL8 and CL9 systems +keep CLN **registration** but no longer use CLN as the **package +channel** — packages come from the SWNG mirrorlist via +`/etc/yum.repos.d/cl.repo` (`cl-channel`) instead. `rhn-client-tools +>= 3.0.1` disables the spacewalk plugin to enforce this. + +The CLN-touching actors in this repo only care about the second concern: +they exist to make the CLN package channel work during ELevate. On +systems where the channel has been switched off they should stand down +even though registration may still be present and valid. + +CLOS-4056: gate those actors on `is_cln_package_channel_active()`. """ import os @@ -38,8 +47,20 @@ def _plugin_explicitly_disabled(conf_path): return False -def is_cln_configured(): - """Return True if CLN plumbing is present and not disabled on this system.""" +def is_cln_package_channel_active(): + """Return True when CLN is the active package channel for this system. + + A True result means the spacewalk DNF/YUM plugin is installed, not + explicitly disabled, and the system has CLN registration state for + the plugin to authenticate with. A False result means the system is + either deregistered or has been moved to the no-auth (SWNG) scheme, + so CLN-targeting actions (channel switch, mirror pinning, version + overrides) are not meaningful and should be skipped. + + This is a deliberately heuristic check — it asks "is CLN going to + serve packages here", not "is the system registered with CLN" (the + two were the same thing pre-no-auth and have since diverged). + """ if not os.path.exists(RHN_SYSTEMID): return False @@ -47,7 +68,6 @@ def is_cln_configured(): if not configs: return False - # If any plugin config explicitly disables the plugin, treat as no-auth. for conf in configs: if _plugin_explicitly_disabled(conf): return False diff --git a/repos/system_upgrade/cloudlinux/libraries/tests/test_cln_detect.py b/repos/system_upgrade/cloudlinux/libraries/tests/test_cln_detect.py index ee2bbae411..a048537029 100644 --- a/repos/system_upgrade/cloudlinux/libraries/tests/test_cln_detect.py +++ b/repos/system_upgrade/cloudlinux/libraries/tests/test_cln_detect.py @@ -21,48 +21,49 @@ def _touch(path, content=""): path.write_text(content) -def test_no_systemid_means_no_cln(clean_paths): - # Without /etc/sysconfig/rhn/systemid the system is not registered with CLN. - assert cln_detect.is_cln_configured() is False +def test_no_systemid_means_channel_inactive(clean_paths): + # Without registration the spacewalk plugin can't authenticate, so even + # if the plugin is installed it is not the active package channel. + assert cln_detect.is_cln_package_channel_active() is False -def test_systemid_but_no_plugin_means_no_cln(clean_paths): +def test_systemid_but_no_plugin_means_channel_inactive(clean_paths): _touch(clean_paths["systemid"]) - assert cln_detect.is_cln_configured() is False + assert cln_detect.is_cln_package_channel_active() is False -def test_systemid_and_enabled_dnf_plugin_means_cln(clean_paths): +def test_systemid_and_enabled_dnf_plugin_means_channel_active(clean_paths): _touch(clean_paths["systemid"]) _touch(clean_paths["dnf_conf"], "[main]\nenabled = 1\n") - assert cln_detect.is_cln_configured() is True + assert cln_detect.is_cln_package_channel_active() is True -def test_explicit_disabled_dnf_plugin_means_no_cln(clean_paths): +def test_explicit_disabled_dnf_plugin_means_channel_inactive(clean_paths): _touch(clean_paths["systemid"]) _touch(clean_paths["dnf_conf"], "[main]\nenabled = 0\n") - assert cln_detect.is_cln_configured() is False + assert cln_detect.is_cln_package_channel_active() is False -def test_explicit_disabled_yum_plugin_means_no_cln(clean_paths): +def test_explicit_disabled_yum_plugin_means_channel_inactive(clean_paths): _touch(clean_paths["systemid"]) _touch(clean_paths["yum_conf"], "[main]\nenabled=0\n") - assert cln_detect.is_cln_configured() is False + assert cln_detect.is_cln_package_channel_active() is False -def test_one_plugin_disabled_one_not_means_no_cln(clean_paths): - # If either plugin config disables it, CLN is not usable. +def test_one_plugin_disabled_one_not_means_channel_inactive(clean_paths): + # If either plugin config disables the plugin, treat the channel as off. _touch(clean_paths["systemid"]) _touch(clean_paths["dnf_conf"], "[main]\nenabled = 1\n") _touch(clean_paths["yum_conf"], "[main]\nenabled = 0\n") - assert cln_detect.is_cln_configured() is False + assert cln_detect.is_cln_package_channel_active() is False -def test_plugin_conf_without_enabled_key_means_cln(clean_paths): - # A plugin config that doesn't mention `enabled` defaults to enabled upstream, - # so we must treat it as CLN active. +def test_plugin_conf_without_enabled_key_means_channel_active(clean_paths): + # A plugin config that does not mention `enabled` defaults to enabled + # upstream, so we must treat the channel as active. _touch(clean_paths["systemid"]) _touch(clean_paths["dnf_conf"], "[main]\ntimeout = 120\n") - assert cln_detect.is_cln_configured() is True + assert cln_detect.is_cln_package_channel_active() is True def test_comments_and_blank_lines_ignored(clean_paths): @@ -71,4 +72,4 @@ def test_comments_and_blank_lines_ignored(clean_paths): clean_paths["dnf_conf"], "# some comment\n\n[main]\n# enabled = 0\nenabled = 1\n", ) - assert cln_detect.is_cln_configured() is True + assert cln_detect.is_cln_package_channel_active() is True From 0a31d423b27c4ac8f6443d6a67d4deb0f418ed94 Mon Sep 17 00:00:00 2001 From: Roman Prilipskii Date: Mon, 27 Apr 2026 12:06:10 -0400 Subject: [PATCH 3/4] CLOS-4056: replace em-dashes with ASCII for Python 2.7 / lint compat The previous two commits introduced em-dashes (U+2014) in docstrings and inline comments. The upstream make lint target now greps for any non-ASCII byte (commit 92aee84b) because Python 2.7 source files reject non-ASCII without an encoding declaration, and the leapp framework still supports running on 2.7 in places. Replace each em-dash with an ASCII hyphen so the files lint clean against that gate. --- .../cloudlinux/actors/checkrhnversionoverride/actor.py | 2 +- .../cloudlinux/actors/pinclnmirror/actor.py | 2 +- .../cloudlinux/actors/resetrhnversionoverride/actor.py | 2 +- .../cloudlinux/actors/switchclnchannel/actor.py | 6 +++--- repos/system_upgrade/cloudlinux/libraries/cln_detect.py | 8 ++++---- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py b/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py index 21a8b3ee13..41cdd8843f 100644 --- a/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py @@ -21,7 +21,7 @@ class CheckRhnVersionOverride(Actor): def process(self): if not is_cln_package_channel_active(): # CLOS-4056: versionOverride only matters when CLN is delivering - # packages — the upgrade rewrites it to drive channel selection. + # packages - the upgrade rewrites it to drive channel selection. # On no-auth (SWNG) systems the package channel is cl-channel, # not CLN, so there is nothing to inspect or warn about even if # /etc/sysconfig/rhn/up2date is still present from registration. diff --git a/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py b/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py index 1bdcb42d9e..478609ce02 100644 --- a/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py @@ -29,7 +29,7 @@ def process(self): if not is_cln_package_channel_active(): # CLOS-4056: pinning the CLN mirror is only meaningful when CLN # is delivering packages. On no-auth (SWNG) systems packages come - # from cl-channel via mirrorlist, so there is nothing to pin — + # from cl-channel via mirrorlist, so there is nothing to pin - # registration may still be in place but is irrelevant here. api.current_logger().info( "CLN is not the active package channel; skipping mirror pinning" diff --git a/repos/system_upgrade/cloudlinux/actors/resetrhnversionoverride/actor.py b/repos/system_upgrade/cloudlinux/actors/resetrhnversionoverride/actor.py index ff446c77a2..408a77f85f 100644 --- a/repos/system_upgrade/cloudlinux/actors/resetrhnversionoverride/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/resetrhnversionoverride/actor.py @@ -20,7 +20,7 @@ def process(self): if not is_cln_package_channel_active(): # CLOS-4056: versionOverride is only set/used by the CLN package # channel flow. If the system isn't on CLN for packages, leave - # /etc/sysconfig/rhn/up2date alone — registration metadata there + # /etc/sysconfig/rhn/up2date alone - registration metadata there # is not ours to touch. return diff --git a/repos/system_upgrade/cloudlinux/actors/switchclnchannel/actor.py b/repos/system_upgrade/cloudlinux/actors/switchclnchannel/actor.py index f7c5675c82..4a77da4740 100644 --- a/repos/system_upgrade/cloudlinux/actors/switchclnchannel/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/switchclnchannel/actor.py @@ -25,7 +25,7 @@ class SwitchClnChannel(Actor): def process(self): if not is_cln_package_channel_active(): # CLOS-4056: CLN is no longer the package channel here (no-auth / - # SWNG mode). Skipping the channel switch is correct — packages + # SWNG mode). Skipping the channel switch is correct - packages # come from cl-channel / cloudlinux9-baseos instead. The system # may still be CLN-registered for licensing; that is a separate # concern this actor does not need to manage. @@ -40,7 +40,7 @@ def process(self): # CLOS-4056: Do not inhibit. Even on systems that ARE using CLN # as the package channel, a transient CLN-server reachability # problem at FirstBoot (DNS/network not up yet) shouldn't block - # the upgrade — the no-auth fallback repos still serve packages. + # the upgrade - the no-auth fallback repos still serve packages. reporting.create_report( [ reporting.Title( @@ -50,7 +50,7 @@ def process(self): "Command {} failed with exit code {}." " The most probable cause of that is a problem with this system's" " CloudLinux Network registration. If this system now uses the" - " no-auth (SWNG) repository scheme, this failure is harmless —" + " no-auth (SWNG) repository scheme, this failure is harmless -" " CL9 packages come from cl-channel / cloudlinux9-baseos instead" " of CLN.".format(e.command, e.exit_code) ), diff --git a/repos/system_upgrade/cloudlinux/libraries/cln_detect.py b/repos/system_upgrade/cloudlinux/libraries/cln_detect.py index f5c6532f87..8bb4bb2a2b 100644 --- a/repos/system_upgrade/cloudlinux/libraries/cln_detect.py +++ b/repos/system_upgrade/cloudlinux/libraries/cln_detect.py @@ -2,17 +2,17 @@ CLN has historically combined two concerns: - 1. **Registration / identity** — the system is registered with the CLN + 1. **Registration / identity** - the system is registered with the CLN server (`/etc/sysconfig/rhn/systemid`, JWT token), used for licensing and inventory regardless of how packages are delivered. - 2. **Package delivery** — the system pulls CloudLinux packages through + 2. **Package delivery** - the system pulls CloudLinux packages through the spacewalk DNF/YUM plugin against the CLN-side channel (`cloudlinux-x86_64-server-N`). The no-auth (SWNG) transition decouples these. New CL8 and CL9 systems keep CLN **registration** but no longer use CLN as the **package -channel** — packages come from the SWNG mirrorlist via +channel** - packages come from the SWNG mirrorlist via `/etc/yum.repos.d/cl.repo` (`cl-channel`) instead. `rhn-client-tools >= 3.0.1` disables the spacewalk plugin to enforce this. @@ -57,7 +57,7 @@ def is_cln_package_channel_active(): so CLN-targeting actions (channel switch, mirror pinning, version overrides) are not meaningful and should be skipped. - This is a deliberately heuristic check — it asks "is CLN going to + This is a deliberately heuristic check - it asks "is CLN going to serve packages here", not "is the system registered with CLN" (the two were the same thing pre-no-auth and have since diverged). """ From bb4a76aa77ef4951aa5de736276680791539fe85 Mon Sep 17 00:00:00 2001 From: Roman Prilipskii Date: Thu, 30 Apr 2026 21:42:44 +0200 Subject: [PATCH 4/4] CLOS-4056: Tighten CLN-related actor comments and clarifications --- .../actors/checkrhnversionoverride/actor.py | 8 ++---- .../libraries/enableyumspacewalkplugin.py | 13 +++++---- .../tests/test_enableyumspacewalkplugin.py | 7 ++--- .../cloudlinux/actors/pinclnmirror/actor.py | 6 ++-- .../actors/resetrhnversionoverride/actor.py | 7 ++--- .../actors/switchclnchannel/actor.py | 15 ++++------ .../cloudlinux/actors/unpinclnmirror/actor.py | 3 +- .../cloudlinux/libraries/cln_detect.py | 28 +++++++++---------- 8 files changed, 39 insertions(+), 48 deletions(-) diff --git a/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py b/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py index 41cdd8843f..3b37334ccc 100644 --- a/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py @@ -20,11 +20,9 @@ class CheckRhnVersionOverride(Actor): @run_on_cloudlinux def process(self): if not is_cln_package_channel_active(): - # CLOS-4056: versionOverride only matters when CLN is delivering - # packages - the upgrade rewrites it to drive channel selection. - # On no-auth (SWNG) systems the package channel is cl-channel, - # not CLN, so there is nothing to inspect or warn about even if - # /etc/sysconfig/rhn/up2date is still present from registration. + # CLOS-4056: versionOverride only matters when CLN is delivering packages, + # since the upgrade rewrites it to drive channel selection. + # On no-auth systems this does not apply. return up2date_config = '/etc/sysconfig/rhn/up2date' diff --git a/repos/system_upgrade/cloudlinux/actors/enableyumspacewalkplugin/libraries/enableyumspacewalkplugin.py b/repos/system_upgrade/cloudlinux/actors/enableyumspacewalkplugin/libraries/enableyumspacewalkplugin.py index 32b75fbc98..2dd7b4a5cb 100644 --- a/repos/system_upgrade/cloudlinux/actors/enableyumspacewalkplugin/libraries/enableyumspacewalkplugin.py +++ b/repos/system_upgrade/cloudlinux/actors/enableyumspacewalkplugin/libraries/enableyumspacewalkplugin.py @@ -10,10 +10,11 @@ ParserClass = configparser.ConfigParser -# DNF plugin config path on the target system (CL8). FirstBoot runs after the -# target OS is already in place; on CL8 the plugin package is -# dnf-plugin-spacewalk (PES replacement for CL7's yum-rhn-plugin, -# pes-events id=1586) and its config ships with enabled=0. +# DNF plugin config path on the target system (CL8). +# FirstBoot runs after the target OS is already in place; +# on CL8 the plugin package is dnf-plugin-spacewalk +# (PES replacement for CL7's yum-rhn-plugin, pes-events id=1586) +# and its config ships with enabled=0. DEFAULT_CONFIG_PATH = '/etc/dnf/plugins/spacewalk.conf' @@ -24,8 +25,8 @@ def _enable_plugin(config_path, parser_cls=ParserClass, log=None): when the plugin is not installed, and otherwise a human-readable problem description suitable for a Leapp report. - Absence of `config_path` is treated as a silent skip: on no-auth / - SWNG systems (CLOS-4056) `rhn-client-tools >= 3.0.1` Obsoletes the + Absence of `config_path` is treated as a silent skip: on no-auth + systems (CLOS-4056) `rhn-client-tools >= 3.0.1` Obsoletes the `dnf-plugin-spacewalk` package, so the config file is either gone by then, or doesn't do anything. """ diff --git a/repos/system_upgrade/cloudlinux/actors/enableyumspacewalkplugin/tests/test_enableyumspacewalkplugin.py b/repos/system_upgrade/cloudlinux/actors/enableyumspacewalkplugin/tests/test_enableyumspacewalkplugin.py index 7e7cba2a79..d74da391e4 100644 --- a/repos/system_upgrade/cloudlinux/actors/enableyumspacewalkplugin/tests/test_enableyumspacewalkplugin.py +++ b/repos/system_upgrade/cloudlinux/actors/enableyumspacewalkplugin/tests/test_enableyumspacewalkplugin.py @@ -17,10 +17,9 @@ def _write(tmp_path, body): def test_missing_config_is_silent_skip(tmp_path): """Config file absent -> silent skip: no change, no title, no report. - On no-auth / SWNG systems (CLOS-4056) the dnf-plugin-spacewalk - package is Obsoleted by rhn-client-tools >= 3.0.1 and the config - file is absent by design. Emitting a 'not found' report there - would be noise. + On no-auth systems (CLOS-4056) the dnf-plugin-spacewalk + package is Obsoleted by rhn-client-tools >= 3.0.1. + Emitting a 'not found' report there would be noise. """ changed, title = _enable_plugin(str(tmp_path / "absent.conf"), ParserClass) assert changed is False diff --git a/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py b/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py index 478609ce02..bc19301a03 100644 --- a/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py @@ -27,10 +27,8 @@ class PinClnMirror(Actor): def process(self): """Pin CLN mirror""" if not is_cln_package_channel_active(): - # CLOS-4056: pinning the CLN mirror is only meaningful when CLN - # is delivering packages. On no-auth (SWNG) systems packages come - # from cl-channel via mirrorlist, so there is nothing to pin - - # registration may still be in place but is irrelevant here. + # CLOS-4056: pinning the CLN mirror is only meaningful when CLN is delivering packages. + # With the no-auth repo scheme active, there's no point in doing so. api.current_logger().info( "CLN is not the active package channel; skipping mirror pinning" ) diff --git a/repos/system_upgrade/cloudlinux/actors/resetrhnversionoverride/actor.py b/repos/system_upgrade/cloudlinux/actors/resetrhnversionoverride/actor.py index 408a77f85f..32109201a3 100644 --- a/repos/system_upgrade/cloudlinux/actors/resetrhnversionoverride/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/resetrhnversionoverride/actor.py @@ -18,10 +18,9 @@ class ResetRhnVersionOverride(Actor): @run_on_cloudlinux def process(self): if not is_cln_package_channel_active(): - # CLOS-4056: versionOverride is only set/used by the CLN package - # channel flow. If the system isn't on CLN for packages, leave - # /etc/sysconfig/rhn/up2date alone - registration metadata there - # is not ours to touch. + # CLOS-4056: versionOverride only matters when CLN is delivering packages, + # since the upgrade rewrites it to drive channel selection. + # On no-auth systems this does not apply. return up2date_config = '/etc/sysconfig/rhn/up2date' diff --git a/repos/system_upgrade/cloudlinux/actors/switchclnchannel/actor.py b/repos/system_upgrade/cloudlinux/actors/switchclnchannel/actor.py index 4a77da4740..dc0ac24317 100644 --- a/repos/system_upgrade/cloudlinux/actors/switchclnchannel/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/switchclnchannel/actor.py @@ -24,11 +24,9 @@ class SwitchClnChannel(Actor): @run_on_cloudlinux def process(self): if not is_cln_package_channel_active(): - # CLOS-4056: CLN is no longer the package channel here (no-auth / - # SWNG mode). Skipping the channel switch is correct - packages - # come from cl-channel / cloudlinux9-baseos instead. The system - # may still be CLN-registered for licensing; that is a separate - # concern this actor does not need to manage. + # CLOS-4056: CLN package channel is inactive, so skipping the channel switch + # is correct - packages come from standard repositories instead. + # Leapp manages those without custom actions through repomaps. api.current_logger().info( "CLN is not the active package channel; skipping channel switch" ) @@ -37,10 +35,9 @@ def process(self): try: cln_switch(target=int(get_target_major_version())) except CalledProcessError as e: - # CLOS-4056: Do not inhibit. Even on systems that ARE using CLN - # as the package channel, a transient CLN-server reachability - # problem at FirstBoot (DNS/network not up yet) shouldn't block - # the upgrade - the no-auth fallback repos still serve packages. + # Do not inhibit. Even on systems that ARE using CLN as the package channel, + # a transient CLN-server reachability problem at FirstBoot + # shouldn't block the upgrade. reporting.create_report( [ reporting.Title( diff --git a/repos/system_upgrade/cloudlinux/actors/unpinclnmirror/actor.py b/repos/system_upgrade/cloudlinux/actors/unpinclnmirror/actor.py index 01ddafadf4..7343117018 100644 --- a/repos/system_upgrade/cloudlinux/actors/unpinclnmirror/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/unpinclnmirror/actor.py @@ -22,8 +22,7 @@ class UnpinClnMirror(Actor): def process(self): if not is_cln_package_channel_active(): # CLOS-4056: pinclnmirror skipped its work for the same reason - # (CLN is not the package channel here), so there is nothing - # for us to unpin. + # (CLN package channel inactive), so there is nothing for us to unpin. return target_userspace = get_target_userspace_path() diff --git a/repos/system_upgrade/cloudlinux/libraries/cln_detect.py b/repos/system_upgrade/cloudlinux/libraries/cln_detect.py index 8bb4bb2a2b..17ad307f07 100644 --- a/repos/system_upgrade/cloudlinux/libraries/cln_detect.py +++ b/repos/system_upgrade/cloudlinux/libraries/cln_detect.py @@ -2,24 +2,24 @@ CLN has historically combined two concerns: - 1. **Registration / identity** - the system is registered with the CLN - server (`/etc/sysconfig/rhn/systemid`, JWT token), used for licensing - and inventory regardless of how packages are delivered. +1. *Registration / identity* - the system is registered with the CLN +server (`/etc/sysconfig/rhn/systemid`, JWT token), used for licensing +regardless of how packages are delivered. - 2. **Package delivery** - the system pulls CloudLinux packages through - the spacewalk DNF/YUM plugin against the CLN-side channel - (`cloudlinux-x86_64-server-N`). +2. *Package delivery* - the system pulls CloudLinux packages +through the spacewalk DNF/YUM plugin against the +CLN-side channel (`cloudlinux-x86_64-server-N`). -The no-auth (SWNG) transition decouples these. New CL8 and CL9 systems -keep CLN **registration** but no longer use CLN as the **package -channel** - packages come from the SWNG mirrorlist via -`/etc/yum.repos.d/cl.repo` (`cl-channel`) instead. `rhn-client-tools ->= 3.0.1` disables the spacewalk plugin to enforce this. +The no-auth repository transition decouples these. +New CL8 and CL9 systems keep CLN *registration*, +but no longer use CLN as the *package channel* - packages come from the SWNG mirrorlist +via `/etc/yum.repos.d/cl.repo` (`cl-channel`) instead. +`rhn-client-tools >= 3.0.1` disables the spacewalk plugin to enforce this. The CLN-touching actors in this repo only care about the second concern: -they exist to make the CLN package channel work during ELevate. On -systems where the channel has been switched off they should stand down -even though registration may still be present and valid. +they exist to make the CLN package channel work during ELevate. +On systems where the channel has been switched off they should stand down, +regardless of registration state. CLOS-4056: gate those actors on `is_cln_package_channel_active()`. """