Skip to content

Commit

Permalink
Fix the issue
Browse files Browse the repository at this point in the history
  • Loading branch information
hosekadam committed Jan 17, 2024
1 parent 18add35 commit 92de78d
Show file tree
Hide file tree
Showing 5 changed files with 42,185 additions and 5 deletions.
7 changes: 5 additions & 2 deletions convert2rhel/data/7/x86_64/configs/centos-7-x86_64.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ gpg_fingerprints = 24c6a8a7f4a80eb5
excluded_pkgs =
anaconda-dracut
centos-bookmarks
centos-indexhtml
centos-logos
cockpit-subscriptions
geoipupdate
kmod-kvdo
Expand All @@ -23,6 +21,11 @@ excluded_pkgs =
yum-rhn-plugin
gnome-documents-libs

# Mapping of packages that need to be swapped during the transaction
swap_pkgs =
centos-logos | redhat-logos
centos-indexhtml | redhat-indexhtml

# List of packages that either contain repofiles or affect variables in the repofiles (e.g. $releasever).
# Delimited by any whitespace(s).
repofile_pkgs =
Expand Down
46 changes: 45 additions & 1 deletion convert2rhel/pkgmanager/handlers/yum/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,45 @@ def _enable_repos(self):
diagnosis="Loading repository metadata failed with error %s." % (str(e)),
)

def _swap_problematic_packages(self):
"""Swap system packages for their RHEL counterparts in the transaction
Some packages need to be manually injected in the transaction as a
"swap", since those packages are not always able to be installed
automatically by yum if they don't exist in the system anymore, this
can cause problems during the transaction as missing dependencies.
"""
# packages_to_backup = []
for old_package, new_package in system_info.swap_pkgs.items():
is_installed = system_info.is_rpm_installed(old_package)
loggerinst.debug("Checking if %s installed for later swap." % old_package)

Check warning on line 177 in convert2rhel/pkgmanager/handlers/yum/__init__.py

View check run for this annotation

Codecov / codecov/patch

convert2rhel/pkgmanager/handlers/yum/__init__.py#L176-L177

Added lines #L176 - L177 were not covered by tests
if is_installed:
loggerinst.debug("Package %s will be swapped during conversion." % old_package)

Check warning on line 179 in convert2rhel/pkgmanager/handlers/yum/__init__.py

View check run for this annotation

Codecov / codecov/patch

convert2rhel/pkgmanager/handlers/yum/__init__.py#L179

Added line #L179 was not covered by tests
# packages_to_backup.append(old_package)
self._base.remove(pattern=old_package)
self._base.install(pattern=new_package)

Check warning on line 182 in convert2rhel/pkgmanager/handlers/yum/__init__.py

View check run for this annotation

Codecov / codecov/patch

convert2rhel/pkgmanager/handlers/yum/__init__.py#L181-L182

Added lines #L181 - L182 were not covered by tests

# Since we don't care about rollback in this case, this doesn't have to be there

# Only perform backup if we are not validating the transaction.
# if not validate_transaction:
# loggerinst.debug(
# "Swapping problematic packages to continue with the transaction:\n%s",
# "\n".join(packages_to_backup),
# )

# TODO think about the backup - is it needed or not
# we can call different function for the backup https://github.com/oamg/convert2rhel/blob/main/convert2rhel/backup.py#L52
# remove_pkgs(
# pkgs_to_remove=packages_to_backup,
# backup=True,
# critical=True,
# set_releasever=True,
# reposdir=BACKUP_DIR,
# custom_releasever=system_info.version.major,
# varsdir=os.path.join(BACKUP_DIR, "yum", "vars"),
# )

