RPM Package Manager, CVS Repository
  http://rpm5.org/cvs/
  ____________________________________________________________________________

  Server: rpm5.org                         Name:   Jeff Johnson
  Root:   /v/rpm/cvs                       Email:  j...@rpm5.org
  Module: mancoosi                         Date:   28-Mar-2011 16:30:20
  Branch: HEAD                             Handle: 2011032814301900

  Added files:
    mancoosi/framework      rpmtest.py

  Log:
    - swipe a copy of rpm4_test.py for developpment/extension.

  Summary:
    Revision    Changes     Path
    1.1         +492 -0     mancoosi/framework/rpmtest.py
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: mancoosi/framework/rpmtest.py
  ============================================================================
  $ cvs diff -u -r0 -r1.1 rpmtest.py
  --- /dev/null 2011-03-28 16:30:19.000000000 +0200
  +++ rpmtest.py        2011-03-28 16:30:20.133414672 +0200
  @@ -0,0 +1,492 @@
  +#!/usr/bin/python
  +# -*- coding: utf-8 -*-
  +
  +import random
  +import time
  +import os
  +import fnmatch
  +import glob
  +import string
  +import sys
  +import rpm
  +import signal
  +import optparse
  +import subprocess
  +import csvwriter
  +
  +from termcolor import colored
  +
  +# Globals
  +
  +initial_contents = {}  # PKGNAME: [(FILE, mtime),...]
  +initial_versions = {}  # PKGNAME: (NEVRA, INSTALLTID)
  +killtimes = []  # list of killtimes
  +rollback_list = []
  +#mainrelease_dir = '/tmp/rpms/baseline/'
  +#multi_updates_dir = '/home/agrr/pacotes/multi-updates/'
  +#multi_release_dir = '/home/agrr/pacotes/multi-base/'
  +precondition_dir = "CM15/RPMS/"
  +multi_test_details = [0, 0]  # (Number of all upgraded transactions, number 
