libvirt: Avoid Glance.show on hard_reboot
When a Libvirt host is rebooted, we can optionally choose to automatically spin back up the instances using the `resume_state_on_host_boot` call. This, in turn, uses `_hard_reboot` to bring back the instances. The problem is that `_get_guest_xml` which `_hard_reboot` is using is always making a call to Glance.show since `image_meta` isn't being passed into it. In addition to this being an extra latency-heavy call, this is big problem because the request is *server-generated* not *user-generated* so we won't have the necessary user-request context to make the Glance call. In the absense of a general user-impersonation mechanism, the current workaround is to use cached image-metadata, which works in this case as well. So the fix is to pass that `image_meta` that we already pull from instance metadata in `_hard_reboot` and pass it into `_get_guest_xml` and thus avoid the extra request to Glance. Change-Id: I2203ac709405ee784ee5ec017aa475575a46a0df Closes-Bug: 1339386
This commit is contained in:
parent
54d0f898f6
commit
65341b2547
|
@ -5664,7 +5664,12 @@ class LibvirtConnTestCase(test.TestCase,
|
|||
conn._destroy(instance)
|
||||
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
|
||||
instance, block_device_info)
|
||||
|
||||
system_meta = utils.instance_sys_meta(instance)
|
||||
image_meta = utils.get_image_from_system_metadata(system_meta)
|
||||
|
||||
conn._get_guest_xml(self.context, instance, network_info, disk_info,
|
||||
image_meta=image_meta,
|
||||
block_device_info=block_device_info,
|
||||
write_to_disk=True).AndReturn(dummyxml)
|
||||
disk_info_json = '[{"virt_disk_size": 2}]'
|
||||
|
@ -5681,6 +5686,50 @@ class LibvirtConnTestCase(test.TestCase,
|
|||
conn._hard_reboot(self.context, instance, network_info,
|
||||
block_device_info)
|
||||
|
||||
@mock.patch('nova.openstack.common.loopingcall.FixedIntervalLoopingCall')
|
||||
@mock.patch('nova.pci.pci_manager.get_instance_pci_devs')
|
||||
@mock.patch('nova.virt.libvirt.LibvirtDriver._prepare_pci_devices_for_use')
|
||||
@mock.patch('nova.virt.libvirt.LibvirtDriver._create_domain_and_network')
|
||||
@mock.patch('nova.virt.libvirt.LibvirtDriver._create_images_and_backing')
|
||||
@mock.patch('nova.virt.libvirt.LibvirtDriver._get_instance_disk_info')
|
||||
@mock.patch('nova.virt.libvirt.utils.write_to_file')
|
||||
@mock.patch('nova.virt.libvirt.utils.get_instance_path')
|
||||
@mock.patch('nova.virt.libvirt.LibvirtDriver._get_guest_config')
|
||||
@mock.patch('nova.virt.libvirt.blockinfo.get_disk_info')
|
||||
@mock.patch('nova.virt.libvirt.LibvirtDriver._destroy')
|
||||
def test_hard_reboot_doesnt_call_glance_show(self,
|
||||
mock_destroy, mock_get_disk_info, mock_get_guest_config,
|
||||
mock_get_instance_path, mock_write_to_file,
|
||||
mock_get_instance_disk_info, mock_create_images_and_backing,
|
||||
mock_create_domand_and_network, mock_prepare_pci_devices_for_use,
|
||||
mock_get_instance_pci_devs, mock_looping_call):
|
||||
"""For a hard reboot, we shouldn't need an additional call to glance
|
||||
to get the image metadata.
|
||||
|
||||
This is important for automatically spinning up instances on a
|
||||
host-reboot, since we won't have a user request context that'll allow
|
||||
the Glance request to go through. We have to rely on the cached image
|
||||
metadata, instead.
|
||||
|
||||
https://bugs.launchpad.net/nova/+bug/1339386
|
||||
"""
|
||||
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||
|
||||
instance = db.instance_create(self.context, self.test_instance)
|
||||
|
||||
network_info = mock.MagicMock()
|
||||
block_device_info = mock.MagicMock()
|
||||
mock_get_disk_info.return_value = {}
|
||||
mock_get_guest_config.return_value = mock.MagicMock()
|
||||
mock_get_instance_path.return_value = '/foo'
|
||||
mock_looping_call.return_value = mock.MagicMock()
|
||||
conn._image_api = mock.MagicMock()
|
||||
|
||||
conn._hard_reboot(self.context, instance, network_info,
|
||||
block_device_info)
|
||||
|
||||
self.assertFalse(conn._image_api.get.called)
|
||||
|
||||
def test_power_on(self):
|
||||
|
||||
def _check_xml_bus(name, xml, block_info):
|
||||
|
@ -5733,12 +5782,9 @@ class LibvirtConnTestCase(test.TestCase,
|
|||
|
||||
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||
with contextlib.nested(
|
||||
mock.patch.object(conn, '_destroy', return_value=None),
|
||||
mock.patch.object(conn, '_create_images_and_backing'),
|
||||
mock.patch.object(conn, '_create_domain_and_network'),
|
||||
mock.patch('nova.image.glance.get_remote_image_service',
|
||||
return_value=(image_service_mock,
|
||||
instance['image_ref']))):
|
||||
mock.patch.object(conn, '_destroy', return_value=None),
|
||||
mock.patch.object(conn, '_create_images_and_backing'),
|
||||
mock.patch.object(conn, '_create_domain_and_network')):
|
||||
conn.get_info = fake_get_info
|
||||
conn._get_instance_disk_info = _check_xml_bus
|
||||
conn._hard_reboot(self.context, instance, network_info,
|
||||
|
|
|
@ -2057,6 +2057,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
# does we need to (re)generate the xml after the images
|
||||
# are in place.
|
||||
xml = self._get_guest_xml(context, instance, network_info, disk_info,
|
||||
image_meta=image_meta,
|
||||
block_device_info=block_device_info,
|
||||
write_to_disk=True)
|
||||
|
||||
|
@ -3433,7 +3434,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
def _get_guest_xml(self, context, instance, network_info, disk_info,
|
||||
image_meta=None, rescue=None,
|
||||
block_device_info=None, write_to_disk=False):
|
||||
# We should get image metadata every time for generating xml
|
||||
|
||||
if image_meta is None:
|
||||
image_ref = instance['image_ref']
|
||||
image_meta = compute_utils.get_image_metadata(
|
||||
|
|
Loading…
Reference in New Issue