Skip to content

Commit

Permalink
Add missing integration tests for single yum transaction
Browse files Browse the repository at this point in the history
While testing convert2rhel manually in a vagrant box, I realized that the
conversion stopped in the yum transaction validation phase, generating a
traceback and not doing a proper rollback after the error appeared.

Since the transaction validation is supposed to trigger the rollback in case of
any failures, it was strange that the tool was not behaving the way it should.

As part of oamg#674 that introduced the fix, we left out the integration tests that
were supposed to cover this scenario.

Signed-off-by: Rodolfo Olivieri <[email protected]>
  • Loading branch information
r0x0d committed Jan 2, 2023
1 parent 47366e9 commit 51dac68
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 15 deletions.
34 changes: 21 additions & 13 deletions convert2rhel/pkgmanager/handlers/yum.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,11 @@ def _set_up_base(self):
self._base.conf.yumvar["releasever"] = system_info.releasever

def _enable_repos(self):
"""Enable a list of required repositories."""
"""Enable a list of required repositories.
:raises SystemInfo: If there is no way to connect to the mirrors in the
repos.
"""
self._base.repos.disableRepo("*")
enabled_repos = system_info.get_enabled_rhel_repos()
loggerinst.info("Enabling RHEL repositories:\n%s" % "\n".join(enabled_repos))
Expand All @@ -134,19 +138,23 @@ def _perform_operations(self):

loggerinst.info("Adding %s packages to the yum transaction set.", system_info.name)

for pkg in original_os_pkgs:
self._base.update(pattern=pkg)
try:
self._base.reinstall(pattern=pkg)
except (pkgmanager.Errors.ReinstallInstallError, pkgmanager.Errors.ReinstallRemoveError):
try:
for pkg in original_os_pkgs:
self._base.update(pattern=pkg)
try:
self._base.downgrade(pattern=pkg)
except (
pkgmanager.Errors.ReinstallInstallError,
pkgmanager.Errors.ReinstallRemoveError,
pkgmanager.Errors.DowngradeError,
):
loggerinst.warning("Package %s not available in RHEL repositories.", pkg)
self._base.reinstall(pattern=pkg)
except (pkgmanager.Errors.ReinstallInstallError, pkgmanager.Errors.ReinstallRemoveError):
try:
self._base.downgrade(pattern=pkg)
except (
pkgmanager.Errors.ReinstallInstallError,
pkgmanager.Errors.ReinstallRemoveError,
pkgmanager.Errors.DowngradeError,
):
loggerinst.warning("Package %s not available in RHEL repositories.", pkg)
except pkgmanager.Errors.NoMoreMirrorsRepoError as e:
loggerinst.debug("Got the following exception message: %s", e)
loggerinst.critical("There are no suitable mirrors available for the loaded repositories.")

