Пример #1
0
def _remove_image_on_exec(context, image_href, user_id, project_id,
                          imagehandler_args, image_path):
    for handler, loc, image_meta in imagehandler.handle_image(context,
                                                              image_href,
                                                              user_id,
                                                              project_id,
                                                              image_path):
        # The loop will stop when the handle function returns success.
        handler.remove_image(context, image_href, image_meta, image_path,
                             user_id, project_id, loc, **imagehandler_args)
    fileutils.delete_if_exists(image_path)
Пример #2
0
    def _fetch_image(self, image_id, expected_locations,
                     expected_handled_location, expected_handled_path,
                     mock__fetch_image):
        def _fake_handler_fetch(context, image_id, image_meta, path,
                                user_id=None, project_id=None, location=None):
            return location == expected_handled_location

        mock__fetch_image.side_effect = _fake_handler_fetch

        for handler_context in imagehandler.handle_image(self.context,
                                image_id, target_path=expected_handled_path):
            (handler, loc, image_meta) = handler_context
            self.assertEqual(handler, imagehandler._IMAGE_HANDLERS[0])
            if (len(expected_locations) > 0):
                self.assertEqual(expected_locations.pop(0), loc)
            handler.fetch_image(context, image_id, image_meta,
                                expected_handled_path, location=loc)
Пример #3
0
def fetch(context, image_href, path, _user_id, _project_id,
          max_size=0, imagehandler_args=None):
    """Fetch image and returns whether the image was stored locally."""
    imagehandler_args = imagehandler_args or {}
    _remove_image_fun = functools.partial(_remove_image_on_exec,
                                          context, image_href,
                                          _user_id, _project_id,
                                          imagehandler_args)

    fetched_to_local = True
    with fileutils.remove_path_on_error(path, remove=_remove_image_fun):
        for handler, loc, image_meta in imagehandler.handle_image(context,
                                                                  image_href,
                                                                  _user_id,
                                                                  _project_id,
                                                                  path):
            # The loop will stop when the handle function returns success.
            handler.fetch_image(context, image_href, image_meta, path,
                                _user_id, _project_id, loc,
                                **imagehandler_args)
            fetched_to_local = handler.is_local()
    return fetched_to_local
Пример #4
0
    def _remove_base_file(self, context, image_id, base_file):
        """Remove a single base file if it is old enough.

        Returns nothing.
        """
        if not os.path.exists(base_file):
            LOG.debug(_('Cannot remove %s, it does not exist'),
                    base_file)
            return

        mtime = os.path.getmtime(base_file)
        age = time.time() - mtime

        maxage = CONF.libvirt.remove_unused_resized_minimum_age_seconds
        if base_file in self.originals:
            maxage = CONF.remove_unused_original_minimum_age_seconds

        if age < maxage:
            LOG.info(_('Base file too young to remove: %s'), base_file)
        else:
            LOG.info(_('Removing base file: %s'), base_file)
            try:
                for handler_context in imagehandler.handle_image(
                                                    target_path=base_file):
                    (handler, loc, image_meta) = handler_context
                    # The loop will stop when the handle function
                    # returns success.
                    handler.remove_image(context, image_id, image_meta,
                                         base_file, location=loc)
                signature = get_info_filename(base_file)
                if os.path.exists(signature):
                    os.remove(signature)
            except OSError as e:
                LOG.error(_('Failed to remove %(base_file)s, '
                            'error was %(error)s'),
                          {'base_file': base_file,
                           'error': e})
Пример #5
0
def fetch_to_raw(context, image_href, path, user_id, project_id,
                 max_size=0, imagehandler_args=None):
    path_tmp = "%s.part" % path
    fetched_to_local = fetch(context, image_href, path_tmp,
                             user_id, project_id,
                             max_size=max_size,
                             imagehandler_args=imagehandler_args)

    if not fetched_to_local:
        return

    imagehandler_args = imagehandler_args or {}
    _remove_image_fun = functools.partial(_remove_image_on_exec,
                                          context, image_href,
                                          user_id, project_id,
                                          imagehandler_args)

    with fileutils.remove_path_on_error(path_tmp, remove=_remove_image_fun):
        data = qemu_img_info(path_tmp)

        fmt = data.file_format
        if fmt is None:
            raise exception.ImageUnacceptable(
                reason=_("'qemu-img info' parsing failed."),
                image_id=image_href)

        backing_file = data.backing_file
        if backing_file is not None:
            raise exception.ImageUnacceptable(image_id=image_href,
                reason=(_("fmt=%(fmt)s backed by: %(backing_file)s") %
                        {'fmt': fmt, 'backing_file': backing_file}))

        # We can't generally shrink incoming images, so disallow
        # images > size of the flavor we're booting.  Checking here avoids
        # an immediate DoS where we convert large qcow images to raw
        # (which may compress well but not be sparse).
        # TODO(p-draigbrady): loop through all flavor sizes, so that
        # we might continue here and not discard the download.
        # If we did that we'd have to do the higher level size checks
        # irrespective of whether the base image was prepared or not.
        disk_size = data.virtual_size
        if max_size and max_size < disk_size:
            msg = _('%(base)s virtual size %(disk_size)s '
                    'larger than flavor root disk size %(size)s')
            LOG.error(msg % {'base': path,
                             'disk_size': disk_size,
                             'size': max_size})
            raise exception.FlavorDiskTooSmall()

        if fmt != "raw" and CONF.force_raw_images:
            staged = "%s.converted" % path
            LOG.debug("%s was %s, converting to raw" % (image_href, fmt))

            with fileutils.remove_path_on_error(staged):
                convert_image(path_tmp, staged, 'raw')

                data = qemu_img_info(staged)
                if data.file_format != "raw":
                    raise exception.ImageUnacceptable(image_id=image_href,
                        reason=_("Converted to raw, but format is now %s") %
                        data.file_format)

                for handler_context in imagehandler.handle_image(context,
                                                                 image_href,
                                                                 user_id,
                                                                 project_id,
                                                                 staged):
                    (handler, loc, image_meta) = handler_context
                    # The loop will stop when the handle function
                    # return success.
                    handler.move_image(context, image_href, image_meta,
                                       staged, path,
                                       user_id, project_id, loc,
                                       **imagehandler_args)

                for handler_context in imagehandler.handle_image(context,
                                                                 image_href,
                                                                 user_id,
                                                                 project_id,
                                                                 path_tmp):
                    (handler, loc, image_meta) = handler_context
                    handler.remove_image(context, image_href, image_meta,
                                         path_tmp, user_id, project_id, loc,
                                         **imagehandler_args)
        else:
            for handler_context in imagehandler.handle_image(context,
                                                             image_href,
                                                             user_id,
                                                             project_id,
                                                             path_tmp):
                (handler, loc, image_meta) = handler_context
                handler.move_image(context, image_href, image_meta,
                                   path_tmp, path,
                                   user_id, project_id, loc,
                                   **imagehandler_args)