Skip to content

Commit 46a2cf9

Browse files
hosekadamr0x0dkokesak
authored
[RHELC-16] Do not disable RHSM repos before pkg backup (#627)
Co-authored-by: Rodolfo Olivieri <rolivier@redhat.com> Co-authored-by: Martin Litwora <mlitwora@redhat.com>
1 parent b548e82 commit 46a2cf9

File tree

15 files changed

+257
-30
lines changed

15 files changed

+257
-30
lines changed

convert2rhel/backup.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -298,10 +298,13 @@ def backup(self):
298298
else:
299299
loggerinst.info("Can't find %s.", self.filepath)
300300

301-
def restore(self):
301+
def restore(self, rollback=True):
302302
"""Restore a previously backed up file"""
303303
backup_filepath = os.path.join(BACKUP_DIR, os.path.basename(self.filepath))
304-
loggerinst.task("Rollback: Restoring %s from backup" % self.filepath)
304+
if rollback:
305+
loggerinst.task("Rollback: Restoring %s from backup" % self.filepath)
306+
else:
307+
loggerinst.info("Restoring %s from backup" % self.filepath)
305308

306309
if not os.path.isfile(backup_filepath):
307310
loggerinst.info("%s hasn't been backed up." % self.filepath)
@@ -314,7 +317,19 @@ def restore(self):
314317
# IOError for py2 and OSError for py3
315318
loggerinst.warning("Error(%s): %s" % (err.errno, err.strerror))
316319
return
317-
loggerinst.info("File %s restored." % self.filepath)
320+
321+
if rollback:
322+
loggerinst.info("File %s restored." % self.filepath)
323+
else:
324+
loggerinst.debug("File %s restored." % self.filepath)
325+
326+
def remove(self):
327+
"""Remove restored file from original place, backup isn't removed"""
328+
try:
329+
os.remove(self.filepath)
330+
loggerinst.debug("File %s removed." % self.filepath)
331+
except (OSError, IOError):
332+
loggerinst.debug("Couldn't remove restored file %s" % self.filepath)
318333

319334

320335
class RestorablePackage(object):

convert2rhel/main.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,14 @@ def pre_ponr_conversion():
222222
loggerinst.task("Convert: Install RHEL certificates for RHSM")
223223
system_cert = cert.SystemCert()
224224
system_cert.install()
225+
226+
# remove non-RHEL packages containing repofiles or affecting variables in the repofiles
227+
# This needs to be before attempt to unregister the system because after unregistration can be lost
228+
# access to repositories needed for backuping removed packages
229+
loggerinst.task("Convert: Remove packages containing .repo files")
230+
pkghandler.remove_repofile_pkgs()
231+
232+
if not toolopts.tool_opts.no_rhsm:
225233
loggerinst.task("Convert: Subscription Manager - Subscribe system")
226234
subscription.subscribe_system()
227235
loggerinst.task("Convert: Get RHEL repository IDs")
@@ -231,10 +239,6 @@ def pre_ponr_conversion():
231239
loggerinst.task("Convert: Subscription Manager - Disable all repositories")
232240
subscription.disable_repos()
233241

234-
# remove non-RHEL packages containing repofiles or affecting variables in the repofiles
235-
loggerinst.task("Convert: Remove packages containing .repo files")
236-
pkghandler.remove_repofile_pkgs()
237-
238242
# we need to enable repos after removing repofile pkgs, otherwise we don't get backups
239243
# to restore from on a rollback
240244
if not toolopts.tool_opts.no_rhsm:

convert2rhel/subscription.py

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from six.moves import urllib
3131

3232
from convert2rhel import backup, i18n, pkghandler, utils
33+
from convert2rhel.redhatrelease import os_release_file
3334
from convert2rhel.systeminfo import system_info
3435
from convert2rhel.toolopts import tool_opts
3536

@@ -88,6 +89,9 @@
8889

8990
_SUBMGR_PKG_REMOVED_IN_CL_85 = "subscription-manager-initial-setup-addon"
9091

92+
# Path to the releasever variable file for dnf.
93+
DNF_RELEASEVER_FILE = "/etc/yum/vars/releasever"
94+
9195

9296
class UnregisterError(Exception):
9397
"""Raised with problems unregistering a system."""
@@ -185,7 +189,15 @@ def register_system():
185189
registration_cmd = RegistrationCommand.from_tool_opts(tool_opts)
186190

187191
try:
192+
# The file /etc/os-release is needed for subscribing the system and is being removed with
193+
# <system-name>-release package in one of the steps before
194+
# RHELC-16
195+
os_release_file.restore(rollback=False)
188196
registration_cmd()
197+
# Need to remove the file, if it would stay there would be leftover /etc/os-release.rpmorig
198+
# after conversion
199+
# RHELC-16
200+
os_release_file.remove()
189201
loggerinst.info("System registration succeeded.")
190202
except KeyboardInterrupt:
191203
# When the user hits Control-C to exit, we shouldn't retry
@@ -446,7 +458,8 @@ def __call__(self):
446458
register_server = system_bus.get_object("com.redhat.RHSM1", "/com/redhat/RHSM1/RegisterServer")
447459
loggerinst.debug("Starting a private DBus to talk to subscription-manager")
448460
address = register_server.Start(
449-
i18n.SUBSCRIPTION_MANAGER_LOCALE, dbus_interface="com.redhat.RHSM1.RegisterServer"
461+
i18n.SUBSCRIPTION_MANAGER_LOCALE,
462+
dbus_interface="com.redhat.RHSM1.RegisterServer",
450463
)
451464

452465
try:
@@ -516,7 +529,10 @@ def __call__(self):
516529
finally:
517530
# Always shut down the private bus
518531
loggerinst.debug("Shutting down private DBus instance")
519-
register_server.Stop(i18n.SUBSCRIPTION_MANAGER_LOCALE, dbus_interface="com.redhat.RHSM1.RegisterServer")
532+
register_server.Stop(
533+
i18n.SUBSCRIPTION_MANAGER_LOCALE,
534+
dbus_interface="com.redhat.RHSM1.RegisterServer",
535+
)
520536

521537
def _set_connection_opts_in_config(self):
522538
"""
@@ -767,10 +783,33 @@ def attach_subscription():
767783
def get_avail_subs():
768784
"""Get list of all the subscriptions available to the user so they are
769785
accessible by index once the user chooses one.
786+
787+
.. note::
788+
Get multiline string holding all the subscriptions available to the
789+
logged-in user
770790
"""
771-
# Get multiline string holding all the subscriptions available to the
772-
# logged-in user
791+
# With the current changes introduced in PR#627, we needed to remove the
792+
# non-RHEL packages that contain repofiles before we do any call to
793+
# subscription-manager, and since we are doing that, this function starts to
794+
# fail because it doesn't have the package that sets the releasever anymore.
795+
# For some reason, subscription-manager needs to call libdnf internally to
796+
# read the repositories on the system, and since libdnf needs to do
797+
# substitutions on those repofiles, mainly the releasever and any other file
798+
# placed in /etc/dnf/vars, this command call fails as it cannot replace the
799+
# releasever variable anymore.
800+
releaver_created = False
801+
if system_info.version.major >= 8:
802+
if not os.path.exists(DNF_RELEASEVER_FILE):
803+
with open(DNF_RELEASEVER_FILE, "w") as handler:
804+
handler.write(system_info.original_releasever)
805+
806+
releaver_created = True
807+
773808
subs_raw, ret_code = utils.run_subprocess(["subscription-manager", "list", "--available"], print_output=False)
809+
810+
if releaver_created:
811+
os.remove(DNF_RELEASEVER_FILE)
812+
774813
if ret_code != 0:
775814
loggerinst.critical("Unable to get list of available subscriptions:\n%s" % subs_raw)
776815
return list(get_sub(subs_raw))
@@ -996,7 +1035,12 @@ def _log_rhsm_download_directory_contents(directory, when_message):
9961035
pkgs = ["<download directory does not exist>"]
9971036
if os.path.isdir(SUBMGR_RPMS_DIR):
9981037
pkgs = os.listdir(SUBMGR_RPMS_DIR)
999-
loggerinst.debug("Contents of %s directory %s:\n%s", SUBMGR_RPMS_DIR, when_message, "\n".join(pkgs))
1038+
loggerinst.debug(
1039+
"Contents of %s directory %s:\n%s",
1040+
SUBMGR_RPMS_DIR,
1041+
when_message,
1042+
"\n".join(pkgs),
1043+
)
10001044

10011045

10021046
def exit_on_failed_download(paths):
@@ -1027,7 +1071,11 @@ def lock_releasever_in_rhel_repositories():
10271071
"Updating /etc/yum.repos.d/rehat.repo to point to RHEL %s instead of the default latest minor version."
10281072
% system_info.releasever
10291073
)
1030-
cmd = ["subscription-manager", "release", "--set=%s" % system_info.releasever]
1074+
cmd = [
1075+
"subscription-manager",
1076+
"release",
1077+
"--set=%s" % system_info.releasever,
1078+
]
10311079

10321080
output, ret_code = utils.run_subprocess(cmd, print_output=False)
10331081
if ret_code != 0:
@@ -1056,7 +1104,9 @@ def update_rhsm_custom_facts():
10561104

10571105
if ret_code != 0:
10581106
loggerinst.warning(
1059-
"Failed to update the RHSM custom facts with return code '%s' and output '%s'.", ret_code, output
1107+
"Failed to update the RHSM custom facts with return code '%s' and output '%s'.",
1108+
ret_code,
1109+
output,
10601110
)
10611111
else:
10621112
loggerinst.info("RHSM custom facts uploaded successfully.")

convert2rhel/systeminfo.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ def __init__(self):
103103
self.kmods_to_ignore = []
104104
# Booted kernel VRA (version, release, architecture), e.g. "4.18.0-240.22.1.el8_3.x86_64"
105105
self.booted_kernel = ""
106+
self.original_releasever = ""
106107

107108
def resolve_system_info(self):
108109
self.logger = logging.getLogger(__name__)
@@ -125,6 +126,7 @@ def resolve_system_info(self):
125126
self.booted_kernel = self._get_booted_kernel()
126127
self.has_internet_access = self._check_internet_access()
127128
self.dbus_running = self._is_dbus_running()
129+
self.original_releasever = _get_original_releasever()
128130

129131
def print_system_information(self):
130132
"""Print system related information."""
@@ -468,6 +470,21 @@ def get_system_release_info(self, system_release_content=None):
468470
return release_info
469471

470472

473+
def _get_original_releasever():
474+
"""Get the original value for releasever using either YUM or DNF."""
475+
from convert2rhel import pkgmanager
476+
477+
original_releasever = ""
478+
if pkgmanager.TYPE == "yum":
479+
yb = pkgmanager.YumBase()
480+
original_releasever = yb.conf.yumvar["releasever"]
481+
else:
482+
db = pkgmanager.Base()
483+
original_releasever = db.conf.releasever
484+
485+
return str(original_releasever)
486+
487+
471488
def _is_sysv_managed_dbus_running():
472489
"""Get DBus status from SysVinit compatible systems."""
473490
# None means the status should be retried because we weren't sure if it is turned off.

convert2rhel/unit_tests/backup_test.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,3 +662,25 @@ def test_restore_previously_installed(self, run_subprocess_with_empty_rpmdb, rpm
662662
)
663663
def test_remove_epoch_from_yum_nevra_notation(pkg_nevra, nvra_without_epoch):
664664
assert backup.remove_epoch_from_yum_nevra_notation(pkg_nevra) == nvra_without_epoch
665+
666+
667+
@pytest.mark.parametrize(
668+
("file", "filepath", "message"),
669+
(
670+
(False, "/invalid/path", "Couldn't remove restored file /invalid/path"),
671+
(True, "filename", "File %s removed."),
672+
),
673+
)
674+
def test_restorable_file_remove(tmpdir, caplog, file, filepath, message):
675+
if file:
676+
path = tmpdir.join(filepath)
677+
path.write("content")
678+
path = str(path)
679+
message = message % path
680+
else:
681+
path = filepath
682+
683+
restorable_file = backup.RestorableFile(path)
684+
restorable_file.remove()
685+
686+
assert message in caplog.text

convert2rhel/unit_tests/main_test.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,11 +209,12 @@ def test_pre_ponr_conversion_order_with_rhsm(self):
209209
intended_call_order["replace_subscription_manager"] = 1
210210
intended_call_order["verify_rhsm_installed"] = 1
211211
intended_call_order["install"] = 1
212+
intended_call_order["remove_repofile_pkgs"] = 1
212213
intended_call_order["subscribe_system"] = 1
213214
intended_call_order["get_rhel_repoids"] = 1
214215
intended_call_order["check_needed_repos_availability"] = 1
215216
intended_call_order["disable_repos"] = 1
216-
intended_call_order["remove_repofile_pkgs"] = 1
217+
217218
intended_call_order["enable_repos"] = 1
218219
intended_call_order["perform_pre_ponr_checks"] = 1
219220
intended_call_order["perform_system_checks"] = 1
@@ -313,15 +314,14 @@ def test_pre_ponr_conversion_order_without_rhsm(self):
313314
intended_call_order["replace_subscription_manager"] = 0
314315
intended_call_order["verify_rhsm_installed"] = 0
315316
intended_call_order["install"] = 0
317+
intended_call_order["remove_repofile_pkgs"] = 1
318+
319+
# Do not expect this one to be called - related to RHSM
316320
intended_call_order["subscribe_system"] = 0
317321
intended_call_order["get_rhel_repoids"] = 0
318322
intended_call_order["check_needed_repos_availability"] = 0
319323
intended_call_order["disable_repos"] = 0
320-
321-
intended_call_order["remove_repofile_pkgs"] = 1
322-
323324
intended_call_order["enable_repos"] = 0
324-
325325
intended_call_order["perform_pre_ponr_checks"] = 1
326326

327327
# Merge the two together like a zipper, creates a tuple which we can assert with - including method call order!

convert2rhel/unit_tests/subscription_test.py

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import dbus
2525
import dbus.connection
2626
import dbus.exceptions
27-
import pexpect
2827
import pytest
2928
import six
3029

@@ -1573,3 +1572,84 @@ def test_update_rhsm_custom_facts_no_rhsm(global_tool_opts, caplog, monkeypatch)
15731572

15741573
subscription.update_rhsm_custom_facts()
15751574
assert "Skipping updating RHSM custom facts." in caplog.records[-1].message
1575+
1576+
1577+
MOCK_LIST_AVAILABLE_SUBS_OUTPUT = """\
1578+
Subscription Name: Red Hat\n
1579+
Provides: Test\n
1580+
SKU: RHTEST\n
1581+
Contract: 123456\n
1582+
Pool ID: 096fbb526ce611ed-97076c9466263bdf\n
1583+
Provides Management: No\n
1584+
Available: Unlimited\n
1585+
Suggested: 1\n
1586+
Service Type: L1-L3\n
1587+
Roles: \n
1588+
Service Level: Self-Support\n
1589+
Usage: \n
1590+
Add-ons: \n
1591+
Subscription Type: Standard\n
1592+
Starts: 03/29/2000\n
1593+
Ends: 03/29/2003\n
1594+
Entitlement Type: Physical\n
1595+
"""
1596+
1597+
1598+
@centos8
1599+
def test_get_avail_subs(pretend_os, tmpdir, monkeypatch):
1600+
return_value = (MOCK_LIST_AVAILABLE_SUBS_OUTPUT, 0)
1601+
cmd = ["subscription-manager", "list", "--available"]
1602+
tmpdir.join("releasever").write("8")
1603+
dnf_releasever_file = str(tmpdir)
1604+
run_subprocess_mock = mock.Mock(
1605+
side_effect=unit_tests.run_subprocess_side_effect((cmd, return_value)),
1606+
)
1607+
monkeypatch.setattr(
1608+
utils,
1609+
"run_subprocess",
1610+
value=run_subprocess_mock,
1611+
)
1612+
monkeypatch.setattr(subscription, "DNF_RELEASEVER_FILE", dnf_releasever_file)
1613+
1614+
result = subscription.get_avail_subs()
1615+
assert result[0].pool_id == "096fbb526ce611ed-97076c9466263bdf"
1616+
1617+
1618+
@centos8
1619+
def test_get_avail_subs_failed_command(pretend_os, tmpdir, monkeypatch, caplog):
1620+
return_value = (MOCK_LIST_AVAILABLE_SUBS_OUTPUT, 1)
1621+
cmd = ["subscription-manager", "list", "--available"]
1622+
tmpdir.join("releasever").write("8")
1623+
dnf_releasever_file = str(tmpdir)
1624+
run_subprocess_mock = mock.Mock(
1625+
side_effect=unit_tests.run_subprocess_side_effect((cmd, return_value)),
1626+
)
1627+
monkeypatch.setattr(
1628+
utils,
1629+
"run_subprocess",
1630+
value=run_subprocess_mock,
1631+
)
1632+
monkeypatch.setattr(subscription, "DNF_RELEASEVER_FILE", dnf_releasever_file)
1633+
1634+
with pytest.raises(SystemExit):
1635+
subscription.get_avail_subs()
1636+
assert "Unable to get list of available subscriptions:" in caplog.records[-1].message
1637+
1638+
1639+
@centos8
1640+
def test_get_avail_subs_no_releasever_file(pretend_os, tmpdir, monkeypatch):
1641+
return_value = (MOCK_LIST_AVAILABLE_SUBS_OUTPUT, 0)
1642+
cmd = ["subscription-manager", "list", "--available"]
1643+
dnf_releasever_file = str(tmpdir.join("releasever"))
1644+
run_subprocess_mock = mock.Mock(
1645+
side_effect=unit_tests.run_subprocess_side_effect((cmd, return_value)),
1646+
)
1647+
monkeypatch.setattr(
1648+
utils,
1649+
"run_subprocess",
1650+
value=run_subprocess_mock,
1651+
)
1652+
monkeypatch.setattr(subscription, "DNF_RELEASEVER_FILE", dnf_releasever_file)
1653+
1654+
result = subscription.get_avail_subs()
1655+
assert result[0].pool_id == "096fbb526ce611ed-97076c9466263bdf"

convert2rhel/unit_tests/systeminfo_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626
import pytest
2727
import six
2828

29-
from convert2rhel import logger, systeminfo, unit_tests, utils # Imports unit_tests/__init__.py
29+
from convert2rhel import logger, pkgmanager, systeminfo, unit_tests, utils # Imports unit_tests/__init__.py
3030
from convert2rhel.systeminfo import RELEASE_VER_MAPPING, Version, system_info
3131
from convert2rhel.toolopts import tool_opts
3232
from convert2rhel.unit_tests import is_rpm_based_os
33-
from convert2rhel.unit_tests.conftest import all_systems, centos8
33+
from convert2rhel.unit_tests.conftest import all_systems, centos7, centos8
3434

3535

3636
six.add_move(six.MovedModule("mock", "mock", "unittest.mock"))

0 commit comments

Comments
 (0)