def _resolve_dependencies(self, validate_transaction):
"""Try to resolve the transaction dependencies.
Expand Down
9 changes: 9 additions & 0 deletions convert2rhel/unit_tests/pkgmanager/handlers/yum_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,15 @@ def test_perform_operations_downgrade_exception(
assert pkgmanager.YumBase.downgrade.call_count == len(system_packages)
assert "not available in RHEL repositories." in caplog.records[-1].message

@centos7
def test_perform_operations_no_more_mirrors_repo_exception(self, pretend_os, _mock_yum_api_calls, monkeypatch):
monkeypatch.setattr(pkgmanager.handlers.yum, "get_system_packages_for_replacement", lambda: ["pkg-1"])
pkgmanager.YumBase.update.side_effect = pkgmanager.Errors.NoMoreMirrorsRepoError
instance = YumTransactionHandler()

with pytest.raises(SystemExit, match="There are no suitable mirrors available for the loaded repositories."):
instance._perform_operations()

@centos7
@pytest.mark.parametrize(
("ret_code", "message", "validate_transaction", "expected"),
Expand Down
4 changes: 4 additions & 0 deletions plans/tier0.fmf
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,7 @@
/log_command_verification:
discover+:
test: log-command

/single_yum_transaction_validation:
discover+:
test: single-yum-transaction-validation
3 changes: 3 additions & 0 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import dataclasses
import logging
import os
import re
import subprocess
import sys
Expand Down Expand Up @@ -30,6 +31,8 @@
SATELLITE_PKG_URL = "https://satellite.sat.engineering.redhat.com/pub/katello-ca-consumer-latest.noarch.rpm"
SATELLITE_PKG_DST = "/usr/share/convert2rhel/subscription-manager/katello-ca-consumer-latest.noarch.rpm"

SYSTEM_RELEASE = os.environ["SYSTEM_RELEASE"]


@pytest.fixture()
def shell(tmp_path):
Expand Down
26 changes: 26 additions & 0 deletions tests/integration/tier0/single-yum-transaction-validation/main.fmf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
summary: Single Yum Transaction Validation
description: >
Verify that we are doing a proper rollback during (and before) the
validation phase in our transactions.

tier: 0

tag+:
- yum
- dnf
- transaction

/transaction_validation_error:
adjust+:
- enabled: false
when: distro == centos-8 or distro == oraclelinux-8
tag+:
- transaction-validation-error
test: |
pytest -svv -m transaction_validation_error

/package_download_error:
tag+:
- package-download-error
test: |
pytest -svv -m package_download_error
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import os
import shutil

import pytest

from conftest import SYSTEM_RELEASE
from envparse import env


PKI_ENTITLEMENT_KEYS_PATH = "/etc/pki/entitlement"


def backup_entitlement_keys():
original_keys = os.listdir(PKI_ENTITLEMENT_KEYS_PATH)

for key in original_keys:
full_key = "{}/{}".format(PKI_ENTITLEMENT_KEYS_PATH, key)
new_key = "{}.bk".format(full_key)
shutil.move(full_key, new_key)


def rollback_entitlement_keys():
""""""
backup_keys = os.listdir(PKI_ENTITLEMENT_KEYS_PATH)

for key in backup_keys:
# This is already in the format with a .bk at the end of it
backup_key = "{}/{}".format(PKI_ENTITLEMENT_KEYS_PATH, key)
original_key = "{}".format(backup_key)
shutil.move(backup_key, original_key)


@pytest.mark.package_download_error
def test_package_download_error(convert2rhel):
"""
Remove the entitlement keys found at /etc/pki/entitlement during package
download phase for both yum and dnf transactions.
This will run the conversion up to the point where we valiate the
transaction, when it reaches a specific point of the validation, we remove
the entitlement keys found in /etc/pki/entitlement/*.pem to ensure that the
tool is doing a proper rollback when there is any failure during the package
download.
The package download happens in different phases for yum and dnf, yum
download the packages during the `processTransaction` method call, while dnf
has a specific method that process and download the packages in the
transaction.
"""

server_sub = "CentOS Linux"
pkgmanager = "yum"
final_message = "There are no suitable mirrors available for the loaded repositories."

if "oracle" in SYSTEM_RELEASE:
server_sub = "Oracle Linux Server"

if "8" in SYSTEM_RELEASE:
pkgmanager = "dnf"
final_message = "Failed to download the transaction packages."

with convert2rhel(
"-y --no-rpm-va --serverurl {} --username {} --password {} --pool {} --debug".format(
env.str("RHSM_SERVER_URL"),
env.str("RHSM_USERNAME"),
env.str("RHSM_PASSWORD"),
env.str("RHSM_POOL"),
)
) as c2r:
c2r.expect("Adding {} packages to the {} transaction set.".format(server_sub, pkgmanager))
backup_entitlement_keys()
assert c2r.expect_exact(final_message, timeout=600) == 0

assert c2r.exitstatus == 1

rollback_entitlement_keys()


@pytest.mark.transaction_validation_error
def test_transaction_validation_error(convert2rhel):
"""
Remove the entitlement keys found at /etc/pki/entitlement during transaction
processing to throw the following yum error: pkgmanager.Errors.YumDownloadError
This will run the conversion up to the point where we valiate the
transaction, when it reaches a specific point of the validation, we remove
the entitlement keys found in /etc/pki/entitlement/*.pem to ensure that the
tool is doing a proper rollback when the transaction is being processed.
"""

with convert2rhel(
"-y --no-rpm-va --serverurl {} --username {} --password {} --pool {} --debug".format(
env.str("RHSM_SERVER_URL"),
env.str("RHSM_USERNAME"),
env.str("RHSM_PASSWORD"),
env.str("RHSM_POOL"),
)
) as c2r:
c2r.expect("Validating the yum transaction set, no modifications to the system will happen this time.")
backup_entitlement_keys()
assert c2r.expect_exact("Failed to validate the yum transaction.", timeout=600) == 0

assert c2r.exitstatus == 1

rollback_entitlement_keys()
4 changes: 3 additions & 1 deletion tests/integration/tier1/single-yum-transaction/main.fmf
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
summary: single-yum-transaction
summary: >
Verify that we are validating and replacing the packages as needed
during the transaction handler.

tier: 1
test: pytest -svv
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def test_single_yum_transaction(convert2rhel, shell):
pkgmanager = "dnf"

with convert2rhel(
("-y --no-rpm-va --serverurl {} --username {} --password {} --pool {} --debug").format(
"-y --no-rpm-va --serverurl {} --username {} --password {} --pool {} --debug".format(
env.str("RHSM_SERVER_URL"),
env.str("RHSM_USERNAME"),
env.str("RHSM_PASSWORD"),
Expand Down

0 comments on commit 51dac68

Please sign in to comment.