def _perform_operations(self):
"""Perform the necessary operations in the transaction.
Expand All @@ -186,19 +225,24 @@ def _perform_operations(self):
# package. This is an inconsistency that could lead to packages
# being outdated in the system after the conversion.
if can_update:
loggerinst.info("Package %s will be updated.", pkg)

Check warning on line 228 in convert2rhel/pkgmanager/handlers/yum/__init__.py

View check run for this annotation

Codecov / codecov/patch

convert2rhel/pkgmanager/handlers/yum/__init__.py#L228

Added line #L228 was not covered by tests
continue

try:
self._base.reinstall(pattern=pkg)
loggerinst.info("Package %s will be reinstalled.", pkg)

Check warning on line 232 in convert2rhel/pkgmanager/handlers/yum/__init__.py

View check run for this annotation

Codecov / codecov/patch

convert2rhel/pkgmanager/handlers/yum/__init__.py#L232

Added line #L232 was not covered by tests
except (pkgmanager.Errors.ReinstallInstallError, pkgmanager.Errors.ReinstallRemoveError):

try:
self._base.downgrade(pattern=pkg)
loggerinst.info("Package %s will be downgraded.", pkg)

Check warning on line 237 in convert2rhel/pkgmanager/handlers/yum/__init__.py

View check run for this annotation

Codecov / codecov/patch

convert2rhel/pkgmanager/handlers/yum/__init__.py#L237

Added line #L237 was not covered by tests
except (
pkgmanager.Errors.ReinstallInstallError,
pkgmanager.Errors.ReinstallRemoveError,
pkgmanager.Errors.DowngradeError,
):
loggerinst.warning("Package %s not available in RHEL repositories.", pkg)

self._swap_problematic_packages()

Check warning on line 245 in convert2rhel/pkgmanager/handlers/yum/__init__.py

View check run for this annotation

Codecov / codecov/patch

convert2rhel/pkgmanager/handlers/yum/__init__.py#L245

Added line #L245 was not covered by tests
except pkgmanager.Errors.NoMoreMirrorsRepoError as e:
loggerinst.debug("Got the following exception message: %s", e)
loggerinst.critical_no_exit("There are no suitable mirrors available for the loaded repositories.")
Expand Down
18 changes: 18 additions & 0 deletions convert2rhel/systeminfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ def __init__(self):
self.eus_system = None
# Packages to be removed before the system conversion
self.excluded_pkgs = []
# Packages that need to perform a swap in the transaction
self.swap_pkgs = {}
# Release packages to be removed before the system conversion
self.repofile_pkgs = []
self.cfg_filename = None
Expand Down Expand Up @@ -124,6 +126,7 @@ def resolve_system_info(self):
self.cfg_filename = self._get_cfg_filename()
self.cfg_content = self._get_cfg_content()
self.excluded_pkgs = self._get_excluded_pkgs()
self.swap_pkgs = self._get_swap_pkgs()
self.repofile_pkgs = self._get_repofile_pkgs()
self.default_rhsm_repoids = self._get_default_rhsm_repoids()
self.eus_rhsm_repoids = self._get_eus_rhsm_repoids()
Expand Down Expand Up @@ -251,6 +254,21 @@ def _get_gpg_key_fingerprints(self):
def _get_excluded_pkgs(self):
return self._get_cfg_opt("excluded_pkgs").split()

def _get_swap_pkgs(self):
pkgs_to_swap = {}

try:
lines = self._get_cfg_opt("swap_pkgs").strip().split("\n")
for line in lines:
old_package, new_package = tuple(line.split("|"))
pkgs_to_swap.update({old_package.strip(): new_package.strip()})

except (AttributeError, ValueError):
# Leave the swap packages dict empty
pass

return pkgs_to_swap

def _get_repofile_pkgs(self):
return self._get_cfg_opt("repofile_pkgs").split()

Expand Down
42 changes: 40 additions & 2 deletions convert2rhel/unit_tests/pkgmanager/handlers/yum/yum_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from convert2rhel import exceptions, pkghandler, pkgmanager, unit_tests, utils
from convert2rhel.pkgmanager.handlers.yum import YumTransactionHandler
from convert2rhel.systeminfo import system_info
from convert2rhel.unit_tests import RemovePkgsMocked, create_pkg_information, mock_decorator
from convert2rhel.unit_tests import RemovePkgsMocked, RunSubprocessMocked, create_pkg_information, mock_decorator

Check notice

Code scanning / CodeQL

Unused import Note

Import of 'RunSubprocessMocked' is not used.
from convert2rhel.unit_tests.conftest import centos7


Expand Down Expand Up @@ -107,6 +107,8 @@ def _mock_yum_api_calls(self, monkeypatch):
monkeypatch.setattr(pkgmanager.YumBase, "downgrade", value=mock.Mock())
monkeypatch.setattr(pkgmanager.YumBase, "resolveDeps", value=mock.Mock(return_value=(0, "Success.")))
monkeypatch.setattr(pkgmanager.YumBase, "processTransaction", value=mock.Mock())
monkeypatch.setattr(pkgmanager.YumBase, "install", value=mock.Mock())
monkeypatch.setattr(pkgmanager.YumBase, "remove", value=mock.Mock())

@centos7
def test_set_up_base(self, pretend_os):
Expand Down Expand Up @@ -144,14 +146,18 @@ def test_enable_repos_repo_error(self, pretend_os, enabled_rhel_repos, _mock_yum

@centos7
def test_perform_operations(self, pretend_os, _mock_yum_api_calls, caplog, monkeypatch):
swap_problematic_packages = mock.Mock()

monkeypatch.setattr(pkghandler, "get_installed_pkg_information", lambda: SYSTEM_PACKAGES)
monkeypatch.setattr(YumTransactionHandler, "_swap_problematic_packages", swap_problematic_packages)
instance = YumTransactionHandler()

instance._perform_operations()

assert pkgmanager.YumBase.update.call_count == len(SYSTEM_PACKAGES)
assert pkgmanager.YumBase.reinstall.call_count == len(SYSTEM_PACKAGES)
assert pkgmanager.YumBase.downgrade.call_count == 0
assert swap_problematic_packages.call_count == 1

@centos7
def test_perform_operations_reinstall_exception(self, pretend_os, _mock_yum_api_calls, caplog, monkeypatch):
Expand All @@ -176,7 +182,7 @@ def test_perform_operations_downgrade_exception(self, pretend_os, _mock_yum_api_

assert pkgmanager.YumBase.reinstall.call_count == len(SYSTEM_PACKAGES)
assert pkgmanager.YumBase.downgrade.call_count == len(SYSTEM_PACKAGES)
assert "not available in RHEL repositories." in caplog.records[-1].message
assert "not available in RHEL repositories." in caplog.text

@centos7
def test_perform_operations_no_more_mirrors_repo_exception(self, pretend_os, _mock_yum_api_calls, monkeypatch):
Expand Down Expand Up @@ -324,6 +330,38 @@ def test_package_marked_for_update(self, pretend_os, _mock_yum_api_calls, monkey
assert pkgmanager.YumBase.reinstall.call_count == 0
assert pkgmanager.YumBase.downgrade.call_count == 0

@centos7
@pytest.mark.parametrize(
("installed_pkgs", "swap_pkgs", "swaps"),
(
(["pkg0", "pkg1"], {"pkg0": "new_pkg0", "pkg1": "new_pkg1"}, 2),
(["pkg1"], {"pkg0": "new_pkg0", "pkg1": "new_pkg1"}, 1),
([], {"pkg0": "new_pkg0", "pkg1": "new_pkg1"}, 0),
(["pkg0", "pkg1", "pkg2"], {}, 0),
([], {}, 0),
),
)
def test_swap_problematic_packages(
self, monkeypatch, installed_pkgs, swap_pkgs, _mock_yum_api_calls, pretend_os, swaps
):
def return_installed(pkg):
"""Dynamically change the return value."""
return True if pkg in installed_pkgs else False

is_rpm_installed = mock.Mock(side_effect=return_installed)

monkeypatch.setattr(system_info, "is_rpm_installed", value=is_rpm_installed)
monkeypatch.setattr(system_info, "swap_pkgs", value=swap_pkgs)

instance = YumTransactionHandler()
# Need to setup the base, in the production code it's done in upper level
instance._set_up_base()

instance._swap_problematic_packages()

assert pkgmanager.YumBase.remove.call_count == swaps
assert pkgmanager.YumBase.install.call_count == swaps


@centos7
@pytest.mark.parametrize(
Expand Down
Loading

0 comments on commit 92de78d

Please sign in to comment.