From ec48e1523dfdd0f1031e1a70c28c56962db66e8a Mon Sep 17 00:00:00 2001 From: Sean Mooney Date: Tue, 8 Dec 2020 16:42:52 +0000 Subject: [PATCH] workarounds: Add libvirt_disable_apic This change adds a new workaround config option to allow disabling the guest apic. Co-authored-by: Lee Yarwood Related-Bug: #1939108 Change-Id: I2da867f2734b590a884b1fe1200c402cbf7e9e1c --- nova/conf/workarounds.py | 10 ++++++ nova/tests/unit/virt/libvirt/test_driver.py | 31 +++++++++++++++++++ nova/virt/libvirt/driver.py | 3 +- ...libvirt-disable-apic-39599bdc2d110a1f.yaml | 13 ++++++++ 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/libvirt-disable-apic-39599bdc2d110a1f.yaml diff --git a/nova/conf/workarounds.py b/nova/conf/workarounds.py index 53a9f3d417a0..4e51c8cc79f9 100644 --- a/nova/conf/workarounds.py +++ b/nova/conf/workarounds.py @@ -353,6 +353,16 @@ Related options: * :oslo.config:option:`DEFAULT.instances_path` * :oslo.config:option:`image_cache.subdirectory_name` * :oslo.config:option:`update_resources_interval` +"""), + cfg.BoolOpt('libvirt_disable_apic', + default=False, + help=""" +With some kernels initializing the guest apic can result in a kernel hang that +renders the guest unusable. This happens as a result of a kernel bug. In most +cases the correct fix it to update the guest image kernel to one that is +patched however in some cases this is not possible. This workaround allows the +emulation of an apic to be disabled per host however it is not recommended to +use outside of a CI or developer cloud. """), ] diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 49b4773fc9d8..9eb75c495252 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -4917,6 +4917,37 @@ class LibvirtConnTestCase(test.NoDBTestCase, self.assertTrue(cfg.features[2].vapic) self.assertEqual(hvid_hidden, cfg.features[2].vendorid_spoof) + @mock.patch.object(host.Host, 'has_min_version', + new=mock.Mock(return_value=True)) + def test_get_guest_config_apic_workaround(self): + self.flags(virt_type='qemu', group='libvirt') + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) + instance_ref = objects.Instance(**self.test_instance) + image_meta = objects.ImageMeta.from_dict(self.test_image_meta) + disk_info = blockinfo.get_disk_info( + CONF.libvirt.virt_type, instance_ref, image_meta) + + cfg = drvr._get_guest_config( + instance_ref, _fake_network_info(self), image_meta, disk_info) + + self.assertEqual(3, len(cfg.features)) + self.assertIsInstance( + cfg.features[0], vconfig.LibvirtConfigGuestFeatureACPI) + self.assertIsInstance( + cfg.features[1], vconfig.LibvirtConfigGuestFeatureAPIC) + self.assertIsInstance( + cfg.features[2], vconfig.LibvirtConfigGuestFeatureVMCoreInfo) + + self.flags(libvirt_disable_apic=True, group='workarounds') + cfg = drvr._get_guest_config( + instance_ref, _fake_network_info(self), image_meta, disk_info) + + self.assertEqual(2, len(cfg.features)) + self.assertIsInstance( + cfg.features[0], vconfig.LibvirtConfigGuestFeatureACPI) + self.assertIsInstance( + cfg.features[1], vconfig.LibvirtConfigGuestFeatureVMCoreInfo) + def test_get_guest_config_windows_hyperv_feature2(self): self._test_get_guest_config_windows_hyperv() diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 8d544c9118e4..e7e2c5536400 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -5859,7 +5859,8 @@ class LibvirtDriver(driver.ComputeDriver): if CONF.libvirt.virt_type in ('qemu', 'kvm'): guest.features.append(vconfig.LibvirtConfigGuestFeatureACPI()) - guest.features.append(vconfig.LibvirtConfigGuestFeatureAPIC()) + if not CONF.workarounds.libvirt_disable_apic: + guest.features.append(vconfig.LibvirtConfigGuestFeatureAPIC()) if CONF.libvirt.virt_type in ('qemu', 'kvm') and os_type == 'windows': hv = vconfig.LibvirtConfigGuestFeatureHyperV() diff --git a/releasenotes/notes/libvirt-disable-apic-39599bdc2d110a1f.yaml b/releasenotes/notes/libvirt-disable-apic-39599bdc2d110a1f.yaml new file mode 100644 index 000000000000..83ab5d7a034c --- /dev/null +++ b/releasenotes/notes/libvirt-disable-apic-39599bdc2d110a1f.yaml @@ -0,0 +1,13 @@ +--- +issues: + - | + Linux guest images that have known kernel bugs related to virtualized apic + initialization previously would sporadically hang. For images where the + kernel cannot be upgraded, a ``[workarounds]`` config option has been + introduced: + + ``[workarounds]libvirt_disable_apic`` + + This option is primarily intended for CI and development clouds as a bridge + for operators to mitigate the issue while they work with their upstream + image vendors.