Пример #1
0
    def verify_base_size(self, base, size, base_size=0):
        """Check that the base image is not larger than size.
           Since images can't be generally shrunk, enforce this
           constraint taking account of virtual image size.
        """

        # Note(pbrady): The size and min_disk parameters of a glance
        #  image are checked against the instance size before the image
        #  is even downloaded from glance, but currently min_disk is
        #  adjustable and doesn't currently account for virtual disk size,
        #  so we need this extra check here.
        # NOTE(cfb): Having a flavor that sets the root size to 0 and having
        #  nova effectively ignore that size and use the size of the
        #  image is considered a feature at this time, not a bug.

        if size is None:
            return

        if size and not base_size:
            base_size = self.get_disk_size(base)

        if size < base_size:
            msg = _LE('%(base)s virtual size %(base_size)s '
                      'larger than flavor root disk size %(size)s')
            LOG.error(msg % {
                'base': base,
                'base_size': base_size,
                'size': size
            })
            raise exception.FlavorDiskSmallerThanImage(flavor_size=size,
                                                       image_size=base_size)
Пример #2
0
def fetch_to_raw(context, image_href, path, max_size=0):
    path_tmp = "%s.part" % path
    fetch(context, image_href, path_tmp, max_size=max_size)

    with fileutils.remove_path_on_error(path_tmp):
        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:
            LOG.error(_LE('%(base)s virtual size %(disk_size)s '
                          'larger than flavor root disk size %(size)s'),
                      {'base': path,
                       'disk_size': disk_size,
                       'size': max_size})
            raise exception.FlavorDiskSmallerThanImage(
                flavor_size=max_size, image_size=disk_size)

        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):
                try:
                    convert_image(path_tmp, staged, fmt, 'raw')
                except exception.ImageUnacceptable as exp:
                    # re-raise to include image_href
                    raise exception.ImageUnacceptable(image_id=image_href,
                        reason=_("Unable to convert image to raw: %(exp)s")
                        % {'exp': exp})

                os.unlink(path_tmp)

                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)

                os.rename(staged, path)
        else:
            os.rename(path_tmp, path)
Пример #3
0
 def _is_resize_needed(self, vhd_path, old_size, new_size, instance):
     if new_size < old_size:
         raise exception.FlavorDiskSmallerThanImage(
             flavor_size=new_size, image_size=old_size)
     elif new_size > old_size:
         LOG.debug("Resizing VHD %(vhd_path)s to new "
                   "size %(new_size)s" %
                   {'new_size': new_size,
                    'vhd_path': vhd_path},
                   instance=instance)
         return True
     return False
Пример #4
0
    def _resize_and_cache_vhd(self, instance, vhd_path):
        vhd_size = self._vhdutils.get_vhd_size(vhd_path)['VirtualSize']

        root_vhd_size_gb = self._get_root_vhd_size_gb(instance)
        root_vhd_size = root_vhd_size_gb * units.Gi

        root_vhd_internal_size = (
            self._vhdutils.get_internal_vhd_size_by_file_size(
                vhd_path, root_vhd_size))

        if root_vhd_internal_size < vhd_size:
            raise exception.FlavorDiskSmallerThanImage(
                flavor_size=root_vhd_size, image_size=vhd_size)
        if root_vhd_internal_size > vhd_size:
            path_parts = os.path.splitext(vhd_path)
            resized_vhd_path = '%s_%s%s' % (path_parts[0], root_vhd_size_gb,
                                            path_parts[1])

            lock_path = os.path.dirname(resized_vhd_path)
            lock_name = "%s-cache.lock" % os.path.basename(resized_vhd_path)

            @utils.synchronized(name=lock_name,
                                external=True,
                                lock_path=lock_path)
            def copy_and_resize_vhd():
                if not self._pathutils.exists(resized_vhd_path):
                    try:
                        LOG.debug(
                            "Copying VHD %(vhd_path)s to "
                            "%(resized_vhd_path)s", {
                                'vhd_path': vhd_path,
                                'resized_vhd_path': resized_vhd_path
                            })
                        self._pathutils.copyfile(vhd_path, resized_vhd_path)
                        LOG.debug(
                            "Resizing VHD %(resized_vhd_path)s to new "
                            "size %(root_vhd_size)s", {
                                'resized_vhd_path': resized_vhd_path,
                                'root_vhd_size': root_vhd_size
                            })
                        self._vhdutils.resize_vhd(resized_vhd_path,
                                                  root_vhd_internal_size,
                                                  is_file_max_size=False)
                    except Exception:
                        with excutils.save_and_reraise_exception():
                            if self._pathutils.exists(resized_vhd_path):
                                self._pathutils.remove(resized_vhd_path)

            copy_and_resize_vhd()
            return resized_vhd_path
Пример #5
0
    def _verify_rescue_image(self, instance, rescue_image_id,
                             rescue_image_path):
        rescue_image_info = self._vhdutils.get_vhd_info(rescue_image_path)
        rescue_image_size = rescue_image_info['VirtualSize']
        flavor_disk_size = instance.root_gb * units.Gi

        if rescue_image_size > flavor_disk_size:
            err_msg = _('Using a rescue image bigger than the instance '
                        'flavor disk size is not allowed. '
                        'Rescue image size: %(rescue_image_size)s. '
                        'Flavor disk size:%(flavor_disk_size)s. '
                        'Rescue image id %(rescue_image_id)s.')
            raise exception.FlavorDiskSmallerThanImage(err_msg %
                {'rescue_image_size': rescue_image_size,
                 'flavor_disk_size': flavor_disk_size,
                 'rescue_image_id': rescue_image_id})