Cleaning up the downloader module and adding progress bar support to it for http downloads and using this for the image downloading parts - which should now show a better download progress status...

This commit is contained in:
Joshua Harlow 2012-03-17 13:02:39 -07:00
parent 419686f229
commit 1bc9559a02
4 changed files with 96 additions and 47 deletions

View File

@ -161,14 +161,16 @@ class PkgInstallComponent(ComponentBase):
msg = "No uri entry found at config location [%s]" % \ msg = "No uri entry found at config location [%s]" % \
(cfg_helpers.make_id(cfg_section, cfg_key)) (cfg_helpers.make_id(cfg_section, cfg_key))
raise excp.ConfigException(msg) raise excp.ConfigException(msg)
# Activate da download!
self.tracewriter.download_happened(target_loc, uri) self.tracewriter.download_happened(target_loc, uri)
dirs_made = down.download(target_loc, uri, branch) dirs_made = down.download(uri, target_loc, branch=branch)
# Here we ensure this is always added so that # Here we ensure this is always added so that
# if a keep old happens then this of course # if a keep old happens then this of course
# won't be recreated, but if u uninstall without keeping old # won't be recreated, but if u uninstall without keeping old
# then this won't be deleted this time around # then this won't be deleted this time around
# adding it in is harmless and will make sure its removed. # adding it in is harmless and will make sure its removed.
dirs_made.append(target_loc) if target_loc not in dirs_made:
dirs_made.append(target_loc)
self.tracewriter.dirs_made(*dirs_made) self.tracewriter.dirs_made(*dirs_made)
return len(locations) return len(locations)

View File

@ -15,8 +15,11 @@
# under the License. # under the License.
from urlparse import urlparse
import re import re
import urllib
import urlparse
import progressbar
from devstack import log as logging from devstack import log as logging
from devstack import shell as sh from devstack import shell as sh
@ -30,30 +33,92 @@ CHECKOUT_CMD = ['git', 'checkout']
PULL_CMD = ['git', 'pull'] PULL_CMD = ['git', 'pull']
def _gitdownload(storewhere, uri, branch=None): class Downloader(object):
dirsmade = list()
if sh.isdir(storewhere): def __init__(self, uri, store_where):
LOG.info("Updating code located at [%s]" % (storewhere)) self.uri = uri
cmd = CHECKOUT_CMD + [GIT_MASTER_BRANCH] self.store_where = store_where
sh.execute(*cmd, cwd=storewhere)
cmd = PULL_CMD def download(self):
sh.execute(*cmd, cwd=storewhere) raise NotImplementedError()
else:
LOG.info("Downloading from [%s] to [%s]" % (uri, storewhere))
dirsmade.extend(sh.mkdirslist(storewhere))
cmd = CLONE_CMD + [uri, storewhere]
sh.execute(*cmd)
if branch and branch != GIT_MASTER_BRANCH:
LOG.info("Adjusting git branch to [%s]" % (branch))
cmd = CHECKOUT_CMD + [branch]
sh.execute(*cmd, cwd=storewhere)
return dirsmade
def download(storewhere, uri, branch=None): class GitDownloader(Downloader):
up = urlparse(uri)
def __init__(self, uri, store_where, **kargs):
Downloader.__init__(self, uri, store_where)
self.branch = kargs.get('branch')
def download(self):
dirsmade = list()
if sh.isdir(self.store_where):
LOG.info("Updating using git: located at %r" % (self.store_where))
cmd = CHECKOUT_CMD + [GIT_MASTER_BRANCH]
sh.execute(*cmd, cwd=self.store_where)
cmd = PULL_CMD
sh.execute(*cmd, cwd=self.store_where)
else:
LOG.info("Downloading using git: %r to %r" % (self.uri, self.store_where))
dirsmade.extend(sh.mkdirslist(self.store_where))
cmd = CLONE_CMD + [self.uri, self.store_where]
sh.execute(*cmd)
if self.branch and self.branch != GIT_MASTER_BRANCH:
LOG.info("Adjusting branch using git: %r" % (self.branch))
cmd = CHECKOUT_CMD + [self.branch]
sh.execute(*cmd, cwd=self.store_where)
return dirsmade
class HttpDownloader(Downloader):
def __init__(self, uri, store_where, **kargs):
Downloader.__init__(self, uri, store_where)
self.quiet = kargs.get('quiet', False)
self.p_bar = None
def _make_bar(self, size):
widgets = [
'Fetching: ', progressbar.Percentage(),
' ', progressbar.Bar(),
' ', progressbar.ETA(),
' ', progressbar.FileTransferSpeed(),
]
return progressbar.ProgressBar(widgets=widgets, maxval=size)
def _report(self, blocks, block_size, total_size):
if self.quiet:
return
byte_down = blocks * block_size
if not self.p_bar:
self.p_bar = self._make_bar(total_size)
self.p_bar.start()
if byte_down > self.p_bar.maxval:
# This seems to happen, huh???
pass
else:
self.p_bar.update(byte_down)
def download(self):
LOG.info('Downloading using http: %r to %r', self.uri, self.store_where)
dirsmade = sh.mkdirslist(sh.dirname(self.store_where))
try:
urllib.urlretrieve(self.uri, self.store_where, self._report)
finally:
if self.p_bar:
self.p_bar.finish()
self.p_bar = None
return dirsmade
def download(uri, storewhere, **kargs):
downloader_cls = None
up = urlparse.urlparse(uri)
if up and up.scheme.lower() == "git" or GIT_EXT_REG.match(up.path): if up and up.scheme.lower() == "git" or GIT_EXT_REG.match(up.path):
return _gitdownload(storewhere, uri, branch) downloader_cls = GitDownloader
else: elif up and up.scheme.lower() == "http":
msg = "Currently we do not know how to download from uri [%s]" % (uri) downloader_cls = HttpDownloader
if not downloader_cls:
msg = "Currently we do not know how to download from uri: %r" % (uri)
raise NotImplementedError(msg) raise NotImplementedError(msg)
downloader = downloader_cls(uri, storewhere, **kargs)
return downloader.download()

