Boot from image destination - volume

Added class DriverImageBlockDevice that implements
creating volume from image on booting VM
from image if destination_type is volume.

Adding converting to legacy if source is image and
destination is a volume.

Change-Id: I8b8a7a2e40c083c18c4808b6b340360138086c1f
blueprint: improve-block-device-handling
This commit is contained in:
Yulia Portnova
2013-08-07 14:58:33 +03:00
committed by Nikola Dipanov
parent dc2a196642
commit 09532a6f02
5 changed files with 186 additions and 25 deletions

View File

@@ -116,8 +116,17 @@ class DriverVolumeBlockDevice(DriverBlockDevice):
'disk_bus', 'boot_index'])
_fields = _legacy_fields | _new_fields
_valid_source = 'volume'
_valid_destination = 'volume'
# Override in subclasses if volume should be created from
# another source.
_source_id_field = None
def _transform(self, bdm):
if not bdm.get('source_type') == 'volume':
if not bdm.get('source_type') == self._valid_source\
or not bdm.get('destination_type') == \
self._valid_destination:
raise _InvalidType
# NOTE (ndipanov): Save it as an attribute as we will
@@ -125,6 +134,9 @@ class DriverVolumeBlockDevice(DriverBlockDevice):
self.volume_size = bdm.get('volume_size')
self.volume_id = bdm.get('volume_id')
if self._source_id_field:
setattr(self, self._source_id_field,
bdm.get(self._source_id_field, None))
self.update(
dict((k, v) for k, v in bdm.iteritems()
if k in self._new_fields | set(['delete_on_termination']))
@@ -187,26 +199,9 @@ class DriverVolumeBlockDevice(DriverBlockDevice):
class DriverSnapshotBlockDevice(DriverVolumeBlockDevice):
def _transform(self, bdm):
if not bdm.get('source_type') == 'snapshot':
raise _InvalidType
# NOTE (ndipanov): Save these as attributes as we will
# need them for attach()
self.volume_size = bdm.get('volume_size')
self.snapshot_id = bdm.get('snapshot_id')
self.volume_id = bdm.get('volume_id')
self.update(
dict((k, v) for k, v in bdm.iteritems()
if k in self._new_fields | set(['delete_on_termination']))
)
self['mount_device'] = bdm.get('device_name')
try:
self['connection_info'] = jsonutils.loads(
bdm.get('connection_info'))
except TypeError:
self['connection_info'] = None
_valid_source = 'snapshot'
_source_id_field = 'snapshot_id'
def attach(self, context, instance, volume_api, virt_driver,
db_api=None, wait_func=None):
@@ -229,6 +224,28 @@ class DriverSnapshotBlockDevice(DriverVolumeBlockDevice):
db_api)
class DriverImageBlockDevice(DriverVolumeBlockDevice):
_valid_source = 'image'
_source_id_field = 'image_id'
def attach(self, context, instance, volume_api, virt_driver,
db_api=None, wait_func=None):
if not self.volume_id:
vol = volume_api.create(context, self.volume_size,
'', '', image_id=self.image_id)
if wait_func:
wait_func(context, vol['id'])
if db_api:
db_api.block_device_mapping_update(context, self.id,
{'volume_id': vol['id']})
self.volume_id = vol['id']
super(DriverImageBlockDevice, self).attach(context, instance,
volume_api, virt_driver,
db_api)
def _convert_block_devices(device_type, block_device_mapping):
def _is_transformable(bdm):
try:
@@ -257,6 +274,9 @@ convert_volumes = functools.partial(_convert_block_devices,
convert_snapshots = functools.partial(_convert_block_devices,
DriverSnapshotBlockDevice)
convert_images = functools.partial(_convert_block_devices,
DriverImageBlockDevice)
def attach_block_devices(block_device_mapping, *attach_args, **attach_kwargs):
map(operator.methodcaller('attach', *attach_args, **attach_kwargs),