Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RHELC-670] Clean up new version check #566

Merged
merged 4 commits into from
Nov 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 73 additions & 43 deletions convert2rhel/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@
import os
import os.path
import re
import shutil
import tempfile

import rpm

from convert2rhel import __version__ as convert2rhel_version
from convert2rhel import __version__ as installed_convert2rhel_version
from convert2rhel import grub, pkgmanager, utils
from convert2rhel.pkghandler import (
call_yum_cmd,
Expand All @@ -46,6 +47,25 @@
KERNEL_REPO_VER_SPLIT_RE = re.compile(r"\W+")
BAD_KERNEL_RELEASE_SUBSTRINGS = ("uek", "rt", "linode")

RPM_GPG_KEY_PATH = os.path.join(utils.DATA_DIR, "gpg-keys", "RPM-GPG-KEY-redhat-release")
# The SSL certificate of the https://cdn.redhat.com/ server
SSL_CERT_PATH = os.path.join(utils.DATA_DIR, "redhat-uep.pem")
CDN_URL = "https://cdn.redhat.com/content/public/convert2rhel/$releasever/$basearch/os/"
CONVERT2RHEL_REPO_CONTENT = """\
[convert2rhel]
name=Convert2RHEL Repository
baseurl=%s
gpgcheck=1
enabled=1
sslcacert=%s
gpgkey=file://%s""" % (
CDN_URL,
SSL_CERT_PATH,
RPM_GPG_KEY_PATH,
)

PKG_NEVR = r"\b(\S+)-(?:([0-9]+):)?(\S+)-(\S+)\b"

LINK_KMODS_RH_POLICY = "https://access.redhat.com/third-party-software-support"
# The kernel version stays the same throughout a RHEL major version
COMPATIBLE_KERNELS_VERS = {
Expand Down Expand Up @@ -76,81 +96,91 @@ def perform_pre_ponr_checks():


def check_convert2rhel_latest():
"""Make sure that we are running the latest version of convert2rhel"""
gpg_path = os.path.join(utils.DATA_DIR, "gpg-keys", "RPM-GPG-KEY-redhat-release")
ssl_cert_path = os.path.join(utils.DATA_DIR, "redhat-uep.pem")
repo_content = (
"[convert2rhel]\n"
"name=Convert2RHEL Repository\n"
"baseurl=https://cdn.redhat.com/content/public/convert2rhel/$releasever/x86_64/os/\n"
"gpgcheck=1\n"
"enabled=1\n"
"sslcacert=%s\n"
"gpgkey=file://%s\n" % (ssl_cert_path, gpg_path)
)
"""Make sure that we are running the latest downstream version of convert2rhel"""
logger.task("Prepare: Checking if this is the latest version of Convert2RHEL")

if not system_info.has_internet_access:
logger.warning("Skipping the check because no internet connection has been detected.")
return

repo_dir = tempfile.mkdtemp(prefix="convert2rhel_repo.", dir=utils.TMP_DIR)
repo_path = os.path.join(repo_dir, "convert2rhel.repo")
store_content_to_file(filename=repo_path, content=CONVERT2RHEL_REPO_CONTENT)

cmd = [
"repoquery",
"--disablerepo=*",
"--enablerepo=convert2rhel",
"--releasever=%s" % system_info.version.major,
"--setopt=reposdir=%s" % repo_dir,
"convert2rhel",
]

repo_dir = tempfile.mkdtemp(prefix="convert2rhel_repo.", dir=utils.TMP_DIR)
# Note: This is safe because we're creating in utils.TMP_DIR which is hardcoded to
# /var/lib/convert2rhel which does not have any world-writable directory components.
utils.mkdir_p(repo_dir)
repo_path = os.path.join(repo_dir, "convert2rhel.repo")
store_content_to_file(filename=repo_path, content=repo_content)

cmd.append("--setopt=reposdir=%s" % repo_dir)
cmd.append("convert2rhel")

raw_output_convert2rhel_versions, return_code = run_subprocess(cmd, print_output=False)
try:
raw_output_convert2rhel_versions, return_code = run_subprocess(cmd, print_output=False)
finally:
shutil.rmtree(repo_dir)

if return_code != 0:
logger.warning(
"Couldn't check if this is the latest version of convert2rhel\n"
"repoquery failed %s, %s" % (return_code, raw_output_convert2rhel_versions)
"Couldn't check if the current installed Convert2RHEL is the latest version.\n"
"repoquery failed with the following output:\n%s" % (raw_output_convert2rhel_versions)
)
return

PKG_NEVR = r"\b(\S+)-(?:([0-9]+):)?(\S+)-(\S+)\b"
convert2rhel_versions = re.findall(PKG_NEVR, raw_output_convert2rhel_versions, re.MULTILINE)
Venefilyn marked this conversation as resolved.
Show resolved Hide resolved
latest_version = ("0", "0.00", "0")
logger.debug("Found %s convert2rhel package(s)" % len(convert2rhel_versions))
latest_available_version = ("0", "0.00", "0")

# This loop will determine the latest available convert2rhel version in the yum repo.
# It assigns the epoch, version, and release ex: ("0", "0.26", "1.el7") to the latest_available_version variable.
for package_version in convert2rhel_versions:
# rpm.lableCompare(pkg1, pkg2) compare two kernel version strings and return
# -1 if str2 is greater then str1, 0 if they are equal, 1 if str1 is greater the str2
ver_compare = rpm.labelCompare(package_version[1:], latest_version)
# rpm.labelCompare(pkg1, pkg2) compare two package version strings and return
# -1 if latest_version is greater than package_version, 0 if they are equal, 1 if package_version is greater than latest_version
ver_compare = rpm.labelCompare(package_version[1:], latest_available_version)
if ver_compare > 0:
latest_version = package_version[1:]

# After the for loop latest_version will have the epoch ,version, and release ex:("0" "0.26" "1.el7") information from convert2rhel yum repo.
# the release for latest_verion will be "1.el7" and the relase for convert2rhel_version will be hard coded as "0" below,
# therefore when the versions are the same the latest_version's release field will cause it to evaluate as later
ver_compare = rpm.labelCompare(("0", convert2rhel_version, "0"), ("0", latest_version[1], "0"))
logger.debug(
"...convert2rhel version %s is newer than %s, updating latest_available_version variable"
% (package_version[1:][1], latest_available_version[1])
)
latest_available_version = package_version[1:]
Andrew-ang9 marked this conversation as resolved.
Show resolved Hide resolved

# After the for loop, the latest_available_version variable will gain the epoch, version, and release
# (e.g. ("0" "0.26" "1.el7")) information from the Convert2RHEL yum repo
# when the versions are the same the latest_available_version's release field will cause it to evaluate as a later version.
# Therefore we need to hardcode "0" for both the epoch and release below for installed_convert2rhel_version
# and latest_available_version respectively, to compare **just** the version field.
ver_compare = rpm.labelCompare(("0", installed_convert2rhel_version, "0"), ("0", latest_available_version[1], "0"))
Venefilyn marked this conversation as resolved.
Show resolved Hide resolved
if ver_compare < 0:
if "CONVERT2RHEL_UNSUPPORTED_VERSION" in os.environ:
if "CONVERT2RHEL_ALLOW_OLDER_VERSION" in os.environ:
logger.warning(
"You are currently running %s and the latest version of convert2rhel is %s.\n"
"'CONVERT2RHEL_UNSUPPORTED_VERSION' environment detected, continuing conversion"
% (convert2rhel_version, latest_version[1])
"You are currently running %s and the latest version of Convert2RHEL is %s.\n"
"'CONVERT2RHEL_ALLOW_OLDER_VERSION' environment variable detected, continuing conversion"
% (installed_convert2rhel_version, latest_available_version[1])
)

else:
if int(system_info.version.major) <= 6:
Andrew-ang9 marked this conversation as resolved.
Show resolved Hide resolved
logger.warning(
"You are currently running %s and the latest version of convert2rhel is %s.\n"
"Only the latest version is supported for conversion." % (convert2rhel_version, latest_version[1])
"You are currently running %s and the latest version of Convert2RHEL is %s.\n"
"We encourage you to update to the latest version."
% (installed_convert2rhel_version, latest_available_version[1])
)

else:
logger.critical(
"You are currently running %s and the latest version of convert2rhel is %s.\n"
"You are currently running %s and the latest version of Convert2RHEL is %s.\n"
"Only the latest version is supported for conversion. If you want to ignore"
" this you can set 'CONVERT2RHEL_UNSUPPORTED_VERSION' to continue"
% (convert2rhel_version, latest_version[1])
" this check, then set the environment variable 'CONVERT2RHEL_ALLOW_OLDER_VERSION=1' to continue."
% (installed_convert2rhel_version, latest_available_version[1])
)

else:
logger.debug("Latest available convert2rhel version is installed.\n" "Continuing conversion.")
logger.debug("Latest available Convert2RHEL version is installed.\n" "Continuing conversion.")


def check_efi():
Expand Down
121 changes: 91 additions & 30 deletions convert2rhel/unit_tests/checks_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,17 @@


@pytest.fixture
def convert2rhel_latest_version_test(monkeypatch, tmpdir, request):
def convert2rhel_latest_version_test(monkeypatch, tmpdir, request, global_system_info):
monkeypatch.setattr(checks, "system_info", global_system_info)
global_system_info.has_internet_access = True

marker = request.param
monkeypatch.setattr(checks, "convert2rhel_version", marker["local_version"])
monkeypatch.setattr(checks, "installed_convert2rhel_version", marker["local_version"])

run_subprocess_mocked = mock.Mock(spec=run_subprocess, return_value=(marker["package_version"], 0))

monkeypatch.setattr(checks, "run_subprocess", run_subprocess_mocked)
monkeypatch.setattr(system_info, "version", namedtuple("Version", ["major", "minor"])(marker["pmajor"], 0))
monkeypatch.setattr(global_system_info, "version", namedtuple("Version", ["major", "minor"])(marker["pmajor"], 0))
monkeypatch.setattr(utils, "TMP_DIR", str(tmpdir))

return marker["local_version"], marker["package_version"]
Expand Down Expand Up @@ -187,36 +190,36 @@ def test_pre_ponr_checks(monkeypatch):
create_transaction_handler_mock.assert_called_once()


def test_repoquery__failure(caplog, monkeypatch, tmpdir, request):
repoquery_output = " error message"
return_code = 1
run_subprocess_mocked = mock.Mock(spec=run_subprocess, return_value=(repoquery_output, return_code))

monkeypatch.setattr(checks, "run_subprocess", run_subprocess_mocked)
monkeypatch.setattr(system_info, "version", namedtuple("Version", ["major", "minor"])(6, 0))
monkeypatch.setattr(utils, "TMP_DIR", str(tmpdir))

@pytest.mark.parametrize(
("convert2rhel_latest_version_test",),
([{"local_version": "0.20", "package_version": "convert2rhel-0:0.22-1.el7.noarch", "pmajor": "7"}],),
indirect=True,
)
def test_convert2rhel_latest_offline(caplog, convert2rhel_latest_version_test, global_system_info):
global_system_info.has_internet_access = False
checks.check_convert2rhel_latest()

log_msg = "Couldn't check if this is the latest version of convert2rhel\n" "repoquery failed %s, %s" % (
return_code,
repoquery_output,
)
convert2rhel_latest_version_test
log_msg = "Skipping the check because no internet connection has been detected."
assert log_msg in caplog.text


@pytest.mark.parametrize(
("convert2rhel_latest_version_test",),
([{"local_version": "0.20", "package_version": "convert2rhel-0:0.22-1.el7.noarch", "pmajor": "6"}],),
(
[{"local_version": "0.20", "package_version": "convert2rhel-0:0.22-1.el7.noarch", "pmajor": "6"}],
[{"local_version": "0.18", "package_version": "convert2rhel-0:1.10-1.el7.noarch", "pmajor": "6"}],
),
indirect=True,
)
def test_convert2rhel_latest_out_of_date_el6(caplog, convert2rhel_latest_version_test):
checks.check_convert2rhel_latest()

local_version, dummy_ = convert2rhel_latest_version_test
local_version, package_version = convert2rhel_latest_version_test
package_version = package_version[15:19]
log_msg = (
"You are currently running %s and the latest version of convert2rhel is 0.22.\n"
"Only the latest version is supported for conversion." % (local_version)
"You are currently running %s and the latest version of Convert2RHEL is %s.\n"
"We encourage you to update to the latest version." % (local_version, package_version)
)
assert log_msg in caplog.text

Expand All @@ -225,19 +228,21 @@ def test_convert2rhel_latest_out_of_date_el6(caplog, convert2rhel_latest_version
("convert2rhel_latest_version_test",),
(
[{"local_version": "0.21", "package_version": "convert2rhel-0:0.22-1.el7.noarch", "pmajor": "7"}],
[{"local_version": "0.21", "package_version": "convert2rhel-0:0.22-1.el7.noarch", "pmajor": "8"}],
[{"local_version": "0.21", "package_version": "convert2rhel-0:1.10-1.el7.noarch", "pmajor": "7"}],
),
indirect=True,
)
def test_convert2rhel_latest_log_check_exit(caplog, convert2rhel_latest_version_test):
with pytest.raises(SystemExit):
checks.check_convert2rhel_latest()
local_version, dummy_ = convert2rhel_latest_version_test
local_version, package_version = convert2rhel_latest_version_test
package_version = package_version[15:19]

log_msg = (
"You are currently running %s and the latest version of convert2rhel is 0.22.\n"
"Only the latest version is supported for conversion. If you want to ignore this you can set 'CONVERT2RHEL_UNSUPPORTED_VERSION' to continue"
% (local_version)
"You are currently running %s and the latest version of Convert2RHEL is %s.\n"
"Only the latest version is supported for conversion. If you want to ignore"
" this check, then set the environment variable 'CONVERT2RHEL_ALLOW_OLDER_VERSION=1' to continue."
% (local_version, package_version)
)
assert log_msg in caplog.text

Expand Down Expand Up @@ -269,18 +274,29 @@ def test_convert2rhel_latest_log_check_exit(caplog, convert2rhel_latest_version_
"enset": "1",
}
],
[
{
"local_version": "0.18",
"package_version": "convert2rhel-0:1.10-1.el7.noarch",
"pmajor": "8",
"enset": "1",
}
],
),
indirect=True,
)
def test_convert2rhel_latest_log_check_env(caplog, monkeypatch, convert2rhel_latest_version_test):
monkeypatch.setattr(os, "environ", {"CONVERT2RHEL_UNSUPPORTED_VERSION": "1"})
monkeypatch.setattr(os, "environ", {"CONVERT2RHEL_ALLOW_OLDER_VERSION": "1"})
checks.check_convert2rhel_latest()

