diff --git a/commands/upgrade/__init__.py b/commands/upgrade/__init__.py index 7528297d82..57b4240ea8 100644 --- a/commands/upgrade/__init__.py +++ b/commands/upgrade/__init__.py @@ -8,7 +8,7 @@ from leapp.exceptions import CommandError, LeappError from leapp.logger import configure_logger from leapp.utils.audit import Execution -from leapp.utils.clicmd import command, command_opt +from leapp.utils.clicmd import command, command_opt, _ensure_command from leapp.utils.output import beautify_actor_exception, report_errors, report_info # NOTE: @@ -16,10 +16,36 @@ # otherwise there might be errors. +def command_opt_with_aliases(name, *aliases, **kwargs): + """Like command_opt, but registers -- AND extra long-form aliases. + + leapp framework's add_option (as of 0.18.0) accepts only one long name, + so a plain `aliases=` kwarg trips on `add_option() got an unexpected + keyword argument 'aliases'`. argparse, however, supports multiple long + forms natively when add_argument is called with several name strings. + We bypass add_option and call the lower-level _add_opt directly. + + `dest` is derived by argparse from the first long form (here `name`), + so existing consumers reading `args.` keep working unchanged. + """ + is_flag = kwargs.pop('is_flag', False) + help_text = kwargs.pop('help', '') + action = kwargs.pop('action', 'store_true' if is_flag else 'store') + inherit = kwargs.pop('inherit', False) + + @_ensure_command + def wrapper(f): + names = ['--' + n.lstrip('-') for n in (name,) + aliases] + f.command._add_opt(*names, action=action, help=help_text, + internal={'wrapped': f, 'inherit': inherit}, + **kwargs) + return f + return wrapper + + @command('upgrade', help='Upgrade the current system to the next available major version.') @command_opt('resume', is_flag=True, help='Continue the last execution after it was stopped (e.g. after reboot)') -@command_opt('nowarn', is_flag=True, help='Do not display interactive warnings', - aliases=['non-interactive']) +@command_opt_with_aliases('nowarn', 'non-interactive', is_flag=True, help='Do not display interactive warnings') @command_opt('reboot', is_flag=True, help='Automatically performs reboot when requested.') @command_opt('whitelist-experimental', action='append', metavar='ActorName', help='Enable experimental actors') @command_opt('debug', is_flag=True, help='Enable debug mode', inherit=False) diff --git a/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py b/repos/system_upgrade/cloudlinux/actors/checkrhnversionoverride/actor.py index 6a21e10b6e..41cdd8843f 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_package_channel_active class CheckRhnVersionOverride(Actor): @@ -17,23 +19,39 @@ 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. + 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/clmysqlrepositorysetup/libraries/clmysql_cloudlinux.py b/repos/system_upgrade/cloudlinux/actors/clmysqlrepositorysetup/libraries/clmysql_cloudlinux.py index 840ff5a43c..14a4760609 100644 --- a/repos/system_upgrade/cloudlinux/actors/clmysqlrepositorysetup/libraries/clmysql_cloudlinux.py +++ b/repos/system_upgrade/cloudlinux/actors/clmysqlrepositorysetup/libraries/clmysql_cloudlinux.py @@ -41,7 +41,7 @@ def clmysql_process(lib, repofile_name, repofile_data): reporting.Summary( "MySQL Governor records the installed database type as '{governor}', " "but the mysqld binary on disk belongs to '{rpm}'. " - "This usually means 'mysqlgovernor.py --mysql-version' was run " + "This usually means '/usr/share/lve/dbgovernor/mysqlgovernor.py --mysql-version' was run " "without a follow-up '--install', or packages were changed manually. " "Proceeding could enable the wrong DNF module stream and break the upgrade.".format( governor=detected.governor_type, rpm=detected.pkg_type @@ -56,11 +56,11 @@ def clmysql_process(lib, repofile_name, repofile_data): hint=( "Examine the current state of the system's DB packages." "Complete the pending Governor install:\n" - " mysqlgovernor.py --mysql-version={governor}\n" - " mysqlgovernor.py --install --yes\n" + " /usr/share/lve/dbgovernor/mysqlgovernor.py --mysql-version={governor}\n" + " /usr/share/lve/dbgovernor/mysqlgovernor.py --install --yes\n" "Or reset Governor to match the actual packages:\n" - " mysqlgovernor.py --mysql-version={rpm}\n" - " mysqlgovernor.py --install --yes\n" + " /usr/share/lve/dbgovernor/mysqlgovernor.py --mysql-version={rpm}\n" + " /usr/share/lve/dbgovernor/mysqlgovernor.py --install --yes\n" "Then restart the upgrade process.".format( governor=detected.governor_type, rpm=detected.pkg_type ) @@ -109,7 +109,7 @@ def clmysql_process(lib, repofile_name, repofile_data): "The detected database type is '{}', but the cl-mysql-meta " "repo URL points to '{}'. " "This may happen when the database version was changed " - "without a follow-up 'mysqlgovernor.py --install', or the " + "without a follow-up '/usr/share/lve/dbgovernor/mysqlgovernor.py --install', or the " "cl-mysql.repo file was manually edited. " "Proceeding with the wrong repository would result in " "an incorrect upgrade operation." @@ -125,13 +125,16 @@ def clmysql_process(lib, repofile_name, repofile_data): reporting.Groups([reporting.Groups.INHIBITOR]), reporting.Remediation( hint=( - "Re-run MySQL Governor to regenerate the repository file: " - "mysqlgovernor.py --install --yes, " - "then restart the upgrade process. " - "Alternatively, if the repository file was manually edited, " - "either correct the baseurl to match the installed DB type or " - "set the desired DB type in Governor and re-run --install " - "to have it write the correct URL." + "Download the correct repository file for the installed " + "database type: " + "curl -o /etc/yum.repos.d/cl-mysql.repo " + "http://repo.cloudlinux.com/other/" + "cl${{releasever}}/mysqlmeta/{expected}-common.repo\n" + "Or re-run MySQL Governor to regenerate it " + "(this reinstalls the full DB stack): " + "/usr/share/lve/dbgovernor/mysqlgovernor.py --install --yes\n" + "Then restart the upgrade process." + .format(expected=expected_fragment) ) ), ] diff --git a/repos/system_upgrade/cloudlinux/actors/enableyumspacewalkplugin/actor.py b/repos/system_upgrade/cloudlinux/actors/enableyumspacewalkplugin/actor.py index 4856c02894..e370791410 100644 --- a/repos/system_upgrade/cloudlinux/actors/enableyumspacewalkplugin/actor.py +++ b/repos/system_upgrade/cloudlinux/actors/enableyumspacewalkplugin/actor.py @@ -11,17 +11,18 @@ class EnableYumSpacewalkPlugin(Actor): consumes = () produces = (Report,) tags = (FirstBootPhaseTag, IPUWorkflowTag) - config = enableyumspacewalkplugin.DEFAULT_CONFIG_PATH + + CONFIG_PATH = enableyumspacewalkplugin.DEFAULT_CONFIG_PATH @run_on_cloudlinux def process(self): _, title = enableyumspacewalkplugin._enable_plugin( - self.config, enableyumspacewalkplugin.ParserClass, self.log + self.CONFIG_PATH, enableyumspacewalkplugin.ParserClass, self.log ) if title: reporting.create_report([ reporting.Title(title), - reporting.Summary("DNF spacewalk plugin must be enabled for CLN channels. Config path: " + self.config), + reporting.Summary("DNF spacewalk plugin must be enabled for CLN channels. Config path: " + self.CONFIG_PATH), reporting.Severity(reporting.Severity.MEDIUM), reporting.Groups([reporting.Groups.SANITY]) ]) diff --git a/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py b/repos/system_upgrade/cloudlinux/actors/pinclnmirror/actor.py index bc1686233f..478609ce02 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_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 @@ -25,6 +26,16 @@ class PinClnMirror(Actor): @run_on_cloudlinux 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. + api.current_logger().info( + "CLN is not the active package channel; skipping mirror pinning" + ) + return + target_userspace = get_target_userspace_path() api.current_logger().info("Pin CLN mirror: target userspace=%s", target_userspace) @@ -54,6 +65,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..408a77f85f 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_package_channel_active class ResetRhnVersionOverride(Actor): @@ -15,11 +17,29 @@ 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. + 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..4a77da4740 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_package_channel_active +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,24 @@ 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. + api.current_logger().info( + "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. 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( @@ -33,17 +49,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..01ddafadf4 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_package_channel_active from leapp.libraries.common.cln_switch import get_target_userspace_path from leapp.tags import FirstBootPhaseTag, IPUWorkflowTag @@ -19,6 +20,12 @@ class UnpinClnMirror(Actor): @run_on_cloudlinux 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. + 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..8bb4bb2a2b --- /dev/null +++ b/repos/system_upgrade/cloudlinux/libraries/cln_detect.py @@ -0,0 +1,75 @@ +"""Detection helpers for the CloudLinux Network (CLN) package channel. + +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. + + 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 + + +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_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 + + configs = [p for p in (SPACEWALK_DNF_CONF, SPACEWALK_YUM_CONF) if os.path.exists(p)] + if not configs: + return False + + 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..a048537029 --- /dev/null +++ b/repos/system_upgrade/cloudlinux/libraries/tests/test_cln_detect.py @@ -0,0 +1,75 @@ +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_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_channel_inactive(clean_paths): + _touch(clean_paths["systemid"]) + assert cln_detect.is_cln_package_channel_active() is False + + +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_package_channel_active() is True + + +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_package_channel_active() is False + + +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_package_channel_active() is False + + +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_package_channel_active() is False + + +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_package_channel_active() 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_package_channel_active() is True diff --git a/repos/system_upgrade/common/libraries/dnfplugin.py b/repos/system_upgrade/common/libraries/dnfplugin.py index 0fc011ab61..2d7c3fbd50 100644 --- a/repos/system_upgrade/common/libraries/dnfplugin.py +++ b/repos/system_upgrade/common/libraries/dnfplugin.py @@ -483,8 +483,6 @@ def _prepare_perform(used_repos, target_userspace_info, xfs_info, storage_info, mount_target=os.path.join(context.base_dir, 'installroot'), scratch_reserve=reserve_space) as overlay: with mounting.mount_upgrade_iso_to_root_dir(target_userspace_info.path, target_iso): - if get_target_major_version() == '9': - _rebuild_rpm_db(context, root='/installroot') yield context, overlay, target_repoids