From a18dbb5670da0c0b63c4bd69055262b4b7b17e58 Mon Sep 17 00:00:00 2001 From: Marcin Juszkiewicz Date: Mon, 23 Mar 2020 12:07:02 +0100 Subject: [PATCH] libvirt: Change UEFI check to handle AArch64 better Nova assumes that images run on UEFI instances will have 'hw_firmware_type' property set. This is wrong assumption because UEFI is the default on AArch64, meaning images do not need to have this set. This results in a failure to remove the instance, with libvirt raising the following error: Instance failed to spawn: libvirt.libvirtError: Requested operation is not valid: cannot undefine domain with nvram Resolve this by checking *both* the image metadata property and the machine arch. Change-Id: I2956fe2e3582c36d1c52a7e3becde1dacd9d41f0 Closes-bug: #1868464 --- nova/tests/unit/virt/libvirt/test_driver.py | 7 +++++++ nova/virt/libvirt/driver.py | 15 +++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index b3f0025c35..71e3bf908e 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -4562,6 +4562,13 @@ class LibvirtConnTestCase(test.NoDBTestCase, mock_support.assert_called_once_with() self.assertEqual(cfg.os_loader_type, "pflash") + @mock.patch('os.path.exists', return_value=True) + def test_check_uefi_support_aarch64(self, mock_exist): + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) + self._stub_host_capabilities_cpu_arch(fields.Architecture.AARCH64) + self.assertTrue(drvr._has_uefi_support()) + self.assertTrue(drvr._check_uefi_support(None)) + def test_get_guest_config_with_block_device(self): drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 45af21c3bb..9ddf6918ce 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -1272,8 +1272,7 @@ class LibvirtDriver(driver.ComputeDriver): try: hw_firmware_type = instance.image_meta.properties.get( 'hw_firmware_type') - support_uefi = (self._has_uefi_support() and - hw_firmware_type == fields.FirmwareType.UEFI) + support_uefi = self._check_uefi_support(hw_firmware_type) guest.delete_configuration(support_uefi) except libvirt.libvirtError as e: with excutils.save_and_reraise_exception() as ctxt: @@ -1793,8 +1792,7 @@ class LibvirtDriver(driver.ComputeDriver): # If any part of this block fails, the domain is # re-defined regardless. if guest.has_persistent_configuration(): - support_uefi = (self._has_uefi_support() and - hw_firmware_type == fields.FirmwareType.UEFI) + support_uefi = self._check_uefi_support(hw_firmware_type) guest.delete_configuration(support_uefi) try: @@ -2553,8 +2551,7 @@ class LibvirtDriver(driver.ComputeDriver): if guest.has_persistent_configuration(): hw_firmware_type = image_meta.properties.get( 'hw_firmware_type') - support_uefi = (self._has_uefi_support() and - hw_firmware_type == fields.FirmwareType.UEFI) + support_uefi = self._check_uefi_support(hw_firmware_type) guest.delete_configuration(support_uefi) # NOTE (rmk): Establish a temporary mirror of our root disk and @@ -5321,6 +5318,12 @@ class LibvirtDriver(driver.ComputeDriver): any((os.path.exists(p) for p in DEFAULT_UEFI_LOADER_PATH[caps.host.cpu.arch]))) + def _check_uefi_support(self, hw_firmware_type): + caps = self._host.get_capabilities() + return (self._has_uefi_support() and + (hw_firmware_type == fields.FirmwareType.UEFI or + caps.host.cpu.arch == fields.Architecture.AARCH64)) + def _get_supported_perf_events(self): if (len(CONF.libvirt.enabled_perf_events) == 0):