virt: add get_device_name_for_instance to the base driver class

Just as libvirt needs to decide on the device names when booting an
instance (as opposed to them being assigned by the user), the same needs
to be done when attaching additional volumes to a running instance.

This patch exposes it on the ComputeDriver base class and makes sure
that it will be called by the compute manager (and that an appropriate
fallback will happen if the drivers do not care about overriding this),
as a pre-req for doing the work in the libvirt driver.

Partial-bug: 1452224
Related-bug: 1231874

Change-Id: I66693a8a6a632b65f930a58905336397ac6c9f29
This commit is contained in:
Nikola Dipanov 2015-05-05 16:14:46 +01:00
parent 74197aaa3f
commit b6733dbdf3
4 changed files with 46 additions and 9 deletions

View File

@ -1648,6 +1648,16 @@ class ComputeManager(manager.Manager):
compute_utils.default_device_names_for_instance(
instance, root_device_name, *block_device_lists)
def _get_device_name_for_instance(self, instance, bdms, block_device_obj):
# NOTE(ndipanov): Copy obj to avoid changing the original
block_device_obj = block_device_obj.obj_clone()
try:
return self.driver.get_device_name_for_instance(
instance, bdms, block_device_obj)
except NotImplementedError:
return compute_utils.get_device_name_for_instance(
instance, bdms, block_device_obj.get("device_name"))
def _default_block_device_names(self, context, instance,
image_meta, block_devices):
"""Verify that all the devices have the device_name set. If not,
@ -4378,20 +4388,22 @@ class ComputeManager(manager.Manager):
objects.BlockDeviceMappingList.get_by_instance_uuid(
context, instance.uuid))
device_name = compute_utils.get_device_name_for_instance(
instance, bdms, device)
# NOTE(vish): create bdm here to avoid race condition
bdm = objects.BlockDeviceMapping(
# NOTE(ndipanov): We need to explicitly set all the fields on the
# object so that obj_load_attr does not fail
new_bdm = objects.BlockDeviceMapping(
context=context,
source_type='volume', destination_type='volume',
instance_uuid=instance.uuid,
instance_uuid=instance.uuid, boot_index=None,
volume_id=volume_id or 'reserved',
device_name=device_name,
device_name=device, guest_format=None,
disk_bus=disk_bus, device_type=device_type)
bdm.create()
return bdm
new_bdm.device_name = self._get_device_name_for_instance(
instance, bdms, new_bdm)
# NOTE(vish): create bdm here to avoid race condition
new_bdm.create()
return new_bdm
return do_reserve()

View File

@ -7176,6 +7176,8 @@ class ComputeTestCase(BaseTestCase):
bdms.sort(key=operator.attrgetter('device_name'))
vol_bdm = bdms[1]
self.assertEqual(vol_bdm.source_type, 'volume')
self.assertIsNone(vol_bdm.boot_index)
self.assertIsNone(vol_bdm.guest_format)
self.assertEqual(vol_bdm.destination_type, 'volume')
self.assertEqual(vol_bdm.device_name, '/dev/vdb')
self.assertEqual(vol_bdm.volume_id, 'fake-volume-id')

View File

@ -769,6 +769,12 @@ class _VirtDriverTestCase(_FakeDriverBackendTestCase):
self.connection.get_instance_disk_info(instance_ref,
block_device_info={})
@catch_notimplementederror
def test_get_device_name_for_instance(self):
instance, _ = self._get_running_instance()
self.connection.get_device_name_for_instance(
instance, [], mock.Mock(spec=objects.BlockDeviceMapping))
class AbstractDriverTestCase(_VirtDriverTestCase, test.TestCase):
def setUp(self):

View File

@ -1349,6 +1349,23 @@ class ComputeDriver(object):
"""Default the missing device names in the block device mapping."""
raise NotImplementedError()
def get_device_name_for_instance(self, instance,
bdms, block_device_obj):
"""Get the next device name based on the block device mapping.
:param instance: nova.objects.instance.Instance that volume is
requesting a device name
:param bdms: a nova.objects.BlockDeviceMappingList for the instance
:param block_device_obj: A nova.objects.BlockDeviceMapping instance
with all info about the requested block
device. device_name does not need to be set,
and should be decided by the driver
implementation if not set.
:returns: The chosen device name.
"""
raise NotImplementedError()
def is_supported_fs_format(self, fs_type):
"""Check whether the file format is supported by this driver