9119d9
From bbda37d1ca472b0d81f52b24f2f945d978b8bce3 Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <bbda37d1ca472b0d81f52b24f2f945d978b8bce3@dist-git>
9119d9
From: Michal Privoznik <mprivozn@redhat.com>
9119d9
Date: Thu, 18 Sep 2014 11:45:39 +0200
9119d9
Subject: [PATCH] domaincaps: Expose UEFI binary path, if it exists
9119d9
9119d9
https://bugzilla.redhat.com/show_bug.cgi?id=1026772
9119d9
9119d9
Check to see if the UEFI binary mentioned in qemu.conf actually
9119d9
exists, and if so expose it in domcapabilities like
9119d9
9119d9
<loader ...>
9119d9
  <value>/path/to/ovmf</value>
9119d9
</loader>
9119d9
9119d9
We introduce some generic domcaps infrastructure for handling
9119d9
a dynamic list of string values, it may be of use for future bits.
9119d9
9119d9
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
9119d9
(cherry picked from commit f05b6a918e283929f5d837cd1668cdcdb3834b9a)
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 docs/formatdomaincaps.html.in                      |  6 +++
9119d9
 docs/schemas/domaincaps.rng                        | 17 +++++---
9119d9
 src/conf/domain_capabilities.c                     | 29 +++++++++++++
9119d9
 src/conf/domain_capabilities.h                     |  8 ++++
9119d9
 src/qemu/qemu_capabilities.c                       | 32 +++++++++++---
9119d9
 src/qemu/qemu_capabilities.h                       |  7 +++-
9119d9
 src/qemu/qemu_driver.c                             |  6 ++-
9119d9
 tests/domaincapsschemadata/domaincaps-full.xml     |  2 +
9119d9
 .../domaincaps-qemu_1.6.50-1.xml                   |  1 +
9119d9
 tests/domaincapstest.c                             | 49 +++++++++++++++++++---
9119d9
 10 files changed, 140 insertions(+), 17 deletions(-)
9119d9
9119d9
diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in
9119d9
index 34d746d..6959dfe 100644
9119d9
--- a/docs/formatdomaincaps.html.in
9119d9
+++ b/docs/formatdomaincaps.html.in
9119d9
@@ -105,6 +105,7 @@
9119d9
   ...
9119d9
   <os supported='yes'>
9119d9
     <loader supported='yes'>
9119d9
+      <value>/usr/share/OVMF/OVMF_CODE.fd</value>
9119d9
       <enum name='type'>
9119d9
         <value>rom</value>
9119d9
         <value>pflash</value>
9119d9
@@ -122,6 +123,11 @@
9119d9
     

For the loader element, the following can occur:

9119d9
 
9119d9
     
9119d9
+      
value
9119d9
+      
List of known loader paths. Currently this is only used
9119d9
+      to advertise known locations of OVMF binaries for qemu. Binaries
9119d9
+      will only be listed if they actually exist on disk.
9119d9
+
9119d9
       
type
9119d9
       
Whether loader is a typical BIOS (rom) or
9119d9
       an UEFI binary (pflash). This refers to
9119d9
diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng
9119d9
index ad8d966..f4a555f 100644
9119d9
--- a/docs/schemas/domaincaps.rng
9119d9
+++ b/docs/schemas/domaincaps.rng
9119d9
@@ -47,6 +47,9 @@
9119d9
   <define name='loader'>
9119d9
     <element name='loader'>
9119d9
       <ref name='supported'/>
9119d9
+      <optional>
9119d9
+        <ref name='value'/>
9119d9
+      </optional>
9119d9
       <ref name='enum'/>
9119d9
     </element>
9119d9
   </define>
9119d9
@@ -85,6 +88,14 @@
9119d9
     </element>
9119d9
   </define>
9119d9
 
