block_device: Copy original volume_type when missing for snapshot based volumes
Attempts to launch an instance from an encrypted volume snapshot would previously fail if a volume_type was not specified in the block_device_mapping of the boot request. To avoid such failures DriverVolSnapshotBlockDevice will now attempt to lookup and use the volume_type of the original volume that the snapshot is based on. This should allow the eventual volume creation request based on the snapshot to succeed in cases where a volume_type is required but not provided in the boot request. Closes-Bug: #1853495 Change-Id: Ic749c49e227e41732dbe04acea303b303acd264a
This commit is contained in:
parent
1cd5563f2d
commit
5679a0bf99
|
@ -1019,6 +1019,37 @@ class TestDriverBlockDevice(test.NoDBTestCase):
|
|||
mock_get_snapshot.assert_not_called()
|
||||
mock_create.assert_not_called()
|
||||
|
||||
def test_snapshot_attach_no_volume_and_no_volume_type(self):
|
||||
bdm = self.driver_classes['volsnapshot'](self.volsnapshot_bdm)
|
||||
instance = fake_instance.fake_instance_obj(self.context,
|
||||
**{'uuid': uuids.uuid})
|
||||
snapshot = {'volume_id': uuids.original_volume_id}
|
||||
original_volume = {'id': uuids.original_volume_id,
|
||||
'volume_type_id': 'original_volume_type'}
|
||||
new_volume = {'id': uuids.new_volume_id}
|
||||
with test.nested(
|
||||
mock.patch.object(self.driver_classes['volume'], 'attach'),
|
||||
mock.patch.object(self.volume_api, 'get_snapshot',
|
||||
return_value=snapshot),
|
||||
mock.patch.object(self.volume_api, 'get',
|
||||
return_value=original_volume),
|
||||
mock.patch.object(self.volume_api, 'create',
|
||||
return_value=new_volume),
|
||||
) as (mock_attach, mock_get_snapshot, mock_get, mock_create):
|
||||
bdm.volume_id = None
|
||||
bdm.volume_type = None
|
||||
bdm.attach(self.context, instance, self.volume_api,
|
||||
self.virt_driver)
|
||||
|
||||
# Assert that the original volume type is fetched, stored within
|
||||
# the bdm and then used to create the new snapshot based volume.
|
||||
mock_get.assert_called_once_with(self.context,
|
||||
uuids.original_volume_id)
|
||||
self.assertEqual('original_volume_type', bdm.volume_type)
|
||||
mock_create.assert_called_once_with(self.context, bdm.volume_size,
|
||||
'', '', volume_type='original_volume_type', snapshot=snapshot,
|
||||
availability_zone=None)
|
||||
|
||||
def test_image_attach_no_volume(self):
|
||||
no_volume_image = self.volimage_bdm_dict.copy()
|
||||
no_volume_image['volume_id'] = None
|
||||
|
|
|
@ -742,6 +742,13 @@ class DriverVolSnapshotBlockDevice(DriverVolumeBlockDevice):
|
|||
if not self.volume_id:
|
||||
snapshot = volume_api.get_snapshot(context,
|
||||
self.snapshot_id)
|
||||
# NOTE(lyarwood): Try to use the original volume type if one isn't
|
||||
# set against the bdm but is on the original volume.
|
||||
if not self.volume_type and snapshot.get('volume_id'):
|
||||
snap_volume_id = snapshot.get('volume_id')
|
||||
orig_volume = volume_api.get(context, snap_volume_id)
|
||||
self.volume_type = orig_volume.get('volume_type_id')
|
||||
|
||||
self.volume_id, self.attachment_id = self._create_volume(
|
||||
context, instance, volume_api, self.volume_size,
|
||||
wait_func=wait_func, snapshot=snapshot)
|
||||
|
|
Loading…
Reference in New Issue