render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
e8e641
From e4b040f7a05e4b160a62cd0ce1bdffed7efe8dfa Mon Sep 17 00:00:00 2001
e8e641
Message-Id: <e4b040f7a05e4b160a62cd0ce1bdffed7efe8dfa@dist-git>
e8e641
From: Andrea Bolognani <abologna@redhat.com>
e8e641
Date: Tue, 11 Apr 2023 17:56:45 +0200
e8e641
Subject: [PATCH] conf: Fix migration in some firmware autoselection scenarios
e8e641
MIME-Version: 1.0
e8e641
Content-Type: text/plain; charset=UTF-8
e8e641
Content-Transfer-Encoding: 8bit
e8e641
e8e641
Introduce a small kludge in the parser to avoid unnecessarily
e8e641
blocking incoming migration from a range of recent libvirt
e8e641
releases.
e8e641
e8e641
https://bugzilla.redhat.com/show_bug.cgi?id=2184966
e8e641
e8e641
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
e8e641
Reviewed-by: Ján Tomko <jtomko@redhat.com>
e8e641
(cherry picked from commit f9ad3023355bcbfc692bbe4997fdfa774866a980)
e8e641
e8e641
Conflicts:
e8e641
e8e641
  * tests/qemuxml2argvtest.c
e8e641
  * tests/qemuxml2xmltest.c
e8e641
    - missing unrelated changes to surrounding code
e8e641
e8e641
  * tests/qemuxml2argvdata/firmware-manual-efi-features.x86_64-latest.args
e8e641
  * tests/qemuxml2xmloutdata/firmware-manual-efi-features.x86_64-latest.xml
e8e641
    - had to be regenerated to account for differences in the
e8e641
      input file, as well as the test code and the behavior of
e8e641
      the firmware selection feature. In particular, the
e8e641
      reference to /bad-test-used-env-home/ is caused by the
e8e641
      fact that qemuxml2xmltest, unlike qemuxml2argvtest,
e8e641
      didn't set cfg->nvramDir before e62db9ee5b..e6c1ca3d11
e8e641
e8e641
https://bugzilla.redhat.com/show_bug.cgi?id=2186383
e8e641
e8e641
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
e8e641
---
e8e641
 src/conf/domain_conf.c                        | 39 ++++++++++++++++++-
e8e641
 ...are-manual-efi-features.x86_64-latest.args | 35 +++++++++++++++++
e8e641
 tests/qemuxml2argvtest.c                      |  6 ++-
e8e641
 ...ware-manual-efi-features.x86_64-latest.xml | 32 +++++++++++++++
e8e641
 tests/qemuxml2xmltest.c                       |  1 +
e8e641
 5 files changed, 110 insertions(+), 3 deletions(-)
e8e641
 create mode 100644 tests/qemuxml2argvdata/firmware-manual-efi-features.x86_64-latest.args
e8e641
 create mode 100644 tests/qemuxml2xmloutdata/firmware-manual-efi-features.x86_64-latest.xml
