diff options
author | Bill Nottingham <notting@nostromo.devel.redhat.com> | 2007-05-20 23:46:09 -0400 |
---|---|---|
committer | Bill Nottingham <notting@nostromo.devel.redhat.com> | 2007-05-20 23:46:09 -0400 |
commit | fd7cb60d57e535ad4917de2360d62c668c7b16d9 (patch) | |
tree | 8655dc51d1dc93886449a5c721c78110d7648b7f /scripts | |
parent | 7d1c80aca5e8e0fbc9fd5d75ce549c5b5799f1fd (diff) | |
parent | 9cc309ee34e3b9b40ffa0bc262d0a221fb0974c4 (diff) | |
download | releng-fd7cb60d57e535ad4917de2360d62c668c7b16d9.tar.gz releng-fd7cb60d57e535ad4917de2360d62c668c7b16d9.tar.xz releng-fd7cb60d57e535ad4917de2360d62c668c7b16d9.zip |
Merge branch 'master' of ssh://git.fedoraproject.org/git/fedora/releng
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/upgradecheck/README | 5 | ||||
-rw-r--r-- | scripts/upgradecheck/upgradecheck-core+extras.conf | 21 | ||||
-rwxr-xr-x | scripts/upgradecheck/upgradecheck.py | 291 |
3 files changed, 317 insertions, 0 deletions
diff --git a/scripts/upgradecheck/README b/scripts/upgradecheck/README new file mode 100644 index 0000000..e9f6c4d --- /dev/null +++ b/scripts/upgradecheck/README @@ -0,0 +1,5 @@ +To generate an upgrade check report, run this: + +sudo ./upgradecheck.py -c upgradecheck-core+extras.conf -n -w -x + +If you want to include packages they may be missing from F7 repos but are in F6 repos, add a -m parameter to the above. diff --git a/scripts/upgradecheck/upgradecheck-core+extras.conf b/scripts/upgradecheck/upgradecheck-core+extras.conf new file mode 100644 index 0000000..966bb39 --- /dev/null +++ b/scripts/upgradecheck/upgradecheck-core+extras.conf @@ -0,0 +1,21 @@ +[main] +metadata_expire=0 +keepcache=0 +reposdir= + +[FC6] +name=FC6 +baseurl=http://download.fedora.redhat.com/pub/fedora/linux/core/6/source/SRPMS/ + +[F7] +name=F7 +baseurl=http://download.fedora.redhat.com/pub/fedora/linux/core/development/source/SRPMS/ + +[FC6-updates] +name=FC6-updates +baseurl=http://download.fedora.redhat.com/pub/fedora/linux/core/updates/6/SRPMS/ + +[FE6] +name=FE6 +baseurl=http://download.fedora.redhat.com/pub/fedora/linux/extras/6/SRPMS/ +#baseurl=file:///srv/rpmbuild/extras/tree/extras/6/SRPMS/ diff --git a/scripts/upgradecheck/upgradecheck.py b/scripts/upgradecheck/upgradecheck.py new file mode 100755 index 0000000..7b5c1f2 --- /dev/null +++ b/scripts/upgradecheck/upgradecheck.py @@ -0,0 +1,291 @@ +#!/usr/bin/python -t + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import os +import sys +import sets +import yum +import koji +import yum.Errors +from yum.misc import getCacheDir +from optparse import OptionParser +from rpmUtils.miscutils import compareEVR +import smtplib +from email.MIMEText import MIMEText +import datetime +import re +import rpmUtils.arch + +if sys.hexversion < 0x020300F0: + sys.stderr.write("%s: Sorry, Python >= 2.3 required.\n" % sys.argv[0]) + sys.exit(1) + +mail_from = "buildsys@fedoraproject.org" +mail_to = "fedora-maintainers@redhat.com" +mail_subject = "Package EVR problems in FC+FE %s" % datetime.date.today() +smtp_server = None + +# Add wanted distributions to "dists". Values should be numbers (as strings), +# and all repos containing that number in their id's will be associated with +# the corresponding distro version. For example, repo id "foo9bar" will be +# associated with distro "9". +dists = ('4', '5', '6', '7') + +# Architectures to operate on. +archs = rpmUtils.arch.getArchList('src') + +# False positive workarounds until obsoletes processing is implemented +# (not really doable as long as we operate on SRPMS): per-package tuples of +# known good paths +known_good = { +# 'koffice': (('FL3-updates', 'FE4'), +# ('FL3-updates', 'FE5'), +# ('FL3-updates', 'FE6'), +# ('FL3-updates', 'FE7'), +# ), + } + +# Where to checkout owners/owners.list +ownersworkdir = '/srv/extras-push/work' + + +def parseArgs(): + usage = "usage: %s [options (see -h)]" % sys.argv[0] + parser = OptionParser(usage=usage) + parser.add_option("-c", "--config", default='/etc/yum.conf', + help='config file to use (defaults to /etc/yum.conf)') + parser.add_option("-t", "--tempcache", default=False, action="store_true", + help="Use a temp dir for storing/accessing yum-cache") + parser.add_option("-d", "--cachedir", default='', + help="custom directory for storing/accessing yum-cache") + parser.add_option("-q", "--quiet", default=False, action="store_true", + help="quiet (no output to stderr)") + parser.add_option("-n", "--nomail", default=False, action="store_true", + help="do not send mail, just output the results") + parser.add_option("-w", "--noowners", default=False, action="store_true", + help="do not do owners.list processing") + parser.add_option("-x", "--nextonly", default=False, action="store_true", + help="check next dist version only for each package, " + "not all newer ones") + parser.add_option("-m", "--missing", default=False, action="store_true", + help="check for packages missing in newer repos") + (opts, args) = parser.parse_args() + return (opts, args) + +class MySolver(yum.YumBase): + def __init__(self, arch = None, config = "/etc/yum.conf"): + yum.YumBase.__init__(self) + + self.arch = arch + self.doConfigSetup(fn = config) + if hasattr(self.repos, 'sqlite'): + self.repos.sqlite = False + self.repos._selectSackType() + + def readMetadata(self): + self.doRepoSetup() + self.doSackSetup(archs) + for repo in self.repos.listEnabled(): + self.repos.populateSack(which=[repo.id]) + + def log(self, value, msg): + pass + +def evrstr(evr): + return evr and "%s:%s-%s" % evr or "(missing)" + +def koji_get_info(name, report, tags=["dist-fc7", "f7-final", "dist-fc7-updates-candidate"]): + koji_server = "http://koji.fedoraproject.org/kojihub" + koji_session = koji.ClientSession(koji_server, {}) + fmt = " %(nvr)-40s %(tag_name)-20s %(owner_name)s" + + for tag in tags: + pkg = koji_session.getLatestBuilds(tag, package=name); + output = [ fmt % x for x in pkg ] + for line in output: + report.append(line) + +def main(): + (opts, cruft) = parseArgs() + + if opts.noowners: + owners = {} + else: + sys.path.append('/srv/extras-push/work/extras-repoclosure') + from PackageOwners import PackageOwners + owners = PackageOwners() + #owners.FromCVS(workdir = ownersworkdir) + if not owners.FromURL(): + sys.exit(1) + + solvers = {} + + for dist in dists: + solver = MySolver(config = opts.config) + for repo in solver.repos.repos.values(): + if re.sub('\D+', '', repo.id) != dist: + repo.disable() + else: + repo.enable() + solvers[dist] = solver + + if os.geteuid() != 0 or opts.tempcache or opts.cachedir != '': + if opts.cachedir != '': + cachedir = opts.cachedir + else: + cachedir = getCacheDir() + if cachedir is None: + print "Error: Could not make cachedir, exiting" + sys.exit(50) + + for repo in solvers.values(): + repo.repos.setCacheDir(cachedir) + + if not opts.quiet: + print 'Reading in repository metadata - please wait....' + + for dist in solvers.keys(): + try: + solvers[dist].readMetadata() + except yum.Errors.RepoError, e: + print 'Metadata read error for dist %s, excluding it' % dist + del solvers[dist] + + pkgdict = {} + for dist in dists: + pkgdict[dist] = {} + + enabled_dists = solvers.keys() + enabled_dists.sort() + + allnames = {} # Python < 2.4 compat, otherwise we'd use sorted(set(...)) + for dist in enabled_dists: + # Would use returnNewestByName() but it's broken in yum 3.0.1 (#220841) + # returnNewestByNameArch() works for our purposes as long as we only + # deal with one arch (src). + for pkg in solvers[dist].pkgSack.returnNewestByNameArch(): + if pkg.name[-10:] == "-debuginfo": pass + allnames[pkg.name] = 1 + pkgdict[dist][pkg.name] = { + "evr": (pkg.epoch, pkg.version, pkg.release), + "repo": pkg.repoid, + } + allnames = allnames.keys() + allnames.sort(lambda x, y: cmp(x.lower(), y.lower())) + + report = [] + missing_report = [] + reports = {} # report per owner, key is owner email addr + + for name in allnames: + pkgdata = map(lambda x: pkgdict[x].get(name), enabled_dists) + broken_paths = [] + + for i in range(len(pkgdata)): + curr = pkgdata[i] + if not curr: + # package missing from this dist, skip + continue + + for next in pkgdata[i+1:]: + if not next: + if opts.missing: + # package missing from this dist, skip + # TODO: warn about holes in continuum? + missing = "%s %s %s not in next repo" % \ + (name, evrstr(curr["evr"]), curr["repo"]) + missing_report.append(missing) + koji_get_info(name, missing_report) + missing_report.append("") + continue + + if compareEVR(curr["evr"], next["evr"]) > 0: + # candidate for brokenness + if not known_good.has_key(name): + known_good[name] = () + if (curr["repo"], next["repo"]) not in known_good[name]: + # yep, it's broken + broken_paths.append((curr, next)) + + if opts.nextonly: + break + + if broken_paths: + if owners: + owner = owners.GetOwner(name) or \ + 'UNKNOWN OWNER (possibly Core package)' + else: + owner = '' + ownerprint = owner.replace('@',' AT ') + if not reports.has_key(owner): + reports[owner] = [] + reports[owner].append(name) + report.append("%s: %s" % (name, ownerprint)) + for broken in broken_paths: + what = " %s > %s (%s > %s)" % \ + (broken[0]["repo"], broken[1]["repo"], + evrstr(broken[0]["evr"]), evrstr(broken[1]["evr"])) + reports[owner].append(what) + report.append(what) + koji_get_info(name, report) + reports[owner].append("") + report.append("") + + # Insert "sorted by owner" report at the top. + oldreport = report + report = [] + if not opts.noowners: + reportkeys = reports.keys() + reportkeys.sort() + for owner in reportkeys: + ownerprint = owner.replace('@',' AT ') + report.append(ownerprint+':') + for line in reports[owner]: + report.append(' '+line) + if report: + report.append('-'*70) + report.append('') + report += oldreport + + report = "\n".join(report) + if report: + if mail_to and not opts.nomail: + msg = MIMEText(report) + msg["Subject"] = mail_subject + msg["From"] = mail_from + msg["To"] = mail_to + s = smtplib.SMTP() + if smtp_server: + s.connect(smtp_server) + else: + s.connect() + s.sendmail(mail_from, [mail_to], msg.as_string()) + s.close() + else: + print report + + if missing_report: + for line in missing_report: + print line + +if __name__ == "__main__": + main() + +# Local variables: +# indent-tabs-mode: nil +# py-indent-offset: 4 +# End: +# ex: ts=4 sw=4 et |