block_device: Add DriverImageBlockDevice to block_device_info

Change-Id: I17e0758e3b77caebd4d142664a8367ab4601ebdf
This commit is contained in:
Lee Yarwood 2022-01-26 17:51:27 +00:00 committed by melanie witt
parent 794d2f98d9
commit 5df97016b4
9 changed files with 241 additions and 83 deletions

View File

@ -71,6 +71,8 @@ called ``block_device_info``, and is generated by
``root_device_name``
Hypervisor's notion of the root device's name
``image``
An image backed disk if used
``ephemerals``
A list of all ephemeral disks
``block_device_mapping``
@ -105,13 +107,6 @@ persist data to the BDM object in the DB.
In other contexts this filtering will not have happened, and
``block_device_mapping`` will contain all volumes.
.. note::
Unlike BDMs, ``block_device_info`` does not currently represent all
disks that an instance might have. Significantly, it will not contain any
representation of an image-backed local disk, i.e. the root disk of a
typical instance which isn't boot-from-volume. Other representations used
by the libvirt driver explicitly reconstruct this missing disk.
libvirt driver specific BDM data structures
===========================================

View File

@ -2025,6 +2025,7 @@ class ComputeManager(manager.Manager):
ephemerals = []
swap = []
block_device_mapping = []
image = []
for device in block_devices:
if block_device.new_format_is_ephemeral(device):
@ -2036,8 +2037,12 @@ class ComputeManager(manager.Manager):
if driver_block_device.is_block_device_mapping(device):
block_device_mapping.append(device)
if driver_block_device.is_local_image(device):
image.append(device)
self._default_device_names_for_instance(instance,
root_device_name,
image,
ephemerals,
swap,
block_device_mapping)

View File