9119d9
+  <define name='value'>
9119d9
+    <zeroOrMore>
9119d9
+      <element name='value'>
9119d9
+        <text/>
9119d9
+      </element>
9119d9
+    </zeroOrMore>
9119d9
+  </define>
9119d9
+
9119d9
   <define name='supported'>
9119d9
     <attribute name='supported'>
9119d9
       <choice>
9119d9
@@ -100,11 +111,7 @@
9119d9
         <attribute name='name'>
9119d9
           <text/>
9119d9
         </attribute>
9119d9
-        <zeroOrMore>
9119d9
-          <element name='value'>
9119d9
-            <text/>
9119d9
-          </element>
9119d9
-        </zeroOrMore>
9119d9
+        <ref name='value'/>
9119d9
       </element>
9119d9
     </zeroOrMore>
9119d9
   </define>
9119d9
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
9119d9
index 5a3c8e7..7c59912 100644
9119d9
--- a/src/conf/domain_capabilities.c
9119d9
+++ b/src/conf/domain_capabilities.c
9119d9
@@ -48,12 +48,28 @@ VIR_ONCE_GLOBAL_INIT(virDomainCaps)
9119d9
 
9119d9
 
9119d9
 static void
9119d9
+virDomainCapsStringValuesFree(virDomainCapsStringValuesPtr values)
9119d9
+{
9119d9
+    size_t i;
9119d9
+
9119d9
+    if (!values || !values->values)
9119d9
+        return;
9119d9
+
9119d9
+    for (i = 0; i < values->nvalues; i++)
9119d9
+        VIR_FREE(values->values[i]);
9119d9
+    VIR_FREE(values->values);
9119d9
+}
9119d9
+
9119d9
+
9119d9
+static void
9119d9
 virDomainCapsDispose(void *obj)
9119d9
 {
9119d9
     virDomainCapsPtr caps = obj;
9119d9
 
9119d9
     VIR_FREE(caps->path);
9119d9
     VIR_FREE(caps->machine);
9119d9
+
9119d9
+    virDomainCapsStringValuesFree(&caps->os.loader.values);
9119d9
 }
9119d9
 
9119d9
 
9119d9
@@ -156,6 +172,18 @@ virDomainCapsEnumFormat(virBufferPtr buf,
9119d9
     return ret;
9119d9
 }
9119d9
 
9119d9
+
9119d9
+static void
9119d9
+virDomainCapsStringValuesFormat(virBufferPtr buf,
9119d9
+                                virDomainCapsStringValuesPtr values)
9119d9
+{
9119d9
+    size_t i;
9119d9
+
9119d9
+    for (i = 0; i < values->nvalues; i++)
9119d9
+        virBufferEscapeString(buf, "<value>%s</value>\n", values->values[i]);
9119d9
+}
9119d9
+
9119d9
+
9119d9
 #define FORMAT_PROLOGUE(item)                                       \