local_version, dummy_ = convert2rhel_latest_version_test
local_version, package_version = convert2rhel_latest_version_test
package_version = package_version[15:19]
log_msg = (
"You are currently running %s and the latest version of convert2rhel is 0.22.\n"
"'CONVERT2RHEL_UNSUPPORTED_VERSION' environment detected, continuing conversion" % (local_version)
"You are currently running %s and the latest version of Convert2RHEL is %s.\n"
"'CONVERT2RHEL_ALLOW_OLDER_VERSION' environment variable detected, continuing conversion"
% (local_version, package_version)
)

assert log_msg in caplog.text


Expand All @@ -293,14 +309,59 @@ def test_convert2rhel_latest_log_check_env(caplog, monkeypatch, convert2rhel_lat
[{"local_version": "0.25", "package_version": "convert2rhel-0:0.17-1.el7.noarch", "pmajor": "6"}],
[{"local_version": "0.25", "package_version": "convert2rhel-0:0.17-1.el7.noarch", "pmajor": "7"}],
[{"local_version": "0.25", "package_version": "convert2rhel-0:0.17-1.el7.noarch", "pmajor": "8"}],
[{"local_version": "1.10", "package_version": "convert2rhel-0:0.18-1.el7.noarch", "pmajor": "8"}],
),
indirect=True,
)
def test_c2r_up_to_date(caplog, monkeypatch, convert2rhel_latest_version_test):
checks.check_convert2rhel_latest()