of nop transactions)
  +global_transaction = None
  +
  +def test_case(list_of_pkgs, max_delay):
  +    global killtimes
  +    print "--> test_case(list_of_pkgs, " + str(max_delay) + ")"
  +    args = ['rpm', '-Uvh', '--force', '--nodeps', '--noscripts']
  +    print 'Test Case: ' + str(list_of_pkgs)
  +
  +    args_final = args + list_of_pkgs
  +
  +    print 'About to run ' + str(args_final)
  +    rpm_pid = os.spawnv(os.P_NOWAIT, '/bin/rpm', args_final)
  +    mult = random.random()
  +    actual_killtime = mult * max_delay * len(list_of_pkgs)
  +    print 'Killtime actual: ' + str(actual_killtime) + ' '
  +
  +    time.sleep(actual_killtime)
  +
  +    killtimes.append(actual_killtime)
  +    sys.stderr.write('Killing rpm after %f\n' % actual_killtime)
  +    os.kill(rpm_pid, signal.SIGKILL)
  +
  +
  +def test_case_single_pkg(pkg, max_delay):
  +    global killtimes
  +    print "--> test_case_single_pkg(pkg, " + str(max_delay) + ")"
  +    args = ['rpm', '-Uvh', '--force', '--nodeps', '--quiet']
  +    (blah, filename) = pkg
  +    args.append(filename)
  +
  +    print 'About to run rpm -Uvh ' + str(args)
  +    rpm_pid = os.spawnv(os.P_NOWAIT, '/bin/rpm', args)
  +    mult = random.random() * max_delay
  +    killtimes.append(mult)
  +
  +    time.sleep(mult)
  +
  +    sys.stderr.write('Killing rpm after %f\n' % mult)
  +    os.kill(rpm_pid, signal.SIGKILL)
  +
  +
  +def install_forced(install_list):
  +    args = ['/bin/rpm', '-Uvh', '--force', '--nodeps', '--quiet'] \
  +        + install_list
  +    p = subprocess.Popen(args)
  +    ret = p.wait()
  +    res = ret == 0
  +    print "<-- install_forced(" + str(install_list) + ") res " + str(res)
  +    return res
  +
  +
  +def do_rollback(rollback_list):
  +    print "--> do_rollback(" + str(rollback_list) + ")"
  +    print 'Rollback for ' + str(rollback_list)
  +
  +    # rollback_list must be really a list !!
  +
  +    if not install_forced(rollback_list):
  +        print colored('Rollback failed!', 'red')
  +    recoverRPMdb()
  +
  +
  +def recoverRPMdb():
  +    rpmdb_dir = '/var/lib/rpm/'
  +    args = ['sudo', '/usr/bin/db_recover', '-e', '-h', rpmdb_dir]
  +    p = subprocess.Popen(args).communicate()[0]
  +    print "<-- recoverRPMdb()"
  +
  +
  +def rpmVerify(pkgname):
  +    args = ['rpm', '-V', pkgname]
  +    verify_output = subprocess.Popen(args,
  +            stdout=subprocess.PIPE).communicate()[0]
  +    if len(0):
  +        print 'Package %s is not OK' % pkgname
  +        res = False
  +    else:
  +        res = True
  +    print "<-- rpmVerify(" + pkgname + ") res " + str(res)
  +
  +
  +def listPkgContent(ts, pkgname):
  +    h = queryByPkgName(ts, pkgname)
  +    if h and h[rpm.RPMTAG_FILENAMES]:
  +        for file in h[rpm.RPMTAG_FILENAMES]:
  +#            print "<-- listPkgContent(ts, " + pkgname + ") fn " + file
  +            yield file
  +
  +
  +def queryByPkgName(ts, name):
  +#    print "--> queryByPkgName(ts, " + name + ")"
  +    match = ts.dbMatch('name', name)
  +    if not match:
  +
  +        # We need to catch the 'timezone' case...
  +
  +        for p in ts.dbMatch():
  +            if p['name'].startswith(pkgname):
  +                return p
  +        else:
  +            return None
  +
  +    for m in match:
  +        return m  # Assume just one match
  +
  +
  +def dumpResultsToCsv(results, filename):
  +    print "--> dumpResultsToCsv(results, filename)"
  +    outfile = open(filename, 'w')
  +    writer = csvwriter.UnicodeWriter(f=outfile)
  +    writer.writerows(results)
  +
  +
  +def pkgNameFromNEVRA(nevra):
  +    list = nevra.split('-')
  +    res = '-'.join(list[0:-2])
  +    print "<-- pkgNameFromNEVRA(" + nevra + ") res " + res
  +    return res
  +
  +
  +def splitNEVR(nevra):
  +    list = nevra.split('-')
  +    res = ('-'.join(list[0:-2]), list[-2], list[-1])
  +    print "<-- splitNEVR(" + nevra + ") res " + res
  +    return res
  +
  +
  +def NEVRA(ts, name):
  +    print "--> NEVRA(ts, name)"
  +    match = ts.dbMatch('name', name)
  +    for h in match:
  +        return printNEVRA(ts, h)
  +
  +
  +def installTID(ts, name):
  +    h = queryByPkgName(ts, name)
  +    res = h[rpm.RPMTAG_INSTALLTID]
  +    print "<-- installTID(ts, " + name + ") res " + str(res)
  +    return res
  +
  +
  +def printNEVRA(ts, pkgname):
  +    h = queryByPkgName(ts, pkgname)
  +    if not h:
  +        print 'Version not found'
  +        return ''
  +    epoch = (str(h['epoch']) + ':' if h['epoch'] else '')
  +    res = '%s-%s%s-%s.%s' % (h['name'], epoch, h['version'],
  +                              h['release'], h['arch'])  # Assume just one 