9119d9
     do {                                                            \
9119d9
         virBufferAsprintf(buf, "<" #item " supported='%s'%s\n",     \
9119d9
@@ -185,6 +213,7 @@ virDomainCapsLoaderFormat(virBufferPtr buf,
9119d9
 {
9119d9
     FORMAT_PROLOGUE(loader);
9119d9
 
9119d9
+    virDomainCapsStringValuesFormat(buf, &loader->values);
9119d9
     ENUM_PROCESS(loader, type, virDomainLoaderTypeToString);
9119d9
     ENUM_PROCESS(loader, readonly, virTristateBoolTypeToString);
9119d9
 
9119d9
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
9119d9
index 768646b..597ac75 100644
9119d9
--- a/src/conf/domain_capabilities.h
9119d9
+++ b/src/conf/domain_capabilities.h
9119d9
@@ -37,6 +37,13 @@ struct _virDomainCapsEnum {
9119d9
     unsigned int values; /* Bitmask of values supported in the corresponding enum */
9119d9
 };
9119d9
 
9119d9
+typedef struct _virDomainCapsStringValues virDomainCapsStringValues;
9119d9
+typedef virDomainCapsStringValues *virDomainCapsStringValuesPtr;
9119d9
+struct _virDomainCapsStringValues {
9119d9
+    char **values;  /* raw string values */
9119d9
+    size_t nvalues; /* number of strings */
9119d9
+};
9119d9
+
9119d9
 typedef struct _virDomainCapsDevice virDomainCapsDevice;
9119d9
 typedef virDomainCapsDevice *virDomainCapsDevicePtr;
9119d9
 struct _virDomainCapsDevice {
9119d9
@@ -47,6 +54,7 @@ typedef struct _virDomainCapsLoader virDomainCapsLoader;
9119d9
 typedef virDomainCapsLoader *virDomainCapsLoaderPtr;
9119d9
 struct _virDomainCapsLoader {
9119d9
     virDomainCapsDevice device;
9119d9
+    virDomainCapsStringValues values;   /* Info about values for the element */
9119d9
     virDomainCapsEnum type;     /* Info about virDomainLoader */
9119d9
     virDomainCapsEnum readonly; /* Info about readonly:virTristateBool */
9119d9
 };
9119d9
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
9119d9
index f398e3a..67bfc36 100644
9119d9
--- a/src/qemu/qemu_capabilities.c
9119d9
+++ b/src/qemu/qemu_capabilities.c
9119d9
@@ -3611,10 +3611,30 @@ virQEMUCapsGetDefaultMachine(virQEMUCapsPtr qemuCaps)
9119d9
 static int
9119d9
 virQEMUCapsFillDomainLoaderCaps(virQEMUCapsPtr qemuCaps,
9119d9
                                 virDomainCapsLoaderPtr loader,
9119d9
-                                virArch arch)
9119d9
+                                virArch arch,
9119d9
+                                virQEMUDriverConfigPtr cfg)
9119d9
 {
9119d9
+    size_t i;
9119d9
+
9119d9
     loader->device.supported = true;
9119d9
 
9119d9
+    if (VIR_ALLOC_N(loader->values.values, cfg->nloader) < 0)
9119d9
+        return -1;
9119d9
+
9119d9
+    for (i = 0; i < cfg->nloader; i++) {
9119d9
+        const char *filename = cfg->loader[i];
9119d9
+
9119d9
+        if (!virFileExists(filename)) {
9119d9
+            VIR_DEBUG("loader filename=%s does not exist", filename);
9119d9
+            continue;
9119d9
+        }
9119d9
+
9119d9
+        if (VIR_STRDUP(loader->values.values[loader->values.nvalues],
9119d9
+                       filename) < 0)
9119d9
+            return -1;
9119d9
+        loader->values.nvalues++;
9119d9
+    }
9119d9
+
9119d9
     VIR_DOMAIN_CAPS_ENUM_SET(loader->type,
9119d9
                              VIR_DOMAIN_LOADER_TYPE_ROM);
9119d9
 
9119d9
@@ -3636,12 +3656,13 @@ virQEMUCapsFillDomainLoaderCaps(virQEMUCapsPtr qemuCaps,
9119d9
 static int
9119d9
 virQEMUCapsFillDomainOSCaps(virQEMUCapsPtr qemuCaps,
9119d9
                             virDomainCapsOSPtr os,
9119d9
-                            virArch arch)
9119d9
+                            virArch arch,
9119d9
+                            virQEMUDriverConfigPtr cfg)
9119d9
 {
9119d9
     virDomainCapsLoaderPtr loader = &os->loader;
9119d9
 
9119d9
     os->device.supported = true;
9119d9
-    if (virQEMUCapsFillDomainLoaderCaps(qemuCaps, loader, arch) < 0)
9119d9
+    if (virQEMUCapsFillDomainLoaderCaps(qemuCaps, loader, arch, cfg) < 0)
9119d9
         return -1;
9119d9
     return 0;
9119d9
 }
9119d9
@@ -3725,7 +3746,8 @@ virQEMUCapsFillDomainDeviceHostdevCaps(virQEMUCapsPtr qemuCaps,
9119d9
 
9119d9
 int
9119d9
 virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps,
9119d9
-                          virQEMUCapsPtr qemuCaps)
9119d9
+                          virQEMUCapsPtr qemuCaps,
9119d9
+                          virQEMUDriverConfigPtr cfg)
9119d9
 {
9119d9
     virDomainCapsOSPtr os = &domCaps->os;
9119d9
     virDomainCapsDeviceDiskPtr disk = &domCaps->disk;
9119d9
@@ -3734,7 +3756,7 @@ virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps,
9119d9
 
9119d9
     domCaps->maxvcpus = maxvcpus;
9119d9
 
9119d9
-    if (virQEMUCapsFillDomainOSCaps(qemuCaps, os, domCaps->arch) < 0 ||
9119d9
+    if (virQEMUCapsFillDomainOSCaps(qemuCaps, os, domCaps->arch, cfg) < 0 ||
9119d9
         virQEMUCapsFillDomainDeviceDiskCaps(qemuCaps, disk) < 0 ||
9119d9
         virQEMUCapsFillDomainDeviceHostdevCaps(qemuCaps, hostdev) < 0)
9119d9
         return -1;
9119d9
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
9119d9
index 828bba3..cf69e59 100644
9119d9
--- a/src/qemu/qemu_capabilities.h
9119d9
+++ b/src/qemu/qemu_capabilities.h
9119d9
@@ -324,7 +324,12 @@ int virQEMUCapsInitGuestFromBinary(virCapsPtr caps,
9119d9
                                    virQEMUCapsPtr kvmbinCaps,
9119d9
                                    virArch guestarch);
9119d9
 
9119d9
+/* Forward declaration */
9119d9
+typedef struct _virQEMUDriverConfig virQEMUDriverConfig;
9119d9
+typedef virQEMUDriverConfig *virQEMUDriverConfigPtr;
9119d9
+
9119d9
 int virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps,
9119d9
-                              virQEMUCapsPtr qemuCaps);
9119d9
+                              virQEMUCapsPtr qemuCaps,
9119d9
+                              virQEMUDriverConfigPtr cfg);
9119d9
 
9119d9
 #endif /* __QEMU_CAPABILITIES_H__*/
9119d9
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
9119d9
index 446dd63..d3ff143 100644
9119d9
--- a/src/qemu/qemu_driver.c
9119d9
+++ b/src/qemu/qemu_driver.c
9119d9
@@ -17068,12 +17068,15 @@ qemuConnectGetDomainCapabilities(virConnectPtr conn,
9119d9
     int virttype; /* virDomainVirtType */
9119d9
     virDomainCapsPtr domCaps = NULL;
9119d9
     int arch = virArchFromHost(); /* virArch */
9119d9
+    virQEMUDriverConfigPtr cfg = NULL;
9119d9
 
9119d9
     virCheckFlags(0, ret);
9119d9
 
9119d9
     if (virConnectGetDomainCapabilitiesEnsureACL(conn) < 0)
9119d9
         return ret;
9119d9
 
9119d9
+    cfg = virQEMUDriverGetConfig(driver);
9119d9
+
9119d9
     if (qemuHostdevHostSupportsPassthroughLegacy())
9119d9
         virttype = VIR_DOMAIN_VIRT_KVM;
9119d9
     else
9119d9
@@ -17140,11 +17143,12 @@ qemuConnectGetDomainCapabilities(virConnectPtr conn,
9119d9
     if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, virttype)))
9119d9
         goto cleanup;
9119d9
 
9119d9
-    if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps) < 0)
9119d9
+    if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps, cfg) < 0)
9119d9
         goto cleanup;
