mirror of
https://pagure.io/fedora-qa/os-autoinst-distri-fedora.git
synced 2024-12-25 19:53:08 +00:00
3f951b47d8
As discussed in https://pagure.io/releng/failed-composes/issue/6538 we noticed a gap in openQA coverage here. We don't check the versions of packages lorax installs to the installer environment, and those packages do not make it to the installed system, so if there's a dep issue that prevents a package in the update from being included in the installer environment, but the same dep issue isn't caught on any other path, we miss the problem. This wires the updvercheck.py script into the _installer_build and _ostree_build tests to catch this kind of problem, and makes it capable of parsing pylorax.log files into its preferred format to enable that. Signed-off-by: Adam Williamson <awilliam@redhat.com>
133 lines
4.7 KiB
Python
133 lines
4.7 KiB
Python
#!/usr/bin/python3
|
|
|
|
"""This script does a version comparison between the versions of packages
|
|
from the update under test and the installed versions of the same-named
|
|
packages, for whichever packages from the update are installed. It expects
|
|
input data that's generated in advisory_check_nonmatching_packages and
|
|
advisory_get_installed_packages; you can run it manually against
|
|
updatepkgs.txt and installedupdatepkgs.txt logs from a completed test run
|
|
if you need to test it or something."""
|
|
|
|
# no, pylint, global scope variable names in a script like this aren't
|
|
# really "constants"
|
|
# pylint:disable=invalid-name
|
|
|
|
import json
|
|
import sys
|
|
from urllib.request import urlopen
|
|
|
|
import rpm # pylint:disable=import-error
|
|
|
|
def printver(pname, pepoch, pversion, prelease):
|
|
"""Print a NEVR in the typical human-readable format."""
|
|
return f"{pname}-{pepoch}:{pversion}-{prelease}"
|
|
|
|
def parse_lorax_log(logfile):
|
|
"""
|
|
Parse a pylorax.log file into a format the rest of the script
|
|
can work with.
|
|
"""
|
|
with open(logfile, "r", encoding="utf-8") as logfh:
|
|
log = logfh.read()
|
|
log = log.splitlines()
|
|
|
|
# Filter to the lines that indicate installed packages
|
|
installed = [line for line in log if line.startswith("Install ")]
|
|
# Drop the "Install " prefix
|
|
installed = [line.split()[1] for line in installed]
|
|
# Do a split to get (lname, lepoch+lversion, lrelease) tuples
|
|
installed = [line.rsplit("-", 2) for line in installed]
|
|
# create an output list
|
|
out = []
|
|
for (lname, ev, lrelease) in installed:
|
|
# fiddle a 0 epoch into all the packages without an explicit one
|
|
if ":" not in ev:
|
|
ev = f"0:{ev}"
|
|
# split the epoch and version out
|
|
(lepoch, lversion) = ev.split(":")
|
|
# strip the arch suffix from the release
|
|
lrelease = lrelease.rsplit(".", 1)[0]
|
|
# output in the format we expect later
|
|
out.append(f"unknown {lname} {lepoch} {lversion} {lrelease}")
|
|
return out
|
|
|
|
try:
|
|
updfname = sys.argv[1]
|
|
instfname = sys.argv[2]
|
|
except IndexError:
|
|
sys.exit("Must specify two input filenames!")
|
|
try:
|
|
updalias = sys.argv[3]
|
|
except IndexError:
|
|
updalias = None
|
|
|
|
|
|
updpkgs = {}
|
|
with open(updfname, "r", encoding="utf-8") as ufh:
|
|
for uline in ufh.readlines():
|
|
(_, name, epoch, version, release) = uline.strip().split(" ")
|
|
updpkgs[name] = (epoch, version, release)
|
|
|
|
problems = []
|
|
warnings = []
|
|
post = set()
|
|
ret = 0
|
|
updstableobs = None
|
|
if "lorax.log" in instfname:
|
|
ilines = parse_lorax_log(instfname)
|
|
else:
|
|
with open(instfname, "r", encoding="utf-8") as ifh:
|
|
ilines = ifh.readlines()
|
|
for iline in ilines:
|
|
(_, name, epoch, version, release) = iline.strip().split(" ")
|
|
if name not in updpkgs:
|
|
# this happens with lorax logs, as they contain every package
|
|
continue
|
|
res = rpm.labelCompare((epoch, version, release), (updpkgs[name])) # pylint:disable=no-member
|
|
if res == 0:
|
|
continue
|
|
instver = printver(name, epoch, version, release)
|
|
updver = printver(name, *updpkgs[name])
|
|
if res < 0:
|
|
problems.append(f"Installed: {instver} is older than update: {updver}.")
|
|
post.add("Installed older than update usually means there is a dependency problem preventing the update version being installed.")
|
|
post.add("Check /var/log/dnf.log, and search for the string 'Problem'.")
|
|
else:
|
|
msg = f"Installed: {instver} is newer than update: {updver}"
|
|
if not updalias:
|
|
problems.append(f"{msg} and this is not an update test, please check if this is a problem")
|
|
continue
|
|
# check if the update is stable
|
|
if updstableobs is None:
|
|
try:
|
|
url = f"https://bodhi.fedoraproject.org/updates/{updalias}"
|
|
resp = json.loads(urlopen(url).read().decode("utf8")) # pylint:disable=consider-using-with
|
|
updstableobs = (resp.get("update", {}).get("status", "") in ("stable", "obsolete"))
|
|
except: # pylint:disable=bare-except
|
|
problems.append(f"{msg} and Bodhi is unreachable.")
|
|
continue
|
|
if updstableobs:
|
|
warnings.append(f"{msg} and update is stable or obsolete, this is probably OK.")
|
|
else:
|
|
problems.append(f"{msg} and update is not stable or obsolete.")
|
|
post.add("Installed newer than update and update not stable or obsolete means older version could be pushed over newer if update goes stable.")
|
|
|
|
if warnings:
|
|
print("WARNINGS")
|
|
for warning in warnings:
|
|
print(warning)
|
|
ret = 2
|
|
|
|
if problems:
|
|
print("PROBLEMS")
|
|
for problem in problems:
|
|
print(problem)
|
|
ret = 3
|
|
|
|
if post:
|
|
print("INVESTIGATION TIPS")
|
|
for postmsg in post:
|
|
print(postmsg)
|
|
|
|
sys.exit(ret)
|