e8e641
e8e641
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
e8e641
index 733399e6da..89637bb282 100644
e8e641
--- a/src/conf/domain_conf.c
e8e641
+++ b/src/conf/domain_conf.c
e8e641
@@ -17021,11 +17021,13 @@ virDomainDefParseBootKernelOptions(virDomainDef *def,
e8e641
 
e8e641
 static int
e8e641
 virDomainDefParseBootFirmwareOptions(virDomainDef *def,
e8e641
-                                     xmlXPathContextPtr ctxt)
e8e641
+                                     xmlXPathContextPtr ctxt,
e8e641
+                                     unsigned int flags)
e8e641
 {
e8e641
     g_autofree char *firmware = virXPathString("string(./os/@firmware)", ctxt);
e8e641
     g_autofree xmlNodePtr *nodes = NULL;
e8e641
     g_autofree int *features = NULL;
e8e641
+    bool abiUpdate = !!(flags & VIR_DOMAIN_DEF_PARSE_ABI_UPDATE);
e8e641
     int fw = 0;
e8e641
     int n = 0;
e8e641
     size_t i;
e8e641
@@ -17033,6 +17035,39 @@ virDomainDefParseBootFirmwareOptions(virDomainDef *def,
e8e641
     if ((n = virXPathNodeSet("./os/firmware/feature", ctxt, &nodes)) < 0)
e8e641
         return -1;
e8e641
 
e8e641
+    /* Migration compatibility kludge.
e8e641
+     *
e8e641
+     * Between 8.6.0 and 9.1.0 (extremes included), the migratable
e8e641
+     * XML produced when feature-based firmware autoselection was
e8e641
+     * enabled looked like
e8e641
+     *
e8e641
+     *   <os>
e8e641
+     *     <firmware>
e8e641
+     *       <feature name='foo' enabled='yes'/>
e8e641
+     *
e8e641
+     * Notice how there's no firmware='foo' attribute for the <os>
e8e641
+     * element, meaning that firmware autoselection is disabled, and
e8e641
+     * yet some <feature> elements, which are used to control the
e8e641
+     * firmware autoselection process, are present. We don't consider
e8e641
+     * this to be a valid combination, and want such a configuration
e8e641
+     * to get rejected when submitted by users.
e8e641
+     *
e8e641
+     * In order to achieve that, while at the same time keeping
e8e641
+     * migration coming from the libvirt versions listed above
e8e641
+     * working, we can simply stop parsing early and ignore the
e8e641
+     * <feature> tags when firmware autoselection is not enabled,
e8e641
+     * *except* if we're defining a new domain.
e8e641
+     *
e8e641
+     * This is safe to do because the configuration will either come
e8e641
+     * from another libvirt instance, in which case it will have a
e8e641
+     * properly filled in <loader> element that contains enough
e8e641
+     * information to successfully define and start the domain, or it
e8e641
+     * will be a random configuration that lacks such information, in
e8e641
+     * which case a different failure will be reported anyway.
e8e641
+     */
e8e641
+    if (n > 0 && !firmware && !abiUpdate)
e8e641
+        return 0;
e8e641
+
e8e641
     if (n > 0)
e8e641
         features = g_new0(int, VIR_DOMAIN_OS_DEF_FIRMWARE_FEATURE_LAST);
e8e641
 
e8e641
@@ -17161,7 +17196,7 @@ virDomainDefParseBootOptions(virDomainDef *def,
e8e641
     case VIR_DOMAIN_OSTYPE_HVM:
e8e641
         virDomainDefParseBootKernelOptions(def, ctxt);
e8e641
 
e8e641
-        if (virDomainDefParseBootFirmwareOptions(def, ctxt) < 0)
e8e641
+        if (virDomainDefParseBootFirmwareOptions(def, ctxt, flags) < 0)
e8e641
             return -1;
e8e641
 
e8e641
         if (virDomainDefParseBootLoaderOptions(def, ctxt, xmlopt, flags) < 0)
e8e641
diff --git a/tests/qemuxml2argvdata/firmware-manual-efi-features.x86_64-latest.args b/tests/qemuxml2argvdata/firmware-manual-efi-features.x86_64-latest.args
e8e641
new file mode 100644
e8e641
index 0000000000..db6c6d06bc
e8e641
--- /dev/null
e8e641
+++ b/tests/qemuxml2argvdata/firmware-manual-efi-features.x86_64-latest.args
e8e641
@@ -0,0 +1,35 @@
e8e641
+LC_ALL=C \
e8e641
+PATH=/bin \
e8e641
+HOME=/tmp/lib/domain--1-test \
e8e641
+USER=test \
e8e641
+LOGNAME=test \
e8e641
+XDG_DATA_HOME=/tmp/lib/domain--1-test/.local/share \
e8e641
+XDG_CACHE_HOME=/tmp/lib/domain--1-test/.cache \
e8e641
+XDG_CONFIG_HOME=/tmp/lib/domain--1-test/.config \
e8e641
+/usr/bin/qemu-system-x86_64 \
e8e641
+-name guest=test,debug-threads=on \
e8e641
+-S \
e8e641
+-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-test/master-key.aes"}' \
e8e641
+-blockdev '{"driver":"file","filename":"/usr/share/OVMF/OVMF_CODE.fd","node-name":"libvirt-pflash0-storage","auto-read-only":true,"discard":"unmap"}' \
e8e641
+-blockdev '{"node-name":"libvirt-pflash0-format","read-only":true,"driver":"raw","file":"libvirt-pflash0-storage"}' \
e8e641
+-blockdev '{"driver":"file","filename":"/var/lib/libvirt/qemu/nvram/test_VARS.fd","node-name":"libvirt-pflash1-storage","auto-read-only":true,"discard":"unmap"}' \
e8e641
+-blockdev '{"node-name":"libvirt-pflash1-format","read-only":false,"driver":"raw","file":"libvirt-pflash1-storage"}' \
e8e641
+-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,pflash0=libvirt-pflash0-format,pflash1=libvirt-pflash1-format \
e8e641
+-accel tcg \
e8e641
+-cpu qemu64 \
e8e641
+-m 1024 \
e8e641
+-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \
e8e641
+-overcommit mem-lock=off \
e8e641
+-smp 1,sockets=1,cores=1,threads=1 \
e8e641
+-uuid 362d1fc1-df7d-193e-5c18-49a71bd1da66 \
e8e641
+-display none \
e8e641
+-no-user-config \
e8e641
+-nodefaults \
e8e641
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
e8e641
+-mon chardev=charmonitor,id=monitor,mode=control \
e8e641
+-rtc base=utc \
e8e641
+-no-shutdown \
e8e641
+-boot strict=on \
e8e641
+-audiodev '{"id":"audio1","driver":"none"}' \
e8e641
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
e8e641
+-msg timestamp=on
e8e641
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
e8e641
index 3fb2d5dc74..99392335b6 100644
e8e641
--- a/tests/qemuxml2argvtest.c
e8e641
+++ b/tests/qemuxml2argvtest.c
e8e641
@@ -1130,7 +1130,11 @@ mymain(void)
e8e641
                         QEMU_CAPS_DEVICE_ISA_SERIAL);
e8e641
     DO_TEST_NOCAPS("firmware-manual-efi");
e8e641
     DO_TEST_PARSE_ERROR_NOCAPS("firmware-manual-efi-no-path");
e8e641
-    DO_TEST_CAPS_LATEST_PARSE_ERROR("firmware-manual-efi-features");
e8e641
+    DO_TEST_CAPS_LATEST("firmware-manual-efi-features");
e8e641
+    DO_TEST_CAPS_ARCH_LATEST_FULL("firmware-manual-efi-features", "x86_64",
e8e641
+                                  ARG_FLAGS, FLAG_EXPECT_PARSE_ERROR,
e8e641
+                                  ARG_PARSEFLAGS, VIR_DOMAIN_DEF_PARSE_ABI_UPDATE,
e8e641
+                                  ARG_END);
e8e641
     DO_TEST_CAPS_LATEST("firmware-manual-bios-rw");
e8e641
     DO_TEST_CAPS_LATEST("firmware-manual-bios-rw-implicit");
e8e641
     DO_TEST("firmware-manual-efi-secure",
e8e641
diff --git a/tests/qemuxml2xmloutdata/firmware-manual-efi-features.x86_64-latest.xml b/tests/qemuxml2xmloutdata/firmware-manual-efi-features.x86_64-latest.xml
e8e641
new file mode 100644
e8e641
index 0000000000..d142be9899
e8e641
--- /dev/null
e8e641
+++ b/tests/qemuxml2xmloutdata/firmware-manual-efi-features.x86_64-latest.xml
e8e641
@@ -0,0 +1,32 @@
e8e641
+<domain type='qemu'>
e8e641
+  <name>test</name>
e8e641
+  <uuid>362d1fc1-df7d-193e-5c18-49a71bd1da66</uuid>
e8e641
+  <memory unit='KiB'>1048576</memory>
e8e641
+  <currentMemory unit='KiB'>1048576</currentMemory>
e8e641
+  <vcpu placement='static'>1</vcpu>
e8e641
+  <os>
e8e641
+    <type arch='x86_64' machine='pc'>hvm</type>
e8e641
+    <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
e8e641
+    <nvram>/bad-test-used-env-home/.config/libvirt/qemu/nvram/test_VARS.fd</nvram>
e8e641
+    <boot dev='hd'/>
e8e641
+  </os>
e8e641
+  <features>
e8e641
+    <acpi/>
e8e641
+  </features>
e8e641
+  <cpu mode='custom' match='exact' check='none'>
e8e641
+    <model fallback='forbid'>qemu64</model>
e8e641
+  </cpu>
e8e641
+  <clock offset='utc'/>
e8e641
+  <on_poweroff>destroy</on_poweroff>
e8e641
+  <on_reboot>restart</on_reboot>
e8e641
+  <on_crash>destroy</on_crash>
e8e641
+  <devices>
e8e641
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
e8e641
+    <controller type='usb' index='0' model='none'/>
e8e641
+    <controller type='pci' index='0' model='pci-root'/>
e8e641
+    <input type='mouse' bus='ps2'/>
e8e641
+    <input type='keyboard' bus='ps2'/>
e8e641
+    <audio id='1' type='none'/>
e8e641
+    <memballoon model='none'/>
e8e641
+  </devices>
e8e641
+</domain>
e8e641
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
e8e641
index 72f724bfce..66e038558f 100644
e8e641
--- a/tests/qemuxml2xmltest.c
e8e641
+++ b/tests/qemuxml2xmltest.c
e8e641
@@ -936,6 +936,7 @@ mymain(void)
e8e641
     DO_TEST_NOCAPS("firmware-manual-bios");
e8e641
     DO_TEST_NOCAPS("firmware-manual-bios-stateless");
e8e641
     DO_TEST_NOCAPS("firmware-manual-efi");
e8e641
+    DO_TEST_CAPS_LATEST("firmware-manual-efi-features");
e8e641
     DO_TEST_CAPS_LATEST("firmware-manual-efi-nvram-network-iscsi");
e8e641
     DO_TEST_CAPS_LATEST("firmware-manual-efi-nvram-network-nbd");
e8e641
     DO_TEST_CAPS_LATEST("firmware-manual-efi-nvram-file");
e8e641
-- 
e8e641
2.40.0