Merge "Allow empty volumes to be created"
This commit is contained in:
commit
d003a85520
@ -186,6 +186,9 @@ class BlockDeviceDict(dict):
|
||||
if source_type not in ('volume', 'image', 'snapshot', 'blank'):
|
||||
raise exception.InvalidBDMFormat(
|
||||
details=_("Invalid source_type field."))
|
||||
elif source_type == 'blank' and device_uuid:
|
||||
raise exception.InvalidBDMFormat(
|
||||
details=_("Invalid device UUID."))
|
||||
elif source_type != 'blank':
|
||||
if not device_uuid:
|
||||
raise exception.InvalidBDMFormat(
|
||||
@ -411,8 +414,9 @@ def new_format_is_swap(bdm):
|
||||
|
||||
|
||||
def new_format_is_ephemeral(bdm):
|
||||
if (bdm.get('source_type') == 'blank' and not
|
||||
new_format_is_swap(bdm)):
|
||||
if (bdm.get('source_type') == 'blank' and
|
||||
bdm.get('destination_type') == 'local' and
|
||||
bdm.get('guest_format') != 'swap'):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -1694,8 +1694,9 @@ class ComputeManager(manager.Manager):
|
||||
root_bdm.save()
|
||||
|
||||
def _is_mapping(bdm):
|
||||
return (bdm.source_type in ('image', 'volume', 'snapshot') and
|
||||
driver_block_device.is_implemented(bdm))
|
||||
return (bdm.source_type in ('image', 'volume', 'snapshot', 'blank')
|
||||
and bdm.destination_type == 'volume'
|
||||
and driver_block_device.is_implemented(bdm))
|
||||
|
||||
ephemerals = filter(block_device.new_format_is_ephemeral,
|
||||
block_devices)
|
||||
@ -1731,6 +1732,11 @@ class ComputeManager(manager.Manager):
|
||||
driver_block_device.convert_images(bdms),
|
||||
context, instance, self.volume_api,
|
||||
self.driver, self._await_block_device_map_created,
|
||||
do_check_attach=do_check_attach) +
|
||||
driver_block_device.attach_block_devices(
|
||||
driver_block_device.convert_blanks(bdms),
|
||||
context, instance, self.volume_api,
|
||||
self.driver, self._await_block_device_map_created,
|
||||
do_check_attach=do_check_attach))
|
||||
}
|
||||
|
||||
|
@ -1094,6 +1094,80 @@ class ComputeVolumeTestCase(BaseTestCase):
|
||||
self.context, instance, bdms)
|
||||
self.assertTrue(mock_create.called)
|
||||
|
||||
@mock.patch.object(nova.virt.block_device, 'get_swap')
|
||||
@mock.patch.object(nova.virt.block_device, 'convert_blanks')
|
||||
@mock.patch.object(nova.virt.block_device, 'convert_images')
|
||||
@mock.patch.object(nova.virt.block_device, 'convert_snapshots')
|
||||
@mock.patch.object(nova.virt.block_device, 'convert_volumes')
|
||||
@mock.patch.object(nova.virt.block_device, 'convert_ephemerals')
|
||||
@mock.patch.object(nova.virt.block_device, 'convert_swap')
|
||||
@mock.patch.object(nova.virt.block_device, 'attach_block_devices')
|
||||
def test_prep_block_device_with_blanks(self, attach_block_devices,
|
||||
convert_swap, convert_ephemerals,
|
||||
convert_volumes, convert_snapshots,
|
||||
convert_images, convert_blanks,
|
||||
get_swap):
|
||||
instance = self._create_fake_instance()
|
||||
instance['root_device_name'] = '/dev/vda'
|
||||
root_volume = objects.BlockDeviceMapping(
|
||||
**fake_block_device.FakeDbBlockDeviceDict({
|
||||
'instance_uuid': 'fake-instance',
|
||||
'source_type': 'image',
|
||||
'destination_type': 'volume',
|
||||
'image_id': 'fake-image-id-1',
|
||||
'volume_size': 1,
|
||||
'boot_index': 0}))
|
||||
blank_volume1 = objects.BlockDeviceMapping(
|
||||
**fake_block_device.FakeDbBlockDeviceDict({
|
||||
'instance_uuid': 'fake-instance',
|
||||
'source_type': 'blank',
|
||||
'destination_type': 'volume',
|
||||
'volume_size': 1,
|
||||
'boot_index': 1}))
|
||||
blank_volume2 = objects.BlockDeviceMapping(
|
||||
**fake_block_device.FakeDbBlockDeviceDict({
|
||||
'instance_uuid': 'fake-instance',
|
||||
'source_type': 'blank',
|
||||
'destination_type': 'volume',
|
||||
'volume_size': 1,
|
||||
'boot_index': 2}))
|
||||
bdms = [blank_volume1, blank_volume2, root_volume]
|
||||
|
||||
def fake_attach_block_devices(bdm, *args, **kwargs):
|
||||
return bdm
|
||||
|
||||
convert_swap.return_value = []
|
||||
convert_ephemerals.return_value = []
|
||||
convert_volumes.return_value = [blank_volume1, blank_volume2]
|
||||
convert_snapshots.return_value = []
|
||||
convert_images.return_value = [root_volume]
|
||||
convert_blanks.return_value = []
|
||||
attach_block_devices.side_effect = fake_attach_block_devices
|
||||
get_swap.return_value = []
|
||||
|
||||
expected_block_device_info = {
|
||||
'root_device_name': '/dev/vda',
|
||||
'swap': [],
|
||||
'ephemerals': [],
|
||||
'block_device_mapping': bdms
|
||||
}
|
||||
|
||||
manager = compute_manager.ComputeManager()
|
||||
manager.use_legacy_block_device_info = False
|
||||
block_device_info = manager._prep_block_device(self.context, instance,
|
||||
bdms)
|
||||
|
||||
convert_swap.assert_called_once_with(bdms)
|
||||
convert_ephemerals.assert_called_once_with(bdms)
|
||||
convert_volumes.assert_called_once_with(bdms)
|
||||
convert_snapshots.assert_called_once_with(bdms)
|
||||
convert_images.assert_called_once_with(bdms)
|
||||
convert_blanks.assert_called_once_with(bdms)
|
||||
|
||||
self.assertEqual(expected_block_device_info, block_device_info)
|
||||
self.assertEqual(4, attach_block_devices.call_count)
|
||||
get_swap.assert_called_once_with([])
|
||||
|
||||
|
||||
class ComputeTestCase(BaseTestCase):
|
||||
def test_wrap_instance_fault(self):
|
||||
@ -6800,6 +6874,64 @@ class ComputeTestCase(BaseTestCase):
|
||||
instance,
|
||||
{}, bdms)
|
||||
|
||||
def test_default_block_device_names_with_blank_volumes(self):
|
||||
instance = self._create_fake_instance()
|
||||
image_meta = {}
|
||||
root_volume = objects.BlockDeviceMapping(
|
||||
**fake_block_device.FakeDbBlockDeviceDict({
|
||||
'id': 1, 'instance_uuid': 'fake-instance',
|
||||
'source_type': 'volume',
|
||||
'destination_type': 'volume',
|
||||
'image_id': 'fake-image-id-1',
|
||||
'boot_index': 0}))
|
||||
blank_volume1 = objects.BlockDeviceMapping(
|
||||
**fake_block_device.FakeDbBlockDeviceDict({
|
||||
'id': 2, 'instance_uuid': 'fake-instance',
|
||||
'source_type': 'blank',
|
||||
'destination_type': 'volume',
|
||||
'boot_index': -1}))
|
||||
blank_volume2 = objects.BlockDeviceMapping(
|
||||
**fake_block_device.FakeDbBlockDeviceDict({
|
||||
'id': 3, 'instance_uuid': 'fake-instance',
|
||||
'source_type': 'blank',
|
||||
'destination_type': 'volume',
|
||||
'boot_index': -1}))
|
||||
ephemeral = objects.BlockDeviceMapping(
|
||||
**fake_block_device.FakeDbBlockDeviceDict({
|
||||
'id': 4, 'instance_uuid': 'fake-instance',
|
||||
'source_type': 'blank',
|
||||
'destination_type': 'local'}))
|
||||
swap = objects.BlockDeviceMapping(
|
||||
**fake_block_device.FakeDbBlockDeviceDict({
|
||||
'id': 5, 'instance_uuid': 'fake-instance',
|
||||
'source_type': 'blank',
|
||||
'destination_type': 'local',
|
||||
'guest_format': 'swap'
|
||||
}))
|
||||
bdms = block_device_obj.block_device_make_list(
|
||||
self.context, [root_volume, blank_volume1, blank_volume2,
|
||||
ephemeral, swap])
|
||||
|
||||
with contextlib.nested(
|
||||
mock.patch.object(self.compute, '_default_root_device_name',
|
||||
return_value='/dev/vda'),
|
||||
mock.patch.object(self.compute, '_instance_update'),
|
||||
mock.patch.object(objects.BlockDeviceMapping, 'save'),
|
||||
mock.patch.object(self.compute,
|
||||
'_default_device_names_for_instance')
|
||||
) as (default_root_device, instance_update, object_save,
|
||||
default_device_names):
|
||||
self.compute._default_block_device_names(self.context, instance,
|
||||
image_meta, bdms)
|
||||
default_root_device.assert_called_once_with(instance, image_meta,
|
||||
bdms[0])
|
||||
instance_update.assert_called_once_with(
|
||||
self.context, instance['uuid'], root_device_name='/dev/vda')
|
||||
self.assertTrue(object_save.called)
|
||||
default_device_names.assert_called_once_with(instance,
|
||||
'/dev/vda', [bdms[-2]], [bdms[-1]],
|
||||
[bdm for bdm in bdms[:-2]])
|
||||
|
||||
def test_reserve_block_device_name(self):
|
||||
instance = self._create_fake_instance_obj(
|
||||
params={'root_device_name': '/dev/vda'})
|
||||
|
@ -279,6 +279,12 @@ class DefaultDeviceNamesForInstanceTestCase(test.NoDBTestCase):
|
||||
'source_type': 'snapshot',
|
||||
'destination_type': 'volume',
|
||||
'snapshot_id': 'fake-snapshot-id-1',
|
||||
'boot_index': -1}),
|
||||
fake_block_device.FakeDbBlockDeviceDict(
|
||||
{'id': 5, 'instance_uuid': 'fake-instance',
|
||||
'device_name': '/dev/vde',
|
||||
'source_type': 'blank',
|
||||
'destination_type': 'volume',
|
||||
'boot_index': -1})])
|
||||
self.flavor = {'swap': 4}
|
||||
self.instance = {'uuid': 'fake_instance', 'ephemeral_gb': 2}
|
||||
@ -326,11 +332,14 @@ class DefaultDeviceNamesForInstanceTestCase(test.NoDBTestCase):
|
||||
for original, new in zip(original_bdm, self.block_device_mapping):
|
||||
self.assertEqual(original.device_name, new.device_name)
|
||||
|
||||
# Asser it defaults the missing one as expected
|
||||
# Assert it defaults the missing one as expected
|
||||
self.block_device_mapping[1]['device_name'] = None
|
||||
self.block_device_mapping[2]['device_name'] = None
|
||||
self._test_default_device_names([], [], self.block_device_mapping)
|
||||
self.assertEqual(self.block_device_mapping[1]['device_name'],
|
||||
'/dev/vdb')
|
||||
self.assertEqual('/dev/vdb',
|
||||
self.block_device_mapping[1]['device_name'])
|
||||
self.assertEqual('/dev/vdc',
|
||||
self.block_device_mapping[2]['device_name'])
|
||||
|
||||
def test_with_ephemerals(self):
|
||||
# Test ephemeral gets assigned
|
||||
@ -340,10 +349,13 @@ class DefaultDeviceNamesForInstanceTestCase(test.NoDBTestCase):
|
||||
self.assertEqual(self.ephemerals[0]['device_name'], '/dev/vdb')
|
||||
|
||||
self.block_device_mapping[1]['device_name'] = None
|
||||
self.block_device_mapping[2]['device_name'] = None
|
||||
self._test_default_device_names(self.ephemerals, [],
|
||||
self.block_device_mapping)
|
||||
self.assertEqual(self.block_device_mapping[1]['device_name'],
|
||||
'/dev/vdc')
|
||||
self.assertEqual('/dev/vdc',
|
||||
self.block_device_mapping[1]['device_name'])
|
||||
self.assertEqual('/dev/vdd',
|
||||
self.block_device_mapping[2]['device_name'])
|
||||
|
||||
def test_with_swap(self):
|
||||
# Test swap only
|
||||
@ -354,11 +366,14 @@ class DefaultDeviceNamesForInstanceTestCase(test.NoDBTestCase):
|
||||
# Test swap and block_device_mapping
|
||||
self.swap[0]['device_name'] = None
|
||||
self.block_device_mapping[1]['device_name'] = None
|
||||
self.block_device_mapping[2]['device_name'] = None
|
||||
self._test_default_device_names([], self.swap,
|
||||
self.block_device_mapping)
|
||||
self.assertEqual(self.swap[0]['device_name'], '/dev/vdb')
|
||||
self.assertEqual(self.block_device_mapping[1]['device_name'],
|
||||
'/dev/vdc')
|
||||
self.assertEqual('/dev/vdc',
|
||||
self.block_device_mapping[1]['device_name'])
|
||||
self.assertEqual('/dev/vdd',
|
||||
self.block_device_mapping[2]['device_name'])
|
||||
|
||||
def test_all_together(self):
|
||||
# Test swap missing
|
||||
@ -379,12 +394,15 @@ class DefaultDeviceNamesForInstanceTestCase(test.NoDBTestCase):
|
||||
self.swap[0]['device_name'] = None
|
||||
self.ephemerals[0]['device_name'] = None
|
||||
self.block_device_mapping[1]['device_name'] = None
|
||||
self.block_device_mapping[2]['device_name'] = None
|
||||
self._test_default_device_names(self.ephemerals,
|
||||
self.swap, self.block_device_mapping)
|
||||
self.assertEqual(self.ephemerals[0]['device_name'], '/dev/vdb')
|
||||
self.assertEqual(self.swap[0]['device_name'], '/dev/vdc')
|
||||
self.assertEqual(self.block_device_mapping[1]['device_name'],
|
||||
'/dev/vdd')
|
||||
self.assertEqual('/dev/vdd',
|
||||
self.block_device_mapping[1]['device_name'])
|
||||
self.assertEqual('/dev/vde',
|
||||
self.block_device_mapping[2]['device_name'])
|
||||
|
||||
|
||||
class UsageInfoTestCase(test.TestCase):
|
||||
|
@ -524,6 +524,16 @@ class TestBlockDeviceDict(test.NoDBTestCase):
|
||||
block_device.BlockDeviceDict.from_api(api),
|
||||
matchers.IsSubDictOf(new))
|
||||
|
||||
def test_from_api_invalid_blank_id(self):
|
||||
api_dict = {'id': 1,
|
||||
'source_type': 'blank',
|
||||
'destination_type': 'volume',
|
||||
'uuid': 'fake-volume-id-1',
|
||||
'delete_on_termination': True,
|
||||
'boot_index': -1}
|
||||
self.assertRaises(exception.InvalidBDMFormat,
|
||||
block_device.BlockDeviceDict.from_api, api_dict)
|
||||
|
||||
def test_legacy(self):
|
||||
for legacy, new in zip(self.legacy_mapping, self.new_mapping):
|
||||
self.assertThat(
|
||||
|
@ -893,6 +893,15 @@ class DefaultDeviceNamesTestCase(test.TestCase):
|
||||
'disk_bus': 'virtio',
|
||||
'destination_type': 'volume',
|
||||
'snapshot_id': 'fake-snapshot-id-1',
|
||||
'boot_index': -1})),
|
||||
objects.BlockDeviceMapping(self.context,
|
||||
**fake_block_device.FakeDbBlockDeviceDict(
|
||||
{'id': 5, 'instance_uuid': 'fake-instance',
|
||||
'device_name': '/dev/vde',
|
||||
'source_type': 'blank',
|
||||
'device_type': 'disk',
|
||||
'disk_bus': 'virtio',
|
||||
'destination_type': 'volume',
|
||||
'boot_index': -1}))]
|
||||
|
||||
def tearDown(self):
|
||||
@ -915,11 +924,14 @@ class DefaultDeviceNamesTestCase(test.TestCase):
|
||||
original_bdm, self.block_device_mapping):
|
||||
self.assertEqual(original.device_name, defaulted.device_name)
|
||||
|
||||
# Asser it defaults the missing one as expected
|
||||
# Assert it defaults the missing one as expected
|
||||
self.block_device_mapping[1]['device_name'] = None
|
||||
self.block_device_mapping[2]['device_name'] = None
|
||||
self._test_default_device_names([], [], self.block_device_mapping)
|
||||
self.assertEqual('/dev/vdd',
|
||||
self.block_device_mapping[1]['device_name'])
|
||||
self.assertEqual('/dev/vde',
|
||||
self.block_device_mapping[2]['device_name'])
|
||||
|
||||
def test_with_ephemerals(self):
|
||||
# Test ephemeral gets assigned
|
||||
@ -929,10 +941,13 @@ class DefaultDeviceNamesTestCase(test.TestCase):
|
||||
self.assertEqual('/dev/vdb', self.ephemerals[0]['device_name'])
|
||||
|
||||
self.block_device_mapping[1]['device_name'] = None
|
||||
self.block_device_mapping[2]['device_name'] = None
|
||||
self._test_default_device_names(self.ephemerals, [],
|
||||
self.block_device_mapping)
|
||||
self.assertEqual('/dev/vdd',
|
||||
self.block_device_mapping[1]['device_name'])
|
||||
self.assertEqual('/dev/vde',
|
||||
self.block_device_mapping[2]['device_name'])
|
||||
|
||||
def test_with_swap(self):
|
||||
# Test swap only
|
||||
@ -943,11 +958,14 @@ class DefaultDeviceNamesTestCase(test.TestCase):
|
||||
# Test swap and block_device_mapping
|
||||
self.swap[0]['device_name'] = None
|
||||
self.block_device_mapping[1]['device_name'] = None
|
||||
self.block_device_mapping[2]['device_name'] = None
|
||||
self._test_default_device_names([], self.swap,
|
||||
self.block_device_mapping)
|
||||
self.assertEqual('/dev/vdc', self.swap[0]['device_name'])
|
||||
self.assertEqual('/dev/vdd',
|
||||
self.block_device_mapping[1]['device_name'])
|
||||
self.assertEqual('/dev/vde',
|
||||
self.block_device_mapping[2]['device_name'])
|
||||
|
||||
def test_all_together(self):
|
||||
# Test swap missing
|
||||
@ -968,9 +986,12 @@ class DefaultDeviceNamesTestCase(test.TestCase):
|
||||
self.swap[0]['device_name'] = None
|
||||
self.ephemerals[0]['device_name'] = None
|
||||
self.block_device_mapping[1]['device_name'] = None
|
||||
self.block_device_mapping[2]['device_name'] = None
|
||||
self._test_default_device_names(self.ephemerals,
|
||||
self.swap, self.block_device_mapping)
|
||||
self.assertEqual('/dev/vdb', self.ephemerals[0]['device_name'])
|
||||
self.assertEqual('/dev/vdc', self.swap[0]['device_name'])
|
||||
self.assertEqual('/dev/vdd',
|
||||
self.block_device_mapping[1]['device_name'])
|
||||
self.assertEqual('/dev/vde',
|
||||
self.block_device_mapping[2]['device_name'])
|
||||
|
@ -12,12 +12,15 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import contextlib
|
||||
|
||||
import mock
|
||||
|
||||
from nova import block_device
|
||||
from nova import context
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova import test
|
||||
from nova.tests import fake_instance
|
||||
from nova.tests import matchers
|
||||
from nova.virt import block_device as driver_block_device
|
||||
from nova.virt import driver
|
||||
@ -31,7 +34,8 @@ class TestDriverBlockDevice(test.NoDBTestCase):
|
||||
'ephemeral': driver_block_device.DriverEphemeralBlockDevice,
|
||||
'volume': driver_block_device.DriverVolumeBlockDevice,
|
||||
'snapshot': driver_block_device.DriverSnapshotBlockDevice,
|
||||
'image': driver_block_device.DriverImageBlockDevice
|
||||
'image': driver_block_device.DriverImageBlockDevice,
|
||||
'blank': driver_block_device.DriverBlankBlockDevice
|
||||
}
|
||||
|
||||
swap_bdm = block_device.BlockDeviceDict(
|
||||
@ -163,6 +167,34 @@ class TestDriverBlockDevice(test.NoDBTestCase):
|
||||
'connection_info': {"fake": "connection_info"},
|
||||
'delete_on_termination': True}
|
||||
|
||||
blank_bdm = block_device.BlockDeviceDict(
|
||||
{'id': 6, 'instance_uuid': 'fake-instance',
|
||||
'device_name': '/dev/sda2',
|
||||
'delete_on_termination': True,
|
||||
'volume_size': 3,
|
||||
'disk_bus': 'scsi',
|
||||
'device_type': 'disk',
|
||||
'source_type': 'blank',
|
||||
'destination_type': 'volume',
|
||||
'connection_info': '{"fake": "connection_info"}',
|
||||
'snapshot_id': 'fake-snapshot-id-1',
|
||||
'volume_id': 'fake-volume-id-2',
|
||||
'boot_index': -1})
|
||||
|
||||
blank_driver_bdm = {
|
||||
'mount_device': '/dev/sda2',
|
||||
'connection_info': {"fake": "connection_info"},
|
||||
'delete_on_termination': True,
|
||||
'disk_bus': 'scsi',
|
||||
'device_type': 'disk',
|
||||
'guest_format': None,
|
||||
'boot_index': -1}
|
||||
|
||||
blank_legacy_driver_bdm = {
|
||||
'mount_device': '/dev/sda2',
|
||||
'connection_info': {"fake": "connection_info"},
|
||||
'delete_on_termination': True}
|
||||
|
||||
def setUp(self):
|
||||
super(TestDriverBlockDevice, self).setUp()
|
||||
self.volume_api = self.mox.CreateMock(cinder.API)
|
||||
@ -275,6 +307,15 @@ class TestDriverBlockDevice(test.NoDBTestCase):
|
||||
self.assertRaises(driver_block_device._InvalidType,
|
||||
self.driver_classes['image'], bdm)
|
||||
|
||||
def test_driver_blank_block_device(self):
|
||||
self._test_driver_device('blank')
|
||||
|
||||
test_bdm = self.driver_classes['blank'](
|
||||
self.blank_bdm)
|
||||
self.assertEqual(6, test_bdm._bdm_obj.id)
|
||||
self.assertEqual('fake-volume-id-2', test_bdm.volume_id)
|
||||
self.assertEqual(3, test_bdm.volume_size)
|
||||
|
||||
def _test_volume_attach(self, driver_bdm, bdm_dict,
|
||||
fake_volume, check_attach=True,
|
||||
fail_check_attach=False, driver_attach=False,
|
||||
@ -546,6 +587,33 @@ class TestDriverBlockDevice(test.NoDBTestCase):
|
||||
self.virt_driver)
|
||||
self.assertEqual(test_bdm.volume_id, 'fake-volume-id-2')
|
||||
|
||||
def test_blank_attach_volume(self):
|
||||
no_blank_volume = self.blank_bdm.copy()
|
||||
no_blank_volume['volume_id'] = None
|
||||
test_bdm = self.driver_classes['blank'](no_blank_volume)
|
||||
instance = fake_instance.fake_instance_obj(mock.sentinel.ctx,
|
||||
**{'uuid': 'fake-uuid'})
|
||||
volume_class = self.driver_classes['volume']
|
||||
volume = {'id': 'fake-volume-id-2',
|
||||
'display_name': 'fake-uuid-blank-vol'}
|
||||
|
||||
with contextlib.nested(
|
||||
mock.patch.object(self.volume_api, 'create', return_value=volume),
|
||||
mock.patch.object(volume_class, 'attach')
|
||||
) as (vol_create, vol_attach):
|
||||
test_bdm.attach(self.context, instance, self.volume_api,
|
||||
self.virt_driver)
|
||||
|
||||
vol_create.assert_called_once_with(self.context,
|
||||
test_bdm.volume_size,
|
||||
'fake-uuid-blank-vol',
|
||||
'')
|
||||
vol_attach.assert_called_once_with(self.context, instance,
|
||||
self.volume_api,
|
||||
self.virt_driver,
|
||||
do_check_attach=True)
|
||||
self.assertEqual('fake-volume-id-2', test_bdm.volume_id)
|
||||
|
||||
def test_convert_block_devices(self):
|
||||
converted = driver_block_device._convert_block_devices(
|
||||
self.driver_classes['volume'],
|
||||
|
@ -324,6 +324,26 @@ class DriverImageBlockDevice(DriverVolumeBlockDevice):
|
||||
do_check_attach=do_check_attach)
|
||||
|
||||
|
||||
class DriverBlankBlockDevice(DriverVolumeBlockDevice):
|
||||
|
||||
_valid_source = 'blank'
|
||||
_proxy_as_attr = set(['volume_size', 'volume_id', 'image_id'])
|
||||
|
||||
def attach(self, context, instance, volume_api,
|
||||
virt_driver, wait_func=None, do_check_attach=True):
|
||||
if not self.volume_id:
|
||||
vol_name = instance.uuid + '-blank-vol'
|
||||
vol = volume_api.create(context, self.volume_size, vol_name, '')
|
||||
if wait_func:
|
||||
wait_func(context, vol['id'])
|
||||
|
||||
self.volume_id = vol['id']
|
||||
|
||||
super(DriverBlankBlockDevice, self).attach(
|
||||
context, instance, volume_api, virt_driver,
|
||||
do_check_attach=do_check_attach)
|
||||
|
||||
|
||||
def _convert_block_devices(device_type, block_device_mapping):
|
||||
def _is_transformable(bdm):
|
||||
try:
|
||||
@ -355,6 +375,9 @@ convert_snapshots = functools.partial(_convert_block_devices,
|
||||
convert_images = functools.partial(_convert_block_devices,
|
||||
DriverImageBlockDevice)
|
||||
|
||||
convert_blanks = functools.partial(_convert_block_devices,
|
||||
DriverBlankBlockDevice)
|
||||
|
||||
|
||||
def attach_block_devices(block_device_mapping, *attach_args, **attach_kwargs):
|
||||
def _log_and_attach(bdm):
|
||||
@ -417,7 +440,7 @@ def get_swap(transformed_list):
|
||||
|
||||
_IMPLEMENTED_CLASSES = (DriverSwapBlockDevice, DriverEphemeralBlockDevice,
|
||||
DriverVolumeBlockDevice, DriverSnapshotBlockDevice,
|
||||
DriverImageBlockDevice)
|
||||
DriverImageBlockDevice, DriverBlankBlockDevice)
|
||||
|
||||
|
||||
def is_implemented(bdm):
|
||||
|
@ -442,6 +442,8 @@ def default_device_names(virt_type, context, instance, root_device_name,
|
||||
driver_block_device.convert_volumes(
|
||||
block_device_mapping) +
|
||||
driver_block_device.convert_snapshots(
|
||||
block_device_mapping) +
|
||||
driver_block_device.convert_blanks(
|
||||
block_device_mapping))
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user