diff --git a/nova/tests/unit/virt/libvirt/test_config.py b/nova/tests/unit/virt/libvirt/test_config.py
index 396edfd02482..1fe3b52e2ed6 100644
--- a/nova/tests/unit/virt/libvirt/test_config.py
+++ b/nova/tests/unit/virt/libvirt/test_config.py
@@ -2318,6 +2318,15 @@ class LibvirtConfigGuestFeatureTest(LibvirtConfigBaseTest):
obj.vapic = True
obj.spinlocks = True
obj.vendorid_spoof = True
+ obj.vpindex = True
+ obj.runtime = True
+ obj.synic = True
+ obj.reset = True
+ obj.frequencies = True
+ obj.reenlightenment = True
+ obj.tlbflush = True
+ obj.ipi = True
+ obj.evmcs = True
xml = obj.to_xml()
self.assertXmlEqual(xml, """
@@ -2326,6 +2335,15 @@ class LibvirtConfigGuestFeatureTest(LibvirtConfigBaseTest):
+
+
+
+
+
+
+
+
+
""")
def test_feature_pmu(self):
diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py
index 7233c00a72cc..cac5a5bcbec8 100644
--- a/nova/tests/unit/virt/libvirt/test_driver.py
+++ b/nova/tests/unit/virt/libvirt/test_driver.py
@@ -27172,6 +27172,35 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
mock_get_guest.return_value.assert_not_called()
self.assertIsNone(mock_find.call_args.args[3])
+ def test_set_features_windows(self):
+ self.flags(virt_type='kvm', group='libvirt')
+ guest = vconfig.LibvirtConfigGuest()
+ self.drvr._set_features(
+ guest, 'windows',
+ objects.ImageMeta(
+ properties=objects.ImageMetaProps()
+ ),
+ objects.Flavor(extra_specs={})
+ )
+ features = guest.features
+ hv = None
+ for feature in features:
+ if feature.root_name == 'hyperv':
+ hv = feature
+ self.assertTrue(hv.relaxed)
+ self.assertTrue(hv.vapic)
+ self.assertTrue(hv.spinlocks)
+ self.assertEqual(8191, hv.spinlock_retries)
+ self.assertTrue(hv.vpindex)
+ self.assertTrue(hv.runtime)
+ self.assertTrue(hv.synic)
+ self.assertTrue(hv.reset)
+ self.assertTrue(hv.frequencies)
+ self.assertTrue(hv.reenlightenment)
+ self.assertTrue(hv.tlbflush)
+ self.assertTrue(hv.ipi)
+ self.assertTrue(hv.evmcs)
+
class LibvirtVolumeUsageTestCase(test.NoDBTestCase):
"""Test for LibvirtDriver.get_all_volume_usage."""
diff --git a/nova/virt/libvirt/config.py b/nova/virt/libvirt/config.py
index 1a81be3ade56..4444d7cd2896 100644
--- a/nova/virt/libvirt/config.py
+++ b/nova/virt/libvirt/config.py
@@ -2732,6 +2732,15 @@ class LibvirtConfigGuestFeatureHyperV(LibvirtConfigGuestFeature):
self.vapic = False
self.spinlocks = False
self.spinlock_retries = self.MIN_SPINLOCK_RETRIES
+ self.vpindex = False
+ self.runtime = False
+ self.synic = False
+ self.reset = False
+ self.frequencies = False
+ self.reenlightenment = False
+ self.tlbflush = False
+ self.ipi = False
+ self.evmcs = False
self.vendorid_spoof = False
self.vendorid = self.SPOOFED_VENDOR_ID
@@ -2748,6 +2757,24 @@ class LibvirtConfigGuestFeatureHyperV(LibvirtConfigGuestFeature):
if self.vendorid_spoof:
root.append(etree.Element("vendor_id", state="on",
value=self.vendorid))
+ if self.vpindex:
+ root.append(etree.Element('vpindex', state='on'))
+ if self.runtime:
+ root.append(etree.Element('runtime', state='on'))
+ if self.synic:
+ root.append(etree.Element('synic', state='on'))
+ if self.reset:
+ root.append(etree.Element('reset', state='on'))
+ if self.frequencies:
+ root.append(etree.Element('frequencies', state='on'))
+ if self.reenlightenment:
+ root.append(etree.Element('reenlightenment', state='on'))
+ if self.tlbflush:
+ root.append(etree.Element('tlbflush', state='on'))
+ if self.ipi:
+ root.append(etree.Element('ipi', state='on'))
+ if self.evmcs:
+ root.append(etree.Element('evmcs', state='on'))
return root
diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py
index b35f17fe3ae4..096433c2ae61 100644
--- a/nova/virt/libvirt/driver.py
+++ b/nova/virt/libvirt/driver.py
@@ -6080,6 +6080,15 @@ class LibvirtDriver(driver.ComputeDriver):
# with Microsoft
hv.spinlock_retries = 8191
hv.vapic = True
+ hv.vpindex = True
+ hv.runtime = True
+ hv.synic = True
+ hv.reset = True
+ hv.frequencies = True
+ hv.reenlightenment = True
+ hv.tlbflush = True
+ hv.ipi = True
+ hv.evmcs = True
# NOTE(kosamara): Spoofing the vendor_id aims to allow the nvidia
# driver to work on windows VMs. At the moment, the nvidia driver
diff --git a/releasenotes/notes/update-libvirt-enlightenments-for-windows-23abea98cc1db667.yaml b/releasenotes/notes/update-libvirt-enlightenments-for-windows-23abea98cc1db667.yaml
new file mode 100644
index 000000000000..c262be152749
--- /dev/null
+++ b/releasenotes/notes/update-libvirt-enlightenments-for-windows-23abea98cc1db667.yaml
@@ -0,0 +1,21 @@
+---
+features:
+ - |
+ The following enlightenments are now added by default to the libvirt XML for Windows guests:
+
+ * vpindex
+ * runtime
+ * synic
+ * reset
+ * frequencies
+ * reenlightenment
+ * tlbflush
+ * ipi
+ * evmc
+
+ This adds to the list of already existing enlightenments, namely:
+
+ * relaxed
+ * vapic
+ * spinlocks retries
+ * vendor_id spoofing