diff --git a/nova/tests/fixtures/libvirt_data.py b/nova/tests/fixtures/libvirt_data.py
index 7940ad2a069a..463cb0ae3f4a 100644
--- a/nova/tests/fixtures/libvirt_data.py
+++ b/nova/tests/fixtures/libvirt_data.py
@@ -82,7 +82,8 @@ def fake_kvm_guest():
obj.features = [
config.LibvirtConfigGuestFeatureACPI(),
config.LibvirtConfigGuestFeatureAPIC(),
- config.LibvirtConfigGuestFeatureKvmHidden()
+ config.LibvirtConfigGuestFeatureKvmHidden(),
+ config.LibvirtConfigGuestFeatureVMCoreInfo(),
]
obj.sysinfo = config.LibvirtConfigGuestSysinfo()
@@ -207,6 +208,7 @@ FAKE_KVM_GUEST = """
+
100
diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py
index 9f5e7865db92..ec65be7ce280 100644
--- a/nova/tests/unit/virt/libvirt/test_driver.py
+++ b/nova/tests/unit/virt/libvirt/test_driver.py
@@ -2571,11 +2571,13 @@ class LibvirtConnTestCase(test.NoDBTestCase,
context=ctxt)
self.assertEqual(cfg.uuid, instance_ref["uuid"])
- self.assertEqual(2, len(cfg.features))
+ 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.assertEqual(cfg.memory, 6 * units.Ki)
self.assertEqual(cfg.vcpus, 28)
self.assertEqual(cfg.os_type, fields.VMMode.HVM)
@@ -4863,13 +4865,15 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual("hypervclock", cfg.clock.timers[3].name)
self.assertTrue(cfg.clock.timers[3].present)
- self.assertEqual(3, len(cfg.features))
+ self.assertEqual(4, len(cfg.features))
self.assertIsInstance(cfg.features[0],
vconfig.LibvirtConfigGuestFeatureACPI)
self.assertIsInstance(cfg.features[1],
vconfig.LibvirtConfigGuestFeatureAPIC)
self.assertIsInstance(cfg.features[2],
vconfig.LibvirtConfigGuestFeatureHyperV)
+ self.assertIsInstance(
+ cfg.features[3], vconfig.LibvirtConfigGuestFeatureVMCoreInfo)
@mock.patch.object(host.Host, 'has_min_version',
new=mock.Mock(return_value=True))
@@ -4894,7 +4898,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
vconfig.LibvirtConfigGuestClock)
self.assertEqual(cfg.clock.offset, "localtime")
- num_features = 4 if hvid_hidden else 3
+ num_features = 5 if hvid_hidden else 4
self.assertEqual(num_features, len(cfg.features))
self.assertIsInstance(cfg.features[0],
vconfig.LibvirtConfigGuestFeatureACPI)
@@ -4902,9 +4906,11 @@ class LibvirtConnTestCase(test.NoDBTestCase,
vconfig.LibvirtConfigGuestFeatureAPIC)
self.assertIsInstance(cfg.features[2],
vconfig.LibvirtConfigGuestFeatureHyperV)
+ self.assertIsInstance(
+ cfg.features[3], vconfig.LibvirtConfigGuestFeatureVMCoreInfo)
if hvid_hidden:
- self.assertIsInstance(cfg.features[3],
- vconfig.LibvirtConfigGuestFeatureKvmHidden)
+ self.assertIsInstance(
+ cfg.features[4], vconfig.LibvirtConfigGuestFeatureKvmHidden)
self.assertTrue(cfg.features[2].relaxed)
self.assertTrue(cfg.features[2].spinlocks)
@@ -4980,11 +4986,13 @@ class LibvirtConnTestCase(test.NoDBTestCase,
cfg = drvr._get_guest_config(instance_ref,
_fake_network_info(self, 2),
image_meta, disk_info)
- self.assertEqual(2, len(cfg.features))
+ 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.assertEqual(cfg.memory, instance_ref.flavor.memory_mb * units.Ki)
self.assertEqual(cfg.vcpus, instance_ref.flavor.vcpus)
self.assertEqual(cfg.os_type, fields.VMMode.HVM)
diff --git a/nova/virt/libvirt/config.py b/nova/virt/libvirt/config.py
index f9475776b3da..c49c187d2d02 100644
--- a/nova/virt/libvirt/config.py
+++ b/nova/virt/libvirt/config.py
@@ -2762,6 +2762,12 @@ class LibvirtConfigGuestSEVLaunchSecurity(LibvirtConfigObject):
return root
+class LibvirtConfigGuestFeatureVMCoreInfo(LibvirtConfigGuestFeature):
+
+ def __init__(self, **kwargs):
+ super().__init__('vmcoreinfo', **kwargs)
+
+
class LibvirtConfigGuest(LibvirtConfigObject):
def __init__(self, **kwargs):
diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py
index 391231c52775..153df2d06ae9 100644
--- a/nova/virt/libvirt/driver.py
+++ b/nova/virt/libvirt/driver.py
@@ -5854,6 +5854,15 @@ class LibvirtDriver(driver.ComputeDriver):
guest.features.append(hv)
if CONF.libvirt.virt_type in ("qemu", "kvm"):
+ # vmcoreinfo support is x86, ARM-only for now
+ guestarch = libvirt_utils.get_arch(image_meta)
+ if guestarch in (
+ fields.Architecture.I686, fields.Architecture.X86_64,
+ fields.Architecture.AARCH64,
+ ):
+ guest.features.append(
+ vconfig.LibvirtConfigGuestFeatureVMCoreInfo())
+
if hide_hypervisor_id:
guest.features.append(
vconfig.LibvirtConfigGuestFeatureKvmHidden())
diff --git a/releasenotes/notes/libvirt-vmcoreinfo-3be69e21dfe7dbd2.yaml b/releasenotes/notes/libvirt-vmcoreinfo-3be69e21dfe7dbd2.yaml
new file mode 100644
index 000000000000..2bd5c9cb98e4
--- /dev/null
+++ b/releasenotes/notes/libvirt-vmcoreinfo-3be69e21dfe7dbd2.yaml
@@ -0,0 +1,10 @@
+---
+features:
+ - |
+ When using the libvirt virt driver with the QEMU or KVM backends, instances
+ will now be created with the *vmcoreinfo* feature enabled by default. This
+ creates a fw_cfg entry for a guest to store dump details, necessary to
+ process kernel dump with KASLR enabled and providing additional kernel
+ details. For more information, refer to the `libvirt`__ documentation.
+
+ __ https://libvirt.org/formatdomain.html#hypervisor-features