def _pick_download_location(self): download_size = self._download_space install_size = self._spaceRequired() df_map = _df_map() mpoint = _pick_mpoint(df_map, download_size, install_size, download_only=True) if mpoint is None: msg = ("Not enough disk space to download the packages; size %s." % download_size) raise payload.PayloadError(msg) log.info("Mountpoint %s picked as download location", mpoint) pkgdir = '%s/%s' % (mpoint, DNF_PACKAGE_CACHE_DIR_SUFFIX) with self._repos_lock: for repo in self._base.repos.iter_enabled(): repo.pkgdir = pkgdir return pkgdir
def install(self): progress_message(N_('Starting package installation process')) # Add the rpm macros to the global transaction environment for macro in self.rpmMacros: rpm.addMacro(macro[0], macro[1]) if self.install_device: self._setupMedia(self.install_device) try: self.checkSoftwareSelection() self._download_location = self._pick_download_location() except payload.PayloadError as e: if errors.errorHandler.cb(e) == errors.ERROR_RAISE: log.error("Installation failed: %r", e) _failure_limbo() if os.path.exists(self._download_location): log.info("Removing existing package download location: %s", self._download_location) shutil.rmtree(self._download_location) pkgs_to_download = self._base.transaction.install_set log.info('Downloading packages to %s.', self._download_location) progressQ.send_message(_('Downloading packages')) progress = DownloadProgress() try: self._base.download_packages(pkgs_to_download, progress) except dnf.exceptions.DownloadError as e: msg = 'Failed to download the following packages: %s' % str(e) exc = payload.PayloadInstallError(msg) if errors.errorHandler.cb(exc) == errors.ERROR_RAISE: log.error("Installation failed: %r", exc) _failure_limbo() log.info('Downloading packages finished.') pre_msg = (N_("Preparing transaction from installation source")) progress_message(pre_msg) queue_instance = multiprocessing.Queue() process = multiprocessing.Process(target=do_transaction, args=(self._base, queue_instance)) process.start() (token, msg) = queue_instance.get() # When the installation works correctly it will get 'install' updates # followed by a 'post' message and then a 'quit' message. # If the installation fails it will send 'quit' without 'post' while token: if token == 'install': msg = _("Installing %s") % msg progressQ.send_message(msg) elif token == 'configure': msg = _("Configuring %s") % msg progressQ.send_message(msg) elif token == 'verify': msg = _("Verifying %s") % msg progressQ.send_message(msg) elif token == 'log': log.info(msg) elif token == 'post': msg = (N_("Performing post-installation setup tasks")) progressQ.send_message(msg) elif token == 'done': break # Installation finished successfully elif token == 'quit': msg = ( "Payload error - DNF installation has ended up abruptly: %s" % msg) raise payload.PayloadError(msg) elif token == 'error': exc = payload.PayloadInstallError("DNF error: %s" % msg) if errors.errorHandler.cb(exc) == errors.ERROR_RAISE: log.error("Installation failed: %r", exc) _failure_limbo() (token, msg) = queue_instance.get() process.join() self._base.close() if os.path.exists(self._download_location): log.info("Cleaning up downloaded packages: %s", self._download_location) shutil.rmtree(self._download_location) else: # Some installation sources, such as NFS, don't need to download packages to # local storage, so the download location might not always exist. So for now # warn about this, at least until the RFE in bug 1193121 is implemented and # we don't have to care about clearing the download location ourselves. log.warning("Can't delete nonexistent download location: %s", self._download_location)