match
  +    print "<-- printNEVRA(ts, " + pkgname + ") res " + res
  +    return res
  +
  +
  +def printNVRA(ts, pkgname):
  +    h = queryByPkgName(ts, pkgname)
  +    if not h:
  +        print 'Version not found'
  +        return ''
  +    res = '%s-%s-%s.%s' % (h['name'], h['version'], h['release'],
  +                            h['arch'])  # Assume just one match
  +    print "<-- printNVRA(ts, " + pkgname + ") res " + res
  +    return res
  +
  +
  +def doublePkgEntry(ts, name):
  +    match = ts.dbMatch('name', name)
  +    res = match.count()
  +    print "<-- doublePkgEntry(ts, " + name + ") res " + str(res)
  +    return res
  +
  +
  +def fileTimestamp(filePath):
  +    try:
  +        timestamp = os.stat(filePath).st_mtime
  +#        print "<-- fileTimestamp(" + filePath + ")"
  +        return timestamp
  +    except OSError:
  +
  +        # print colored("Filepath %s not found" % filePath, 'red')
  +
  +        pass
  +
  +
  +def rpmqa():
  +    print "--> rpmqa()"
  +    ts = rpm.TransactionSet()
  +    for h in ts.dbMatch():
  +        print h
  +
  +
  +def checkResultsSinglePkg(ts, pkg_test):
  +    global global_transaction
  +    print 'Single Pkg test for upgrading %s, waiting time %f seg.' \
  +        % (pkg_test, killtimes[-1])
  +    res = True
  +
  +    # After all the messup caused by (failed) installs we can't reuse the ts
  +
  +    global_transaction.closeDB()
  +    global_transaction = rpm.TransactionSet()
  +    res = doublePkgEntry(global_transaction, pkg_test)
  +    if res > 1:
  +        print colored('Two versions detected for package %s'
  +                      % pkg_test, 'red')
  +        res = False
  +    elif res == 0:
  +        print colored('No version of package %s was found' % pkg_test,
  +                      'green')
  +    else:
  +        print colored('Just one version of package %s was found'
  +                      % pkg_test, 'green')
  +
  +    print "<-- checkResultsSinglePkg(ts, " + str(pkg_test) + ") res " + 
str(res)
  +    return res
  +
  +
  +def check_fs_consistency(pkgname):
  +    contents = initial_contents[pkgname]
  +
  +    # contents: List of (file, timestamp) tuples
  +
  +    for f in contents:
  +        if os.path.exists(f[0]):
  +            if fileTimestamp(f[0]) > f[1]:
  +                print 'File was modified'
  +            else:
  +                print colored('File %s not touched' % f[0], 'red')
  +                res = False
  +        else:
  +            print colored('Non-existing file %s ' % f[0], 'red')
  +            res = False
  +    else:
  +
  +        res = True
  +    print "<-- check_fs_consistency(" + pkgname + ") res " + str(res)
  +    return res
  +
  +
  +def readRpmHeader(ts, filename):
  +    fd = os.open(filename, os.O_RDONLY)
  +    ts.setVSFlags(rpm.RPMVSF_NODSA | rpm._RPMVSF_NOSIGNATURES)  # Ignore 
signatures, please
  +    h = ts.hdrFromFdno(fd)
  +    os.close(fd)
  +    print "<-- readRpmHeader(ts, " + filename + ")"
  +    return h
  +
  +
  +def compareWithInstalledVersion(ts, pkgfile):
  +    h = readRpmHeader(ts, pkgfile)
  +    pkg_ds = h.dsOfHeader()
  +    inst_h = queryByPkgName(h['name'])
  +    inst_ds = inst_h.dsOfHeader()
  +    pkg_evr = pkg_ds.EVR()
  +    instr_evr = inst_ds.EVR()
  +
  +    if pkg_evr == instr_evr:
  +        res = 0
  +    elif pkg_evr > instr_evr:
  +        res = 1
  +    else:
  +        res = -1
  +    print "<-- compareWithInstalledVersion(ts, " + pkgfile + ") res " + 
