From 3136d594a40aa2fd5e5ce3a47d25d761d31aaaa9 Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Mon, 1 Dec 2025 22:56:20 +0900 Subject: [PATCH] libvirt: Add capability to load loader and nvram from xml ... so that we can load these from existing guest XML. This is a preparation work to use firmware auto-selection by libvirt, and is required to avoid re-selection during hard-reboot. Partially-Implements: blueprint libvirt-firmware-auto-selection Change-Id: I899cb7d6ee364def8d1298b77c24cc5156c71126 Signed-off-by: Takashi Kajinami --- nova/tests/unit/virt/libvirt/test_config.py | 84 ++++++++++++++++++++- nova/virt/libvirt/config.py | 18 ++++- nova/virt/libvirt/driver.py | 1 + 3 files changed, 97 insertions(+), 6 deletions(-) diff --git a/nova/tests/unit/virt/libvirt/test_config.py b/nova/tests/unit/virt/libvirt/test_config.py index e9f2dc6fd8d4..155f31501921 100644 --- a/nova/tests/unit/virt/libvirt/test_config.py +++ b/nova/tests/unit/virt/libvirt/test_config.py @@ -2863,9 +2863,10 @@ class LibvirtConfigGuestTest(LibvirtConfigBaseTest): obj.os_mach_type = "pc-q35-5.1" obj.os_loader = '/tmp/OVMF_CODE.secboot.fd' obj.os_loader_type = 'pflash' - obj.os_nvram = '/foo/bar/instance-00000012_VARS.fd' + obj.os_loader_readonly = True obj.os_loader_secure = True obj.os_loader_stateless = True + obj.os_nvram = '/foo/bar/instance-00000012_VARS.fd' xml = obj.to_xml() self.assertxmlequal( @@ -2878,7 +2879,7 @@ class LibvirtConfigGuestTest(LibvirtConfigBaseTest): hvm /tmp/OVMF_CODE.secboot.fd - /foo/bar/instance-00000012_VARS.fd + /foo/bar/instance-00000012_VARS.fd """, # noqa: E501 xml, @@ -3135,6 +3136,11 @@ class LibvirtConfigGuestTest(LibvirtConfigBaseTest): self.assertEqual('/tmp/vmlinuz', obj.os_kernel) self.assertEqual('/usr/lib/xen/boot/hvmloader', obj.os_loader) self.assertIsNone(obj.os_loader_type) + self.assertIsNone(obj.os_loader_readonly) + self.assertIsNone(obj.os_loader_secure) + self.assertIsNone(obj.os_loader_stateless) + self.assertIsNone(obj.os_nvram) + self.assertIsNone(obj.os_nvram_template) self.assertEqual('/tmp/ramdisk', obj.os_initrd) self.assertEqual('console=xvc0', obj.os_cmdline) self.assertEqual('root=xvda', obj.os_root) @@ -3149,9 +3155,11 @@ class LibvirtConfigGuestTest(LibvirtConfigBaseTest): hvm /tmp/OVMF_CODE.fd + /var/lib/libvirt/qemu/nvram/instance.fd - """ + """ # noqa: E501 + obj = config.LibvirtConfigGuest() obj.parse_str(xmldoc) @@ -3161,6 +3169,76 @@ class LibvirtConfigGuestTest(LibvirtConfigBaseTest): self.assertIsNone(obj.os_kernel) self.assertEqual('/tmp/OVMF_CODE.fd', obj.os_loader) self.assertEqual('pflash', obj.os_loader_type) + self.assertTrue(obj.os_loader_readonly) + self.assertIsNone(obj.os_loader_secure) + self.assertIsNone(obj.os_loader_stateless) + self.assertEqual('/var/lib/libvirt/qemu/nvram/instance.fd', + obj.os_nvram) + self.assertEqual('/tmp/OVMF_VARS.fd', obj.os_nvram_template) + self.assertIsNone(obj.os_initrd) + self.assertIsNone(obj.os_cmdline) + self.assertIsNone(obj.os_root) + self.assertIsNone(obj.os_init_path) + self.assertEqual([], obj.os_boot_dev) + self.assertFalse(obj.os_bootmenu) + self.assertIsNone(obj.os_smbios) + + xmldoc = """ + + + hvm + /tmp/OVMF_CODE.secboot.fd + /var/lib/libvirt/qemu/nvram/instance.fd + + + """ # noqa: E501 + + obj = config.LibvirtConfigGuest() + obj.parse_str(xmldoc) + + self.assertIsNone(obj.virt_type) + self.assertEqual('hvm', obj.os_type) + self.assertIsNone(obj.os_mach_type) + self.assertIsNone(obj.os_kernel) + self.assertEqual('/tmp/OVMF_CODE.secboot.fd', obj.os_loader) + self.assertEqual('pflash', obj.os_loader_type) + self.assertTrue(obj.os_loader_readonly) + self.assertTrue(obj.os_loader_secure) + self.assertIsNone(obj.os_loader_stateless) + self.assertEqual('/var/lib/libvirt/qemu/nvram/instance.fd', + obj.os_nvram) + self.assertEqual('/tmp/OVMF_VARS.secboot.fd', obj.os_nvram_template) + self.assertIsNone(obj.os_initrd) + self.assertIsNone(obj.os_cmdline) + self.assertIsNone(obj.os_root) + self.assertIsNone(obj.os_init_path) + self.assertEqual([], obj.os_boot_dev) + self.assertFalse(obj.os_bootmenu) + self.assertIsNone(obj.os_smbios) + + xmldoc = """ + + + hvm + /tmp/OVMF_CODE.fd + + + """ # noqa: E501 + + obj = config.LibvirtConfigGuest() + obj.parse_str(xmldoc) + + self.assertIsNone(obj.virt_type) + self.assertEqual('hvm', obj.os_type) + self.assertIsNone(obj.os_mach_type) + self.assertIsNone(obj.os_kernel) + self.assertEqual('/tmp/OVMF_CODE.fd', obj.os_loader) + self.assertEqual('pflash', obj.os_loader_type) + self.assertTrue(obj.os_loader_readonly) + self.assertIsNone(obj.os_loader_secure) + self.assertTrue(obj.os_loader_stateless) + self.assertIsNone(obj.os_nvram) + self.assertIsNone(obj.os_nvram_template) self.assertIsNone(obj.os_initrd) self.assertIsNone(obj.os_cmdline) self.assertIsNone(obj.os_root) diff --git a/nova/virt/libvirt/config.py b/nova/virt/libvirt/config.py index 476cace03158..0f0296baa073 100644 --- a/nova/virt/libvirt/config.py +++ b/nova/virt/libvirt/config.py @@ -3125,6 +3125,7 @@ class LibvirtConfigGuest(LibvirtConfigObject): self.os_loader = None self.os_firmware = None self.os_loader_type = None + self.os_loader_readonly = None self.os_loader_secure = None self.os_loader_stateless = None self.os_nvram = None @@ -3200,13 +3201,16 @@ class LibvirtConfigGuest(LibvirtConfigObject): if ( self.os_loader is not None or self.os_loader_type is not None or + self.os_loader_readonly is not None or self.os_loader_secure is not None or self.os_loader_stateless is not None ): loader = self._text_node("loader", self.os_loader) if self.os_loader_type is not None: loader.set("type", self.os_loader_type) - loader.set("readonly", "yes") + if self.os_loader_readonly is not None: + loader.set( + "readonly", self.get_yes_no_str(self.os_loader_readonly)) if self.os_loader_secure is not None: loader.set( "secure", self.get_yes_no_str(self.os_loader_secure)) @@ -3346,8 +3350,16 @@ class LibvirtConfigGuest(LibvirtConfigObject): self.os_kernel = c.text elif c.tag == 'loader': self.os_loader = c.text - if c.get('type') == 'pflash': - self.os_loader_type = 'pflash' + self.os_loader_type = c.get('type') + if c.get('readonly'): + self.os_loader_readonly = (c.get('readonly') == 'yes') + if c.get('secure'): + self.os_loader_secure = (c.get('secure') == 'yes') + if c.get('stateless'): + self.os_loader_stateless = (c.get('stateless') == 'yes') + elif c.tag == 'nvram': + self.os_nvram = c.text + self.os_nvram_template = c.get('template') elif c.tag == 'initrd': self.os_initrd = c.text elif c.tag == 'cmdline': diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 4e0ca3667af8..6e8a5b430633 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -7196,6 +7196,7 @@ class LibvirtDriver(driver.ComputeDriver): guest.os_loader = loader guest.os_loader_type = 'pflash' + guest.os_loader_readonly = True if hw_firmware_stateless: guest.os_loader_stateless = True else: