[libvirt] [PATCH V3 4/6] libxl: implement connectGetDomainCapabilities

Jim Fehlig jfehlig at suse.com
Fri Jun 10 22:34:53 UTC 2016


Add domain capabilities for PV and HVM domains.

Signed-off-by: Jim Fehlig <jfehlig at suse.com>
---

V3:
- Change introduction of connectGetDomainCapabilities to 1.3.6

 src/libxl/libxl_capabilities.c             | 140 +++++++++++++++++++++++++++++
 src/libxl/libxl_capabilities.h             |   7 ++
 src/libxl/libxl_driver.c                   |  74 +++++++++++++++
 tests/Makefile.am                          |   5 ++
 tests/domaincapsschemadata/libxl-xenfv.xml |  68 ++++++++++++++
 tests/domaincapsschemadata/libxl-xenpv.xml |  58 ++++++++++++
 tests/domaincapstest.c                     |  61 +++++++++++++
 tests/testutilsxen.h                       |   1 +
 8 files changed, 414 insertions(+)

diff --git a/src/libxl/libxl_capabilities.c b/src/libxl/libxl_capabilities.c
index aef2c2d..45f0988 100644
--- a/src/libxl/libxl_capabilities.c
+++ b/src/libxl/libxl_capabilities.c
@@ -30,8 +30,10 @@
 #include "virerror.h"
 #include "virfile.h"
 #include "viralloc.h"
+#include "virstring.h"
 #include "domain_conf.h"
 #include "capabilities.h"
+#include "domain_capabilities.h"
 #include "vircommand.h"
 #include "libxl_capabilities.h"
 
@@ -396,6 +398,109 @@ libxlCapsInitGuests(libxl_ctx *ctx, virCapsPtr caps)
     return 0;
 }
 
+static int
+libxlMakeDomainOSCaps(const char *machine,
+                      virDomainCapsOSPtr os,
+                      virFirmwarePtr *firmwares,
+                      size_t nfirmwares)
+{
+    virDomainCapsLoaderPtr capsLoader = &os->loader;
+    size_t i;
+
+    os->supported = true;
+
+    if (STREQ(machine, "xenpv"))
+        return 0;
+
+    capsLoader->supported = true;
+    if (VIR_ALLOC_N(capsLoader->values.values, nfirmwares) < 0)
+        return -1;
+
+    for (i = 0; i < nfirmwares; i++) {
+        if (VIR_STRDUP(capsLoader->values.values[capsLoader->values.nvalues],
+                       firmwares[i]->name) < 0)
+            return -1;
+        capsLoader->values.nvalues++;
+    }
+
+    VIR_DOMAIN_CAPS_ENUM_SET(capsLoader->type,
+                             VIR_DOMAIN_LOADER_TYPE_ROM,
+                             VIR_DOMAIN_LOADER_TYPE_PFLASH);
+    VIR_DOMAIN_CAPS_ENUM_SET(capsLoader->readonly,
+                             VIR_TRISTATE_BOOL_YES);
+
+    return 0;
+}
+
+static int
+libxlMakeDomainDeviceDiskCaps(virDomainCapsDeviceDiskPtr dev)
+{
+    dev->supported = true;
+
+    VIR_DOMAIN_CAPS_ENUM_SET(dev->diskDevice,
+                             VIR_DOMAIN_DISK_DEVICE_DISK,
+                             VIR_DOMAIN_DISK_DEVICE_CDROM);
+
+    VIR_DOMAIN_CAPS_ENUM_SET(dev->bus,
+                             VIR_DOMAIN_DISK_BUS_IDE,
+                             VIR_DOMAIN_DISK_BUS_SCSI,
+                             VIR_DOMAIN_DISK_BUS_XEN);
+
+    return 0;
+}
+
+static int
+libxlMakeDomainDeviceGraphicsCaps(virDomainCapsDeviceGraphicsPtr dev)
+{
+    dev->supported = true;
+
+    VIR_DOMAIN_CAPS_ENUM_SET(dev->type,
+                             VIR_DOMAIN_GRAPHICS_TYPE_SDL,
+                             VIR_DOMAIN_GRAPHICS_TYPE_VNC,
+                             VIR_DOMAIN_GRAPHICS_TYPE_SPICE);
+
+    return 0;
+}
+
+static int
+libxlMakeDomainDeviceVideoCaps(virDomainCapsDeviceVideoPtr dev)
+{
+    dev->supported = true;
+
+    VIR_DOMAIN_CAPS_ENUM_SET(dev->modelType,
+                             VIR_DOMAIN_VIDEO_TYPE_VGA,
+                             VIR_DOMAIN_VIDEO_TYPE_CIRRUS,
+                             VIR_DOMAIN_VIDEO_TYPE_XEN);
+
+    return 0;
+}
+
+static int
+libxlMakeDomainDeviceHostdevCaps(virDomainCapsDeviceHostdevPtr dev)
+{
+    dev->supported = true;
+    /* VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES is for containers only */
+    VIR_DOMAIN_CAPS_ENUM_SET(dev->mode,
+                             VIR_DOMAIN_HOSTDEV_MODE_SUBSYS);
+
+    VIR_DOMAIN_CAPS_ENUM_SET(dev->startupPolicy,
+                             VIR_DOMAIN_STARTUP_POLICY_DEFAULT,
+                             VIR_DOMAIN_STARTUP_POLICY_MANDATORY,
+                             VIR_DOMAIN_STARTUP_POLICY_REQUISITE,
+                             VIR_DOMAIN_STARTUP_POLICY_OPTIONAL);
+
+    VIR_DOMAIN_CAPS_ENUM_SET(dev->subsysType,
+                             VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI);
+
+    /* No virDomainHostdevCapsType for libxl */
+    virDomainCapsEnumClear(&dev->capsType);
+
+    virDomainCapsEnumClear(&dev->pciBackend);
+    VIR_DOMAIN_CAPS_ENUM_SET(dev->pciBackend,
+                             VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN);
+    return 0;
+}
+
 virCapsPtr
 libxlMakeCapabilities(libxl_ctx *ctx)
 {
@@ -424,6 +529,41 @@ libxlMakeCapabilities(libxl_ctx *ctx)
     return NULL;
 }
 