9119d9
 
9119d9
     ret = virDomainCapsFormat(domCaps);
9119d9
  cleanup:
9119d9
+    virObjectUnref(cfg);
9119d9
     virObjectUnref(domCaps);
9119d9
     virObjectUnref(qemuCaps);
9119d9
     return ret;
9119d9
diff --git a/tests/domaincapsschemadata/domaincaps-full.xml b/tests/domaincapsschemadata/domaincaps-full.xml
9119d9
index 9722772..96202bc 100644
9119d9
--- a/tests/domaincapsschemadata/domaincaps-full.xml
9119d9
+++ b/tests/domaincapsschemadata/domaincaps-full.xml
9119d9
@@ -6,6 +6,8 @@
9119d9
   <vcpu max='255'/>
9119d9
   <os supported='yes'>
9119d9
     <loader supported='yes'>
9119d9
+      <value>/foo/bar</value>
9119d9
+      <value>/tmp/my_path</value>
9119d9
       <enum name='type'>
9119d9
         <value>rom</value>
9119d9
         <value>pflash</value>
9119d9
diff --git a/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml b/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml
9119d9
index 568cecb..346ef65 100644
9119d9
--- a/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml
9119d9
+++ b/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml
9119d9
@@ -5,6 +5,7 @@
9119d9
   <arch>x86_64</arch>
