1
0
mirror of https://pagure.io/fedora-qa/os-autoinst-distri-fedora.git synced 2024-12-18 08:33:08 +00:00
os-autoinst-distri-fedora/updvercheck.py

133 lines
4.7 KiB
Python
Raw Permalink Normal View History

#!/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)