View File

@ -19,12 +19,13 @@ import json
import os import os
import tarfile import tarfile
import tempfile import tempfile
import urllib
import urllib2 import urllib2
from devstack import downloader as down
from devstack import log from devstack import log
from devstack import shell from devstack import shell
from devstack import utils from devstack import utils
from devstack.components import keystone from devstack.components import keystone
@ -61,27 +62,9 @@ class Image(object):
self.initrd_id = '' self.initrd_id = ''
self.tmp_folder = None self.tmp_folder = None
self.registry = ImageRegistry(token) self.registry = ImageRegistry(token)
self.last_report = 0
def _format_progress(self, curr_size, total_size):
if curr_size > total_size:
curr_size = total_size
progress = ("%d" % (curr_size)) + "b"
progress += "/"
progress += ("%d" % (total_size)) + "b"
perc_done = "%.02f" % (((curr_size) / (float(total_size)) * 100.0)) + "%"
return "[%s](%s)" % (progress, perc_done)
def _report(self, blocks, block_size, size):
downloaded = blocks * block_size
if (downloaded - self.last_report) > Image.REPORTSIZE:
progress = self._format_progress((blocks * block_size), size)
LOG.info('Download progress: %s', progress)
self.last_report = downloaded
def _download(self): def _download(self):
LOG.info('Downloading %s to %s', self.url, self.download_file_name) return down.download(self.url, self.download_file_name)
urllib.urlretrieve(self.url, self.download_file_name, self._report)
def _unpack(self): def _unpack(self):
parts = self.download_name.split('.') parts = self.download_name.split('.')

View File

@ -17,7 +17,6 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import json
import os import os
import random import random
import re import re