str(res)
  +    return res
  +
  +
  +# TODO: Review and fix
  +
  +
  +def checkResults(ts, pkgs):
  +    global global_transaction
  +    global multi_test_details
  +
  +    total_pkgs = len(pkgs)
  +    version_wrong = 0
  +    files_wrong = 0
  +    was_updated = not_updated = 0
  +
  +    global_transaction.closeDB()
  +    global_transaction = rpm.TransactionSet()
  +
  +    for (p, file) in pkgs:
  +        print '''Initial version: %s
  +Current version: %s
  +''' \
  +            % (initial_versions[p], printNEVRA(global_transaction, p))
  +        if printNEVRA(global_transaction, p) != initial_versions[p]:
  +            print colored('Version for pkg %s is different' % p, 'red')
  +            was_updated += 1
  +        else:
  +            print colored('Version for pkg %s is the same' % p, 'red')
  +            not_updated += 1
  +
  +    if was_updated > 0 and not_updated > 0:
  +        print colored('Multiple-package test failed', 'red')
  +        res = False
  +    else:
  +        print colored('Multiple-package test success', 'green')
  +        if was_updated == 0:
  +            multi_test_details[1] += 1
  +        else:
  +            multi_test_details[0] += 1
  +
  +        res = True
  +
  +    print '''Within this transaction %d pkgs were updated and %d were not 
updated''' \
  +        % (was_updated, not_updated)
  +
  +    print "<-- checkResults(ts, " + str(pkgs) + ") res " + str(res)
  +    return res
  +
  +
  +    # print '''Results:\n\t %d out of %d Packages failed the database 
test\n\t
  +    #      %d out of %d failed the timestamps test''' % (version_wrong, 
total_pkgs,files_wrong,
  +    # ....  total_pkgs)
  +    # return [prettyPrintPkgList(pkgs), str(total_pkgs), str(version_wrong), 
