Viewing file: up2date.py (37.77 KB) -rwxr-xr-x Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
#!/usr/bin/python -u # # Client code for Update Agent # Copyright (c) 1999-2002 Red Hat, Inc. Distributed under GPL. # # Author: Preston Brown <pbrown@redhat.com> # Adrian Likins <alikins@redhat.com # Cristian Gafton <gafton@redhat.com> # """ Guts of the up2date client. This module provides abstration of all the remote rpc calls that the client needs to make, includes the dependency solve, and other assorted bits. """
import os import string import sys sys.path.insert(0, "/usr/share/rhn/") sys.path.insert(1,"/usr/share/rhn/up2date_client") import fnmatch, glob import rpm import up2dateUtils import up2dateLog import up2dateErrors import up2dateAuth import repoDirector import rhnPackageInfo import checkbootloader import rpmUtils import rpcServer import depSolver import rollbacks import transaction import elilocfg import lilocfg import grubcfg import rhnChannel import config import signal
from rhpl.translate import _, N_
def reloadConfig(): cfg = config.initUp2dateConfig() cfg.load()
# get around cached dependencies. Gross ugly hack. #rpm.addMacro("_dbi_tags","Packages:Name:Basenames:Group:Requirename:Providename:Conflictname:Triggername")
# turn off epoch promotion for the time being rpm.setEpochPromote(0)
##try: ## log = up2dateLog.initLog() ##except IOError, e: ## print "Unable to open log file. The error was: %s" % e ## print _("You must run the Update Agent as root.") ## sys.exit(1)
def checkForStorageDir(): cfg = config.initUp2dateConfig() directory = cfg["storageDir"] if os.access(directory, os.X_OK): return 0 else: return 1
def computeAvailablePackages(): pkgs = rhnPackageInfo.getAvailableAllArchPackageList() installedPkgs = rpmUtils.getInstalledPackageList()
availablePackages = [] installedPkgNames = map(lambda a: a[0], installedPkgs) for pkg in pkgs: if pkg[0] not in installedPkgNames: availablePackages.append(pkg) return availablePackages
def computeUnavailablePackages(): pkgs = rhnPackageInfo.getAvailablePackageList() installedPkgs = rpmUtils.getInstalledPackageList(getArch=1)
unAvailablePackages = [] availPkgNames = map(lambda a: a[0], pkgs) for pkg in installedPkgs: if pkg[0] not in availPkgNames: unAvailablePackages.append(pkg)
return unAvailablePackages
# needed for actions, maybe client to at some point def getErrataInfo(errata_id): s = rpcServer.getServer() packages = rpcServer.doCall( s.errata.getErrataInfo, up2dateAuth.getSystemId(), errata_id) return packages
# pass the lite flag if you only want the "lite" header def getHeader(pkg,lite=None): hdr = None repos = repoDirector.initRepoDirector() hdr,call_type = rpcServer.doCall(repos.getHeader, pkg) return hdr
def removeHeader(pkg): cfg = config.initUp2dateConfig() # first see if it is on disk: fileNames = glob.glob("%s/%s.%s.hdr" % (cfg["storageDir"], up2dateUtils.pkgToString(pkg), up2dateUtils.archGlob())) for fileName in fileNames: try: os.remove(fileName) except: raise up2dateErrors.FileError(_("cannot remove %s") % fileName)
fileNames = glob.glob("%s/%s.noarch.hdr" % (cfg["storageDir"], up2dateUtils.pkgToString(pkg))) for fileName in fileNames: try: os.remove(fileName) except: raise up2dateErrors.FileError(_("cannot remove %s") % fileName)
def isPackageCached(pkg): cfg = config.initUp2dateConfig() baseFileName = "%s-%s-%s.%s.rpm" % (pkg[0], pkg[1], pkg[2], pkg[4])
fileName = "%s/%s" % (cfg["storageDir"], baseFileName)
if (os.access(fileName, os.R_OK)): size = os.stat(fileName)[6] if size == long(pkg[5]): return 1 return 0
# if we find we have apt style toy header, when we really need the real ones # go and fetch the real header from the package... this need to be def getRealHeader(pkg, msgCallback = None, progressCallback = None): cfg = config.initUp2dateConfig() baseFileName = "%s-%s-%s.%s.rpm" % (pkg[0], pkg[1], pkg[2], pkg[4]) fileName = "%s/%s" % (cfg["storageDir"], baseFileName) fd = os.open(fileName, os.R_OK) _ts = transaction.initReadOnlyTransaction() # this is fun. We need to turn off all the gpg/sig/etc checking # if the user hasnt requested sig checking. _ts.pushVSFlags(-1) hdr = _ts.hdrFromFdno(fd) return hdr
def getPackage(pkg, msgCallback = None, progressCallback = None, onlySource=None): # This is a hack around rpm. RPM sets its own signal handler for # SIGINT, but that breaks python. Before we download any packages, # reset the SIGINT handler back to the default, so that up2date can # be terminated by the user. signal.signal(signal.SIGINT, signal.SIG_DFL)
cfg = config.initUp2dateConfig() repos = repoDirector.initRepoDirector() if not onlySource: buf = rpcServer.doCall(repos.getPackage, pkg, msgCallback, progressCallback)
# retrieve source packages as well if cfg['retrieveSource'] or onlySource: hdr = getHeader(pkg) srcrpm = hdr['sourcerpm'] channels = rhnChannel.getChannels() channel = channels.getByName(pkg[6]) buf = rpcServer.doCall(repos.getPackageSource, channel, srcrpm, msgCallback, progressCallback) return 0
def removePackage(pkg): log = up2dateLog.initLog() cfg = config.initUp2dateConfig() # first see if it is on disk fileNames = glob.glob("%s/%s.%s.*" % (cfg["storageDir"], up2dateUtils.pkgToString(pkg), pkg[4])) for fileName in fileNames: log.log_me("deleting %s" % fileName) try: os.remove(fileName) except: raise up2dateErrors.FileError(_("cannot remove %s") % fileName) fileNames = glob.glob("%s/%s.noarch.*" % (cfg["storageDir"], up2dateUtils.pkgToString(pkg))) for fileName in fileNames: log.log_me("deleting %s" % fileName) try: os.remove(fileName) except: raise up2dateErrors.FileError(_("cannot remove %s") % fileName)
def avail_package_dict(): # returns a hash version of the Avialable Package List availablePkgList = rhnPackageInfo.getAvailablePackageList() pkgDict = {} for pkg in availablePkgList: pkgDict[up2dateUtils.pkgToStringArch(pkg)] = pkg return pkgDict
def getArchesOfAvailablePackages(availablePkgList,pkgName): archList = [] for pkg in availablePkgList: if pkgName == pkg[0]: archList.append(pkg[4])
return archList
# convience class to make removeInstalledPackagesFromList cleaner class UpdateList: def __init__(self): self.updateDict = {} self.__updateIndex = None
def nameList(self): return self.updateDict.keys()
# gen a list of just the name,version,release,epoch, and arch fields def nvreaList(self): return map(lambda a: a[:5], self.updatedList())
def nvreList(self): return map(lambda a: a[:4], self.updatedList())
def appendIfNewer(self, installedPkg, pkg): pkgName = pkg[0] # do we already have a package like this? if not self.updateDict.has_key(pkgName): self.updateDict[pkgName] = pkg return # do we have a match for name-version-release if pkg[:4] in self.nvreList(): # see if this is a better matching architecture archScore = rpm.archscore(pkg[4]) # incompatible arch if archScore <= 0: return oldScore = rpm.archscore(self.updateDict[pkgName][4]) if archScore < oldScore: # retain the better arch self.updateDict[pkgName][4] = pkg[4] return # else, we might gave an older one that needs updating ret = up2dateUtils.comparePackages(self.updateDict[pkgName],pkg) if ret > 0: # if pkg is newer self.updateDict[pkgName] = pkg
def updatedList(self): return self.updateDict.values()
def delete(self, pkg): del self.updateDict[pkg[0]]
# check if the signature matches the redhat.com one def hasBadSignature(pkg): cfg = config.initUp2dateConfig() hdr = getHeader(pkg) fileName = "%s/%s.%s.rpm" % (cfg["storageDir"], up2dateUtils.pkgToString(pkg), hdr['arch'])
fd = os.open(fileName, os.O_RDONLY) _ts = transaction.initReadOnlyTransaction() _ts.setVSFlags(0) ret = 0 try: hdr = _ts.hdrFromFdno(fd) except rpm.error, e: if str(e) == "public key not availaiable": ret = 4 if str(e) == "public key not available": ret = 4 if str(e) == "public key not trusted": ret = 3 if str(e) == "error reading package header": ret = 2
if hdr['SIGGPG'] == None or (hdr['SIGGPG'] == []): ret = 1
os.close(fd) # all the gory bits of checking the sig is in rpmUtils now return ret
# The new dryRun def dryRun(pkgList,msgCallback = None, progressCallback = None, refreshCallback=None): log = up2dateLog.initLog() log.log_debug("Called dryRun", pkgList)
cfg = config.initUp2dateConfig() availPkgs = rhnPackageInfo.getAvailableAllArchPackageList() availPkgs.sort()
# we out the packages newer or equal to the ones installed installedPkgs = rpmUtils.getInstalledPackageList(getArch=1) tmpPkgs = [] availCpy = availPkgs[:] for iPkg in installedPkgs: for index in range(len(availPkgs)): aPkg = availPkgs[index] if iPkg[0] == aPkg[0]: ret = up2dateUtils.comparePackages(aPkg, iPkg) #avail is older than installed if ret < 0: try: availCpy.remove(aPkg) except ValueError: # had multiple versions of package, ignore pass # avail is same as installed if ret == 0: if aPkg[0] != iPkg[4]: continue try: availCpy.remove(aPkg) except ValueError: # multiple versions of that package, only # one in availPkgs/Cpy pass if ret > 0: continue availPkgs = availCpy availPkgs.sort()
cfg['useNewDepSolve'] = 0
if cfg['useNewDepSolve']: depsolve = depSolver.DepSolver(pkgList, availPkgs) depsolve.set_callback("msg", msgCallback) depsolve.set_callback("progress", progressCallback) depsolve.set_callback("refresh", refreshCallback)
depsolve.setup() # everything should happen here ret = depsolve.solvedep() rc = depsolve.run() else: depsolve = depSolver.DependencySolver(pkgList, availPkgs)
# set the callbacks wwe need depsolve.set_callback("msg", msgCallback) depsolve.set_callback("progress", progressCallback) depsolve.set_callback("refresh", refreshCallback) # set up the trabsaction set & all depsolve.setup() while 1: ret = depsolve.solvedep() #log.log_debug("Got code %d from solvedep" % ret) if ret == 0: break elif ret < 0: # not really reached raise up2dateErrors.DependencyError(_( "Could not complete dependency resolution"))
foo = depsolve.run() rc = foo[0] pkgDepData = foo[1] pkgReqData = foo[2]
if progressCallback: progressCallback(1, 1)
newList = [] for s in depsolve.selected: if not s in pkgList: # pkgList.append(s) newList.append(s)
pkgList = depsolve.selected
# print showDepPackages(pkgDepData, pkgReqData) if rc and len(rc): msg = "" msgs = [] if len(newList): msg = msg + _("The following packages were added to your selection to satisfy dependencies:\n") msg = msg + _("""Name Version Release\n""") msg = msg + """--------------------------------------------------------------\n"""
for pkg in newList: msg = msg + "%-40s%-15s%-20s\n" % (pkg[0], pkg[1], pkg[2]) msg = msg + "\n" for code in rc: msg = msg + code[0] + "\n" # print _("Tse raise up2dateErrors.ConflictError( _("Test install failed because of package conflicts:\n") + msg, rc) return (newList, pkgList)
def showDepPackages(depPkgData, pkgReqData, verbose=None): pkgs = depPkgData.keys() pkgs.sort()
verbose = 1 reqPkgData = {} for pkg in pkgReqData.keys(): reqs = pkgReqData[pkg] for req in reqs: if not reqPkgData.has_key(req): reqPkgData[req] = [] reqPkgData[req].append(pkg)
# print "reqPkgData" # print reqPkgData # print # print "depPkgData" # print depPkgData
# pkgReqsToPkgSolves = {} # for pkg in pkgs: # for dep in depPkgData[pkg]: msg = "" msg = msg + _("The following packages were added to your selection to satisfy dependencies:\n") msg = msg + _("""Package Required by\n""") msg = msg + """----------------------------------------------------------------------------\n""" # loop over all the packagse that solve a dep for pkg in pkgs: pkgStr = "%s-%s-%s.%s" % (pkg[0], pkg[1], pkg[2], pkg[4]) # for each dep that package solves for dep in depPkgData[pkg]: # see what packages needed raise that dep reqPkgs = reqPkgData[dep] # multiple pkgs can raise multiple deps for reqPkg in reqPkgs: if verbose: msg = msg + "%-40s%-40s%-40s\n" % (pkgStr, "%s-%s-%s" % (reqPkg[0], reqPkg[1], reqPkg[2]), dep) else: msg = msg + "%-40s%-40s\n" % (pkgStr, "%s-%s-%s" % (reqPkg[0], reqPkg[1], reqPkg[2])) return msg
def undo(): # FIXME: instrument this with better error handling rollback = rollbacks.Rollback() print "Rolling back the packages installed:" print rollback.previewUndo() ret = 0 try: rollback.undo() except up2dateErrors.NoRollbacksToUndoError, e: print e.errmsg # except: # print "rollback failed" # ret = 1 return ret
# def getAllPkgInfo(allPkgList, pkg): log = up2dateLog.initLog() pkgArchs = [] for package in allPkgList: if list(pkg)[:4] == package[:4]: if pkg[4] != "": if list(pkg[:5]) == package[:5]: return package else: pkgArchs.append(package) # print pkgArchs if pkgArchs: pkgArchs.sort(up2dateUtils.comparePackagesArch) pkgArchs.reverse() if pkgArchs[0] == 0: # no valid arches log.log_me("No valid arches for pkg %s found" % pkg) return None return pkgArchs[0]
return None
def printit(msg): print msg
def genTransaction(transactionData): # generate a rpm.TransactionSet from a TransactionData object #
allPkgs = rhnPackageInfo.getAllAvailablePackageList()
ts = rpm.TransactionSet()
pkgList = transactionData.data['packages']
kernels = [] packagesToGet = [] missing_packages = []
adds = [] removes = [] removeinstances = [] for (pkg,mode) in pkgList: # pkgList already picks out the best arch for the #system... # add it to the transaction setup approriately if mode == 'u' or mode == 'i': package = getAllPkgInfo(allPkgs, pkg) if not package: missing_packages.append(pkg) continue
hdr = getHeader(package) packagesToGet.append(package) if not hdr: raise up2dateErrors.RpmError(_( "Could not find header for %s") % pkg) if "kernel" in hdr['Providename']: kernels.append(hdr) adds.append(hdr) ts.addInstall(hdr,hdr, mode) elif mode == "e": # since the server doesnt know about arch, but maybe, just maybe # it will some day, handle both cases if pkg[4] == "": instances = rpmUtils.installedHeaderIndex(name=pkg[0], version=pkg[1], release=pkg[2]) hdrs = rpmUtils.installedHeaderByKeyword(name=pkg[0], version=pkg[1], release=pkg[2]) else: # were specifing the arch, so grab it explicityly instances = rpmUtils.installedHeaderIndexByPkg(pkg) hdrs = rpmUtils.installedHeaderByPkg(pkg) for instance in instances: ts.addErase(instance) removeinstances.append(instance) for hdr in hdrs: removes.append(hdr) else: # dunno what this is, but we might use it ts.addInstall(hdr, hdr, mode)
if missing_packages: errmsg = _("Some of the packages in this transaction are not available.") raise up2dateErrors.PackageNotAvailableError(errmsg, missing_packages)
if transactionData.data.has_key('vsflags'): vsflag = 0 for flag in transactionData.data['vsflags']: vsflag = vsflag | flag ts.setVSFlags(vsflag)
# should probabaly dep check before we actually # download the package
for package in packagesToGet: # FIXME: progress callbacks... getPackage(package)
#ts.setVSFlags(8) ts.setProbFilter(rpm.RPMPROB_FILTER_OLDPACKAGE) return (ts, adds, removes)
def runTransaction(ts, added, removed, rpmCallback, transdir=None, rollbacktrans=1): log = up2dateLog.initLog() cfg = config.initUp2dateConfig() if transdir == None: transdir = cfg['storageDir'] # reset the flags, but save the current ones origflags = ts.setFlags(0) oldInstalledPackages = rpmUtils.getInstalledPackageList()
deps = ts.check() ts.order()
if deps: raise up2dateErrors.DependencyError(_( "Dependencies should have already been resolved, "\ "but they are not."), deps)
if cfg["justdb"]: ts.setFlags(origflags | rpm.RPMTRANS_FLAG_JUSTDB) else: transflag = 0 # rollback if configured to, but not if this is a rollback itself if cfg["enableRollbacks"] and rollbacktrans: log.log_me("Creating rollback packages...") transflag = rpm.RPMTRANS_FLAG_REPACKAGE ts.setFlags(origflags | transflag)
runPkgPreSpecialCases(removed, added) rpmUtils.runTransaction(ts,rpmCallback, transdir)
newInstalledPackages = rpmUtils.getInstalledPackageList()
removedPackages = [] addedPackages = []
# find packages that were removed for pkg in oldInstalledPackages: if pkg not in newInstalledPackages: removedPackages.append(pkg)
for pkg in newInstalledPackages: if pkg not in oldInstalledPackages: addedPackages.append(pkg)
if cfg['useRhn']: if len(removedPackages): rhnPackageInfo.remoteDelPackages(removedPackages) if len(addedPackages): rhnPackageInfo.remoteAddPackages(addedPackages)
# runPkgSpecialCases needs the headers to be most useful, # but maybe we can hack it to work just on package names # (for example, packagest that get removed as artifacts of # obsoletes...) runPkgPostSpecialCases(removed, added)
def installPackages(pkgList, rpmCallback): log = up2dateLog.initLog() try: log.log_me("installing packages: %s " % up2dateUtils.pprint_pkglist(pkgList)) except: pass
cfg = config.initUp2dateConfig() total = len(pkgList)
ts = rpm.TransactionSet() ts.setVSFlags(8)
added = [] removed = [] kernels = [] for p_i in range(total): hdr = getHeader(pkgList[p_i]) if hdr: pkg = pkgList[p_i] channels = rhnChannel.getChannels() channel = channels.getByLabel(pkg[6]) # the apt headers tend to be incomplete, so make # sure we have a real header from the package here try: hdr = getRealHeader(pkg) except rpm.error, e: raise up2dateErrors.RpmError("%s" % e) install=0 # see if any of the providenames are packages we just # want to install for providename in hdr['Providename']: if providename in cfg['pkgsToInstallNotUpdate']: install = 1 if install: ts.addInstall(hdr,hdr, "i") added.append(hdr) else: ts.addInstall(hdr, hdr, "u") added.append(hdr) if "kernel" in hdr['Providename']: kernels.append(hdr) else: raise up2dateErrors.RpmError(_( "Could not find header for %s") % pkgList[p_i])
# look though the packages associated with the transaction and # see if any have already been repackages
# detect if this version of rpm supports repackageRepackage or no supportsReRepackage = 1 try: tmp = rpm.allowsReRepackage except AttributeError: supportsReRepackage = None rollbacktrans = 1
if not supportsReRepackage: repackagelist = [] for te in ts: epoch = "" arch = "" # epoch and arch can both be "None" now... if te.E(): epoch = te.E() if te.A(): arch = te.A() pkg = (te.N(), te.V(), te.R(), epoch, arch) hdrs = rpmUtils.installedHeaderByPkg( pkg )
if hdrs: if hdrs[0]['removetid']: repackagelist.append((te.N(), te.V(), te.R())) rollbacktrans = None
if repackagelist: print print _("Warning: The following packages are being updated, but these packages\n"\ "have already been repackaged and this is currently not supported.\n"\ "Repackage support for this transaction has been disabled.\n") print "-"*40 for p in repackagelist: print "%s-%s-%s" % (p[0],p[1],p[2]) print runTransaction(ts, added, removed,rpmCallback, rollbacktrans = rollbacktrans)
return kernels
def runPkgPreSpecialCases( removed,added): addedPackageMethods = {} addedPackageMethods['up2date'] = [printUp2dateWarning] # addedPackageMethods['zsh'] = [printPreMessage]
addedPackageProvidesMethods = {} # addedPackageProvidesMethods['kernel'] = installBootLoader
removedPackageMethods = {} removedPackageProvidesMethods = {}
addedProvidesPackages = {} addedNamePackages = {} removedProvidesPackages = {} removedNamePackages = {}
# gang the packages up so we can send them all the same # time (kernel needs to know about all kernels being installed) for hdr in added: if addedPackageMethods.has_key(hdr['name']): if addedNamePackages.has_key(hdr['name']): addedNamePackages[hdr['name']].append(hdr) else: addedNamePackages[hdr['name']] = [hdr]
for provide in hdr['provides']: if addedPackageProvidesMethods.has_key(provide): if addedProvidesPackages.has_key(provide): addedProvidesPackages[provide].append(hdr) else: addedProvidesPackages[provide] = [hdr]
for hdr in removed: if removedPackageMethods.has_key(hdr['name']): if removedNamePackages.has_key(hdr['name']): removedNamePackages[hdr['name']].append(hdr) else: removedNamePackages[hdr['name']] = [hdr]
hitProvides = None for provide in hdr['provides']: if removedPackageProvidesMethods.has_key(provide): if removedProvidesPackages.has_key(provide): removedProvidesPackages[provide].append(hdr) else: removedProvidesPackages[provide] = [hdr]
# the methos take a list of hdr's of matching packages for pkgName in addedNamePackages.keys(): for method in addedPackageMethods[pkgName]: apply(method, addedNamePackages[pkgName])
for pkgName in removedNamePackages.keys(): for method in removedPackageMethods[pkgName]: apply(method, removedNamePackages[pkgName])
for provideName in addedProvidesPackages.keys(): for method in addedPackageProvidesMethods[provideName]: apply(method, [addedProvidesPackages[provideName]])
for provideName in removedProvidesPackages.keys(): for method in removedProvidesPackages[provideName]: apply(method, [removedProvidesPackages[provideName]]) def printUp2dateWarning(hdrs): print "New Up2date available"
##def printPreMessage(hdr): ## print "I run before installing: %s\n\n" % hdr['name']
##def printPostMessage(hdr): ## print "\I run after installing: %s\n\n" % hdr['name']
##class PackageActions: ## def __init__(self): ## # this bit gives me perl flashbacks... ## self.methods = {} ## for i in ['added', 'removed']: ## self.methods[i] = {} ## for j in ['pre', 'post']: ## self.methods[i][j] = {} ## for l in ['pkgname', 'provide']: ## self.methods[i][j][l] = {}
## def add(self, pkgDirection, place, keyname, pkgName,method): ## if not self.methods[pkgDirection][place][keyname].has_key(pkgName): ## self.methods[pkgDirection][place][keyname][pkgName] = [] ## self.methods[pkgDirection][place][keyname][pkgName].append(method) ## def get(self, pkgDirection, place, keyname, pkgName): ## return self.methods[pkgDirection][place][keyname][pkgName]
## def run(self, pkgDirection, place, keyname, packages): ## packageToMethod = {} ## # walk over the list of headers, see if we have methods defined for these ## # package names, split this on pkgname/provide since we have to iterate over ## # all the package provides, but not the package names ## if keyname == "pkgname": ## for pkg in packages: ## if self.methods[pkgDirection][place][keyname].has_key(pkg['name']): ## if not packageToMethod.has_key[pkg['name']]: ## packageToMethod[pkg['name']] = [] ## packageToMethod[ pkg['name'] ].append( self.methods[pkgDirection][place][keyname][pkg['name']] ) ## if keyname == "provides": ## for pkg in packages: ## for provide in pkg['provides']: ## if self.methods[pkgDirection][place][keyname].has_key(provide): ## if not packageToMethod.has_key[provide]: ## packageToMethod[provide] = [] ## packageToMethod[ provide ].append( self.methods[pkgDirection][place][keyname][provide] )
### print packageToMethod ### print provideToMethod
def runPkgPostSpecialCases(removed, added): # this is supposed to handle all the freaking cruft things like kernel # packages make us do. # # It can also be used as a way for a user to put in special cases per # package that gets ran
# we could extend this to allow slurpling up "action" style # methods so we could generate this more or less on the fly, # aka, per package pre/post actions. Actually, we might want to # take this a step farther and add our own concept of pre install, # post install, pre remove, post remove. All that just so people # dont have to rebuild a package... sigh. addedPackageMethods = {} addedPackageMethods['up2date'] = [printUp2dateWarning] #addedPackageMethods['zsh'] = [printPostMessage]
addedPackageProvidesMethods = {} addedPackageProvidesMethods['kernel'] = [installBootLoader]
removedPackageMethods = {} removedPackageProvidesMethods = {} removedPackageProvidesMethods['kernel'] = [unInstallBootLoader]
addedProvidesPackages = {} addedNamePackages = {} removedProvidesPackages = {} removedNamePackages = {}
# gang the packages up so we can send them all the same # time (kernel needs to know about all kernels being installed) for hdr in added: if addedPackageMethods.has_key(hdr['name']): if addedNamePackages.has_key(hdr['name']): addedNamePackages[hdr['name']].append(hdr) else: addedNamePackages[hdr['name']] = [hdr]
hitProvides = None for provide in hdr['provides']: if addedPackageProvidesMethods.has_key(provide): if addedProvidesPackages.has_key(provide): addedProvidesPackages[provide].append(hdr) else: addedProvidesPackages[provide] = [hdr]
for hdr in removed: if removedPackageMethods.has_key(hdr['name']): if removedNamePackages.has_key(hdr['name']): removedNamePackages[hdr['name']].append(hdr) else: removedNamePackages[hdr['name']] = [hdr]
hitProvides = None for provide in hdr['provides']: if removedPackageProvidesMethods.has_key(provide): if removedProvidesPackages.has_key(provide): removedProvidesPackages[provide].append(hdr) else: removedProvidesPackages[provide] = [hdr]
# the methos take a list of hdr's of matching packages for pkgName in addedNamePackages.keys(): for method in addedPackageMethods[pkgName]: apply(method, addedNamePackages[pkgName])
for pkgName in removedNamePackages.keys(): for method in removedPackageMethods[pkgName]: apply(method, removedNamePackages[pkgName])
for provideName in addedProvidesPackages.keys(): for method in addedPackageProvidesMethods[provideName]: apply(method, [addedProvidesPackages[provideName]])
for provideName in removedProvidesPackages.keys(): for method in removedPackageProvidesMethods[provideName]: apply(method, [removedProvidesPackages[provideName]])
def removePackages(pkgList, rpmCallback): log = up2dateLog.initLog() try: log.log_me("removing packages: %s " % up2dateUtils.pprint_pkglist(pkgList)) except: pass
cfg = config.initUp2dateConfig() total = len(pkgList)
# delete any existing db, open in write mode ts = rpm.TransactionSet() # RPMTRANS_FLAGS_REVERSE = (1 << 15) ts.setVSFlags(8 | (1 << 15))
# FIXME: just that a package is installed before claiming # it cant be removed
remove_list = [] for p_i in range(total): pkgName = "%s-%s-%s" % (pkgList[p_i][0],pkgList[p_i][1],pkgList[p_i][2]) if cfg["removeSkipList"]: for pattern in cfg["removeSkipList"]: # check the package name against the globs in removeSkipList if fnmatch.fnmatch(pkgList[p_i][0], pattern): raise up2dateErrors.RpmRemoveSkipListError, pkgName else: remove_list.append(pkgName) else: remove_list.append(pkgName)
failed_packages = {} for pkgName in remove_list: try: ts.addErase(pkgName) except rpm.error, e: failed_packages[pkgName] = str(e)
# if we get failed packages, raise the hash # of failed packages if len(failed_packages.keys()): raise up2dateErrors.RpmRemoveError, failed_packages runTransaction(ts, [], [], rpmCallback) return 0
def unInstallBootLoader(kernels): cfg = config.initUp2dateConfig() log = up2dateLog.initLog() # option to disable this permanently for those using grub,etc if cfg["noBootLoader"]: return
# dont run the new lilo if were running "justdb" if cfg["justdb"]: return log.log_me("Modifying bootloader config to removed the old kernel info") krnList = [] kernelList = [] for krn in kernels: extraInfo = krn['name'] # this logics a bit weird if extraInfo == None: infoString = "" elif extraInfo == "kernel": infoString = "" else: # if its a kernel is named like "kernelsdfasd" the # info blurb is gonna be "kernelsdfasd". I can live # with that. infoString = string.split(extraInfo, "-", 1)[-1:][0] # just in case some kook names a kernel "kernel-" if infoString == "": infoString = extraInfo
verRel = "%s-%s%s" % (krn['version'], krn['release'],infoString) kernelList.append((verRel,extraInfo)) log.log_me("Adding %s to bootloader config" % verRel)
bootloader = checkbootloader.whichBootLoader() bootloader = "LILO" if up2dateUtils.archGlob() == 'i?86' and bootloader == "LILO": __uninstall_lilo(kernelList) elif up2dateUtils.archGlob() == 'i?86' and bootloader == "GRUB": # at the moment, kernel rpms are supposed to grok grub # and do the Right Thing. Just a placeholder for doc purposes __uninstall_grub(kernelList)
def installBootLoader(kernels):
cfg = config.initUp2dateConfig() log = up2dateLog.initLog() # option to disable this permanently for those using grub,etc if cfg["noBootLoader"]: return
# dont run the new lilo if were running "justdb" if cfg["justdb"]: return
log.log_me("Modifying bootloader config to include the new kernel info") kernelList = [] # annoying, but kernels provide "kernel", "kernel-drm", "kernel-dfasdf", etc for krn in kernels: extraInfo = krn['name'] # this logics a bit weird if extraInfo == None: infoString = "" elif extraInfo == "kernel": infoString = "" else: # if its a kernel is named like "kernelsdfasd" the # info blurb is gonna be "kernelsdfasd". I can live # with that. infoString = string.split(extraInfo, "-", 1)[-1:][0] # just in case some kook names a kernel "kernel-" if infoString == "": infoString = extraInfo
verRel = "%s-%s%s" % (krn['version'], krn['release'],infoString) kernelList.append((verRel,extraInfo)) log.log_me("Adding %s to bootloader config" % verRel)
bootloader = checkbootloader.whichBootLoader() arch_glob = up2dateUtils.archGlob() if arch_glob == 'i?86' and bootloader == "LILO": __install_lilo(kernelList) elif arch_glob in ('i?86', 'ia32e', 'x86_64') and bootloader == "GRUB": # at the moment, kernel rpms are supposed to grok grub # and do the Right Thing. Just a placeholder for doc purposes __install_grub(kernelList) elif arch_glob == "ia64": __install_elilo(kernelList)
def __install_elilo(kernelList): log = up2dateLog.initLog() log.log_me("Running elilo with the new configuration") ret = elilocfg.installNewImages(kernelList,test=0) return ret
def __install_lilo(kernelList): log = up2dateLog.initLog() log.log_me("Running lilo with the new configuration") ret = lilocfg.installNewImages(kernelList,test=0) return ret
def __uninstall_lilo(kernelList): log = up2dateLog.initLog() log.log_me("Running lilo with the new configuration") ret = lilocfg.removeImages(kernelList,test=0) return ret
def __install_grub(kernelList): log = up2dateLog.initLog() log.log_me("Installing the kernel via grub") ret = grubcfg.installNewImages(kernelList,test=0) return ret
def test():
# login and whatnot up2dateAuth.updateLoginInfo() # lets build a transaction that removes all the "kde-*" packages # and adds all the gnome* packages removeHdrs = rpmUtils.installedHeaderByKeyword(name="kde*")
# create a TransactionData object tsd = transaction.TransactionData()
for hdr in removeHdrs: # stringify epoch if hdr['epoch']: epoch = str(hdr['epoch']) else: epoch = "0" pkg = [hdr['name'], hdr['version'], hdr['release'], epoch, hdr['arch']] mode = 'e' # print "blip: %s" % pkg tsd.data['packages'].append((pkg, mode))
import fnmatch pkgs = rhnPackageInfo.getAvailablePackageList() for pkg in pkgs: if fnmatch.fnmatch(pkg[0], "gnome*"): mode = 'i' print "blargh: (%s,%s)" % (pkg,mode) tsd.data['packages'].append((pkg,mode))
print tsd print tsd.display()
tsi = genTransaction(tsd) print tsi
# for callback import wrapperUtils rpmCallback = wrapperUtils.RpmCallback() runTransaction(tsi, [], [], rpmCallback)
if __name__ == "__main__": test()
|