Пример #1
0
    def download(self, context, image_id, data=None):
        """Calls out to Glance for data and writes data."""
        if data and 'file' in CONF.allowed_direct_url_schemes:
            direct_url, locations = self.get_location(context, image_id)
            urls = [direct_url] + [loc.get('url') for loc in locations or []]
            for url in urls:
                if url is None:
                    continue
                parsed_url = urllib.parse.urlparse(url)
                if parsed_url.scheme == "file":
                    # a system call to cp could have significant performance
                    # advantages, however we do not have the path to files at
                    # this point in the abstraction.
                    with open(parsed_url.path, "rb") as f:
                        shutil.copyfileobj(f, data)
                    return

        try:
            image_chunks = self._client.call(context, 'data', image_id)
        except Exception:
            _reraise_translated_image_exception(image_id)

        if image_chunks is None:
            raise exception.ImageDownloadFailed(
                image_href=image_id, reason=_('image contains no data.'))

        if not data:
            return image_chunks
        else:
            for chunk in image_chunks:
                data.write(chunk)
Пример #2
0
def fetch(context: context.RequestContext,
          image_service: glance.GlanceImageService, image_id: str, path: str,
          _user_id, _project_id) -> None:
    # TODO(vish): Improve context handling and add owner and auth data
    #             when it is added to glance.  Right now there is no
    #             auth checking in glance, so we assume that access was
    #             checked before we got here.
    start_time = timeutils.utcnow()
    with fileutils.remove_path_on_error(path):
        with open(path, "wb") as image_file:
            try:
                image_service.download(context, image_id,
                                       tpool.Proxy(image_file))
            except IOError as e:
                if e.errno == errno.ENOSPC:
                    params = {'path': os.path.dirname(path), 'image': image_id}
                    reason = _("No space left in image_conversion_dir "
                               "path (%(path)s) while fetching "
                               "image %(image)s.") % params
                    LOG.exception(reason)
                    raise exception.ImageTooBig(image_id=image_id,
                                                reason=reason)

                reason = ("IOError: %(errno)s %(strerror)s" % {
                    'errno': e.errno,
                    'strerror': e.strerror
                })
                LOG.error(reason)
                raise exception.ImageDownloadFailed(image_href=image_id,
                                                    reason=reason)

    duration = timeutils.delta_seconds(start_time, timeutils.utcnow())

    # NOTE(jdg): use a default of 1, mostly for unit test, but in
    # some incredible event this is 0 (cirros image?) don't barf
    if duration < 1:
        duration = 1
    fsz_mb = os.stat(image_file.name).st_size / units.Mi
    mbps = (fsz_mb / duration)
    msg = ("Image fetch details: dest %(dest)s, size %(sz).2f MB, "
           "duration %(duration).2f sec")
    LOG.debug(msg, {
        "dest": image_file.name,
        "sz": fsz_mb,
        "duration": duration
    })
    msg = "Image download %(sz).2f MB at %(mbps).2f MB/s"
    LOG.info(msg, {"sz": fsz_mb, "mbps": mbps})