str(files_wrong), str(killtimes[-1])]
  +
  +
  +def prettyPrintPkgList(list):
  +    out = ''
  +    for p in list:
  +        out += ', ' + p[0]
  +    return out
  +
  +
  +if __name__ == '__main__':
  +
  +    parser = \
  +        optparse.OptionParser(usage='Usage: %prog [options] PackageDir 
[MaxDelay] [#Iters]...'
  +                              , version='%prog-0.1',
  +                              conflict_handler='resolve')
  +
  +    parser.add_option('-s', '--singlepkg', action='store_true',
  +                      dest='singlepkg',
  +                      help='Run test for single package transactions')
  +    parser.add_option('-d', '--debug', action='store_true', dest='debug'
  +                      ,
  +                      help='Dont actually run the tests, just print what 
would be done'
  +                      )
  +    parser.add_option('-p', '--package-set', type='int',
  +                      dest='package_set',
  +                      help='''Choose which package set to use for the 
multi-package test: [1-10] '''
  +                      )
  +
  +    (opts, args) = parser.parse_args()
  +
  +    if len(args) < 1:
  +        parser.print_help()
  +        sys.exit(-1)
  +
  +    ts = rpm.TransactionSet()
  +    global_transaction = ts
  +    to_install = []
  +    to_upgrade = []
  +    to_upgrade_multi = set()
  +
  +    output_file = time.strftime('%d%m%Y-%H%M%S', time.gmtime()) + '.csv'
  +    global_results = [['List of packages', '# packages', 'Failures DB',
  +                      'Failures timestamps', 'Kill interval (sec)']]
  +
  +    package_sets = [
  +        'openldap,openldap-clients,openldap-doc,openldap-servers',
  +        
'postgresql8.3,postgresql8.3-contrib,postgresql8.3-devel,postgresql8.3-docs'
  +            ,
  +        'ghostscript,ghostscript-X,ghostscript-common,ghostscript-doc',
  +        'ruby,ruby-devel,ruby-doc',
  +        
'apache-mod_dbd,apache-mod_disk_cache,apache-mod_deflate,apache-mod_mod_proxy'
  +            ,
  +        'beagle,beagle-crawl-system,beagle-evolution',
  +        'bind,bind-devel,bind-doc',
  +        'evolution,evolution-data-server,evolution-exchange',
  +        'git,git-core,git-cvs,git-svn',
  +        'mysql,mysql-bench,mysql-common,mysql-doc',
  +        ]
  +
  +    if opts.package_set and not opts.singlepkg:
  +        for pkgname in package_sets[opts.package_set - 1].split(','):
  +         pat = args[0] + os.path.sep + pkgname + '-'
  +            if string.find(pkgname, '-') < 0:
  +                pat += '[0-9]'
  +            pat += '*.rpm'
  +            flist = glob.glob(pat)
  +            for file in flist:
  +                if pkgname not in initial_versions.keys():
  +                    initial_contents[pkgname] = [(f, fileTimestamp(f))
  +                            for f in listPkgContent(ts, pkgname)]
  +                    initial_versions[pkgname] = printNVRA(ts, pkgname)
  +                 print "+++ add(" + pkgname + ", " + file + ")"
  +                    to_upgrade_multi.add((pkgname, file))
  +    else:
  +     flist = os.listdir(args[0])
  +        for file in flist:
  +            if fnmatch.fnmatch(file, '*.rpm'):
  +                basename = os.path.splitext(file)[0]  # Remove extension
  +                pkgname = pkgNameFromNEVRA(basename)
  +                filename = args[0] + os.path.sep + file
  +                installed_NEVR = queryByPkgName(ts, pkgname)
  +                to_upgrade.append((pkgname, filename))
  +                initial_contents[pkgname] = [(f, fileTimestamp(f))
  +                        for f in listPkgContent(ts, pkgname)]
  +                initial_versions[pkgname] = printNVRA(ts, pkgname)
  +
  +    n_iters = (int(args[2]) if len(args) > 2 else 10)
  +    max_delay = (args[1] if len(args) > 1 else 3)
  +
  +    if opts.debug:
  +        print 'Selected %d Packages for Upgrades: \n%s' \
  +            % (len(to_upgrade), str(to_upgrade))
  +        print 'Selected %d Packages for New Install: \n%s' \
  +            % (len(to_install), str(to_install))
  +        for p in to_upgrade:
  +            print 'Dry run of filesystem checks for ' + p[0]
  +            print str(check_fs_consistency(p[0]))
  +
  +        sys.exit(0)
  +
  +    success_cases = 0
  +
  +    if opts.singlepkg:
  +        pkg_test = random.choice(to_upgrade)  # Same-pkg test
  +    total_dashes = int(n_iters * 100 / n_iters)
  +    for n in range(n_iters):
  +        if opts.singlepkg:
  +
  +           # pkg_test = args[3] if len(args) > 3 else 
random.choice(to_upgrade)[1]
  +           # pkg_test = random.choice(to_upgrade) #Random package test
  +           # to_upgrade.remove(pkg_test) #Avoid repeating the choice
  +
  +            (p, filename) = pkg_test
  +            test_case_single_pkg(pkg_test, float(max_delay))
  +            if checkResultsSinglePkg(ts, p):
  +                success_cases += 1
  +            to_rollback = []
  +         if initial_versions[p]:
  +                to_rollback.append(precondition_dir
  +                            + initial_versions[p] + '.rpm')
  +         if to_rollback:
  +                do_rollback(to_rollback)
  +        else:
  +
  +            if len(to_upgrade_multi) > 0:
  +                filenames_multi = [filename for (p, filename) in
  +                                   to_upgrade_multi]
  +                test_case(filenames_multi, float(max_delay))
  +                if checkResults(ts, to_upgrade_multi):
  +                    success_cases += 1
  +                to_rollback = []
  +                for (p, filename) in to_upgrade_multi:
  +                 if initial_versions[p]:
  +                        to_rollback.append(precondition_dir
  +                            + initial_versions[p] + '.rpm')
  +
  +             if to_rollback:
  +                    do_rollback(to_rollback)
  +
  +    print 'Test aggregate results: %d/%d pkgs' % (success_cases,
  +            n_iters)
  +    if not opts.singlepkg:
  +        print 'Multiple package test details: %d transactions to completion 
/%d initial state' \
  +            % (multi_test_details[0], multi_test_details[1])
  +
  +    print 'Average killtimes: %f' % (sum(killtimes) / len(killtimes))
  +
  +    # dumpResultsToCsv(global_results, output_file)
  @@ .
______________________________________________________________________
RPM Package Manager                                    http://rpm5.org
CVS Sources Repository                                rpm-cvs@rpm5.org

Reply via email to