def writeMultiLibConfig(self): #if not self.data.packages.multiLib: # return return # write out the yum config with the new multilib_policy value # FIXME: switch to using yum-config-manager once it stops expanding # all yumvars and writing out the expanded pairs to the conf yb = yum.YumBase() yum_conf_path = "/etc/yum.conf" yb.preconf.fn = CF.D.TGTSYS_ROOT + yum_conf_path yb.conf.multilib_policy = "all" # this will appear in yum.conf, which is silly yb.conf.config_file_path = yum_conf_path # hack around yum having expanded $basearch in the cachedir value cachedir = yb.conf.cachedir.replace("/%s/" % yb.arch.basearch, "/$basearch/") yb.conf.cachedir = cachedir yum_conf = CF.D.TGTSYS_ROOT + yum_conf_path if os.path.exists(yum_conf): try: os.rename(yum_conf, yum_conf + ".anacbak") except OSError as e: logger.error("failed to back up yum.conf: %s" % e) try: yb.conf.write(open(yum_conf, "w")) except Exception as e: logger.error("failed to write out yum.conf: %s" % e)
def selectKernelPackage(self): kernels = self.kernelPackages selected = None # XXX This is optimistic. I'm curious if yum will DTRT if I just say # "select this kernel" without jumping through hoops to figure out # which arch it should use. for kernel in kernels: try: # XXX might need explicit arch specification self._selectYumPackage(kernel) except NoSuchPackage as e: logger.info("no %s package" % kernel) continue else: logger.info("selected %s" % kernel) selected = kernel # select module packages for this kernel # select the devel package if gcc will be installed if self._yum.tsInfo.matchNaevr(name="gcc"): logger.info("selecting %s-devel" % kernel) # XXX might need explicit arch specification self._selectYumPackage("%s-devel" % kernel) break if not selected: logger.error("failed to select a kernel from %s" % kernels)
def packages(self): from yum.Errors import RepoError with _yum_lock: if not self._packages: try: self._packages = self._yum.pkgSack.returnPackages() except RepoError as e: logger.error("failed to get package list: %s" % e) return self._packages
def gatherRepoMetadata(self): # now go through and get metadata for all enabled repos logger.info("gathering repo metadata") for repo_id in self.repos: repo = self._yum.repos.getRepo(repo_id) if repo.enabled: try: self._getRepoMetadata(repo) except PayloadError as e: logger.error("failed to grab repo metadata for %s: %s" % (repo_id, e)) self.disableRepo(repo_id) logger.info("metadata retrieval complete")
def _configureBaseRepo(self): logger.info("configuring base repo") if CF.S.BASE_REPO_URL.startswith('/'): url = "file://" + CF.S.BASE_REPO_URL else: url = CF.S.BASE_REPO_URL with _yum_lock: self._yum.preconf.releasever = self._getReleaseVersion(url) self._yumCacheDirHack() try: self._addYumRepo(CF.S.BASE_REPO_NAME, url) except: logger.error("base repo (%s) not valid -- removing it" % (url, )) self._removeYumRepo(CF.S.BASE_REPO_NAME) raise
def _writeInstallConfig(self): """ Write out the yum config that will be used to install packages. Write out repo config files for all enabled repos, then create a new YumBase instance with the new filesystem tree as its install root. """ self._repos_dir = "/tmp/yum.repos.d" if not os.path.isdir(self._repos_dir): os.mkdir(self._repos_dir) for repo in self._yum.repos.listEnabled(): cfg_path = "%s/%s.repo" % (self._repos_dir, repo.id) #ks_repo = self.getRepo(repo.id) with open(cfg_path, "w") as f: f.write("[%s]\n" % repo.id) f.write("name=Install - %s\n" % repo.id) f.write("enabled=1\n") if repo.mirrorlist: f.write("mirrorlist=%s" % repo.mirrorlist) elif repo.baseurl: f.write("baseurl=%s\n" % repo.baseurl[0]) else: logger.error("repo %s has no baseurl or mirrorlist" % repo.id) f.close() os.unlink(cfg_path) continue releasever = self._yum.conf.yumvar['releasever'] self._writeYumConfig() self._resetYum(root=CF.D.TGTSYS_ROOT, keep_cache=True) logger.debug("setting releasever to previous value of %s" % releasever) self._yum.preconf.releasever = releasever self._yumCacheDirHack() self.gatherRepoMetadata() # trigger setup of self._yum.config logger.debug("installation yum config repos: %s" % ",".join([r.id for r in self._yum.repos.listEnabled()]))
def _getRepoMetadata(self, yumrepo): """ Retrieve repo metadata if we don't already have it. """ from yum.Errors import RepoError, RepoMDError # And try to grab its metadata. We do this here so it can be done # on a per-repo basis, so we can then get some finer grained error # handling and recovery. logger.debug("getting repo metadata for %s" % yumrepo.id) with _yum_lock: try: yumrepo.getPrimaryXML() except RepoError as e: raise Exception('MetadataError', e.value) # Not getting group info is bad, but doesn't seem like a fatal error. # At the worst, it just means the groups won't be displayed in the UI # which isn't too bad, because you may be doing a kickstart install and # picking packages instead. logger.debug("getting group info for %s" % yumrepo.id) try: yumrepo.getGroups() except RepoMDError: logger.error("failed to get groups for repo %s" % yumrepo.id)
def install(self): """ Install the payload. """ from yum.Errors import PackageSackError, RepoError, YumBaseError logger.info("preparing transaction") logger.debug("initialize transaction set") with _yum_lock: self._yum.initActionTs() if rpmUtils and rpmUtils.arch.isMultiLibArch(): self._yum.ts.ts.setColor(3) logger.debug("populate transaction set") try: # uses dsCallback.transactionPopulation self._yum.populateTs(keepold=0) except RepoError as e: logger.error("error populating transaction: %s" % e) exn = PayloadInstallError(str(e)) #if errorHandler.cb(exn) == ERROR_RAISE: raise exn logger.debug("check transaction set") self._yum.ts.check() logger.debug("order transaction set") self._yum.ts.order() self._yum.ts.clean() # Write scriptlet output to a file to be logged later script_log = tempfile.NamedTemporaryFile(delete=False) self._yum.ts.ts.scriptFd = script_log.fileno() rpm.setLogFile(script_log) #@UndefinedVariable # create the install callback rpmcb = RPMCallback(self._yum, script_log, self.progress, upgrade=False) if self.flags.testing: self._yum.ts.setFlags(rpm.RPMTRANS_FLAG_TEST) #@UndefinedVariable logger.info("running transaction") self.progress.send_step() try: self._yum.runTransaction(cb=rpmcb) except PackageSackError as e: logger.error("error running transaction: %s" % e) exn = PayloadInstallError(str(e)) #if errorHandler.cb(exn) == ERROR_RAISE: raise exn except YumBaseError as e: logger.error("error [2] running transaction: %s" % e) for error in e.errors: logger.error("%s" % error[0]) exn = PayloadInstallError(str(e)) #if errorHandler.cb(exn) == ERROR_RAISE: raise exn else: logger.info("transaction complete") self.progress.send_step() finally: self._yum.ts.close() iutil.resetRpmDb() script_log.close() # log the contents of the scriptlet logfile logger.info("==== start rpm scriptlet logs ====") with open(script_log.name) as f: for l in f: logger.info(l) logger.info("==== end rpm scriptlet logs ====") os.unlink(script_log.name)
def install(self): """ Install the payload. """ from yum.Errors import PackageSackError, RepoError, YumBaseError logger.info("preparing transaction") logger.debug("initialize transaction set") with _yum_lock: self._yum.initActionTs() if rpmUtils and rpmUtils.arch.isMultiLibArch(): self._yum.ts.ts.setColor(3) logger.debug("populate transaction set") try: # uses dsCallback.transactionPopulation self._yum.populateTs(keepold=0) except RepoError as e: logger.error("error populating transaction: %s" % e) exn = PayloadInstallError(str(e)) #if errorHandler.cb(exn) == ERROR_RAISE: raise exn logger.debug("check transaction set") self._yum.ts.check() logger.debug("order transaction set") self._yum.ts.order() self._yum.ts.clean() # Write scriptlet output to a file to be logged later script_log = tempfile.NamedTemporaryFile(delete=False) self._yum.ts.ts.scriptFd = script_log.fileno() rpm.setLogFile(script_log) #@UndefinedVariable # create the install callback rpmcb = RPMCallback(self._yum, script_log, self.progress, upgrade=False) if self.flags.testing: self._yum.ts.setFlags( rpm.RPMTRANS_FLAG_TEST) #@UndefinedVariable logger.info("running transaction") self.progress.send_step() try: self._yum.runTransaction(cb=rpmcb) except PackageSackError as e: logger.error("error running transaction: %s" % e) exn = PayloadInstallError(str(e)) #if errorHandler.cb(exn) == ERROR_RAISE: raise exn except YumBaseError as e: logger.error("error [2] running transaction: %s" % e) for error in e.errors: logger.error("%s" % error[0]) exn = PayloadInstallError(str(e)) #if errorHandler.cb(exn) == ERROR_RAISE: raise exn else: logger.info("transaction complete") self.progress.send_step() finally: self._yum.ts.close() iutil.resetRpmDb() script_log.close() # log the contents of the scriptlet logfile logger.info("==== start rpm scriptlet logs ====") with open(script_log.name) as f: for l in f: logger.info(l) logger.info("==== end rpm scriptlet logs ====") os.unlink(script_log.name)
def callback(self, event, amount, total, key, userdata): """ Yum install callback. """ if event == rpm.RPMCALLBACK_TRANS_START: #@UndefinedVariable if amount == 6: self.progress.send_message(_("Preparing transaction from installation source")) self.total_actions = total self.completed_actions = 0 elif event == rpm.RPMCALLBACK_TRANS_PROGRESS: #@UndefinedVariable # amount / total complete pass elif event == rpm.RPMCALLBACK_TRANS_STOP: #@UndefinedVariable # we are done pass elif event == rpm.RPMCALLBACK_INST_OPEN_FILE: #@UndefinedVariable # update status that we're installing/upgrading %h # return an open fd to the file txmbr = self._get_txmbr(key)[1] # If self.completed_actions is still None, that means this package # is being opened to retrieve a %pretrans script. Don't log that # we're installing the package unless we've been called with a # TRANS_START event. if self.completed_actions is not None: if self.upgrade: mode = _("Upgrading") else: mode = _("Installing") self.completed_actions += 1 msg_format = "%s %s (%d/%d)" progress_package = txmbr.name if txmbr.arch not in ["noarch", self.base_arch]: progress_package = "%s.%s" % (txmbr.name, txmbr.arch) progress_msg = msg_format % (mode, progress_package, self.completed_actions, self.total_actions) log_msg = msg_format % (mode, txmbr.po, self.completed_actions, self.total_actions) logger.info(log_msg) self.install_log.write(log_msg+"\n") self.install_log.flush() self.progress.send_message(progress_msg) self.package_file = None repo = self._yum.repos.getRepo(txmbr.po.repoid) while self.package_file is None: try: # checkfunc gets passed to yum's use of URLGrabber which # then calls it with the file being fetched. verifyPkg # makes sure the checksum matches the one in the metadata. # # From the URLGrab documents: # checkfunc=(function, ('arg1', 2), {'kwarg': 3}) # results in a callback like: # function(obj, 'arg1', 2, kwarg=3) # obj.filename = '/tmp/stuff' # obj.url = 'http://foo.com/stuff' checkfunc = (self._yum.verifyPkg, (txmbr.po, 1), {}) package_path = repo.getPackage(txmbr.po, checkfunc=checkfunc) except yum.URLGrabError as e: logger.error("URLGrabError: %s" % (e,)) exn = PayloadInstallError("failed to get package") #if errorHandler.cb(exn, txmbr.po) == ERROR_RAISE: raise exn except (yum.Errors.NoMoreMirrorsRepoError, IOError): if os.path.exists(txmbr.po.localPkg()): os.unlink(txmbr.po.localPkg()) logger.debug("retrying download of %s" % txmbr.po) continue exn = PayloadInstallError("failed to open package") #if errorHandler.cb(exn, txmbr.po) == ERROR_RAISE: raise exn except yum.Errors.RepoError: continue self.package_file = open(package_path) return self.package_file.fileno() elif event == rpm.RPMCALLBACK_INST_PROGRESS: #@UndefinedVariable txmbr = self._get_txmbr(key)[1] progress_package = txmbr.name if txmbr.arch not in ["noarch", self.base_arch]: progress_package = "%s.%s" % (txmbr.name, txmbr.arch) #self.progress.send_message('%s (%s/%s)' % (progress_package, amount, total)) elif event == rpm.RPMCALLBACK_INST_CLOSE_FILE: #@UndefinedVariable # close and remove the last opened file # update count of installed/upgraded packages package_path = self.package_file.name self.package_file.close() self.package_file = None if package_path.startswith(_yum_cache_dir): try: os.unlink(package_path) except OSError as e: logger.debug("unable to remove file %s" % e.strerror) # rpm doesn't tell us when it's started post-trans stuff which can # take a very long time. So when it closes the last package, just # display the message. if self.completed_actions == self.total_actions: self.progress.send_message(_("Performing post-install setup tasks")) elif event == rpm.RPMCALLBACK_UNINST_START: #@UndefinedVariable # update status that we're cleaning up %key #self.progress.set_text(_("Cleaning up %s" % key)) pass elif event in (rpm.RPMCALLBACK_CPIO_ERROR, #@UndefinedVariable rpm.RPMCALLBACK_UNPACK_ERROR, #@UndefinedVariable rpm.RPMCALLBACK_SCRIPT_ERROR): #@UndefinedVariable name = self._get_txmbr(key)[0] # Script errors store whether or not they're fatal in "total". So, # we should only error out for fatal script errors or the cpio and # unpack problems. if event != rpm.RPMCALLBACK_SCRIPT_ERROR or total: #@UndefinedVariable exn = PayloadInstallError("cpio, unpack, or fatal script error") #if errorHandler.cb(exn, name) == ERROR_RAISE: raise exn
def callback(self, event, amount, total, key, userdata): """ Yum install callback. """ if event == rpm.RPMCALLBACK_TRANS_START: #@UndefinedVariable if amount == 6: self.progress.send_message( _("Preparing transaction from installation source")) self.total_actions = total self.completed_actions = 0 elif event == rpm.RPMCALLBACK_TRANS_PROGRESS: #@UndefinedVariable # amount / total complete pass elif event == rpm.RPMCALLBACK_TRANS_STOP: #@UndefinedVariable # we are done pass elif event == rpm.RPMCALLBACK_INST_OPEN_FILE: #@UndefinedVariable # update status that we're installing/upgrading %h # return an open fd to the file txmbr = self._get_txmbr(key)[1] # If self.completed_actions is still None, that means this package # is being opened to retrieve a %pretrans script. Don't log that # we're installing the package unless we've been called with a # TRANS_START event. if self.completed_actions is not None: if self.upgrade: mode = _("Upgrading") else: mode = _("Installing") self.completed_actions += 1 msg_format = "%s %s (%d/%d)" progress_package = txmbr.name if txmbr.arch not in ["noarch", self.base_arch]: progress_package = "%s.%s" % (txmbr.name, txmbr.arch) progress_msg = msg_format % (mode, progress_package, self.completed_actions, self.total_actions) log_msg = msg_format % (mode, txmbr.po, self.completed_actions, self.total_actions) logger.info(log_msg) self.install_log.write(log_msg + "\n") self.install_log.flush() self.progress.send_message(progress_msg) self.package_file = None repo = self._yum.repos.getRepo(txmbr.po.repoid) while self.package_file is None: try: # checkfunc gets passed to yum's use of URLGrabber which # then calls it with the file being fetched. verifyPkg # makes sure the checksum matches the one in the metadata. # # From the URLGrab documents: # checkfunc=(function, ('arg1', 2), {'kwarg': 3}) # results in a callback like: # function(obj, 'arg1', 2, kwarg=3) # obj.filename = '/tmp/stuff' # obj.url = 'http://foo.com/stuff' checkfunc = (self._yum.verifyPkg, (txmbr.po, 1), {}) package_path = repo.getPackage(txmbr.po, checkfunc=checkfunc) except yum.URLGrabError as e: logger.error("URLGrabError: %s" % (e, )) exn = PayloadInstallError("failed to get package") #if errorHandler.cb(exn, txmbr.po) == ERROR_RAISE: raise exn except (yum.Errors.NoMoreMirrorsRepoError, IOError): if os.path.exists(txmbr.po.localPkg()): os.unlink(txmbr.po.localPkg()) logger.debug("retrying download of %s" % txmbr.po) continue exn = PayloadInstallError("failed to open package") #if errorHandler.cb(exn, txmbr.po) == ERROR_RAISE: raise exn except yum.Errors.RepoError: continue self.package_file = open(package_path) return self.package_file.fileno() elif event == rpm.RPMCALLBACK_INST_PROGRESS: #@UndefinedVariable txmbr = self._get_txmbr(key)[1] progress_package = txmbr.name if txmbr.arch not in ["noarch", self.base_arch]: progress_package = "%s.%s" % (txmbr.name, txmbr.arch) #self.progress.send_message('%s (%s/%s)' % (progress_package, amount, total)) elif event == rpm.RPMCALLBACK_INST_CLOSE_FILE: #@UndefinedVariable # close and remove the last opened file # update count of installed/upgraded packages package_path = self.package_file.name self.package_file.close() self.package_file = None if package_path.startswith(_yum_cache_dir): try: os.unlink(package_path) except OSError as e: logger.debug("unable to remove file %s" % e.strerror) # rpm doesn't tell us when it's started post-trans stuff which can # take a very long time. So when it closes the last package, just # display the message. if self.completed_actions == self.total_actions: self.progress.send_message( _("Performing post-install setup tasks")) elif event == rpm.RPMCALLBACK_UNINST_START: #@UndefinedVariable # update status that we're cleaning up %key #self.progress.set_text(_("Cleaning up %s" % key)) pass elif event in ( rpm.RPMCALLBACK_CPIO_ERROR, #@UndefinedVariable rpm.RPMCALLBACK_UNPACK_ERROR, #@UndefinedVariable rpm.RPMCALLBACK_SCRIPT_ERROR): #@UndefinedVariable name = self._get_txmbr(key)[0] # Script errors store whether or not they're fatal in "total". So, # we should only error out for fatal script errors or the cpio and # unpack problems. if event != rpm.RPMCALLBACK_SCRIPT_ERROR or total: #@UndefinedVariable exn = PayloadInstallError( "cpio, unpack, or fatal script error") #if errorHandler.cb(exn, name) == ERROR_RAISE: raise exn