From e212a1e7449c0374011061e338491610479f8adb Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Tue, 2 Dec 2025 00:19:55 +0900 Subject: [PATCH] libvirt: Add capability to load smm feature from existing xml Some firmwares require smm feature. While the feature doesn't have to be explicitly enabled when auto-selection is enabled, it should be enabled explicitly when firmware files are pre-defined. Partially-Implements: blueprint libvirt-firmware-auto-selection Change-Id: Ia194dcfacd2b743761e720d947a6807689a96da3 Signed-off-by: Takashi Kajinami --- nova/tests/unit/virt/libvirt/test_config.py | 14 ++++++++++++++ nova/virt/libvirt/config.py | 21 +++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/nova/tests/unit/virt/libvirt/test_config.py b/nova/tests/unit/virt/libvirt/test_config.py index 155f31501921..082863014fbe 100644 --- a/nova/tests/unit/virt/libvirt/test_config.py +++ b/nova/tests/unit/virt/libvirt/test_config.py @@ -3135,6 +3135,7 @@ class LibvirtConfigGuestTest(LibvirtConfigBaseTest): self.assertEqual('fake_machine_type', obj.os_mach_type) self.assertEqual('/tmp/vmlinuz', obj.os_kernel) self.assertEqual('/usr/lib/xen/boot/hvmloader', obj.os_loader) + self.assertNotIn(config.LibvirtConfigGuestFeatureSMM(), obj.features) self.assertIsNone(obj.os_loader_type) self.assertIsNone(obj.os_loader_readonly) self.assertIsNone(obj.os_loader_secure) @@ -3157,6 +3158,10 @@ class LibvirtConfigGuestTest(LibvirtConfigBaseTest): /tmp/OVMF_CODE.fd /var/lib/libvirt/qemu/nvram/instance.fd + + + + """ # noqa: E501 @@ -3167,6 +3172,7 @@ class LibvirtConfigGuestTest(LibvirtConfigBaseTest): self.assertEqual('hvm', obj.os_type) self.assertIsNone(obj.os_mach_type) self.assertIsNone(obj.os_kernel) + self.assertIn(config.LibvirtConfigGuestFeatureSMM(), obj.features) self.assertEqual('/tmp/OVMF_CODE.fd', obj.os_loader) self.assertEqual('pflash', obj.os_loader_type) self.assertTrue(obj.os_loader_readonly) @@ -3190,6 +3196,9 @@ class LibvirtConfigGuestTest(LibvirtConfigBaseTest): /tmp/OVMF_CODE.secboot.fd /var/lib/libvirt/qemu/nvram/instance.fd + + + """ # noqa: E501 @@ -3200,6 +3209,7 @@ class LibvirtConfigGuestTest(LibvirtConfigBaseTest): self.assertEqual('hvm', obj.os_type) self.assertIsNone(obj.os_mach_type) self.assertIsNone(obj.os_kernel) + self.assertIn(config.LibvirtConfigGuestFeatureSMM(), obj.features) self.assertEqual('/tmp/OVMF_CODE.secboot.fd', obj.os_loader) self.assertEqual('pflash', obj.os_loader_type) self.assertTrue(obj.os_loader_readonly) @@ -3222,6 +3232,9 @@ class LibvirtConfigGuestTest(LibvirtConfigBaseTest): hvm /tmp/OVMF_CODE.fd + + + """ # noqa: E501 @@ -3232,6 +3245,7 @@ class LibvirtConfigGuestTest(LibvirtConfigBaseTest): self.assertEqual('hvm', obj.os_type) self.assertIsNone(obj.os_mach_type) self.assertIsNone(obj.os_kernel) + self.assertNotIn(config.LibvirtConfigGuestFeatureSMM(), obj.features) self.assertEqual('/tmp/OVMF_CODE.fd', obj.os_loader) self.assertEqual('pflash', obj.os_loader_type) self.assertTrue(obj.os_loader_readonly) diff --git a/nova/virt/libvirt/config.py b/nova/virt/libvirt/config.py index 0f0296baa073..584241002875 100644 --- a/nova/virt/libvirt/config.py +++ b/nova/virt/libvirt/config.py @@ -827,8 +827,10 @@ class LibvirtConfigCPUFeature(LibvirtConfigObject): return ft - def __eq__(self, obj): - return obj.name == self.name + def __eq__(self, other): + if not isinstance(other, LibvirtConfigCPUFeature): + return False + return other.name == self.name def __ne__(self, obj): return obj.name != self.name @@ -2901,6 +2903,11 @@ class LibvirtConfigGuestFeature(LibvirtConfigObject): super(LibvirtConfigGuestFeature, self).__init__(root_name=name, **kwargs) + def __eq__(self, other): + if not isinstance(other, LibvirtConfigGuestFeature): + return False + return other.root_name == self.root_name + class LibvirtConfigGuestFeatureACPI(LibvirtConfigGuestFeature): @@ -2934,6 +2941,11 @@ class LibvirtConfigGuestFeatureSMM(LibvirtConfigGuestFeature): def __init__(self, **kwargs): super(LibvirtConfigGuestFeatureSMM, self).__init__("smm", **kwargs) + # NOTE(tkajinam): The smm feature also supports tseg sub-element, which + # has not set by nova or libvirt. Using the tseg option requires + # huge caution according to libvirt doc[1], so the option is + # intentionally left unimplemented now. + # [1] https://libvirt.org/formatdomain.html#hypervisor-features def format_dom(self): root = super(LibvirtConfigGuestFeatureSMM, self).format_dom() @@ -3379,6 +3391,7 @@ class LibvirtConfigGuest(LibvirtConfigObject): def parse_dom(self, xmldoc): self.virt_type = xmldoc.get('type') # Note: This cover only for: LibvirtConfigGuestDisks + # LibvirtConfigGuestFeatureSMM # LibvirtConfigGuestFilesys # LibvirtConfigGuestHostdevPCI # LibvirtConfigGuestHostdevMDEV @@ -3442,6 +3455,10 @@ class LibvirtConfigGuest(LibvirtConfigObject): self._parse_os(c) elif c.tag == 'iothreads': self.iothreads = int(c.text) + elif c.tag == 'features': + for f in c: + if f.tag == 'smm' and f.get('state', 'on') == 'on': + self.features.append(LibvirtConfigGuestFeatureSMM()) else: self._parse_basic_props(c)