9119d9
   <os supported='yes'>
9119d9
     <loader supported='yes'>
9119d9
+      <value>/usr/share/OVMF/OVMF_CODE.fd</value>
9119d9
       <enum name='type'>
9119d9
         <value>rom</value>
9119d9
         <value>pflash</value>
9119d9
diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c
9119d9
index 0c4b09f..8543963 100644
9119d9
--- a/tests/domaincapstest.c
9119d9
+++ b/tests/domaincapstest.c
9119d9
@@ -34,6 +34,27 @@ typedef int (*virDomainCapsFill)(virDomainCapsPtr domCaps,
9119d9
 #define SET_ALL_BITS(x) \
9119d9
     memset(&(x.values), 0xff, sizeof(x.values))
9119d9
 
9119d9
+static int ATTRIBUTE_SENTINEL
9119d9
+fillStringValues(virDomainCapsStringValuesPtr values, ...)
9119d9
+{
9119d9
+    int ret = 0;
9119d9
+    va_list list;
9119d9
+    const char *str;
9119d9
+
9119d9
+    va_start(list, values);
9119d9
+    while ((str = va_arg(list, const char *))) {
9119d9
+        if (VIR_REALLOC_N(values->values, values->nvalues + 1) < 0 ||
9119d9
+            VIR_STRDUP(values->values[values->nvalues], str) < 0) {
9119d9
+            ret = -1;
9119d9
+            break;
9119d9
+        }
9119d9
+        values->nvalues++;
9119d9
+    }
9119d9
+    va_end(list);
9119d9
+
9119d9
+    return ret;
9119d9
+}
9119d9
+
9119d9
 static int
9119d9
 fillAll(virDomainCapsPtr domCaps,
9119d9
         void *opaque ATTRIBUTE_UNUSED)
9119d9
@@ -49,6 +70,11 @@ fillAll(virDomainCapsPtr domCaps,
9119d9
     loader->device.supported = true;
9119d9
     SET_ALL_BITS(loader->type);
9119d9
     SET_ALL_BITS(loader->readonly);
9119d9
+    if (fillStringValues(&loader->values,
9119d9
+                         "/foo/bar",
9119d9
+                         "/tmp/my_path",
9119d9
+                         NULL) < 0)
9119d9
+        return -1;
9119d9
 
9119d9
     disk->device.supported = true;
9119d9
     SET_ALL_BITS(disk->diskDevice);
9119d9
@@ -66,13 +92,21 @@ fillAll(virDomainCapsPtr domCaps,
9119d9
 
9119d9
 #ifdef WITH_QEMU
9119d9
 # include "testutilsqemu.h"
9119d9
+
9119d9
+struct fillQemuCapsData {
9119d9
+    virQEMUCapsPtr qemuCaps;
9119d9
+    virQEMUDriverConfigPtr cfg;
9119d9
+};
9119d9
+
9119d9
 static int
9119d9
 fillQemuCaps(virDomainCapsPtr domCaps,
9119d9
              void *opaque)
9119d9
 {
9119d9
-    virQEMUCapsPtr qemuCaps = (virQEMUCapsPtr) opaque;
9119d9
+    struct fillQemuCapsData *data = (struct fillQemuCapsData *) opaque;
9119d9
+    virQEMUCapsPtr qemuCaps = data->qemuCaps;
9119d9
+    virQEMUDriverConfigPtr cfg = data->cfg;
9119d9
 
9119d9
-    if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps) < 0)
9119d9
+    if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps, cfg) < 0)
9119d9
         return -1;
9119d9
 
9119d9
     /* The function above tries to query host's KVM & VFIO capabilities by
9119d9
@@ -97,7 +131,7 @@ buildVirDomainCaps(const char *emulatorbin,
9119d9
                    virDomainCapsFill fillFunc,
9119d9
                    void *opaque)
9119d9
 {
9119d9
-    virDomainCapsPtr domCaps;
9119d9
+    virDomainCapsPtr domCaps, ret = NULL;
9119d9
 
9119d9
     if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, type)))
9119d9
         goto cleanup;
9119d9
@@ -107,8 +141,9 @@ buildVirDomainCaps(const char *emulatorbin,
9119d9
         domCaps = NULL;
9119d9
     }
9119d9
 
9119d9
+    ret = domCaps;
9119d9
  cleanup:
9119d9
-    return domCaps;
9119d9
+    return ret;
9119d9
 }
9119d9
 
9119d9
 struct test_virDomainCapsFormatData {
9119d9
@@ -182,13 +217,16 @@ mymain(void)
9119d9
 
9119d9
 #ifdef WITH_QEMU
9119d9
 
9119d9
+    virQEMUDriverConfigPtr cfg = virQEMUDriverConfigNew(false);
9119d9
+
9119d9
 # define DO_TEST_QEMU(Filename, QemuCapsFile, Emulatorbin, Machine, Arch, Type, ...)    \
9119d9
     do {                                                                                \
9119d9
         const char *capsPath = abs_srcdir "/qemucapabilitiesdata/" QemuCapsFile ".caps";    \
9119d9
         virQEMUCapsPtr qemuCaps = qemuTestParseCapabilities(capsPath);                  \
9119d9
+        struct fillQemuCapsData fillData = {.qemuCaps = qemuCaps, .cfg = cfg};          \
9119d9
         struct test_virDomainCapsFormatData data = {.filename = Filename,               \
9119d9
             .emulatorbin = Emulatorbin, .machine = Machine, .arch = Arch,               \
9119d9
-            .type = Type, .fillFunc = fillQemuCaps, .opaque = qemuCaps};                \
9119d9
+            .type = Type, .fillFunc = fillQemuCaps, .opaque = &fillData};               \
9119d9
         if (!qemuCaps) {                                                                \
9119d9
             fprintf(stderr, "Unable to build qemu caps from %s\n", capsPath);           \
9119d9
             ret = -1;                                                                   \
9119d9
@@ -199,6 +237,7 @@ mymain(void)
9119d9
     DO_TEST_QEMU("qemu_1.6.50-1", "caps_1.6.50-1", "/usr/bin/qemu-system-x86_64",
9119d9
                  "pc-1.2",  VIR_ARCH_X86_64, VIR_DOMAIN_VIRT_KVM);
9119d9
 
9119d9
+    virObjectUnref(cfg);
9119d9
 #endif /* WITH_QEMU */
9119d9
 
9119d9
     return ret;
9119d9
-- 
9119d9
2.1.0
9119d9