summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikola Dipanov <ndipanov@redhat.com>2013-08-14 20:58:07 +0200
committerNikola Dipanov <ndipanov@redhat.com>2013-09-05 10:02:00 +0200
commitf9f247ef42c690bf1bd1ae65135c6e7fbd0d3c8c (patch)
treec5fb659b69b128de667e901ea479a2d8bea97b1f
parent3b1f7c55c10eec9d438a7d147aba1124b5ff9452 (diff)
downloadnova-f9f247ef42c690bf1bd1ae65135c6e7fbd0d3c8c.tar.gz
Enable libvirt driver to use the new BDM format
This patch makes the necessary changes in the libvirt driver to enable it to use some of the features of the new block device mapping format. After this patch it will be possible to set the bus, and device_type per block device, and libvirt driver will honor these when spawning an instance (note that attaching a volume still does not use the new data format). It utilizes some of the existing code in the blockinfo module to be able to default device names (it does so by overriding the methods introduced in I84541f8ff6e1b5978734e5def69946d014c66fdf), and also assign default values to fields like device_type and disk_bus if it is not provided or if it is bogus. As this implies the driver changing the block devices in the database, a new virtapi method block_device_mapping_update is added to accommodate this. Some of the libvirt specific code paths in the general defaulting function in compute utils have been removed as they are not needed since the driver now takes care of this. Further to that, this patch modifies some of the code paths in the libvirt driver that use the block device info directly (and not through the blockinfo module) to be aware of the new format. Due to very nicely factored code - there were only a few instances of this in the driver itself. It also overrides the libvirt driver's need_legacy_block_device_info method to tell the compute manager to feed it the new format when needed. This patch concludes the blueprint: improve-block-device-handling Change-Id: I8efd6af6706a097fb540e040a86ccbeaf131631f
-rw-r--r--nova/block_device.py5
-rwxr-xr-xnova/compute/manager.py4
-rw-r--r--nova/compute/utils.py64
-rw-r--r--nova/tests/compute/test_compute_utils.py34
-rw-r--r--nova/tests/compute/test_virtapi.py4
-rw-r--r--nova/tests/virt/libvirt/test_libvirt.py57
-rw-r--r--nova/tests/virt/libvirt/test_libvirt_blockinfo.py328
-rwxr-xr-xnova/virt/fake.py3
-rw-r--r--nova/virt/libvirt/blockinfo.py251
-rwxr-xr-xnova/virt/libvirt/driver.py74
-rw-r--r--nova/virt/virtapi.py7
11 files changed, 643 insertions, 188 deletions
diff --git a/nova/block_device.py b/nova/block_device.py
index 9636e81f84..1f0ba62ccf 100644
--- a/nova/block_device.py
+++ b/nova/block_device.py
@@ -406,6 +406,11 @@ def strip_dev(device_name):
return _dev.sub('', device_name) if device_name else device_name
+def prepend_dev(device_name):
+ """Make sure there is a leading '/dev/'."""
+ return device_name and '/dev/' + strip_dev(device_name)
+
+
_pref = re.compile('^((x?v|s)d)')
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index b16d4dd0e5..6391295094 100755
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -412,6 +412,10 @@ class ComputeVirtAPI(virtapi.VirtAPI):
return capi.block_device_mapping_get_all_by_instance(context, instance,
legacy=legacy)
+ def block_device_mapping_update(self, context, bdm_id, values):
+ return self._compute.conductor_api.block_device_mapping_update(
+ context, bdm_id, values)
+
class ComputeManager(manager.SchedulerDependentManager):
"""Manages the running instances from creation to destruction."""
diff --git a/nova/compute/utils.py b/nova/compute/utils.py
index 5f54e1d537..59fe18e737 100644
--- a/nova/compute/utils.py
+++ b/nova/compute/utils.py
@@ -135,54 +135,21 @@ def default_device_names_for_instance(instance, root_device_name,
update_function, *block_device_lists):
"""Generate missing device names for an instance."""
- def _device_names(iterables):
- return [bdm['device_name']
- for bdm in itertools.chain(*iterables) if bdm['device_name']]
-
- dev_list = _device_names(block_device_lists)
+ dev_list = [bdm['device_name']
+ for bdm in itertools.chain(*block_device_lists)
+ if bdm['device_name']]
if root_device_name not in dev_list:
dev_list.append(root_device_name)
- inst_type = flavors.extract_flavor(instance)
-
- is_libvirt = driver.compute_driver_matches('libvirt.LibvirtDriver')
- libvirt_default_ephemerals = []
-
- bdm_named_lists = zip(('ephemerals', 'swap', 'block_device_mapping'),
- block_device_lists)
-
- for name, bdm_list in bdm_named_lists:
- # Libvirt will create a default ephemeral if instance allows
- # and was not overridden.
- if (is_libvirt and name == 'ephemerals' and not bdm_list and
- instance['ephemeral_gb'] > 0):
- default_eph = get_next_device_name(instance,
- [root_device_name],
- root_device_name)
- if default_eph not in dev_list:
- dev_list.append(default_eph)
- libvirt_default_ephemerals.append(default_eph)
-
- # Libvirt will create a default swap if it's in instance type
- # and it was not supplied or overridden
- if (is_libvirt and name == 'swap' and not bdm_list and
- inst_type['swap'] > 0):
-
- ephemerals = (_device_names(bdm_named_lists[0][1]) or
- libvirt_default_ephemerals)
- default_swap = get_next_device_name(instance,
- [root_device_name] + ephemerals, root_device_name)
- if default_swap not in dev_list:
- dev_list.append(default_swap)
-
- for bdm in bdm_list:
- dev = bdm.get('device_name')
- if not dev:
- dev = get_next_device_name(instance, dev_list,
- root_device_name)
- bdm['device_name'] = dev
- if update_function:
- update_function(bdm)
- dev_list.append(dev)
+
+ for bdm in itertools.chain(*block_device_lists):
+ dev = bdm.get('device_name')
+ if not dev:
+ dev = get_next_device_name(instance, dev_list,
+ root_device_name)
+ bdm['device_name'] = dev
+ if update_function:
+ update_function(bdm)
+ dev_list.append(dev)
def get_next_device_name(instance, device_name_list,
@@ -217,11 +184,6 @@ def get_next_device_name(instance, device_name_list,
if driver.compute_driver_matches('xenapi.XenAPIDriver'):
prefix = '/dev/xvd'
- # NOTE(xqueralt): This can be removed when we have libvirt
- # defaulting it's own device names.
- if driver.compute_driver_matches('libvirt.LibvirtDriver'):
- prefix = '/dev/vd'
-
if req_prefix != prefix:
LOG.debug(_("Using %(prefix)s instead of %(req_prefix)s"),
{'prefix': prefix, 'req_prefix': req_prefix})
diff --git a/nova/tests/compute/test_compute_utils.py b/nova/tests/compute/test_compute_utils.py
index d13ec64fe6..7c9eb5d915 100644
--- a/nova/tests/compute/test_compute_utils.py
+++ b/nova/tests/compute/test_compute_utils.py
@@ -355,40 +355,6 @@ class DefaultDeviceNamesForInstanceTestCase(test.TestCase):
self.assertEquals(self.block_device_mapping[1]['device_name'],
'/dev/vdd')
- def test_libvirt_default_eph(self):
- self.block_device_mapping[1]['device_name'] = None
- self._test_default_device_names(None, [], [],
- self.block_device_mapping)
- self.assertEquals(self.block_device_mapping[1]['device_name'],
- '/dev/vdb')
-
- # Test that default eph will be taken into account on libvirt
- self.is_libvirt = True
- self.instance_type['swap'] = 0
- self.block_device_mapping[1]['device_name'] = None
- self._test_default_device_names(None, [], [],
- self.block_device_mapping)
- self.assertEquals(self.block_device_mapping[1]['device_name'],
- '/dev/vdc')
-
- def test_libvirt_default_swap(self):
- # Test that default swap will be taken into account on libvirt
- self.is_libvirt = True
- self.instance['ephemeral_gb'] = 0
- self.block_device_mapping[1]['device_name'] = None
- self._test_default_device_names(None, [], [],
- self.block_device_mapping)
- self.assertEquals(self.block_device_mapping[1]['device_name'],
- '/dev/vdc')
-
- def test_libvirt_default_swap_ephemeral(self):
- self.is_libvirt = True
- self.block_device_mapping[1]['device_name'] = None
- self._test_default_device_names(None, [], [],
- self.block_device_mapping)
- self.assertEquals(self.block_device_mapping[1]['device_name'],
- '/dev/vdd')
-
def test_update_fn_gets_called(self):
def _update(bdm):
self.update_called = True
diff --git a/nova/tests/compute/test_virtapi.py b/nova/tests/compute/test_virtapi.py
index 717ff75b8b..04b8c5f312 100644
--- a/nova/tests/compute/test_virtapi.py
+++ b/nova/tests/compute/test_virtapi.py
@@ -79,6 +79,10 @@ class VirtAPIBaseTest(test.TestCase, test.APICoverage):
self.assertExpected('block_device_mapping_get_all_by_instance',
{'uuid': 'fake_uuid'}, legacy=False)
+ def test_block_device_mapping_update(self):
+ self.assertExpected('block_device_mapping_update',
+ 'fake_bdm', 'fake_values')
+
class FakeVirtAPITest(VirtAPIBaseTest):
diff --git a/nova/tests/virt/libvirt/test_libvirt.py b/nova/tests/virt/libvirt/test_libvirt.py
index 2355053d2b..c8ab42a2d0 100644
--- a/nova/tests/virt/libvirt/test_libvirt.py
+++ b/nova/tests/virt/libvirt/test_libvirt.py
@@ -1202,8 +1202,8 @@ class LibvirtConnTestCase(test.TestCase):
def test_xml_disk_bus_ide_and_virtio(self):
swap = {'device_name': '/dev/vdc',
'swap_size': 1}
- ephemerals = [{'num': 0,
- 'virtual_name': 'ephemeral0',
+ ephemerals = [{'device_type': 'disk',
+ 'disk_bus': 'virtio',
'device_name': '/dev/vdb',
'size': 1}]
block_device_info = {
@@ -3106,7 +3106,10 @@ class LibvirtConnTestCase(test.TestCase):
block_device_info = {'root_device_name': '/dev/vda',
'block_device_mapping': [
- {'mount_device': 'vda'}]}
+ {'mount_device': 'vda',
+ 'boot_index': 0}
+ ]
+ }
# Volume-backed instance created without image
instance_ref = self.test_instance
@@ -4777,6 +4780,54 @@ class LibvirtConnTestCase(test.TestCase):
"""
self._test_attach_detach_interface_get_config("detach_interface")
+ def test_default_root_device_name(self):
+ instance = {'uuid': 'fake_instance'}
+ image_meta = {'id': 'fake'}
+ root_bdm = {'source_type': 'image',
+ 'detination_type': 'volume',
+ 'image_id': 'fake_id'}
+ self.flags(libvirt_type='fake_libvirt_type')
+
+ self.mox.StubOutWithMock(blockinfo, 'get_disk_bus_for_device_type')
+ self.mox.StubOutWithMock(blockinfo, 'get_root_info')
+
+ blockinfo.get_disk_bus_for_device_type('fake_libvirt_type',
+ image_meta,
+ 'disk').InAnyOrder().\
+ AndReturn('virtio')
+ blockinfo.get_disk_bus_for_device_type('fake_libvirt_type',
+ image_meta,
+ 'cdrom').InAnyOrder().\
+ AndReturn('ide')
+ blockinfo.get_root_info('fake_libvirt_type',
+ image_meta, root_bdm,
+ 'virtio', 'ide').AndReturn({'dev': 'vda'})
+ self.mox.ReplayAll()
+
+ conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
+ self.assertEqual(conn.default_root_device_name(instance, image_meta,
+ root_bdm), '/dev/vda')
+
+ def test_default_device_names_for_instance(self):
+ instance = {'uuid': 'fake_instance'}
+ root_device_name = '/dev/vda'
+ ephemerals = [{'device_name': 'vdb'}]
+ swap = [{'device_name': 'vdc'}]
+ block_device_mapping = [{'device_name': 'vdc'}]
+ self.flags(libvirt_type='fake_libvirt_type')
+
+ self.mox.StubOutWithMock(blockinfo, 'default_device_names')
+
+ blockinfo.default_device_names('fake_libvirt_type', instance,
+ root_device_name, mox.IgnoreArg(),
+ ephemerals, swap, block_device_mapping)
+ self.mox.ReplayAll()
+
+ conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
+ conn.default_device_names_for_instance(instance, root_device_name,
+ ephemerals, swap,
+ block_device_mapping)
+
class HostStateTestCase(test.TestCase):
diff --git a/nova/tests/virt/libvirt/test_libvirt_blockinfo.py b/nova/tests/virt/libvirt/test_libvirt_blockinfo.py
index c5c0756a0b..8c1f847945 100644
--- a/nova/tests/virt/libvirt/test_libvirt_blockinfo.py
+++ b/nova/tests/virt/libvirt/test_libvirt_blockinfo.py
@@ -15,6 +15,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+import copy
+
+import mock
+
from nova import block_device
from nova.compute import flavors
from nova import context
@@ -22,6 +26,7 @@ from nova import db
from nova import exception
from nova import test
import nova.tests.image.fake
+from nova.tests import matchers
from nova.virt.libvirt import blockinfo
@@ -53,14 +58,10 @@ class LibvirtBlockInfoTest(test.TestCase):
def test_volume_in_mapping(self):
swap = {'device_name': '/dev/sdb',
'swap_size': 1}
- ephemerals = [{'num': 0,
- 'virtual_name': 'ephemeral0',
- 'device_name': '/dev/sdc1',
- 'size': 1},
- {'num': 2,
- 'virtual_name': 'ephemeral2',
- 'device_name': '/dev/sdd',
- 'size': 1}]
+ ephemerals = [{'device_type': 'disk', 'guest_format': 'ext3',
+ 'device_name': '/dev/sdc1', 'size': 10},
+ {'disk_bus': 'ide', 'guest_format': None,
+ 'device_name': '/dev/sdd', 'size': 10}]
block_device_mapping = [{'mount_device': '/dev/sde',
'device_path': 'fake_device'},
{'mount_device': '/dev/sdf',
@@ -301,11 +302,11 @@ class LibvirtBlockInfoTest(test.TestCase):
block_device_info = {
'ephemerals': [
- {'num': 0, 'virtual_name': 'ephemeral0',
+ {'device_type': 'disk', 'guest_format': 'ext3',
'device_name': '/dev/vdb', 'size': 10},
- {'num': 1, 'virtual_name': 'ephemeral1',
+ {'disk_bus': 'ide', 'guest_format': None,
'device_name': '/dev/vdc', 'size': 10},
- {'num': 2, 'virtual_name': 'ephemeral2',
+ {'device_type': 'floppy',
'device_name': '/dev/vdd', 'size': 10},
]
}
@@ -315,9 +316,10 @@ class LibvirtBlockInfoTest(test.TestCase):
expect = {
'disk': {'bus': 'virtio', 'dev': 'vda', 'type': 'disk'},
- 'disk.eph0': {'bus': 'virtio', 'dev': 'vdb', 'type': 'disk'},
- 'disk.eph1': {'bus': 'virtio', 'dev': 'vdc', 'type': 'disk'},
- 'disk.eph2': {'bus': 'virtio', 'dev': 'vdd', 'type': 'disk'},
+ 'disk.eph0': {'bus': 'virtio', 'dev': 'vdb',
+ 'type': 'disk', 'format': 'ext3'},
+ 'disk.eph1': {'bus': 'ide', 'dev': 'vdc', 'type': 'disk'},
+ 'disk.eph2': {'bus': 'virtio', 'dev': 'vdd', 'type': 'floppy'},
'disk.swap': {'bus': 'virtio', 'dev': 'vde', 'type': 'disk'},
'root': {'bus': 'virtio', 'dev': 'vda', 'type': 'disk'}
}
@@ -353,6 +355,8 @@ class LibvirtBlockInfoTest(test.TestCase):
'block_device_mapping': [
{'connection_info': "fake",
'mount_device': "/dev/vda",
+ 'boot_index': 0,
+ 'device_type': 'disk',
'delete_on_termination': True},
]
}
@@ -376,6 +380,7 @@ class LibvirtBlockInfoTest(test.TestCase):
'block_device_mapping': [
{'connection_info': "fake",
'mount_device': "/dev/vdb",
+ 'boot_index': -1,
'delete_on_termination': True},
]
}
@@ -399,12 +404,17 @@ class LibvirtBlockInfoTest(test.TestCase):
'block_device_mapping': [
{'connection_info': "fake",
'mount_device': "/dev/vda",
+ 'boot_index': 0,
+ 'disk_bus': 'scsi',
'delete_on_termination': True},
{'connection_info': "fake",
'mount_device': "/dev/vdb",
+ 'boot_index': -1,
'delete_on_termination': True},
{'connection_info': "fake",
'mount_device': "/dev/vdc",
+ 'boot_index': -1,
+ 'device_type': 'cdrom',
'delete_on_termination': True},
]
}
@@ -413,10 +423,10 @@ class LibvirtBlockInfoTest(test.TestCase):
block_device_info)
expect = {
- '/dev/vda': {'bus': 'virtio', 'dev': 'vda', 'type': 'disk'},
+ '/dev/vda': {'bus': 'scsi', 'dev': 'vda', 'type': 'disk'},
'/dev/vdb': {'bus': 'virtio', 'dev': 'vdb', 'type': 'disk'},
- '/dev/vdc': {'bus': 'virtio', 'dev': 'vdc', 'type': 'disk'},
- 'root': {'bus': 'virtio', 'dev': 'vda', 'type': 'disk'}
+ '/dev/vdc': {'bus': 'virtio', 'dev': 'vdc', 'type': 'cdrom'},
+ 'root': {'bus': 'scsi', 'dev': 'vda', 'type': 'disk'}
}
self.assertEqual(mapping, expect)
@@ -430,9 +440,9 @@ class LibvirtBlockInfoTest(test.TestCase):
'swap': {'device_name': '/dev/vdy',
'swap_size': 10},
'ephemerals': [
- {'num': 0, 'virtual_name': 'ephemeral0',
+ {'device_type': 'disk', 'guest_format': 'ext3',
'device_name': '/dev/vdb', 'size': 10},
- {'num': 1, 'virtual_name': 'ephemeral1',
+ {'disk_bus': 'ide', 'guest_format': None,
'device_name': '/dev/vdc', 'size': 10},
],
'block_device_mapping': [
@@ -448,13 +458,52 @@ class LibvirtBlockInfoTest(test.TestCase):
expect = {
'disk': {'bus': 'virtio', 'dev': 'vdf', 'type': 'disk'},
'/dev/vda': {'bus': 'virtio', 'dev': 'vda', 'type': 'disk'},
- 'disk.eph0': {'bus': 'virtio', 'dev': 'vdb', 'type': 'disk'},
- 'disk.eph1': {'bus': 'virtio', 'dev': 'vdc', 'type': 'disk'},
+ 'disk.eph0': {'bus': 'virtio', 'dev': 'vdb',
+ 'type': 'disk', 'format': 'ext3'},
+ 'disk.eph1': {'bus': 'ide', 'dev': 'vdc', 'type': 'disk'},
'disk.swap': {'bus': 'virtio', 'dev': 'vdy', 'type': 'disk'},
'root': {'bus': 'virtio', 'dev': 'vdf', 'type': 'disk'}
}
self.assertEqual(mapping, expect)
+ def test_get_disk_mapping_updates_original(self):
+ user_context = context.RequestContext(self.user_id, self.project_id)
+ instance_ref = db.instance_create(user_context, self.test_instance)
+
+ block_device_info = {
+ 'root_device_name': '/dev/vda',
+ 'swap': {'device_name': '/dev/vdb',
+ 'device_type': 'really_lame_type',
+ 'swap_size': 10},
+ 'ephemerals': [{'disk_bus': 'no_such_bus',
+ 'device_type': 'yeah_right',
+ 'device_name': '/dev/vdc', 'size': 10}],
+ 'block_device_mapping': [
+ {'connection_info': "fake",
+ 'mount_device': None,
+ 'device_type': 'lawnmower',
+ 'delete_on_termination': True}]
+ }
+ expected_swap = {'device_name': '/dev/vdb', 'disk_bus': 'virtio',
+ 'device_type': 'disk', 'swap_size': 10}
+ expected_ephemeral = {'disk_bus': 'virtio',
+ 'device_type': 'disk',
+ 'device_name': '/dev/vdc', 'size': 10}
+ expected_bdm = {'connection_info': "fake",
+ 'mount_device': '/dev/vdd',
+ 'device_type': 'disk',
+ 'disk_bus': 'virtio',
+ 'delete_on_termination': True}
+
+ blockinfo.get_disk_mapping("kvm", instance_ref,
+ "virtio", "ide", block_device_info)
+
+ self.assertEqual(expected_swap, block_device_info['swap'])
+ self.assertEqual(expected_ephemeral,
+ block_device_info['ephemerals'][0])
+ self.assertEqual(expected_bdm,
+ block_device_info['block_device_mapping'][0])
+
def test_get_disk_bus(self):
bus = blockinfo.get_disk_bus_for_device_type('kvm')
self.assertEqual(bus, 'virtio')
@@ -503,3 +552,240 @@ class LibvirtBlockInfoTest(test.TestCase):
self.flags(config_drive_format='test')
self.assertRaises(exception.ConfigDriveUnknownFormat,
blockinfo.get_config_drive_type)
+
+ def test_get_info_from_bdm(self):
+ bdms = [{'device_name': '/dev/vds', 'device_type': 'disk',
+ 'disk_bus': 'usb', 'swap_size': 4},
+ {'device_type': 'disk', 'guest_format': 'ext3',
+ 'device_name': '/dev/vdb', 'size': 2},
+ {'disk_bus': 'ide', 'guest_format': None,
+ 'device_name': '/dev/vdc', 'size': 3},
+ {'connection_info': "fake",
+ 'mount_device': "/dev/sdr",
+ 'disk_bus': 'lame_bus',
+ 'device_type': 'cdrom',
+ 'delete_on_termination': True},
+ {'connection_info': "fake",
+ 'mount_device': "/dev/vdo",
+ 'disk_bus': 'scsi',
+ 'device_type': 'lame_type',
+ 'delete_on_termination': True}]
+ expected = [{'dev': 'vds', 'type': 'disk', 'bus': 'usb'},
+ {'dev': 'vdb', 'type': 'disk',
+ 'bus': 'virtio', 'format': 'ext3'},
+ {'dev': 'vdc', 'type': 'disk', 'bus': 'ide'},
+ {'dev': 'sdr', 'type': 'cdrom', 'bus': 'scsi'},
+ {'dev': 'vdo', 'type': 'disk', 'bus': 'scsi'}]
+
+ for bdm, expected in zip(bdms, expected):
+ self.assertEqual(expected,
+ blockinfo.get_info_from_bdm('kvm', bdm, {}))
+
+ # Test that passed bus and type are considered
+ bdm = {'device_name': '/dev/vda'}
+ expected = {'dev': 'vda', 'type': 'disk', 'bus': 'ide'}
+ self.assertEqual(
+ expected, blockinfo.get_info_from_bdm('kvm', bdm, {},
+ disk_bus='ide',
+ dev_type='disk'))
+
+ # Test that lame bus values are defaulted properly
+ bdm = {'disk_bus': 'lame_bus', 'device_type': 'cdrom'}
+ with mock.patch.object(blockinfo,
+ 'get_disk_bus_for_device_type',
+ return_value='ide') as get_bus:
+ blockinfo.get_info_from_bdm('kvm', bdm, {})
+ get_bus.assert_called_once_with('kvm', None, 'cdrom')
+
+ # Test that missing device is defaulted as expected
+ bdm = {'disk_bus': 'ide', 'device_type': 'cdrom'}
+ expected = {'dev': 'vdd', 'type': 'cdrom', 'bus': 'ide'}
+ mapping = {'root': {'dev': 'vda'}}
+ with mock.patch.object(blockinfo,
+ 'find_disk_dev_for_disk_bus',
+ return_value='vdd') as find_dev:
+ got = blockinfo.get_info_from_bdm(
+ 'kvm', bdm, mapping, assigned_devices=['vdb', 'vdc'])
+ find_dev.assert_called_once_with(
+ {'root': {'dev': 'vda'},
+ 'vdb': {'dev': 'vdb'},
+ 'vdc': {'dev': 'vdc'}}, 'ide')
+ self.assertEqual(expected, got)
+
+ @mock.patch('nova.virt.libvirt.blockinfo.find_disk_dev_for_disk_bus',
+ return_value='vda')
+ @mock.patch('nova.virt.libvirt.blockinfo.get_disk_bus_for_disk_dev',
+ return_value='virtio')
+ def test_get_root_info_no_bdm(self, mock_get_bus, mock_find_dev):
+ blockinfo.get_root_info('kvm', None, None, 'virtio', 'ide')
+ mock_find_dev.assert_called_once_with({}, 'virtio')
+
+ blockinfo.get_root_info('kvm', None, None, 'virtio', 'ide',
+ root_device_name='/dev/vda')
+ mock_get_bus.assert_called_once_with('kvm', '/dev/vda')
+
+ @mock.patch('nova.virt.libvirt.blockinfo.get_info_from_bdm')
+ def test_get_root_info_bdm(self, mock_get_info):
+ root_bdm = {'mount_device': '/dev/vda',
+ 'disk_bus': 'scsi',
+ 'device_type': 'disk'}
+ # No root_device_name
+ blockinfo.get_root_info('kvm', None, root_bdm, 'virtio', 'ide')
+ mock_get_info.assert_called_once_with('kvm', root_bdm, {})
+ mock_get_info.reset_mock()
+ # Both device names
+ blockinfo.get_root_info('kvm', None, root_bdm, 'virtio', 'ide',
+ root_device_name='sda')
+ mock_get_info.assert_called_once_with('kvm', root_bdm, {})
+ mock_get_info.reset_mock()
+ # Missing device names
+ del root_bdm['mount_device']
+ blockinfo.get_root_info('kvm', None, root_bdm, 'virtio', 'ide',
+ root_device_name='sda')
+ mock_get_info.assert_called_once_with('kvm',
+ {'device_name': 'sda',
+ 'disk_bus': 'scsi',
+ 'device_type': 'disk'}, {})
+
+
+class DefaultDeviceNamesTestCase(test.TestCase):
+ def setUp(self):
+ super(DefaultDeviceNamesTestCase, self).setUp()
+ self.instance = {
+ 'uuid': '32dfcb37-5af1-552b-357c-be8c3aa38310',
+ 'memory_kb': '1024000',
+ 'basepath': '/some/path',
+ 'bridge_name': 'br100',
+ 'vcpus': 2,
+ 'project_id': 'fake',
+ 'bridge': 'br101',
+ 'image_ref': '155d900f-4e14-4e4c-a73d-069cbf4541e6',
+ 'root_gb': 10,
+ 'ephemeral_gb': 20,
+ 'instance_type_id': 2}
+ self.root_device_name = '/dev/vda'
+ self.libvirt_type = 'kvm'
+ self.instance_type = {'swap': 4}
+ self.patcher = mock.patch('nova.compute.flavors.extract_flavor',
+ return_value=self.instance_type)
+ self.patcher.start()
+
+ self.ephemerals = [
+ {'id': 1, 'instance_uuid': 'fake-instance',
+ 'device_name': '/dev/vdb',
+ 'source_type': 'blank',
+ 'destination_type': 'local',
+ 'device_type': 'disk',
+ 'disk_bus': 'virtio',
+ 'delete_on_termination': True,
+ 'guest_format': None,
+ 'volume_size': 1,
+ 'boot_index': -1}]
+
+ self.swap = [
+ {'id': 2, 'instance_uuid': 'fake-instance',
+ 'device_name': '/dev/vdc',
+ 'source_type': 'blank',
+ 'destination_type': 'local',
+ 'device_type': 'disk',
+ 'disk_bus': 'virtio',
+ 'delete_on_termination': True,
+ 'guest_format': 'swap',
+ 'volume_size': 1,
+ 'boot_index': -1}]
+
+ self.block_device_mapping = [
+ {'id': 3, 'instance_uuid': 'fake-instance',
+ 'device_name': '/dev/vda',
+ 'source_type': 'volume',
+ 'destination_type': 'volume',
+ 'device_type': 'disk',
+ 'disk_bus': 'virtio',
+ 'volume_id': 'fake-volume-id-1',
+ 'boot_index': 0},
+ {'id': 4, 'instance_uuid': 'fake-instance',
+ 'device_name': '/dev/vdd',
+ 'source_type': 'snapshot',
+ 'device_type': 'disk',
+ 'disk_bus': 'virtio',
+ 'destination_type': 'volume',
+ 'snapshot_id': 'fake-snapshot-id-1',
+ 'boot_index': -1}]
+
+ def tearDown(self):
+ super(DefaultDeviceNamesTestCase, self).tearDown()
+ self.patcher.stop()
+
+ def _test_default_device_names(self, update_function, *block_device_lists):
+ blockinfo.default_device_names(self.libvirt_type, self.instance,
+ self.root_device_name,
+ update_function, *block_device_lists)
+
+ def test_only_block_device_mapping(self):
+ # Test no-op
+ original_bdm = copy.deepcopy(self.block_device_mapping)
+ self._test_default_device_names(None, [], [],
+ self.block_device_mapping)
+ self.assertThat(original_bdm,
+ matchers.DictListMatches(self.block_device_mapping))
+
+ # Asser it defaults the missing one as expected
+ self.block_device_mapping[1]['device_name'] = None
+ self._test_default_device_names(None, [], [],
+ self.block_device_mapping)
+ self.assertEquals(self.block_device_mapping[1]['device_name'],
+ '/dev/vdd')
+
+ def test_with_ephemerals(self):
+ # Test ephemeral gets assigned
+ self.ephemerals[0]['device_name'] = None
+ self._test_default_device_names(None, self.ephemerals, [],
+ self.block_device_mapping)
+ self.assertEquals(self.ephemerals[0]['device_name'], '/dev/vdb')
+
+ self.block_device_mapping[1]['device_name'] = None
+ self._test_default_device_names(None, self.ephemerals, [],
+ self.block_device_mapping)
+ self.assertEquals(self.block_device_mapping[1]['device_name'],
+ '/dev/vdd')
+
+ def test_with_swap(self):
+ # Test swap only
+ self.swap[0]['device_name'] = None
+ self._test_default_device_names(None, [], self.swap, [])
+ self.assertEquals(self.swap[0]['device_name'], '/dev/vdc')
+
+ # Test swap and block_device_mapping
+ self.swap[0]['device_name'] = None
+ self.block_device_mapping[1]['device_name'] = None
+ self._test_default_device_names(None, [], self.swap,
+ self.block_device_mapping)
+ self.assertEquals(self.swap[0]['device_name'], '/dev/vdc')
+ self.assertEquals(self.block_device_mapping[1]['device_name'],
+ '/dev/vdd')
+
+ def test_all_together(self):
+ # Test swap missing
+ self.swap[0]['device_name'] = None
+ self._test_default_device_names(None, self.ephemerals,
+ self.swap, self.block_device_mapping)
+ self.assertEquals(self.swap[0]['device_name'], '/dev/vdc')
+
+ # Test swap and eph missing
+ self.swap[0]['device_name'] = None
+ self.ephemerals[0]['device_name'] = None
+ self._test_default_device_names(None, self.ephemerals,
+ self.swap, self.block_device_mapping)
+ self.assertEquals(self.ephemerals[0]['device_name'], '/dev/vdb')
+ self.assertEquals(self.swap[0]['device_name'], '/dev/vdc')
+
+ # Test all missing
+ self.swap[0]['device_name'] = None
+ self.ephemerals[0]['device_name'] = None
+ self.block_device_mapping[1]['device_name'] = None
+ self._test_default_device_names(None, self.ephemerals,
+ self.swap, self.block_device_mapping)
+ self.assertEquals(self.ephemerals[0]['device_name'], '/dev/vdb')
+ self.assertEquals(self.swap[0]['device_name'], '/dev/vdc')
+ self.assertEquals(self.block_device_mapping[1]['device_name'],
+ '/dev/vdd')
diff --git a/nova/virt/fake.py b/nova/virt/fake.py
index feff2bf01b..ae977762e8 100755
--- a/nova/virt/fake.py
+++ b/nova/virt/fake.py
@@ -499,3 +499,6 @@ class FakeVirtAPI(virtapi.VirtAPI):
if legacy:
bdms = block_device.legacy_mapping(bdms)
return bdms
+
+ def block_device_mapping_update(self, context, bdm_id, values):
+ return db.block_device_mapping_update(context, bdm_id, values)
diff --git a/nova/virt/libvirt/blockinfo.py b/nova/virt/libvirt/blockinfo.py
index 1b8832d23f..5e4745d2da 100644
--- a/nova/virt/libvirt/blockinfo.py
+++ b/nova/virt/libvirt/blockinfo.py
@@ -57,20 +57,27 @@ variables / types used
(disk bus, disk dev, device type)
+ and possibly these optional fields: ('format',)
+
* 'disk_bus': the guest bus type ('ide', 'virtio', 'scsi', etc)
* 'disk_dev': the device name 'vda', 'hdc', 'sdf', 'xvde' etc
* 'device_type': type of device eg 'disk', 'cdrom', 'floppy'
+ * 'format': Which format to apply to the device if applicable
+
"""
+import itertools
+
from oslo.config import cfg
from nova import block_device
from nova.compute import flavors
from nova import exception
from nova.openstack.common.gettextutils import _
+from nova.virt import block_device as driver_block_device
from nova.virt import configdrive
from nova.virt import driver
@@ -78,6 +85,9 @@ from nova.virt import driver
CONF = cfg.CONF
+SUPPORTED_DEVICE_TYPES = ('disk', 'cdrom', 'floppy')
+
+
def has_disk_dev(mapping, disk_dev):
"""Determine if a disk device name has already been used.
@@ -291,8 +301,8 @@ def get_next_disk_info(mapping, disk_bus,
'type': device_type}
-def get_eph_disk(ephemeral):
- return 'disk.eph' + str(ephemeral['num'])
+def get_eph_disk(index):
+ return 'disk.eph' + str(index)
def get_config_drive_type():
@@ -315,6 +325,140 @@ def get_config_drive_type():
return config_drive_type
+def get_info_from_bdm(virt_type, bdm, mapping={}, disk_bus=None,
+ dev_type=None, allowed_types=None,
+ assigned_devices=None):
+ allowed_types = allowed_types or SUPPORTED_DEVICE_TYPES
+ device_name = block_device.strip_dev(get_device_name(bdm))
+
+ bdm_type = bdm.get('device_type') or dev_type
+ if bdm_type not in allowed_types:
+ bdm_type = 'disk'
+
+ bdm_bus = bdm.get('disk_bus') or disk_bus
+ if not is_disk_bus_valid_for_virt(virt_type, bdm_bus):
+ if device_name:
+ bdm_bus = get_disk_bus_for_disk_dev(virt_type, device_name)
+ else:
+ bdm_bus = get_disk_bus_for_device_type(virt_type, None, bdm_type)
+
+ if not device_name:
+ if assigned_devices:
+ padded_mapping = dict((dev, {'dev': dev})
+ for dev in assigned_devices)
+ padded_mapping.update(mapping)
+ else:
+ padded_mapping = mapping
+
+ device_name = find_disk_dev_for_disk_bus(padded_mapping, bdm_bus)
+
+ bdm_info = {'bus': bdm_bus,
+ 'dev': device_name,
+ 'type': bdm_type}
+
+ bdm_format = bdm.get('guest_format')
+ if bdm_format:
+ bdm_info.update({'format': bdm_format})
+
+ return bdm_info
+
+
+def get_device_name(bdm):
+ """Get the device name if present regardless of the bdm format."""
+ return bdm.get('device_name') or bdm.get('mount_device')
+
+
+def get_root_info(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 aplies 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 (image_meta and image_meta.get('disk_format') == 'iso'):
+ root_device_bus = cdrom_bus
+ root_device_type = 'cdrom'
+ else:
+ root_device_bus = disk_bus
+ root_device_type = 'disk'
+ if root_device_name:
+ root_device_bus = get_disk_bus_for_disk_dev(virt_type,
+ root_device_name)
+ else:
+ root_device_name = find_disk_dev_for_disk_bus({}, root_device_bus)
+
+ return {'bus': root_device_bus,
+ 'type': root_device_type,
+ 'dev': block_device.strip_dev(root_device_name)}
+ else:
+ if not get_device_name(root_bdm) and root_device_name:
+ root_bdm = root_bdm.copy()
+ root_bdm['device_name'] = root_device_name
+ return get_info_from_bdm(virt_type, root_bdm, {})
+
+
+def default_device_names(virt_type, instance, root_device_name,
+ update_func, ephemerals, swap, block_device_mapping):
+
+ block_device_info = {
+ 'root_device_name': root_device_name,
+ 'swap': driver_block_device.get_swap(
+ driver_block_device.convert_swap(swap)),
+ 'ephemerals': driver_block_device.convert_ephemerals(ephemerals),
+ 'block_device_mapping': (
+ driver_block_device.convert_volumes(
+ block_device_mapping) +
+ driver_block_device.convert_snapshots(
+ block_device_mapping))
+ }
+
+ devices = dict((bdm.get('id'), bdm) for bdm in
+ itertools.chain(ephemerals, swap, block_device_mapping))
+
+ get_disk_info(virt_type, instance, 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']):
+ if driver_bdm.id in devices:
+ bdm = devices[driver_bdm.id]
+ # NOTE (ndipanov): We may have chosen different values
+ # for bus and type so update those along with device name
+ bdm['device_name'] = get_device_name(driver_bdm)
+ bdm['disk_bus'] = driver_bdm['disk_bus']
+ # Swap does not have device type in driver format
+ bdm['device_type'] = driver_bdm.get('device_type', 'disk')
+ if update_func:
+ update_func(bdm)
+
+
+def has_default_ephemeral(instance, disk_bus, block_device_info, mapping):
+ ephemerals = driver.block_device_info_get_ephemerals(block_device_info)
+ if instance['ephemeral_gb'] <= 0 or ephemerals:
+ return None
+ else:
+ info = get_next_disk_info(mapping, disk_bus)
+ if block_device.volume_in_mapping(info['dev'], block_device_info):
+ return None
+ return info
+
+
+def update_bdm(bdm, info):
+ device_name_field = ('device_name'
+ if 'device_name' in bdm
+ else 'mount_device')
+ # Do not update the device name if it was already present
+ bdm.update(dict(zip((device_name_field,
+ 'disk_bus', 'device_type'),
+ ((bdm.get(device_name_field) or
+ block_device.prepend_dev(info['dev'])),
+ info['bus'], info['type']))))
+
+
def get_disk_mapping(virt_type, instance,
disk_bus, cdrom_bus,
block_device_info=None,
@@ -332,6 +476,13 @@ def get_disk_mapping(virt_type, instance,
mapping = {}
+ pre_assigned_device_names = \
+ [block_device.strip_dev(get_device_name(bdm)) for bdm in itertools.chain(
+ 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)]
+
if virt_type == "lxc":
# NOTE(zul): This information is not used by the libvirt driver
# however we need to populate mapping so the image can be
@@ -360,60 +511,49 @@ def get_disk_mapping(virt_type, instance,
return mapping
- if image_meta and image_meta.get('disk_format') == 'iso':
- root_disk_bus = cdrom_bus
- root_device_type = 'cdrom'
- else:
- root_disk_bus = disk_bus
- root_device_type = 'disk'
+ try:
+ root_bdm = (bdm for bdm in
+ driver.block_device_info_get_mapping(block_device_info)
+ if bdm.get('boot_index') == 0).next()
+ except StopIteration:
+ # NOTE (ndipanov): This happens when we boot from image as
+ # there is no driver represenation of local targeted images
+ # and they will not be in block_device_info list.
+ root_bdm = None
+
+ root_device_name = block_device.strip_dev(
+ driver.block_device_info_get_root(block_device_info))
+ root_info = get_root_info(virt_type, image_meta, root_bdm,
+ disk_bus, cdrom_bus, root_device_name)
- root_device_name = driver.block_device_info_get_root(block_device_info)
- if root_device_name is not None:
- root_device = block_device.strip_dev(root_device_name)
- root_info = {'bus': get_disk_bus_for_disk_dev(virt_type,
- root_device),
- 'dev': root_device,
- 'type': root_device_type}
- else:
- root_info = get_next_disk_info(mapping,
- root_disk_bus,
- root_device_type)
mapping['root'] = root_info
- if not block_device.volume_in_mapping(root_info['dev'],
- block_device_info):
+ # NOTE (ndipanov): This implicitely 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
+ # overriden. 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
- eph_info = get_next_disk_info(mapping,
- disk_bus)
- ephemeral_device = False
- if not (block_device.volume_in_mapping(eph_info['dev'],
- block_device_info) or
- 0 in [eph['num'] for eph in
- driver.block_device_info_get_ephemerals(
- block_device_info)]):
- if instance['ephemeral_gb'] > 0:
- ephemeral_device = True
-
- if ephemeral_device:
- mapping['disk.local'] = eph_info
-
- for eph in driver.block_device_info_get_ephemerals(
- block_device_info):
- disk_dev = block_device.strip_dev(eph['device_name'])
- disk_bus = get_disk_bus_for_disk_dev(virt_type, disk_dev)
-
- mapping[get_eph_disk(eph)] = {'bus': disk_bus,
- 'dev': disk_dev,
- 'type': 'disk'}
+ default_eph = has_default_ephemeral(instance, disk_bus, block_device_info,
+ mapping)
+ if default_eph:
+ mapping['disk.local'] = default_eph
- swap = driver.block_device_info_get_swap(block_device_info)
- if driver.swap_is_usable(swap):
- disk_dev = block_device.strip_dev(swap['device_name'])
- disk_bus = get_disk_bus_for_disk_dev(virt_type, disk_dev)
+ for idx, eph in enumerate(driver.block_device_info_get_ephemerals(
+ block_device_info)):
+ eph_info = get_info_from_bdm(
+ virt_type, eph, mapping, disk_bus,
+ assigned_devices=pre_assigned_device_names)
+ mapping[get_eph_disk(idx)] = eph_info
+ update_bdm(eph, eph_info)
- mapping['disk.swap'] = {'bus': disk_bus,
- 'dev': disk_dev,
- 'type': 'disk'}
+ swap = driver.block_device_info_get_swap(block_device_info)
+ if swap and swap.get('swap_size', 0) > 0:
+ swap_info = get_info_from_bdm(virt_type, swap, mapping, disk_bus)
+ mapping['disk.swap'] = swap_info
+ update_bdm(swap, swap_info)
elif inst_type['swap'] > 0:
swap_info = get_next_disk_info(mapping,
disk_bus)
@@ -425,12 +565,11 @@ def get_disk_mapping(virt_type, instance,
block_device_info)
for vol in block_device_mapping:
- disk_dev = vol['mount_device'].rpartition("/")[2]
- disk_bus = get_disk_bus_for_disk_dev(virt_type, disk_dev)
-
- mapping[vol['mount_device']] = {'bus': disk_bus,
- 'dev': disk_dev,
- 'type': 'disk'}
+ vol_info = get_info_from_bdm(
+ virt_type, vol, mapping,
+ assigned_devices=pre_assigned_device_names)
+ mapping[block_device.prepend_dev(vol_info['dev'])] = vol_info
+ update_bdm(vol, vol_info)
if configdrive.required_by(instance):
device_type = get_config_drive_type()
diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py
index 6e76bf3221..1f92e362be 100755
--- a/nova/virt/libvirt/driver.py
+++ b/nova/virt/libvirt/driver.py
@@ -2311,13 +2311,14 @@ class LibvirtDriver(driver.ComputeDriver):
size=size,
ephemeral_size=ephemeral_gb)
- for eph in driver.block_device_info_get_ephemerals(block_device_info):
+ for idx, eph in enumerate(driver.block_device_info_get_ephemerals(
+ block_device_info)):
fn = functools.partial(self._create_ephemeral,
- fs_label='ephemeral%d' % eph['num'],
+ fs_label='ephemeral%d' % idx,
os_type=instance["os_type"])
size = eph['size'] * 1024 * 1024 * 1024
fname = "ephemeral_%s_%s" % (eph['size'], os_type_with_default)
- image(blockinfo.get_eph_disk(eph)).cache(
+ image(blockinfo.get_eph_disk(idx)).cache(
fetch_func=fn,
filename=fname,
size=size,
@@ -2565,13 +2566,14 @@ class LibvirtDriver(driver.ComputeDriver):
self.virtapi.instance_update(
nova_context.get_admin_context(), instance['uuid'],
{'default_ephemeral_device':
- '/dev/' + disklocal.target_dev})
+ block_device.prepend_dev(disklocal.target_dev)})
- for eph in driver.block_device_info_get_ephemerals(
- block_device_info):
+ for idx, eph in enumerate(
+ driver.block_device_info_get_ephemerals(
+ block_device_info)):
diskeph = self.get_guest_disk_config(
instance,
- blockinfo.get_eph_disk(eph),
+ blockinfo.get_eph_disk(idx),
disk_mapping, inst_type)
devices.append(diskeph)
@@ -2583,11 +2585,13 @@ class LibvirtDriver(driver.ComputeDriver):
devices.append(diskswap)
self.virtapi.instance_update(
nova_context.get_admin_context(), instance['uuid'],
- {'default_swap_device': '/dev/' + diskswap.target_dev})
+ {'default_swap_device': block_device.prepend_dev(
+ diskswap.target_dev)})
for vol in block_device_mapping:
connection_info = vol['connection_info']
- info = disk_mapping[vol['mount_device']]
+ vol_dev = block_device.prepend_dev(vol['mount_device'])
+ info = disk_mapping[vol_dev]
cfg = self.volume_driver_method('connect_volume',
connection_info,
info)
@@ -2652,8 +2656,9 @@ class LibvirtDriver(driver.ComputeDriver):
guest.cpu = self.get_guest_cpu_config()
- if 'root' in disk_mapping and disk_mapping['root']['dev'] is not None:
- root_device_name = "/dev/" + disk_mapping['root']['dev']
+ if 'root' in disk_mapping:
+ root_device_name = block_device.prepend_dev(
+ disk_mapping['root']['dev'])
else:
root_device_name = None
@@ -2995,12 +3000,7 @@ class LibvirtDriver(driver.ComputeDriver):
for vol in block_device_mapping:
connection_info = vol['connection_info']
disk_dev = vol['mount_device'].rpartition("/")[2]
- disk_info = {
- 'dev': disk_dev,
- 'bus': blockinfo.get_disk_bus_for_disk_dev(CONF.libvirt_type,
- disk_dev),
- 'type': 'disk',
- }
+ disk_info = blockinfo.get_info_from_bdm(CONF.libvirt_type, vol)
self.volume_driver_method('connect_volume',
connection_info,
disk_info)
@@ -3928,12 +3928,7 @@ class LibvirtDriver(driver.ComputeDriver):
for vol in block_device_mapping:
connection_info = vol['connection_info']
disk_dev = vol['mount_device'].rpartition("/")[2]
- disk_info = {
- 'dev': disk_dev,
- 'bus': blockinfo.get_disk_bus_for_disk_dev(CONF.libvirt_type,
- disk_dev),
- 'type': 'disk',
- }
+ disk_info = blockinfo.get_info_from_bdm(CONF.libvirt_type, vol)
self.volume_driver_method('connect_volume',
connection_info,
disk_info)
@@ -4522,6 +4517,39 @@ class LibvirtDriver(driver.ComputeDriver):
LOG.info(_('Deletion of %s complete'), target, instance=instance)
return True
+ @property
+ def need_legacy_block_device_info(self):
+ return False
+
+ def default_root_device_name(self, instance, image_meta, root_bdm):
+
+ disk_bus = blockinfo.get_disk_bus_for_device_type(CONF.libvirt_type,
+ image_meta,
+ "disk")
+ cdrom_bus = blockinfo.get_disk_bus_for_device_type(CONF.libvirt_type,
+ image_meta,
+ "cdrom")
+ root_info = blockinfo.get_root_info(CONF.libvirt_type,
+ image_meta, root_bdm,
+ disk_bus, cdrom_bus)
+ return block_device.prepend_dev(root_info['dev'])
+
+ def default_device_names_for_instance(self, instance, root_device_name,
+ *block_device_lists):
+ ephemerals, swap, block_device_mapping = block_device_lists[:3]
+
+ def _update_func(bdm):
+ bdm_id = bdm.get('id')
+ self.virtapi.block_device_mapping_update(
+ nova_context.get_admin_context(),
+ bdm_id, bdm)
+
+ blockinfo.default_device_names(CONF.libvirt_type,
+ instance, root_device_name,
+ _update_func,
+ ephemerals, swap,
+ block_device_mapping)
+
class HostState(object):
"""Manages information about the compute node through libvirt."""
diff --git a/nova/virt/virtapi.py b/nova/virt/virtapi.py
index 332eccd5b0..3fb5ef5141 100644
--- a/nova/virt/virtapi.py
+++ b/nova/virt/virtapi.py
@@ -99,3 +99,10 @@ class VirtAPI(object):
:param legacy: get bdm info in legacy format (or not)
"""
raise NotImplementedError()
+
+ def block_device_mapping_update(self, context, bdm_id, bdm_values):
+ """Update the databse for the passed block device mapping
+ :param context: security context
+ :param bdm: the block device mapping dict
+ """
+ raise NotImplementedError()