[PATCH] DNFPayload: display the download progress on the hub.
David Shea
dshea at redhat.com
Mon Feb 24 15:14:50 UTC 2014
On 02/24/2014 09:55 AM, Ales Kozumplik wrote:
> From: Ales Kozumplik <ales at redhat.com>
>
> ---
> anaconda.spec.in | 2 +-
> pyanaconda/packaging/dnfpayload.py | 62 ++++++++++++++++++++++++++++++++++++--
> 2 files changed, 60 insertions(+), 4 deletions(-)
>
> diff --git a/anaconda.spec.in b/anaconda.spec.in
> index 7215e32..b648831 100755
> --- a/anaconda.spec.in
> +++ b/anaconda.spec.in
> @@ -23,7 +23,7 @@ Source0: %{name}-%{version}.tar.bz2
> %define intltoolver 0.31.2-3
> %define pykickstartver 1.99.46
> %define yumver 3.4.3-91
> -%define dnfver 0.4.14
> +%define dnfver 0.4.15
> %define partedver 1.8.1
> %define pypartedver 2.5-2
> %define pythonpyblockver 0.45
> diff --git a/pyanaconda/packaging/dnfpayload.py b/pyanaconda/packaging/dnfpayload.py
> index ecf7bb1..b2382de 100644
> --- a/pyanaconda/packaging/dnfpayload.py
> +++ b/pyanaconda/packaging/dnfpayload.py
> @@ -25,6 +25,7 @@ from pyanaconda.flags import flags
> from pyanaconda.i18n import _
> from pyanaconda.progress import progressQ
>
> +import collections
> import itertools
> import logging
> import multiprocessing
> @@ -41,7 +42,7 @@ try:
> import dnf
> import dnf.exceptions
> import dnf.repo
> - import dnf.output
> + import dnf.callback
> import rpm
> except ImportError as e:
> log.error("dnfpayload: component import failed: %s", e)
> @@ -102,7 +103,7 @@ def _pick_mpoint(df, requested):
> return sorted(sufficients.iteritems(), key=operator.itemgetter(1),
> reverse=True)[0][0]
>
> -class PayloadRPMDisplay(dnf.output.LoggingTransactionDisplay):
> +class PayloadRPMDisplay(dnf.callback.LoggingTransactionDisplay):
> def __init__(self, queue):
> super(PayloadRPMDisplay, self).__init__()
> self._queue = queue
> @@ -123,6 +124,53 @@ class PayloadRPMDisplay(dnf.output.LoggingTransactionDisplay):
> elif action == self.TRANS_POST:
> self._queue.put(('post', None))
>
> +class DownloadProgress(dnf.callback.DownloadProgress):
> + def __init__(self):
> + self.downloads = collections.defaultdict(int)
> + self.last_time = time.time()
> + self.total_files = 0
> + self.total_size = Size(0)
> +
> + def _paced(fn):
> + """Execute `fn` no more often then every 2 seconds."""
> + def paced_fn(self, *args):
> + now = time.time()
> + if now - self.last_time < 2:
> + return
> + self.last_time = now
> + return fn(self, *args)
> + return paced_fn
> +
> + @_paced
> + def _update(self):
> + msg = _('Downloading %(total_files)s RPMs, '
> + '%(downloaded)s / %(total_size)s (%(percent)d%%) done.')
> + downloaded = Size(sum(self.downloads.values()))
> + vals = {
> + 'downloaded' : downloaded,
> + 'percent' : int(100 * downloaded/self.total_size),
> + 'total_files' : self.total_files,
> + 'total_size' : self.total_size
> + }
> + progressQ.send_message(msg % vals)
> +
> + def end(self, payload, status, err_msg):
> + nevra = str(payload)
> + if status is dnf.callback.STATUS_OK:
> + self.downloads[nevra] = payload.download_size
> + self._update()
> + return
> + log.critical("Failed to download '%s': %d - %s", nevra, status, err_msg)
> +
> + def progress(self, payload, done):
> + nevra = str(payload)
> + self.downloads[nevra] = done
> + self._update()
> +
> + def start(self, total_files, total_size):
> + self.total_files = total_files
> + self.total_size = Size(total_size)
> +
> def do_transaction(base, queue):
> try:
> display = PayloadRPMDisplay(queue)
> @@ -419,7 +467,15 @@ class DNFPayload(packaging.PackagePayload):
> pkgs_to_download = self._base.transaction.install_set
> log.info('Downloading pacakges.')
> progressQ.send_message(_('Downloading packages'))
> - self._base.download_packages(pkgs_to_download)
> + progress = DownloadProgress()
> + try:
> + self._base.download_packages(pkgs_to_download, progress)
> + except dnf.exception.DownloadError as e:
> + msg = 'Failed to download the following packages: %s' % str(e)
> + exc = packaging.PayloadInstallError(msg)
> + if errors.errorHandler.cb(exc) == errors.ERROR_RAISE:
> + _failure_limbo()
> +
> log.info('Downloading packages finished.')
>
> pre_msg = _("Preparing transaction from installation source")
pylint reports the following issues:
************* Module pyanaconda/packaging/dnfpayload.py
E1101:128,23: DownloadProgress: Module 'dnf.callback' has no
'DownloadProgress' member
E0213:135,4: DownloadProgress._paced: Method should have "self" as first
argument
E1102:142,19: DownloadProgress._paced.paced_fn: fn is not callable
E1101:475,15: DNFPayload.install: Module 'dnf' has no 'exception' member
More information about the anaconda-patches
mailing list