libvirt: check if ImageMeta.disk_format is set before accessing it

Commit 4f43bbafa4 changed
blockinfo.get_root_info to access the disk_format attribute on the
passed in image_meta (ImageMeta object) like an object, but if that
attribute is not set you'll get an error.

image_meta can be an empty object in the case of evacuate where
image_ref is passed as None to the compute manager's rebuild_instance
method in the case of evacuate, so image_meta defaults to {}. So when
the ImageMeta object is created in LibvirtDriver.spawn, there is nothing
in it.

We have to check if the attribute is set before accessing it using
obj_attr_is_set because the ImageMeta class does not include the
NovaObjectDictCompat mixin, so we can't use
image_meta.get('disk_format').

Closes-Bug: #1501831

Change-Id: I95e543415b881603bb997ae0e159017c03e58a53
This commit is contained in:
Matt Riedemann 2015-10-02 13:00:43 -07:00
parent a1ae2d60aa
commit 0717d064a5
2 changed files with 25 additions and 1 deletions

View File

@ -868,6 +868,26 @@ class LibvirtBlockInfoTest(test.NoDBTestCase):
'virtio', 'ide', root_device_name='/dev/vda')
mock_get_bus.assert_called_once_with('kvm', '/dev/vda')
@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_empty_image_meta(self, mock_get_bus,
mock_find_dev):
# The evacuate operation passes image_ref=None to the compute node for
# rebuild which then defaults image_meta to {}, so we don't have any
# attributes in the ImageMeta object passed to get_root_info and we
# need to make sure we don't try lazy-loading anything.
instance = objects.Instance(**self.test_instance)
image_meta = objects.ImageMeta.from_dict({})
blockinfo.get_root_info(instance, 'kvm', image_meta, None,
'virtio', 'ide')
mock_find_dev.assert_called_once_with({}, 'virtio')
blockinfo.get_root_info(instance, 'kvm', image_meta, 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):
instance = objects.Instance(**self.test_instance)

View File

@ -429,7 +429,11 @@ def get_root_info(instance, virt_type, image_meta, root_bdm,
root_bdm.get('source_type') == 'image' and
root_bdm.get('destination_type') == 'local'))
if no_root_bdm:
if image_meta.disk_format == 'iso':
# 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.
if (image_meta.obj_attr_is_set('disk_format') and
image_meta.disk_format == 'iso'):
root_device_bus = cdrom_bus
root_device_type = 'cdrom'
else: