summaryrefslogtreecommitdiff
path: root/nova/virt/libvirt/imagebackend.py
diff options
context:
space:
mode:
Diffstat (limited to 'nova/virt/libvirt/imagebackend.py')
-rw-r--r--nova/virt/libvirt/imagebackend.py111
1 files changed, 81 insertions, 30 deletions
diff --git a/nova/virt/libvirt/imagebackend.py b/nova/virt/libvirt/imagebackend.py
index 08bad69489..0a64ef43dd 100644
--- a/nova/virt/libvirt/imagebackend.py
+++ b/nova/virt/libvirt/imagebackend.py
@@ -81,14 +81,24 @@ def _update_utime_ignore_eacces(path):
class Image(metaclass=abc.ABCMeta):
SUPPORTS_CLONE = False
-
- def __init__(self, path, source_type, driver_format, is_block_dev=False):
+ SUPPORTS_LUKS = False
+
+ def __init__(
+ self,
+ path,
+ source_type,
+ driver_format,
+ is_block_dev=False,
+ disk_info_mapping=None
+ ):
"""Image initialization.
:param path: libvirt's representation of the path of this disk.
:param source_type: block or file
:param driver_format: raw or qcow2
:param is_block_dev:
+ :param disk_info_mapping: disk_info['mapping'][device] metadata
+ specific to this image generated by nova.virt.libvirt.blockinfo.
"""
if (CONF.ephemeral_storage_encryption.enabled and
not self._supports_encryption()):
@@ -105,6 +115,8 @@ class Image(metaclass=abc.ABCMeta):
self.is_block_dev = is_block_dev
self.preallocate = False
+ self.disk_info_mapping = disk_info_mapping
+
# NOTE(dripton): We store lines of json (path, disk_format) in this
# file, for some image types, to prevent attacks based on changing the
# disk_format.
@@ -145,22 +157,23 @@ class Image(metaclass=abc.ABCMeta):
pass
def libvirt_info(
- self, disk_info, cache_mode, extra_specs, boot_order=None,
- disk_unit=None,
+ self, cache_mode, extra_specs, boot_order=None, disk_unit=None,
):
"""Get `LibvirtConfigGuestDisk` filled for this image.
- :disk_info: Metadata generated by libvirt.blockinfo.get_disk_mapping
:cache_mode: Caching mode for this image
:extra_specs: Instance type extra specs dict.
:boot_order: Disk device boot order
"""
- disk_bus = disk_info['bus']
+ if self.disk_info_mapping is None:
+ raise AttributeError(
+ 'Image must have disk_info_mapping to call libvirt_info()')
+ disk_bus = self.disk_info_mapping['bus']
info = vconfig.LibvirtConfigGuestDisk()
info.source_type = self.source_type
- info.source_device = disk_info['type']
+ info.source_device = self.disk_info_mapping['type']
info.target_bus = disk_bus
- info.target_dev = disk_info['dev']
+ info.target_dev = self.disk_info_mapping['dev']
info.driver_cache = cache_mode
info.driver_discard = self.discard_mode
info.driver_io = self.driver_io
@@ -522,11 +535,16 @@ class Flat(Image):
when creating a disk from a qcow2 if force_raw_images is not set in config.
"""
- def __init__(self, instance=None, disk_name=None, path=None):
+ def __init__(
+ self, instance=None, disk_name=None, path=None, disk_info_mapping=None
+ ):
self.disk_name = disk_name
path = (path or os.path.join(libvirt_utils.get_instance_path(instance),
disk_name))
- super(Flat, self).__init__(path, "file", "raw", is_block_dev=False)
+ super().__init__(
+ path, "file", "raw", is_block_dev=False,
+ disk_info_mapping=disk_info_mapping
+ )
self.preallocate = (
strutils.to_slug(CONF.preallocate_images) == 'space')
@@ -568,15 +586,21 @@ class Flat(Image):
def copy_raw_image(base, target, size):
libvirt_utils.copy_image(base, target)
if size:
- image = imgmodel.LocalFileImage(target,
- self.driver_format)
- disk.extend(image, size)
+ self.resize_image(size)
generating = 'image_id' not in kwargs
if generating:
if not self.exists():
# Generating image in place
prepare_template(target=self.path, *args, **kwargs)
+
+ # NOTE(plibeau): extend the disk in the case of image is not
+ # accessible anymore by the customer and the base image is
+ # available on source compute during the resize of the
+ # instance.
+ else:
+ if size:
+ self.resize_image(size)
else:
if not os.path.exists(base):
prepare_template(target=base, *args, **kwargs)
@@ -608,10 +632,15 @@ class Flat(Image):
class Qcow2(Image):
- def __init__(self, instance=None, disk_name=None, path=None):
+ def __init__(
+ self, instance=None, disk_name=None, path=None, disk_info_mapping=None
+ ):
path = (path or os.path.join(libvirt_utils.get_instance_path(instance),
disk_name))
- super(Qcow2, self).__init__(path, "file", "qcow2", is_block_dev=False)
+ super().__init__(
+ path, "file", "qcow2", is_block_dev=False,
+ disk_info_mapping=disk_info_mapping
+ )
self.preallocate = (
strutils.to_slug(CONF.preallocate_images) == 'space')
@@ -625,7 +654,8 @@ class Qcow2(Image):
@utils.synchronized(filename, external=True, lock_path=self.lock_path)
def create_qcow2_image(base, target, size):
- libvirt_utils.create_cow_image(base, target, size)
+ libvirt_utils.create_image(
+ target, 'qcow2', size, backing_file=base)
# Download the unmodified base image unless we already have a copy.
if not os.path.exists(base):
@@ -689,7 +719,10 @@ class Lvm(Image):
def escape(filename):
return filename.replace('_', '__')
- def __init__(self, instance=None, disk_name=None, path=None):
+ def __init__(
+ self, instance=None, disk_name=None, path=None,
+ disk_info_mapping=None
+ ):
self.ephemeral_key_uuid = instance.get('ephemeral_key_uuid')
if self.ephemeral_key_uuid is not None:
@@ -718,7 +751,10 @@ class Lvm(Image):
self.lv_path = os.path.join('/dev', self.vg, self.lv)
path = '/dev/mapper/' + dmcrypt.volume_name(self.lv)
- super(Lvm, self).__init__(path, "block", "raw", is_block_dev=True)
+ super(Lvm, self).__init__(
+ path, "block", "raw", is_block_dev=True,
+ disk_info_mapping=disk_info_mapping
+ )
# TODO(sbauza): Remove the config option usage and default the
# LVM logical volume creation to preallocate the full size only.
@@ -826,7 +862,9 @@ class Rbd(Image):
SUPPORTS_CLONE = True
- def __init__(self, instance=None, disk_name=None, path=None):
+ def __init__(
+ self, instance=None, disk_name=None, path=None, disk_info_mapping=None
+ ):
if not CONF.libvirt.images_rbd_pool:
raise RuntimeError(_('You should specify'
' images_rbd_pool'
@@ -848,31 +886,32 @@ class Rbd(Image):
if self.driver.ceph_conf:
path += ':conf=' + self.driver.ceph_conf
- super(Rbd, self).__init__(path, "block", "rbd", is_block_dev=False)
+ super().__init__(
+ path, "block", "rbd", is_block_dev=False,
+ disk_info_mapping=disk_info_mapping
+ )
self.discard_mode = CONF.libvirt.hw_disk_discard
def libvirt_info(
- self, disk_info, cache_mode, extra_specs, boot_order=None,
- disk_unit=None,
+ self, cache_mode, extra_specs, boot_order=None, disk_unit=None
):
"""Get `LibvirtConfigGuestDisk` filled for this image.
- :disk_info: Metadata generated by libvirt.blockinfo.get_disk_mapping
:cache_mode: Caching mode for this image
:extra_specs: Instance type extra specs dict.
:boot_order: Disk device boot order
"""
info = vconfig.LibvirtConfigGuestDisk()
- disk_bus = disk_info['bus']
+ disk_bus = self.disk_info_mapping['bus']
hosts, ports = self.driver.get_mon_addrs()
- info.source_device = disk_info['type']
+ info.source_device = self.disk_info_mapping['type']
info.driver_format = 'raw'
info.driver_cache = cache_mode
info.driver_discard = self.discard_mode
info.target_bus = disk_bus
- info.target_dev = disk_info['dev']
+ info.target_dev = self.disk_info_mapping['dev']
info.source_type = 'network'
info.source_protocol = 'rbd'
info.source_name = '%s/%s' % (self.driver.pool, self.rbd_name)
@@ -1189,10 +1228,15 @@ class Rbd(Image):
class Ploop(Image):
- def __init__(self, instance=None, disk_name=None, path=None):
+ def __init__(
+ self, instance=None, disk_name=None, path=None, disk_info_mapping=None
+ ):
path = (path or os.path.join(libvirt_utils.get_instance_path(instance),
disk_name))
- super(Ploop, self).__init__(path, "file", "ploop", is_block_dev=False)
+ super().__init__(
+ path, "file", "ploop", is_block_dev=False,
+ disk_info_mapping=disk_info_mapping
+ )
self.resolve_driver_format()
@@ -1295,18 +1339,25 @@ class Backend(object):
raise RuntimeError(_('Unknown image_type=%s') % image_type)
return image
- def by_name(self, instance, name, image_type=None):
+ def by_name(self, instance, name, image_type=None, disk_info_mapping=None):
"""Return an Image object for a disk with the given name.
:param instance: the instance which owns this disk
:param name: The name of the disk
:param image_type: (Optional) Image type.
Default is CONF.libvirt.images_type.
+ :param disk_info_mapping: (Optional) Disk info mapping dict
:return: An Image object for the disk with given name and instance.
:rtype: Image
"""
+ # NOTE(artom) To pass functional tests, wherein the code here is loaded
+ # *before* any config with self.flags() is done, we need to have the
+ # default inline in the method, and not in the kwarg declaration.
+ image_type = image_type or CONF.libvirt.images_type
backend = self.backend(image_type)
- return backend(instance=instance, disk_name=name)
+ return backend(
+ instance=instance, disk_name=name,
+ disk_info_mapping=disk_info_mapping)
def by_libvirt_path(self, instance, path, image_type=None):
"""Return an Image object for a disk with the given libvirt path.