local_version, dummy_ = convert2rhel_latest_version_test
log_msg = "Latest available convert2rhel version is installed.\n" "Continuing conversion."
log_msg = "Latest available Convert2RHEL version is installed.\n" "Continuing conversion."
assert log_msg in caplog.text


@pytest.mark.parametrize(
("convert2rhel_latest_version_test",),
([{"local_version": "1.10", "package_version": "convert2rhel-0:0.18-1.el7.noarch", "pmajor": "8"}],),
indirect=True,
)
def test_c2r_up_to_date_repoquery_error(caplog, convert2rhel_latest_version_test, monkeypatch):
monkeypatch.setattr(checks, "run_subprocess", mock.Mock(return_value=("Repoquery did not run", 1)))

checks.check_convert2rhel_latest()

log_msg = (
"Couldn't check if the current installed Convert2RHEL is the latest version.\n"
"repoquery failed with the following output:\nRepoquery did not run"
)
assert log_msg in caplog.text


@pytest.mark.parametrize(
("convert2rhel_latest_version_test",),
(
[
{
"local_version": "0.19",
"package_version": "convert2rhel-0:0.18-1.el7.noarch\nconvert2rhel-0:0.17-1.el7.noarch\nconvert2rhel-0:0.20-1.el7.noarch",
"pmajor": "8",
}
],
),
indirect=True,
)
def test_c2r_up_to_date_multiple_packages(caplog, convert2rhel_latest_version_test, monkeypatch):

with pytest.raises(SystemExit):
checks.check_convert2rhel_latest()

log_msg = (
"You are currently running 0.19 and the latest version of Convert2RHEL is 0.20.\n"
"Only the latest version is supported for conversion. If you want to ignore"
" this check, then set the environment variable 'CONVERT2RHEL_ALLOW_OLDER_VERSION=1' to continue."
)

assert log_msg in caplog.text


Expand Down
Loading