'''This provides bcfg2 support for yum''' __revision__ = '0.1' import Bcfg2.Client.Tools.RPMng, ConfigParser, sys try: set except NameError: from sets import Set as set YAD = True CP = ConfigParser.ConfigParser() try: if '-C' in sys.argv: CP.read([sys.argv[sys.argv.index('-C') + 1]]) else: CP.read(['/etc/bcfg2.conf']) if CP.get('YUMng', 'autodep') == 'false': YAD = False except: pass class YUMng(Bcfg2.Client.Tools.RPMng.RPMng): '''Support for Yum packages''' pkgtype = 'yum' __name__ = 'YUMng' __execs__ = ['/usr/bin/yum', '/var/lib/rpm'] __handles__ = [('Package', 'yum'), ('Package', 'rpm')] __req__ = {'Package': ['name', 'version']} __ireq__ = {'Package': ['name', 'version']} __new_req__ = {'Package': ['name'], 'Instance': ['version', 'release', 'arch']} __new_ireq__ = {'Package': ['name', 'uri'], \ 'Instance': ['simplefile', 'version', 'release', 'arch']} __gpg_req__ = {'Package': ['name', 'version']} __gpg_ireq__ = {'Package': ['name', 'version']} __new_gpg_req__ = {'Package': ['name'], 'Instance': ['version', 'release']} __new_gpg_ireq__ = {'Package': ['name'], 'Instance': ['version', 'release']} conflicts = ['RPMng'] def Install(self, packages): ''' Try and fix everything that RPMng.VerifyPackages() found wrong for each Package Entry. This can result in individual RPMs being installed (for the first time), deleted, downgraded or upgraded. NOTE: YUM can not reinstall a package that it thinks is already installed. packages is a list of Package Elements that has self.states[] == False The following effects occur: - self.states{} is conditionally updated for each package. - self.installed{} is rebuilt, possibly multiple times. - self.instance_status{} is conditionally updated for each instance of a package. - Each package will be added to self.modified[] if its self.states{} entry is set to True. ''' self.logger.info('Runing YUMng.Install()') install_pkgs = [] gpg_keys = [] upgrade_pkgs = [] # Remove extra instances. # Can not reverify because we don't have a package entry. if len(self.extra_instances) > 0: self.RemovePackages(self.extra_instances) # Figure out which instances of the packages actually need something # doing to them and place in the appropriate work 'queue'. for pkg in packages: for inst in [inst for inst in pkg if inst.tag == 'Instance' or inst.tag == 'Package']: if self.instance_status[inst].get('installed', False) == False: if pkg.get('name') == 'gpg-pubkey': gpg_keys.append(inst) else: install_pkgs.append(inst) elif self.instance_status[inst].get('version_fail', False) == True: upgrade_pkgs.append(inst) # Install GPG keys. # Alternatively specify the required keys using 'gpgkey' in the # repository definition in yum.conf. YUM will install the keys # automatically. if len(gpg_keys) > 0: for inst in gpg_keys: self.logger.info("Installing GPG keys.") key_arg = os.path.join(self.instance_status[inst].get('pkg').get('uri'), \ inst.get('simplefile')) cmdrc, output = self.cmd.run("rpm --import %s" % key_arg) if cmdrc != 0: self.logger.debug("Unable to install %s-%s" % \ (self.instance_status[inst].get('pkg').get('name'), \ self.str_evra(inst))) else: self.logger.debug("Installed %s-%s-%s" % \ (self.instance_status[inst].get('pkg').get('name'), \ inst.get('version'), inst.get('release'))) self.RefreshPackages() self.gpg_keyids = self.getinstalledgpg() pkg = self.instance_status[gpg_keys[0]].get('pkg') self.states[pkg] = self.VerifyPackage(pkg, []) # Install packages. if len(install_pkgs) > 0: self.logger.info("Attempting to install packages") if YAD: pkgtool = "/usr/bin/yum -d0 -y install %s" else: pkgtool = "/usr/bin/yum -d0 install %s" install_args = [] for inst in install_pkgs: pkg_arg = self.instance_status[inst].get('pkg').get('name') + '-' if inst.get('epoch', False): pkg_arg = pkg_arg + inst.get('epoch') + ':' pkg_arg = pkg_arg + inst.get('version') + '-' + inst.get('release') if inst.get('arch', False): pkg_arg = pkg_arg + '.' + inst.get('arch') install_args.append(pkg_arg) cmdrc, output = self.cmd.run(pkgtool % " ".join(install_args)) if cmdrc == 0: # The yum command succeeded. All packages installed. self.logger.info("Single Pass for Install Succeded") self.RefreshPackages() # Reverify all the packages that we might have just changed. # There may be multiple instances per package, only do the # verification once. install_pkg_set = set([self.instance_status[inst].get('pkg') \ for inst in install_pkgs]) self.logger.info("Reverifying Installed Packages") for inst in install_pkgs: pkg_entry = self.instance_status[inst].get('pkg') if pkg_entry in install_pkg_set: self.logger.debug("Reverifying Installed %s" % \ (pkg_entry.get('name'))) install_pkg_set.remove(pkg_entry) self.states[pkg_entry] = self.VerifyPackage(pkg_entry, \ self.instance_status[inst].get('modlist')) else: # We already reverified this pacakge. continue else: # The yum command failed. No packages installed. # Try installing instances individually. self.logger.error("Single Pass Install of Packages Failed") installed_instances = [] for inst in install_pkgs: pkg_arg = self.instance_status[inst].get('pkg').get('name') + '-' if inst.get('epoch', False): pkg_arg = pkg_arg + inst.get('epoch') + ':' pkg_arg = pkg_arg + inst.get('version') + '-' + inst.get('release') if inst.get('arch', False): pkg_arg = pkg_arg + '.' + inst.get('arch') cmdrc, output = self.cmd.run(pkgtool % pkg_arg) if cmdrc == 0: installed_instances.append(inst) else: self.logger.debug("%s %s would not install." % \ (self.instance_status[inst].get('pkg').get('name'), \ self.str_evra(inst))) install_pkg_set = set([self.instance_status[inst].get('pkg') \ for inst in install_pkgs]) self.RefreshPackages() for inst in installed_instances: pkg = inst.get('pkg') # Reverify all the packages that we might have just changed. # There may be multiple instances per package, only do the # verification once. if pkg in install_pkg_set: self.logger.debug("Reverifying Installed Package %s" % \ (pkg_entry.get('name'))) install_pkg_set.remove(pkg) self.states[pkg_entry] = self.VerifyPackage(pkg, \ self.instance_status[inst].get('modlist')) else: # We already reverified this pacakge. continue # Fix upgradeable packages. if len(upgrade_pkgs) > 0: self.logger.info("Attempting to upgrade packages") if YAD: pkgtool = "/usr/bin/yum -d0 -y update %s" else: pkgtool = "/usr/bin/yum -d0 update %s" upgrade_args = [] for inst in upgrade_pkgs: pkg_arg = self.instance_status[inst].get('pkg').get('name') + '-' if inst.haskey('epoch'): pkg_arg = pkg_arg + inst.get('epoch') + ':' pkg_arg = pkg_arg + inst.get('version') + '-' + inst.get('release') if inst.haskey('arch'): pkg_arg = pkg_arg + '.' + inst.get('arch') upgrade_args.append(pkg_arg) cmdrc, output = self.cmd.run(pkgtool % " ".join(upgrade_args)) if cmdrc == 0: # The yum command succeeded. All packages installed. self.logger.info("Single Pass for Install Succeded") self.RefreshPackages() # Reverify all the packages that we might have just changed. # There may be multiple instances per package, only do the # verification once. install_pkg_set = set([self.instance_status[inst].get('pkg') \ for inst in upgrade_pkgs]) self.logger.info("Reverifying Installed Packages") for inst in upgrade_pkgs: pkg_entry = self.instance_status[inst].get('pkg') if pkg_entry in install_pkg_set: self.logger.debug("Reverifying Installed %s" % \ (pkg_entry.get('name'))) install_pkg_set.remove(pkg_entry) self.states[pkg_entry] = self.VerifyPackage(pkg_entry, \ self.instance_status[inst].get('modlist')) else: # We already reverified this pacakge. continue else: # The yum command failed. No packages installed. # Try installing instances individually. self.logger.error("Single Pass Install of Packages Failed") installed_instances = [] for inst in upgrade_pkgs: pkg_arg = self.instance_status[inst].get('pkg').get('name') + '-' if inst.haskey('epoch'): pkg_arg = pkg_arg + inst.get('epoch') + ':' pkg_arg = pkg_arg + inst.get('version') + '-' + inst.get('release') if inst.haskey('arch'): pkg_arg = pkg_arg + '.' + inst.get('arch') cmdrc, output = self.cmd.run(pkgtool % pkg_arg) if cmdrc == 0: installed_instances.append(inst) else: self.logger.debug("%s %s would not install." % \ (self.instance_status[inst].get('pkg').get('name'), \ self.str_evra(inst))) install_pkg_set = set([self.instance_status[inst].get('pkg') \ for inst in upgrade_pkgs]) self.RefreshPackages() for inst in installed_instances: pkg = inst.get('pkg') # Reverify all the packages that we might have just changed. # There may be multiple instances per package, only do the # verification once. if pkg in install_pkg_set: self.logger.debug("Reverifying Installed Package %s" % \ (pkg_entry.get('name'))) install_pkg_set.remove(pkg) self.states[pkg_entry] = self.VerifyPackage(pkg, \ self.instance_status[inst].get('modlist')) else: # We already reverified this pacakge. continue for entry in [ent for ent in packages if self.states[ent]]: self.modified.append(entry) def RemovePackages(self, packages): ''' Remove specified entries. packages is a list of Package Entries with Instances generated by FindExtraPackages(). ''' self.logger.debug('Running YUMng.RemovePackages()') if YAD: pkgtool = "/usr/bin/yum -d0 -y erase %s" else: pkgtool = "/usr/bin/yum -d0 erase %s" erase_args = [] for pkg in packages: for inst in pkg: if pkg.get('name') != 'gpg-pubkey': pkg_arg = pkg.get('name') + '-' if inst.get('epoch', False): pkg_arg = pkg_arg + inst.get('epoch') + ':' pkg_arg = pkg_arg + inst.get('version') + '-' + inst.get('release') if inst.get('arch', False): pkg_arg = pkg_arg + '.' + inst.get('arch') erase_args.append(pkg_arg) else: self.logger.info("WARNING: gpg-pubkey package not in configuration %s %s"\ % (pkgspec.get('name'), self.str_evra(pkgspec))) self.logger.info(" This package will be deleted in a future version of the RPMng driver.") cmdrc, output = self.cmd.run(pkgtool % " ".join(erase_args)) if cmdrc == 0: self.modified += packages for pkg in erase_args: self.logger.info("Deleted %s" % (pkg)) else: self.logger.info("Bulk erase failed with errors:") self.logger.debug("Erase results = %s" % output) self.logger.info("Attempting individual erase for each package.") for pkg in packages: pkg_modified = False for inst in pkg: if pkg.get('name') != 'gpg-pubkey': pkg_arg = pkg.get('name') + '-' if inst.haskey('epoch'): pkg_arg = pkg_arg + inst.get('epoch') + ':' pkg_arg = pkg_arg + inst.get('version') + '-' + inst.get('release') if inst.haskey('arch'): pkg_arg = pkg_arg + '.' + inst.get('arch') else: self.logger.info("WARNING: gpg-pubkey package not in configuration %s %s"\ % (pkgspec.get('name'), self.str_evra(pkgspec))) self.logger.info(" This package will be deleted in a future version of the RPMng driver.") cmdrc, output = self.cmd.run(self.pkgtool % pkg_arg) if cmdrc == 0: pkg_modified = True self.logger.info("Deleted %s" % pkg_arg) else: self.logger.error("unable to delete %s" % pkg_arg) self.logger.debug("Failure = %s" % output) if pkg_modified == True: self.modified.append(pkg) self.RefreshPackages() self.extra = self.FindExtraPackages()