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 Feb 13, 2023
1 parent 3210770 commit 7264167
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 20 deletions.
37 changes: 21 additions & 16 deletions convert2rhel/pkgmanager/handlers/yum/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,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("*")
# Set the download progress display
self._base.repos.setProgressBar(PackageDownloadCallback())
Expand All @@ -149,22 +153,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/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()
7 changes: 4 additions & 3 deletions tests/integration/tier1/single-yum-transaction/main.fmf
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
summary: Single yum transaction
summary: Verify the single yum transaction

description: |
Handle the unified yum transactions so that it handles packages without error. Previous iterations used a lot of
different steps, whereas now it is one transaction that can be rolled back more easily.
Handle the unified yum transactions so that it handles packages without
error. Previous iterations used a lot of different steps, whereas now it is
one transaction that can be rolled back more easily.

link: https://issues.redhat.com/browse/RHELC-576

Expand Down
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 7264167

Please sign in to comment.