+/*
+ * Currently Xen has no interface to report maxvcpus supported
+ * for the various domain types (PV, HVM, PVH). HVM_MAX_VCPUS
+ * is defined in $xensrc/xen/include/public/hvm/hvm_info_table.h
+ * PV has no equivalent and is relunctantly set here until Xen
+ * can report such capabilities.
+ */
+#define HVM_MAX_VCPUS 128
+#define PV_MAX_VCPUS  512
+
+int
+libxlMakeDomainCapabilities(virDomainCapsPtr domCaps,
+                            virFirmwarePtr *firmwares,
+                            size_t nfirmwares)
+{
+    virDomainCapsOSPtr os = &domCaps->os;
+    virDomainCapsDeviceDiskPtr disk = &domCaps->disk;
+    virDomainCapsDeviceGraphicsPtr graphics = &domCaps->graphics;
+    virDomainCapsDeviceVideoPtr video = &domCaps->video;
+    virDomainCapsDeviceHostdevPtr hostdev = &domCaps->hostdev;
+
+    if (STREQ(domCaps->machine, "xenfv"))
+        domCaps->maxvcpus = HVM_MAX_VCPUS;
+    else
+        domCaps->maxvcpus = PV_MAX_VCPUS;
+
+    if (libxlMakeDomainOSCaps(domCaps->machine, os, firmwares, nfirmwares) < 0 ||
+        libxlMakeDomainDeviceDiskCaps(disk) < 0 ||
+        libxlMakeDomainDeviceGraphicsCaps(graphics) < 0 ||
+        libxlMakeDomainDeviceVideoCaps(video) < 0 ||
+        libxlMakeDomainDeviceHostdevCaps(hostdev) < 0)
+        return -1;
+    return 0;
+}
+
 #define LIBXL_QEMU_DM_STR  "Options specific to the Xen version:"
 
 int
diff --git a/src/libxl/libxl_capabilities.h b/src/libxl/libxl_capabilities.h
index df1c327..992b780 100644
--- a/src/libxl/libxl_capabilities.h
+++ b/src/libxl/libxl_capabilities.h
@@ -27,6 +27,8 @@
 
 # include "virobject.h"
 # include "capabilities.h"
+# include "domain_capabilities.h"
+# include "virfirmware.h"
 
 
 # ifndef LIBXL_FIRMWARE_DIR
@@ -45,6 +47,11 @@ virCapsPtr
 libxlMakeCapabilities(libxl_ctx *ctx);
 
 int
+libxlMakeDomainCapabilities(virDomainCapsPtr domCaps,
+                            virFirmwarePtr *firmwares,
+                            size_t nfirmwares);
+
+int
 libxlDomainGetEmulatorType(const virDomainDef *def);
 
 #endif /* LIBXL_CAPABILITIES_H */
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index afc5ac3..c12c1cf 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -5562,6 +5562,79 @@ libxlDomainInterfaceAddresses(virDomainPtr dom,
 }
 
 
+static char *
+libxlConnectGetDomainCapabilities(virConnectPtr conn,
+                                  const char *emulatorbin,
+                                  const char *arch_str,
+                                  const char *machine,
+                                  const char *virttype_str,
+                                  unsigned int flags)
+{
+    libxlDriverPrivatePtr driver = conn->privateData;
+    libxlDriverConfigPtr cfg;
+    char *ret = NULL;
+    int virttype = VIR_DOMAIN_VIRT_XEN;
+    virDomainCapsPtr domCaps = NULL;
+    int arch = virArchFromHost(); /* virArch */
+
+    virCheckFlags(0, ret);
+
+    if (virConnectGetDomainCapabilitiesEnsureACL(conn) < 0)
+        return ret;
+
+    cfg = libxlDriverConfigGet(driver);
+
+    if (virttype_str &&
+        (virttype = virDomainVirtTypeFromString(virttype_str)) < 0) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("unknown virttype: %s"),
+                       virttype_str);
+        goto cleanup;
+    }
+
+    if (virttype != VIR_DOMAIN_VIRT_XEN) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("unknown virttype: %s"),
+                       virttype_str);
+        goto cleanup;
+    }
+
+    if (arch_str && (arch = virArchFromString(arch_str)) == VIR_ARCH_NONE) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("unknown architecture: %s"),
+                       arch_str);
+        goto cleanup;
+    }
+
+    if (emulatorbin == NULL)
+        emulatorbin = "/usr/bin/qemu-system-x86_64";
+
+    if (machine) {
+        if (STRNEQ(machine, "xenpv") && STRNEQ(machine, "xenfv")) {
+            virReportError(VIR_ERR_INVALID_ARG, "%s",
+                           _("Xen only supports 'xenpv' and 'xenfv' machines"));
+            goto cleanup;
+        }
+    } else {
+        machine = "xenpv";
+    }
+
+    if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, virttype)))
+        goto cleanup;
+
+    if (libxlMakeDomainCapabilities(domCaps, cfg->firmwares,
+                                    cfg->nfirmwares) < 0)
+        goto cleanup;
+
+    ret = virDomainCapsFormat(domCaps);
+
+ cleanup:
+    virObjectUnref(domCaps);
+    virObjectUnref(cfg);
+    return ret;
+}
+
+
 static virHypervisorDriver libxlHypervisorDriver = {
     .name = LIBXL_DRIVER_NAME,
     .connectOpen = libxlConnectOpen, /* 0.9.0 */
@@ -5663,6 +5736,7 @@ static virHypervisorDriver libxlHypervisorDriver = {
     .domainMigrateConfirm3Params = libxlDomainMigrateConfirm3Params, /* 1.2.6 */
     .nodeGetSecurityModel = libxlNodeGetSecurityModel, /* 1.2.16 */
     .domainInterfaceAddresses = libxlDomainInterfaceAddresses, /* 1.3.5 */
+    .connectGetDomainCapabilities = libxlConnectGetDomainCapabilities, /* 1.3.6 */
 };
 
 static virConnectDriver libxlConnectDriver = {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 18ffab6..4a1e0f3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -930,6 +930,11 @@ domaincapstest_SOURCES += testutilsqemu.c testutilsqemu.h
 domaincapstest_LDADD += $(qemu_LDADDS) $(GNULIB_LIBS)
 endif WITH_QEMU
 
+if WITH_LIBXL
+domaincapstest_SOURCES += testutilsxen.c testutilsxen.h
+domaincapstest_LDADD += ../src/libvirt_driver_libxl_impl.la
+endif WITH_LIBXL
+
 if WITH_LIBVIRTD
 libvirtdconftest_SOURCES = \
 	libvirtdconftest.c testutils.h testutils.c \
diff --git a/tests/domaincapsschemadata/libxl-xenfv.xml b/tests/domaincapsschemadata/libxl-xenfv.xml
new file mode 100644
index 0000000..9436ef8
--- /dev/null
+++ b/tests/domaincapsschemadata/libxl-xenfv.xml
@@ -0,0 +1,68 @@
+<domainCapabilities>
+  <path>/usr/bin/qemu-system-x86_64</path>
+  <domain>xen</domain>
+  <machine>xenfv</machine>
+  <arch>x86_64</arch>
+  <vcpu max='128'/>
+  <os supported='yes'>
+    <loader supported='yes'>
+      <value>/usr/lib/xen/boot/hvmloader</value>
+      <value>/usr/lib/xen/boot/ovmf.bin</value>
+      <enum name='type'>
+        <value>rom</value>
+        <value>pflash</value>
+      </enum>
+      <enum name='readonly'>
+        <value>yes</value>
+      </enum>
+    </loader>
+  </os>
+  <devices>
+    <disk supported='yes'>
+      <enum name='diskDevice'>
+        <value>disk</value>
+        <value>cdrom</value>
+      </enum>
+      <enum name='bus'>
+        <value>ide</value>
+        <value>scsi</value>
+        <value>xen</value>
+      </enum>
+    </disk>
+    <graphics supported='yes'>
+      <enum name='type'>
+        <value>sdl</value>
+        <value>vnc</value>
+        <value>spice</value>
+      </enum>
+    </graphics>
+    <video supported='yes'>
+      <enum name='modelType'>
+        <value>vga</value>
+        <value>cirrus</value>
+        <value>xen</value>
+      </enum>
+    </video>
+    <hostdev supported='yes'>
+      <enum name='mode'>
+        <value>subsystem</value>
+      </enum>
+      <enum name='startupPolicy'>
+        <value>default</value>
+        <value>mandatory</value>
+        <value>requisite</value>
+        <value>optional</value>
+      </enum>
+      <enum name='subsysType'>
+        <value>pci</value>
+      </enum>
+      <enum name='capsType'/>
+      <enum name='pciBackend'>
+        <value>xen</value>
+      </enum>
+    </hostdev>
+  </devices>
+  <features>
+    <gic supported='no'/>
+  </features>
+</domainCapabilities>
diff --git a/tests/domaincapsschemadata/libxl-xenpv.xml b/tests/domaincapsschemadata/libxl-xenpv.xml
new file mode 100644
index 0000000..ab00a28
--- /dev/null
+++ b/tests/domaincapsschemadata/libxl-xenpv.xml
@@ -0,0 +1,58 @@
+<domainCapabilities>
+  <path>/usr/bin/qemu-system-x86_64</path>
+  <domain>xen</domain>
+  <machine>xenpv</machine>
+  <arch>x86_64</arch>
+  <vcpu max='512'/>
+  <os supported='yes'>
+    <loader supported='no'/>
+  </os>
+  <devices>
+    <disk supported='yes'>
+      <enum name='diskDevice'>
+        <value>disk</value>
+        <value>cdrom</value>
+      </enum>
+      <enum name='bus'>
+        <value>ide</value>
+        <value>scsi</value>
+        <value>xen</value>
+      </enum>
+    </disk>
+    <graphics supported='yes'>
+      <enum name='type'>
+        <value>sdl</value>
+        <value>vnc</value>
+        <value>spice</value>
+      </enum>
+    </graphics>
+    <video supported='yes'>
+      <enum name='modelType'>
+        <value>vga</value>
+        <value>cirrus</value>
+        <value>xen</value>
+      </enum>
+    </video>
+    <hostdev supported='yes'>
+      <enum name='mode'>
+        <value>subsystem</value>
+      </enum>
+      <enum name='startupPolicy'>
+        <value>default</value>
+        <value>mandatory</value>
+        <value>requisite</value>
+        <value>optional</value>
+      </enum>
+      <enum name='subsysType'>
+        <value>pci</value>
+      </enum>
+      <enum name='capsType'/>
+      <enum name='pciBackend'>
+        <value>xen</value>
+      </enum>
+    </hostdev>
+  </devices>
+  <features>
+    <gic supported='no'/>
+  </features>
+</domainCapabilities>
diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c
index 83ce0e5..9fb2c97 100644
--- a/tests/domaincapstest.c
+++ b/tests/domaincapstest.c
@@ -162,10 +162,41 @@ fillQemuCaps(virDomainCapsPtr domCaps,
 #endif /* WITH_QEMU */
 
 
+#ifdef WITH_LIBXL
+# include "testutilsxen.h"
+
+static int
+fillXenCaps(virDomainCapsPtr domCaps)
+{
+    virFirmwarePtr *firmwares;
+    int ret = -1;
+
+    if (VIR_ALLOC_N(firmwares, 2) < 0)
+        return ret;
+
+    if (VIR_ALLOC(firmwares[0]) < 0 || VIR_ALLOC(firmwares[1]) < 0)
+        goto cleanup;
+    if (VIR_STRDUP(firmwares[0]->name, "/usr/lib/xen/boot/hvmloader") < 0 ||
+        VIR_STRDUP(firmwares[1]->name, "/usr/lib/xen/boot/ovmf.bin") < 0)
+        goto cleanup;
+
+    if (libxlMakeDomainCapabilities(domCaps, firmwares, 2) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    virFirmwareFreeList(firmwares, 2);
+    return ret;
+}
+#endif /* WITH_LIBXL */
+
+
 enum testCapsType {
     CAPS_NONE,
     CAPS_ALL,
     CAPS_QEMU,
+    CAPS_LIBXL,
 };
 
 struct testData {
@@ -213,6 +244,13 @@ test_virDomainCapsFormat(const void *opaque)
             goto cleanup;
 #endif
         break;
+
+    case CAPS_LIBXL:
+#if WITH_LIBXL
+        if (fillXenCaps(domCaps) < 0)
+            goto cleanup;
+#endif
+        break;
     }
 
     if (!(domCapsXML = virDomainCapsFormat(domCaps)))
@@ -280,6 +318,20 @@ mymain(void)
         VIR_FREE(name);                                                 \
     } while (0)
 
+#define DO_TEST_LIBXL(Name, Emulator, Machine, Arch, Type)              \
+    do {                                                                \
+        struct testData data = {                                        \
+            .name = Name,                                               \
+            .emulator = Emulator,                                       \
+            .machine = Machine,                                         \
+            .arch = Arch,                                               \
+            .type = Type,                                               \
+            .capsType = CAPS_LIBXL,                                     \
+        };                                                              \
+        if (virTestRun(Name, test_virDomainCapsFormat, &data) < 0)     \
+            ret = -1;                                                   \
+    } while (0)
+
     DO_TEST("basic", "/bin/emulatorbin", "my-machine-type",
             "x86_64", VIR_DOMAIN_VIRT_UML, CAPS_NONE);
     DO_TEST("full", "/bin/emulatorbin", "my-machine-type",
@@ -313,6 +365,15 @@ mymain(void)
 
 #endif /* WITH_QEMU */
 
+#if WITH_LIBXL
+
+    DO_TEST_LIBXL("libxl-xenpv", "/usr/bin/qemu-system-x86_64",
+                  "xenpv", "x86_64", VIR_DOMAIN_VIRT_XEN);
+    DO_TEST_LIBXL("libxl-xenfv", "/usr/bin/qemu-system-x86_64",
+                  "xenfv", "x86_64", VIR_DOMAIN_VIRT_XEN);
+
+#endif /* WITH_LIBXL */
+
     return ret;
 }
 
diff --git a/tests/testutilsxen.h b/tests/testutilsxen.h
index c78350d..8b997c3 100644
--- a/tests/testutilsxen.h
+++ b/tests/testutilsxen.h
@@ -2,6 +2,7 @@
 # define _TESTUTILSXEN_H_
 
 # include "capabilities.h"
+# include "libxl/libxl_capabilities.h"
 
 virCapsPtr testXenCapsInit(void);
 
-- 
2.1.4




More information about the libvir-list mailing list