Viewing file: packages.py (18.25 KB) -rwxr-xr-x Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
#!/usr/bin/python
# Copyright (c) 1999-2002 Red Hat, Inc. Distributed under GPL. # # Author: Adrian Likins <alikins@redhat.com> #
import sys sys.path.append("/usr/share/rhn/") from up2date_client import up2dateErrors from up2date_client import up2dateAuth from up2date_client import up2dateLog from up2date_client import up2dateUtils from up2date_client import up2date from up2date_client import config from up2date_client import rpcServer from up2date_client import rpmUtils from up2date_client import rollbacks from up2date_client import rhnPackageInfo from up2date_client import transaction import rpm import time import os
cfg = config.initUp2dateConfig() log = up2dateLog.initLog()
# mark this module as acceptable __rhnexport__ = [ 'update', 'remove', 'refresh_list', 'fullUpdate', 'checkNeedUpdate', 'runTransaction', 'verify', 'verifyAll',
]
global fd def rpmCallback(what, amount, total, hdr, path): if what == rpm.RPMCALLBACK_INST_OPEN_FILE: global fd fileName = "%s/%s-%s-%s.%s.rpm" % (path, hdr['name'], hdr['version'], hdr['release'], hdr['arch']) try: fd = os.open(fileName, os.O_RDONLY) except: print "Error opening %s for reading" % fileName return -1
return fd elif what == rpm.RPMCALLBACK_INST_START: if type(hdr) == type(""): print "Repackaging..." else: fileName = "%s-%s-%s.%s.rpm" % (hdr['name'], hdr['version'], hdr['release'], hdr['arch']) elif what == rpm.RPMCALLBACK_INST_CLOSE_FILE: os.close(fd)
elif what == rpm.RPMCALLBACK_INST_PROGRESS: pass elif what == rpm.RPMCALLBACK_UNINST_STOP: pass
def remove(pkgList): """We have been told that we should remove packages"""
if type(pkgList) != type([]): return (13, "Invalid arguments passed to function",{})
log.log_debug("Called remove_packages", pkgList)
# FIXME: figure out the error handling try: up2date.removePackages(pkgList, rpmCallback) except up2dateErrors.DependencyError, e: # just return the list of deps if we failed data = {} data['version'] = 0 data['name'] = "packages.remove.failed_deps" data['failed_deps'] = __cleanDeps(e.deps) return (14, "%s" % e, data) except up2dateErrors.RpmRemoveError, e: # if we later need finer grained info, we can data = {} data['version'] = 0 data['name'] = "packages.remove.rpmremoveerrors" data['rpmremoveerrors'] = e.data return (15, "%s" % e, data) except up2dateErrors.RpmRemoveSkipListError, e: return (16, "%s could not be removed because it was "\ "on the skip list" % e, {})
# if were succesful, return "4" up2dateUtils.touchTimeStamp() return (0, "%s removed successfully" % pkgList, {})
# Check if the locally installed package list changed, if # needed the list is updated on the server # In case of error avoid pushing data to stay safe # def checkNeedUpdate(rhnsd=None): data = {} update = None dbpath = "/var/lib/rpm" cfg = config.initUp2dateConfig() if cfg['dbpath']: dbpath = cfg['dbpath'] RPM_PACKAGE_FILE="%s/Packages" % dbpath
try: dbtime = os.stat(RPM_PACKAGE_FILE)[8] # 8 is st_mtime except: return (0, "unable to stat the rpm database", data) try: last = os.stat(up2dateUtils.LAST_UPDATE_FILE)[8] except: last = 0;
# Never update the package list more than once every 1/2 hour if last >= (dbtime - 10): return (0, "rpm database not modified since last update (or package list recently updated)", data) if last == 0: try: file = open(up2dateUtils.LAST_UPDATE_FILE, "w+") file.close() except: return (0, "unable to open the timestamp file", data) # Never update the package list more than once every hour. ret = up2dateUtils.touchTimeStamp() if ret: return ret # call the refresh_list action with a argument so we know it's # from rhnsd return refresh_list(rhnsd=1)
def noneToEmpty(value): if value == None: return "" return value
# stringing nay None's in dep tuples def __cleanDeps(deps): clean_deps = [] for dep in deps: ( (name, version, release), (needsName, needsVersion), flags, suggested, sense) = dep
values = [name, version, release, needsName, needsVersion, flags, suggested, sense] name, version,release, needsName, needsVersion, \ flags, suggested, sense = map(noneToEmpty, values) clean_deps.append(((name,version,release), (needsName, needsVersion), flags, suggested, sense)) return tuple(clean_deps)
def __cleanFailures(failures): clean_failures = [] for failure in failures: (msg, (flags, suggest, sense)) = failure values = [flags, suggest, sense] flags, suggest, sense = map(noneToEmpty, values) clean_failures.append((msg, (flags, suggest, sense))) return clean_failures
def __cleanConflicts(conflicts):
clean_conflicts = [] for conflict_index in range(len(conflicts)): reason = conflicts[conflict_index][0] pkg = conflicts[conflict_index][1] tmp = list(pkg[:]) for i in range(len(pkg)): if pkg[i] == None: tmp[i] = "" clean_conflicts.append((reason, tmp)) return clean_conflicts
# try to share this big old pile of exception handling: def _catchErrors(method, name, args): ret = None try: ret = apply(method, args) # except up2dateErrors.RpmError, e: # return (18, "Failed: packages requested raised "\ # "dependency problems", {}) except up2dateErrors.RpmInstallError, e: data = {} data['version'] = "0" data['name'] = "%s.package_install_failure" % name if e.pkg: data = {'package_that_failed':e.pkg} return (32, "Failed: Packages failed to install "\ "properly: %s" % e.errmsg, data) except up2dateErrors.SkipListError, e: data = {} if e.pkglist: data = {'packages_on_skip_list': e.pkglist} # The version field is the version of the data struct data['version'] = "0" data['name'] = "%s.packages_on_skip_list" % name return (30, "Failed: Some of the packages specified were "\ "on a skip list", data) except up2dateErrors.DependencyError, e: data = {} if e.deps: # deps might have None's, cleanse them data = {'failed_deps':__cleanDeps(e.deps)} data["version"] = "0" data["name"] = "%s.failed_deps" % name return (18, "Failed: packages requested raised "\ "dependency problems", data) except up2dateErrors.TransactionError, e: data = {} if e.deps: # deps might have None's, cleanse them data = {'failed_elements': __cleanFailures(e.deps)} # data = {'failed_deps':__cleanDeps(e.deps)} data["version"] = "0" data["name"] = "%s.failed_transaction" % name # FIXME: pretty up the test string error return (40, "Failed: The transaction failed for the following reasons:\n%s" % data['failed_elements'], data) except up2dateErrors.UnsolvedDependencyError, e: data = {} if e.dep: data = {'failed_deps':e.dep} if e.pkgs: data["packages"] = e.pkgs packages = up2dateUtils.pkglistToString(e.pkgs) else: packages = "" data["version"] = "0" data["name"] = "%s.deps_on_skip_list" % name return(29, "The dependency %s is provided by the folowing "\ "packages: %s, but they are not available due to client "\ "configuration (skip lists, etc)" % (e.dep, packages), data) except up2dateErrors.ConflictError, e: if e.rc: # we cant marshall long ints, so make sure we cast them to ints try: tmprc = e.rc # old rpm always makes this an int, new rpm makes it a # long int, we nee if type(e.rc[0][1][2]) == type(1L): tmprc = [ (e.rc[0][0], (e.rc[0][1][0], e.rc[0][1][1], int(e.rc[0][1][2])) )]
except TypeError: tmprc = "There was a parsing error with the rpm "\ "conflict message" except OverflowError: # must of be a real long int, this shouldnt ever # happen in this case, but dont traceback just in case tmprc = "There was an overflow error converting "\ "the return code to ints" data = {'package_conflicts': __cleanConflicts(tmprc)} else: data = {} data["version"] = "0" data["name"] = "%s.package_conflicts" % name return (26, "Failed: There was a package conflict error "\ "with the package set: %s" % e, data) except up2dateErrors.FileConflictError, e: if e.rc: data = {'package_file_conflicts': e.rc} else: data = {} data["version"] = "0" data["name"] = "%s.package_file_conflicts" % name return (27, "Failed: There was file conflict error with the "\ "package set: %s" % e, data) except up2dateErrors.DependencySenseError, e: data = {} if e.sense: data = {'dependency_sense':e.sense} data["version"] = "0" data["name"] = "%s.dependency_sense" % name return (28, "There was a dependency sense error with "\ "the sense: %s" % e.sense, data) except up2dateErrors.CommunicationError, e: return (21, "Failed: There was a communication error "\ "talking to the server", {}) except up2dateErrors.FileNotFoundError, e: data = {'missing_package_error': e} data["version"] = "0" data["name"] = "%s.file_not_found" % name return (31, "Failed: There was a File Not Found error. "\ "The error was: %s" % e, data) except up2dateErrors.GPGVerificationUnsignedPackageError, e: data = {'unsigned_package':e.pkg} data["version"] = "0" data["name"] = "%s.unsigned_package" % name return (22, "Failed: There was a package gpg verification error. "\ "The error was: %s" % e, data) except up2dateErrors.GPGVerificationError, e: data = {'gpg_failed_package':e.pkg} data["version"] = 0 data["name"] = "%s.gpg_failed_package" % name return (23, "Failed: There was a package gpg verification error. "\ "The error was: %s" % e, {}) except up2dateErrors.GPGInstallationError: return (24, "Failed: gpg is not properly installed "\ "on this machine", {}) except up2dateErrors.GPGKeyringError: return (25, "Failed: The package signing key for Red Hat, Inc. "\ "is not on the gpg keyring", {}) except up2dateErrors.GPGVerificationUntrustedKeyError, e: return (42, "Failed: There was a package gpg verification error. "\ "The error was: %s" % e, {}) except up2dateErrors.GPGVerificationUnknownKeyError, e: return (43, "Failed: There was a package gpg verification error. "\ "The error was: %s" % e, {}) except up2dateErrors.PackageNotAvailableError, e: data = {} data['missing_packages'] = e.missing_packages data['version'] = 0 data['name'] = "%s.packages_not_available" % name return (41, "Failed: Some of the packages requested are not available.", data) except up2dateErrors.OutOfSpaceError, e: data = {'space_required':e.ts} data['space_available'] = e.freeDiskSpace data['version'] = 0 data['name'] = "%s.out_of_space" % name return (33, "Failed: The was an error installing the package: "\ "the error was: %s" % e, data) return ret
def update(pkgList): """We have been told that we should retrieve/install packages"""
if type(pkgList) != type([]): return (13, "Invalid arguments passed to function", {})
log.log_debug("Called update_packages", pkgList)
# if e,v,r is "", pretend it is version 0, release 0, epoch "" for pkg in pkgList: if pkg[1] == pkg[2] == pkg[3] == "": pkg[1] = pkg[2] = 0 pkg[3] = ""
# run the method, but move all the exception catching # elsewhere so we can share it ret = _catchErrors(batchRun, "packages.update", (0, pkgList)) # little odd, if it returns a tuple, it's an error if type(ret) == type(()): return ret
# update the time stamp indicating we've updated the package list up2dateUtils.touchTimeStamp() # bit of a hack, but slightly "better messaging" if cfg["retrieveOnly"]: return (0, "Packages sucessfully retrieved but due to "\ "client specified options, the packages were downloaded, "\ "but not installed.", {}) else: return (0, "Packages were installed successfully", {})
def fullUpdate(force=0): if force: cfg['forceInstall'] = 1 ret = _catchErrors(batchRun, "packages.fullUpdate", (1,[],1))
data = {} data['version'] = "0" data['name'] = "packages.fullUpdate.succesfulUpdate" data['packagesNotFound'] = ret.packagesNotFound data['skippedPackages'] = ret.skippedPackages data['obsoletedPackages'] = ret.obsoletedPackages data['installedObsoletingPackages'] = ret.installedObsoletingPackages data['packagesToInstall'] = ret.packagesToInstall data['depPackages'] = ret.depPackages data['kernelsToInstall'] = ret.kernelsToInstall return (0, "Full update completed", data)
def batchRun(onlyList, pkgList, fullUpdate=0): from up2date_client import wrapper if pkgList: ret = wrapper.batchRun(onlyList, [], fullUpdate, fromDaemon = 1, actionPkgs = pkgList) else: ret = wrapper.batchRun(onlyList, [], fullUpdate, fromDaemon = 1, returnInfo=1) return ret
# push again the list of rpm packages to the server def refresh_list(rhnsd=None): s = rpcServer.getServer()
log.log_debug("Called refresh_rpmlist")
ret = None
rhnPackageInfo.updatePackageProfile() try: rhnPackageInfo.updatePackageProfile() except: print "ERROR: refreshing remote package list for System Profile" return (20, "Error refreshing package list", {})
try: rhnPackageInfo.updateTransactions() except: print "ERROR: refreshing remote transaction list for System Profile" return (20, "Error refreshing transaction list", {})
up2dateUtils.touchTimeStamp() return (0, "rpmlist refreshed", {})
def runTransaction(transactionData):
# build a transaction.TransactionData object tsd = transaction.TransactionData() tsd.data = transactionData
# pass it to genTransaction to get a real rpm transaction try: (ts, added, removed) = up2date.genTransaction(tsd) except up2dateErrors.PackageNotAvailableError, e: data = {} data['missing_packages'] = e.missing_packages data['version'] = 0 data['name'] = "packages.runTransaction.packages_not_available" return (41, "Failed: Some of the packages requested are not available.", data)
# pass it to runTransaction to do the useful bits... # catch errrors will need to be extended to catch transaction specific # error cases
# ret = apply(up2date.runTransaction, ( ts, rpmCallback)) ret = _catchErrors(up2date.runTransaction, "packages.runTransaction", ( ts, added, removed, rpmCallback)) # little odd, if it returns a tuple, it's an error if type(ret) == type(()): return ret
# update the time stamp indicating we've updated the package list up2dateUtils.touchTimeStamp()
return (0, "packages.transaction ran successfully", {})
def verify(packages): log.log_debug("Called packages.verify")
data = {} data['name'] = "packages.verify" data['version'] = 0 ret, missing_packages = rpmUtils.verifyPackages(packages) data['verify_info'] = ret if len(missing_packages): data['name'] = "packages.verify.missing_packages" data['version'] = 0 data['missing_packages'] = missing_packages return(43, "packages requested to be verified are missing", data)
return (0, "packages verified", data)
def verifyAll(): log.log_debug("Called packages.verifyAll")
data = {} data['name'] = "packages.verifyAll" data['version'] = 0
ret = rpmUtils.verifyAllPackages() data['verify_info'] = ret return (0, "packages verified", data)
def main():
up2dateAuth.updateLoginInfo() packages1 = [(('wget', '1.8.2', '5', ''), 'u'), (('cvs', '1.11.2', '8', ''), 'u')]
# kernel-smp-2.4.21-4.EL packages2 = [(('kernel-smp', '2.4.21', '4.0.1.EL', '', 'i686') , 'e'), (('kernel-smp', '2.4.21', '4.EL', '', "i686"), 'i')]
packages2a = [(('kernel-smp', '2.4.21', '4.EL', '', "i686"), 'i'), (('kernel-smp', '2.4.21', '4.0.1.EL', '', 'i686') , 'e')]
packages3 = [(('kernel-smp', '2.4.21', '4.0.1.EL', '', 'i686') , 'i'), (('kernel-smp', '2.4.21', '4.EL', '', "i686"), 'e')]
packages3a = [(('kernel-smp', '2.4.21', '4.EL', '', "i686"), 'e'), (('kernel-smp', '2.4.21', '4.0.1.EL', '', 'i686') , 'i')] data = {'packages':packages2}
pkgs = [("glibc", "","", "", ""), ('pam', "", "", "", "")] print verify(pkgs) print verifyAll() #print runTransaction(data) #print fullUpdate(force=0) #glibc-2.3.1-38 # gnome-utils-2.1.4-2 # print remove([["gnome-utils", "2.1.4", "2"]]) # print checkNeedUpdate() # refresh_list() ## pkgList = [['alchemist-devel', '1.0.24', '4', ''], ## ['amanda-client', '2.4.2p2', '9', ''], ## ['amanda-devel', '2.4.2p2', '9', '']]
# pkgList = [['alchemist', '1.0.24', '4', ''], # ['anaconda', '7.3.94', '0.200208021426', ''], # ['anaconda-help', '7.3.94', '0.200208051123', '']] # print update(pkgList)
if __name__ == "__main__": main()
|