@ -1389,13 +1389,14 @@ class ComputeVolumeTestCase(BaseTestCase):
@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_local_images')
@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):
convert_swap, convert_local_images,
convert_ephemerals, convert_volumes,
convert_snapshots, convert_images,
convert_blanks, get_swap):
instance = self._create_fake_instance_obj()
instance['root_device_name'] = '/dev/vda'
root_volume = objects.BlockDeviceMapping(
@ -1426,6 +1427,7 @@ class ComputeVolumeTestCase(BaseTestCase):
return bdm
convert_swap.return_value = []
convert_local_images.return_value = []
convert_ephemerals.return_value = []
convert_volumes.return_value = [blank_volume1, blank_volume2]
convert_snapshots.return_value = []
@ -1438,6 +1440,7 @@ class ComputeVolumeTestCase(BaseTestCase):
'root_device_name': '/dev/vda',
'swap': [],
'ephemerals': [],
'image': [],
'block_device_mapping': bdms
}
@ -1452,6 +1455,7 @@ class ComputeVolumeTestCase(BaseTestCase):
self.assertIsNotNone(bdm.device_name)
convert_swap.assert_called_once_with(bdms)
convert_local_images.assert_called_once_with(bdms)
convert_ephemerals.assert_called_once_with(bdms)
bdm_args = tuple(bdms)
convert_volumes.assert_called_once_with(bdm_args)
@ -3212,6 +3216,7 @@ class ComputeTestCase(BaseTestCase,
expected = {
'swap': None,
'ephemerals': [],
'image': [],
'root_device_name': None,
'block_device_mapping': driver_bdms
}
@ -3240,6 +3245,7 @@ class ComputeTestCase(BaseTestCase,
expected = {
'swap': None,
'ephemerals': [],
'image': [],
'root_device_name': None,
'block_device_mapping': driver_bdms
}
@ -3318,6 +3324,7 @@ class ComputeTestCase(BaseTestCase,
'size': 2
}
],
'image': [],
'block_device_mapping': [],
'root_device_name': None
}
@ -6108,7 +6115,7 @@ class ComputeTestCase(BaseTestCase,
mock_pre.assert_called_once_with(
test.MatchType(nova.context.RequestContext),
test.MatchType(objects.Instance),
{'swap': None, 'ephemerals': [],
{'swap': None, 'ephemerals': [], 'image': [],
'root_device_name': None,
'block_device_mapping': []},
mock.ANY, mock.ANY, mock.ANY)
@ -6474,7 +6481,7 @@ class ComputeTestCase(BaseTestCase,
self.assertEqual(2, mock_notify.call_count)
post_live_migration.assert_has_calls([
mock.call(c, instance, {'swap': None, 'ephemerals': [],
'root_device_name': None,
'image': [], 'root_device_name': None,
'block_device_mapping': []},
migrate_data)])
migrate_instance_start.assert_has_calls([
@ -6705,7 +6712,7 @@ class ComputeTestCase(BaseTestCase,
mock_setup.assert_called_once_with(c, instance, self.compute.host,
teardown=True)
mock_rollback.assert_called_once_with(c, instance, [],
{'swap': None, 'ephemerals': [],
{'swap': None, 'ephemerals': [], 'image': [],
'root_device_name': None,
'block_device_mapping': []},
destroy_disks=True, migrate_data=None)
@ -8134,7 +8141,7 @@ class ComputeTestCase(BaseTestCase,
self.compute._default_block_device_names(instance, {}, bdms)
self.assertEqual('/dev/vda', instance.root_device_name)
mock_def.assert_called_once_with(instance, '/dev/vda', [], [],
mock_def.assert_called_once_with(instance, '/dev/vda', [], [], [],
[bdm for bdm in bdms])
@mock.patch.object(objects.BlockDeviceMapping, 'save')
@ -8148,7 +8155,7 @@ class ComputeTestCase(BaseTestCase,
self.compute._default_block_device_names(instance, {}, bdms)
mock_def.assert_called_once_with(instance, '/dev/vda', [], [],
mock_def.assert_called_once_with(instance, '/dev/vda', [], [], [],
[bdm for bdm in bdms])
@mock.patch.object(objects.Instance, 'save')
@ -8170,7 +8177,7 @@ class ComputeTestCase(BaseTestCase,
self.assertEqual('/dev/vda', instance.root_device_name)
mock_default_dev.assert_called_once_with(instance, mock.ANY, bdms[0])
mock_default_name.assert_called_once_with(instance, '/dev/vda', [], [],
[bdm for bdm in bdms])
[], [bdm for bdm in bdms])
def test_default_block_device_names_with_blank_volumes(self):
instance = self._create_fake_instance_obj()
@ -8230,7 +8237,7 @@ class ComputeTestCase(BaseTestCase,
self.assertEqual('/dev/vda', instance.root_device_name)
self.assertTrue(object_save.called)
default_device_names.assert_called_once_with(instance,
'/dev/vda', [bdms[-2]], [bdms[-1]],
'/dev/vda', [], [bdms[-2]], [bdms[-1]],
[bdm for bdm in bdms[:-2]])
def test_reserve_block_device_name(self):

View File

@ -74,6 +74,7 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
def _test_block_device_info(self, with_eph=True, with_swap=True,
with_bdms=True):
swap = {'device_name': '/dev/vdb', 'swap_size': 1}
image = [{'device_type': 'disk', 'boot_index': 0}]
ephemerals = [{'device_type': 'disk', 'guest_format': 'ext4',
'device_name': '/dev/vdc1', 'size': 10},
{'disk_bus': 'ide', 'guest_format': None,
@ -84,6 +85,7 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
'device_path': 'fake_device'}]
return {'root_device_name': '/dev/vda',
'swap': swap if with_swap else {},
'image': image,
'ephemerals': ephemerals if with_eph else [],
'block_device_mapping':
block_device_mapping if with_bdms else []}
@ -178,11 +180,16 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
instance_ref = objects.Instance(**self.test_instance)
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
block_device_info = {
'image': [
{'device_type': 'disk', 'boot_index': 0},
]
}
with mock.patch.object(instance_ref, 'get_flavor',
return_value=instance_ref.flavor) as get_flavor:
mapping = blockinfo.get_disk_mapping("kvm", instance_ref,
"virtio", "ide",
image_meta)
mapping = blockinfo.get_disk_mapping(
"kvm", instance_ref, "virtio", "ide", image_meta,
block_device_info=block_device_info)
# Since there was no block_device_info passed to get_disk_mapping we
# expect to get the swap info from the flavor in the instance.
get_flavor.assert_called_once_with()
@ -202,7 +209,8 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
instance_ref = objects.Instance(**self.test_instance)
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
block_device_info = {
'root_device_name': '/dev/sda'
'root_device_name': '/dev/sda',
'image': [{'device_type': 'disk', 'boot_index': 0}],
}
mapping = blockinfo.get_disk_mapping("kvm", instance_ref,
@ -490,9 +498,12 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
instance_ref = objects.Instance(**self.test_instance)
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
mapping = blockinfo.get_disk_mapping("lxc", instance_ref,
"lxc", "lxc",
image_meta)
block_device_info = {
'image': [{'device_type': 'disk', 'boot_index': 0}],
}
mapping = blockinfo.get_disk_mapping(
"lxc", instance_ref, "lxc", "lxc", image_meta,
block_device_info=block_device_info)
expect = {
'disk': {'bus': 'lxc', 'dev': None,
'type': 'disk', 'boot_index': '1'},
@ -527,9 +538,14 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
instance_ref.flavor.swap = 5
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
mapping = blockinfo.get_disk_mapping("kvm", instance_ref,
"virtio", "ide",
image_meta)
block_device_info = {
'image': [
{'device_type': 'disk', 'boot_index': 0},
]
}
mapping = blockinfo.get_disk_mapping(
"kvm", instance_ref, "virtio", "ide", image_meta,
block_device_info=block_device_info)
expect = {
'disk': {'bus': 'virtio', 'dev': 'vda',
@ -549,6 +565,7 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
instance_ref.ephemeral_gb = 0
block_dev_info = {'swap': None, 'root_device_name': u'/dev/vda',
'image': [],
'ephemerals': [],
'block_device_mapping': [{'boot_index': None,
'mount_device': u'/dev/vdb',
@ -591,8 +608,14 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
instance_ref = objects.Instance(**self.test_instance)
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
block_device_info = {
'image': [
{'device_type': 'disk', 'boot_index': 0},
]
}
mapping = blockinfo.get_disk_mapping(
"kvm", instance_ref, "virtio", "ide", image_meta)
"kvm", instance_ref, "virtio", "ide", image_meta,
block_device_info=block_device_info)
# Pick the first drive letter on the bus that is available
# as the config drive. Delete the last device hardcode as
@ -647,8 +670,14 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
instance_ref = objects.Instance(**self.test_instance)
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
block_device_info = {
'image': [
{'device_type': 'disk', 'boot_index': 0},
]
}
mapping = blockinfo.get_disk_mapping(
"kvm", instance_ref, "virtio", "ide", image_meta)
"kvm", instance_ref, "virtio", "ide", image_meta,
block_device_info=block_device_info)
expect = {
'disk': {
@ -697,9 +726,14 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
instance_ref = objects.Instance(**self.test_instance)
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
mapping = blockinfo.get_disk_mapping("kvm", instance_ref,
"virtio", "ide",
image_meta)
block_device_info = {
'image': [
{'device_type': 'disk', 'boot_index': 0},
]
}
mapping = blockinfo.get_disk_mapping(
"kvm", instance_ref, "virtio", "ide", image_meta,
block_device_info=block_device_info)
expect = {
'disk': {'bus': 'virtio', 'dev': 'vda',
@ -718,6 +752,9 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
block_device_info = {
'image': [
{'device_type': 'disk', 'boot_index': 0},
],
'ephemerals': [
{'device_type': 'disk', 'guest_format': 'ext4',
'device_name': '/dev/vdb', 'size': 10},
@ -754,6 +791,8 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
block_device_info = {
'swap': {'device_name': '/dev/vdb',
'swap_size': 10},
'image': [{'device_type': 'disk',
'boot_index': 0}],
}
mapping = blockinfo.get_disk_mapping("kvm", instance_ref,
"virtio", "ide",
@ -775,6 +814,7 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
block_device_info = {
'image': [],
'block_device_mapping': [
{'connection_info': "fake",
'mount_device': "/dev/vda",
@ -803,6 +843,7 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
image_meta = {}
block_device_info = {
'image': [],
'block_device_mapping': [
{'connection_info': None,
'mount_device': None,
@ -858,6 +899,7 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
block_device_info = {
'image': [],
'block_device_mapping': [
{'connection_info': "fake",
'mount_device': "/dev/vda",
@ -899,6 +941,7 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
'root_device_name': '/dev/vdf',
'swap': {'device_name': '/dev/vdy',
'swap_size': 10},
'image': [{'device_type': 'disk', 'boot_index': 0}],
'ephemerals': [
{'device_type': 'disk', 'guest_format': 'ext4',
'device_name': '/dev/vdb', 'size': 10},
@ -940,6 +983,8 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
'swap': {'device_name': '/dev/vdb',
'device_type': 'really_lame_type',
'swap_size': 10},
'image': [{'device_name': '/dev/vda',
'device_type': 'disk'}],
'ephemerals': [{'disk_bus': 'no_such_bus',
'device_type': 'yeah_right',
'device_name': '/dev/vdc', 'size': 10}],
@ -951,6 +996,8 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
}
expected_swap = {'device_name': '/dev/vdb', 'disk_bus': 'virtio',
'device_type': 'disk', 'swap_size': 10}
expected_image = {'device_name': '/dev/vda', 'device_type': 'disk',
'disk_bus': 'virtio'}
expected_ephemeral = {'disk_bus': 'virtio',
'device_type': 'disk',
'device_name': '/dev/vdc', 'size': 10}
@ -970,6 +1017,7 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
self.assertFalse(get_flavor_mock.called)
self.assertEqual(expected_swap, block_device_info['swap'])
self.assertEqual(expected_image, block_device_info['image'][0])
self.assertEqual(expected_ephemeral,
block_device_info['ephemerals'][0])
self.assertEqual(expected_bdm,
@ -1441,6 +1489,15 @@ class DefaultDeviceNamesTestCase(test.NoDBTestCase):
'destination_type': 'volume',
'boot_index': -1}))]
self.image = [
objects.BlockDeviceMapping(self.context,
**fake_block_device.FakeDbBlockDeviceDict(
{'id': 6, 'instance_uuid': uuids.instance,
'source_type': 'image',
'destination_type': 'local',
'device_type': 'disk',
'boot_index': 0}))]
def tearDown(self):
super(DefaultDeviceNamesTestCase, self).tearDown()
for patcher in self.patchers:
@ -1450,7 +1507,7 @@ class DefaultDeviceNamesTestCase(test.NoDBTestCase):
'nova.virt.libvirt.utils.get_arch',
return_value=obj_fields.Architecture.X86_64)
def _test_default_device_names(self, eph, swap, bdm, mock_get_arch):
bdms = eph + swap + bdm
bdms = self.image + eph + swap + bdm
bdi = driver.get_block_device_info(self.instance, bdms)
blockinfo.default_device_names(self.virt_type,
self.context,

View File

@ -20410,7 +20410,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
**fake_block_device.FakeDbBlockDeviceDict(
{'id': 0,
'source_type': 'volume', 'destination_type': 'volume',
'device_name': '/dev/sda'}))
'device_name': '/dev/sda', 'boot_index': 0}))
info = {'block_device_mapping': driver_block_device.convert_volumes(
[bdm])}
info['block_device_mapping'][0]['connection_info'] = conn_info
@ -24941,7 +24941,8 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
'id': 1,
'source_type': 'volume',
'destination_type': 'volume',
'device_name': '/dev/vda'}))
'device_name': '/dev/vda',
'boot_index': 0}))
bdms = driver_block_device.convert_volumes([bdm])
block_device_info = {'root_device_name': '/dev/vda',
'ephemerals': [],

View File

@ -49,7 +49,8 @@ class TestDriverBlockDevice(test.NoDBTestCase):
'volume': driver_block_device.DriverVolumeBlockDevice,
'volsnapshot': driver_block_device.DriverVolSnapshotBlockDevice,
'volimage': driver_block_device.DriverVolImageBlockDevice,
'volblank': driver_block_device.DriverVolBlankBlockDevice
'volblank': driver_block_device.DriverVolBlankBlockDevice,
'image': driver_block_device.DriverImageBlockDevice,
}
swap_bdm_dict = block_device.BlockDeviceDict(
@ -210,6 +211,27 @@ class TestDriverBlockDevice(test.NoDBTestCase):
'boot_index': -1,
'volume_type': None}
image_bdm_dict = block_device.BlockDeviceDict(
{'id': 7, 'instance_uuid': uuids.instance,
'device_name': '/dev/vda',
'source_type': 'image',
'destination_type': 'local',
'disk_bus': 'virtio',
'device_type': 'disk',
'guest_format': 'ext4',
'boot_index': 0,
'image_id': 'fake-image-id-1',
'volume_size': 5})
image_driver_bdm = {
'device_name': '/dev/vda',
'device_type': 'disk',
'guest_format': 'ext4',
'disk_bus': 'virtio',
'boot_index': 0,
'image_id': 'fake-image-id-1',
'size': 5}
def setUp(self):
super(TestDriverBlockDevice, self).setUp()
self.volume_api = mock.MagicMock(autospec=cinder.API)
@ -219,6 +241,8 @@ class TestDriverBlockDevice(test.NoDBTestCase):
# create bdm objects for testing
self.swap_bdm = fake_block_device.fake_bdm_object(
self.context, self.swap_bdm_dict)
self.image_bdm = fake_block_device.fake_bdm_object(
self.context, self.image_bdm_dict)
self.ephemeral_bdm = fake_block_device.fake_bdm_object(
self.context, self.ephemeral_bdm_dict)
self.volume_bdm = fake_block_device.fake_bdm_object(
@ -337,6 +361,10 @@ class TestDriverBlockDevice(test.NoDBTestCase):
if field == 'attachment_id':
# Must set UUID values on UUID fields.
fake_value = ATTACHMENT_ID
elif isinstance(test_bdm._bdm_obj.fields[fld],
fields.UUIDField):
# Generically handle other UUID fields.
fake_value = uuids.fake_value
else:
fake_value = 'fake_changed_value'
test_bdm[field] = fake_value
@ -377,6 +405,20 @@ class TestDriverBlockDevice(test.NoDBTestCase):
def test_driver_swap_default_size(self):
self._test_driver_default_size('swap')
def test_driver_image_block_device(self):
self._test_driver_device("image")
def test_driver_image_default_size(self):
self._test_driver_default_size('image')
def test_driver_image_block_device_destination_not_local(self):
self._test_driver_device('image')
bdm = self.image_bdm_dict.copy()
bdm['destination_type'] = 'volume'
self.assertRaises(driver_block_device._InvalidType,
self.driver_classes['image'],
fake_block_device.fake_bdm_object(self.context, bdm))
def test_driver_ephemeral_block_device(self):
self._test_driver_device("ephemeral")
@ -406,7 +448,7 @@ class TestDriverBlockDevice(test.NoDBTestCase):
self.assertEqual(test_bdm.volume_size, 3)
self.assertEqual('fake-snapshot-id-1', test_bdm.get('snapshot_id'))
def test_driver_image_block_device(self):
def test_driver_volume_image_block_device(self):
self._test_driver_device('volimage')
test_bdm = self.driver_classes['volimage'](
@ -416,7 +458,7 @@ class TestDriverBlockDevice(test.NoDBTestCase):
self.assertEqual(test_bdm.volume_size, 1)
self.assertEqual('fake-image-id-1', test_bdm.get('image_id'))
def test_driver_image_block_device_destination_local(self):
def test_driver_volume_image_block_device_destination_local(self):
self._test_driver_device('volimage')
bdm = self.volimage_bdm_dict.copy()
bdm['destination_type'] = 'local'
@ -1263,12 +1305,8 @@ class TestDriverBlockDevice(test.NoDBTestCase):
def test_is_implemented(self):
for bdm in (self.volimage_bdm, self.volume_bdm, self.swap_bdm,
self.ephemeral_bdm, self.volsnapshot_bdm):
self.ephemeral_bdm, self.volsnapshot_bdm, self.image_bdm):
self.assertTrue(driver_block_device.is_implemented(bdm))
local_image = self.volimage_bdm_dict.copy()
local_image['destination_type'] = 'local'
self.assertFalse(driver_block_device.is_implemented(
fake_block_device.fake_bdm_object(self.context, local_image)))
def test_is_block_device_mapping(self):
test_swap = self.driver_classes['swap'](self.swap_bdm)

View File

@ -227,6 +227,36 @@ class DriverSwapBlockDevice(DriverBlockDevice):
})
class DriverImageBlockDevice(DriverBlockDevice):
_valid_source = 'image'
_proxy_as_attr_inherited = set(['image_id'])
_new_only_fields = set([
'disk_bus',
'device_type',
'guest_format',
'boot_index',
])
_fields = set([
'device_name',
'size']) | _new_only_fields
_legacy_fields = (
_fields - _new_only_fields | set(['num', 'virtual_name']))
def _transform(self):
if (not self._bdm_obj.get('source_type') == 'image' or
not self._bdm_obj.get('destination_type') == 'local'):
raise _InvalidType
self.update({
'device_name': self._bdm_obj.device_name,
'size': self._bdm_obj.volume_size or 0,
'disk_bus': self._bdm_obj.disk_bus,
'device_type': self._bdm_obj.device_type,
'guest_format': self._bdm_obj.guest_format,
'image_id': self._bdm_obj.image_id,
'boot_index': 0,
})
class DriverEphemeralBlockDevice(DriverBlockDevice):
_new_only_fields = set(['disk_bus', 'device_type', 'guest_format'])
_fields = set(['device_name', 'size']) | _new_only_fields
@ -802,15 +832,15 @@ def _convert_block_devices(device_type, block_device_mapping):
convert_swap = functools.partial(_convert_block_devices,
DriverSwapBlockDevice)
convert_local_images = functools.partial(_convert_block_devices,
DriverImageBlockDevice)
convert_ephemerals = functools.partial(_convert_block_devices,
DriverEphemeralBlockDevice)
convert_volumes = functools.partial(_convert_block_devices,
DriverVolumeBlockDevice)
convert_snapshots = functools.partial(_convert_block_devices,
DriverVolSnapshotBlockDevice)
@ -897,9 +927,15 @@ def get_swap(transformed_list):
return None
_IMPLEMENTED_CLASSES = (DriverSwapBlockDevice, DriverEphemeralBlockDevice,
DriverVolumeBlockDevice, DriverVolSnapshotBlockDevice,
DriverVolImageBlockDevice, DriverVolBlankBlockDevice)
_IMPLEMENTED_CLASSES = (
DriverSwapBlockDevice,
DriverEphemeralBlockDevice,
DriverVolumeBlockDevice,
DriverVolSnapshotBlockDevice,
DriverVolImageBlockDevice,
DriverVolBlankBlockDevice,
DriverImageBlockDevice
)
def is_implemented(bdm):
@ -912,6 +948,10 @@ def is_implemented(bdm):
return False
def is_local_image(bdm):
return bdm.source_type == 'image' and bdm.destination_type == 'local'
def is_block_device_mapping(bdm):
return (bdm.source_type in ('image', 'volume', 'snapshot', 'blank') and
bdm.destination_type == 'volume' and

View File

@ -44,6 +44,7 @@ def get_block_device_info(instance, block_device_mapping):
of a dict containing the following keys:
- root_device_name: device name of the root disk
- image: An instance of DriverImageBlockDevice or None
- ephemerals: a (potentially empty) list of DriverEphemeralBlockDevice
instances
- swap: An instance of DriverSwapBlockDevice or None
@ -54,6 +55,8 @@ def get_block_device_info(instance, block_device_mapping):
from nova.virt import block_device as virt_block_device
return {
'root_device_name': instance.root_device_name,
'image': virt_block_device.convert_local_images(
block_device_mapping),
'ephemerals': virt_block_device.convert_ephemerals(
block_device_mapping),
'block_device_mapping':
@ -79,6 +82,14 @@ def swap_is_usable(swap):
return swap and swap['device_name'] and swap['swap_size'] > 0
def block_device_info_get_image(block_device_info):
block_device_info = block_device_info or {}
# get_disk_mapping() supports block_device_info=None and thus requires that
# we return a list here.
image = block_device_info.get('image') or []
return image
def block_device_info_get_ephemerals(block_device_info):
block_device_info = block_device_info or {}
ephemerals = block_device_info.get('ephemerals') or []

View File

@ -414,13 +414,7 @@ def get_device_name(bdm):
def get_root_info(instance, virt_type, image_meta, root_bdm,
disk_bus, cdrom_bus, root_device_name=None):
# NOTE (ndipanov): This is a hack to avoid considering an image
# BDM with local target, as we don't support them
# yet. Only applies when passed non-driver format
no_root_bdm = (not root_bdm or (
root_bdm.get('source_type') == 'image' and
root_bdm.get('destination_type') == 'local'))
if no_root_bdm:
if root_bdm is None:
# NOTE(mriedem): In case the image_meta object was constructed from
# an empty dict, like in the case of evacuate, we have to first check
# if disk_format is set on the ImageMeta object.
@ -452,10 +446,13 @@ def default_device_names(virt_type, context, instance, block_device_info,
image_meta):
get_disk_info(virt_type, instance, image_meta, block_device_info)
for driver_bdm in itertools.chain(block_device_info['ephemerals'],
[block_device_info['swap']] if
block_device_info['swap'] else [],
block_device_info['block_device_mapping']):
for driver_bdm in itertools.chain(
block_device_info['image'],
block_device_info['ephemerals'],
[block_device_info['swap']] if
block_device_info['swap'] else [],
block_device_info['block_device_mapping']
):
driver_bdm.save()
@ -563,41 +560,48 @@ def _get_disk_mapping(virt_type, instance, disk_bus, cdrom_bus, image_meta,
:returns: Disk mapping for the given instance.
"""
mapping = {}
pre_assigned_device_names = \
[block_device.strip_dev(get_device_name(bdm)) for bdm in itertools.chain(
driver_bdms = itertools.chain(
driver.block_device_info_get_image(block_device_info),
driver.block_device_info_get_ephemerals(block_device_info),
[driver.block_device_info_get_swap(block_device_info)],
driver.block_device_info_get_mapping(block_device_info))
if get_device_name(bdm)]
driver.block_device_info_get_mapping(block_device_info)
)
# NOTE (ndipanov): root_bdm can be None when we boot from image
# as there is no driver representation of local targeted images
# and they will not be in block_device_info list.
root_bdm = block_device.get_root_bdm(
driver.block_device_info_get_mapping(block_device_info))
pre_assigned_device_names = [
block_device.strip_dev(get_device_name(bdm))
for bdm in driver_bdms if get_device_name(bdm)
]
# Try to find the root driver bdm, either an image based disk or volume
root_bdm = None
if any(driver.block_device_info_get_image(block_device_info)):
root_bdm = driver.block_device_info_get_image(block_device_info)[0]
elif driver.block_device_info_get_mapping(block_device_info):
root_bdm = block_device.get_root_bdm(
driver.block_device_info_get_mapping(block_device_info))
root_device_name = block_device.strip_dev(
driver.block_device_info_get_root_device(block_device_info))
root_info = get_root_info(
instance, virt_type, image_meta, root_bdm,
disk_bus, cdrom_bus, root_device_name)
mapping['root'] = root_info
# NOTE (ndipanov): This implicitly relies on image->local BDMs not
# being considered in the driver layer - so missing
# bdm with boot_index 0 means - use image, unless it was
# overridden. This can happen when using legacy syntax and
# no root_device_name is set on the instance.
if not root_bdm and not block_device.volume_in_mapping(root_info['dev'],
block_device_info):
mapping['disk'] = root_info
elif root_bdm:
# NOTE (ft): If device name is not set in root bdm, root_info has a
# generated one. We have to copy device name to root bdm to prevent its
# second generation in loop through bdms. If device name is already
# set, nothing is changed.
# NOTE (ft): If device name is not set in root bdm, root_info has a
# generated one. We have to copy device name to root bdm to prevent its
# second generation in loop through bdms. If device name is already
# set, nothing is changed.
# NOTE(melwitt): root_bdm can be None in the case of a ISO root device, for
# example.
if root_bdm:
update_bdm(root_bdm, root_info)
if (
driver.block_device_info_get_image(block_device_info) or
root_bdm is None
):
mapping['disk'] = root_info
default_eph = get_default_ephemeral_info(instance, disk_bus,
block_device_info, mapping)
if default_eph: