[libvirt] [PATCH 2/5] conf: Introduce viremulator_capabilities

Michal Privoznik mprivozn at redhat.com
Fri Jun 20 14:19:07 UTC 2014


The virEmulatorCapabilities is going to hold emulator capabilities,
surprisingly. It's intended to be able to cover qemuCaps, lxcCaps
(once we invent them, if ever) and so on. Among with adding the code
itself, both some documentation and basic testing is introduced too.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 docs/formatemulatorcaps.html.in                    |  52 ++++++++
 docs/schemas/Makefile.am                           |   1 +
 docs/schemas/emulatorcapability.rng                |  26 ++++
 docs/sitemap.html.in                               |   4 +
 libvirt.spec.in                                    |   1 +
 mingw-libvirt.spec.in                              |   2 +
 src/Makefile.am                                    |   3 +-
 src/conf/viremulator_capabilities.c                | 139 +++++++++++++++++++++
 src/conf/viremulator_capabilities.h                |  47 +++++++
 src/libvirt_private.syms                           |   6 +
 tests/Makefile.am                                  |  10 +-
 .../viremulatorcaps-basic.xml                      |   5 +
 tests/viremulatorcapabilitiesschematest            |  11 ++
 tests/viremulatorcapabilitiestest.c                | 117 +++++++++++++++++
 14 files changed, 422 insertions(+), 2 deletions(-)
 create mode 100644 docs/formatemulatorcaps.html.in
 create mode 100644 docs/schemas/emulatorcapability.rng
 create mode 100644 src/conf/viremulator_capabilities.c
 create mode 100644 src/conf/viremulator_capabilities.h
 create mode 100644 tests/viremulatorcapabilitiesdata/viremulatorcaps-basic.xml
 create mode 100755 tests/viremulatorcapabilitiesschematest
 create mode 100644 tests/viremulatorcapabilitiestest.c

diff --git a/docs/formatemulatorcaps.html.in b/docs/formatemulatorcaps.html.in
new file mode 100644
index 0000000..beea1a9
--- /dev/null
+++ b/docs/formatemulatorcaps.html.in
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <body>
+    <h1>Emulator capabilities XML format</h1>
+
+    <ul id="toc"></ul>
+
+    <h2><a name="Motivation">Motivation</a></h2>
+
+    <p>Sometimes, when a new domain is to be created it may come handy to know
+    the capabilities of the hypervisor so the correct combination of devices and
+    drivers is used. For example, when management application is considering the
+    mode for a host device's passthrough there are several options depending not
+    only on host, but on hypervisor in question too. If the hypervisor is qemu
+    then it needs to be more recent to support VFIO, while legacy KVM is
+    achievable just fine with older one.</p>
+
+    <p>The main difference between <a
+        href="formatcaps.html">virConnectGetCapabilities</a> and the emulator
+    capabilities API is, the former one aims more on the host capabilities (e.g.
+    NUMA topology, security models in effect, etc.) while the latter one
+    specializes on the hypervisor capabilities.</p>
+
+    <h2><a name="elements">Element and attribute overview</a></h2>
+
+    <p>The root element that emulator capability XML document starts with has
+    name <code>emulatorCapabilities</code>. It contains at least three direct
+    child elements:</p>
+
+<pre>
+<emulatorCapabilities>
+  <path>/usr/bin/qemu-system-x86_64</path>
+  <domain>kvm</domain>
+  <machine>pc-i440fx-2.1</machine>
+  ...
+</emulatorCapabilities>
+</pre>
+    <dl>
+      <dt>path</dt>
+      <dd>The full path to the emulator binary.</dd>
+
+      <dt>domain</dt>
+      <dd>Describes the <a href="formatdomain.html#elements">virtualization
+          type</a> (or so called domain type).</dd>
+
+      <dt>machine</dt>
+      <dd>The domain's <a href="formatdomain.html#elementsOSBIOS">machine
+          type</a>.</dd>
+    </dl>
+  </body>
+</html>
diff --git a/docs/schemas/Makefile.am b/docs/schemas/Makefile.am
index d71c327..3072f4f 100644
--- a/docs/schemas/Makefile.am
+++ b/docs/schemas/Makefile.am
@@ -21,6 +21,7 @@ schema_DATA = \
 	domain.rng \
 	domaincommon.rng \
 	domainsnapshot.rng \
+	emulatorcapability.rng \
 	interface.rng \
 	network.rng \
 	networkcommon.rng \
diff --git a/docs/schemas/emulatorcapability.rng b/docs/schemas/emulatorcapability.rng
new file mode 100644
index 0000000..2548cef
--- /dev/null
+++ b/docs/schemas/emulatorcapability.rng
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!-- A Relax NG schema for the libvirt capabilities XML format -->
+<grammar xmlns="http://relaxng.org/ns/structure/1.0"
+    datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+  <include href='basictypes.rng'/>
+  <start>
+    <ref name='emulatorCapabilities'/>
+  </start>
+
+
+  <define name='emulatorCapabilities'>
+    <element name='emulatorCapabilities'>
+      <interleave>
+        <element name='path'>
+          <ref name="absFilePath"/>
+        </element>
+        <element name='domain'>
+          <text/>
+        </element>
+        <element name='machine'>
+          <text/>
+        </element>
+      </interleave>
+    </element>
+  </define>
+</grammar>
diff --git a/docs/sitemap.html.in b/docs/sitemap.html.in
index 78e84e3..6ed4e4d 100644
--- a/docs/sitemap.html.in
+++ b/docs/sitemap.html.in
@@ -175,6 +175,10 @@
                 <span>The driver capabilities XML format</span>
               </li>
               <li>
+                <a href="formatemulatorcaps.html">Emulator capabilities</a>
+                <span>The emulator capabilities XML format</span>
+              </li>
+              <li>
                 <a href="formatnode.html">Node Devices</a>
                 <span>The host device XML format</span>
               </li>
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 344748c..2545503 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -2164,6 +2164,7 @@ exit 0
 %{_datadir}/libvirt/schemas/domain.rng
 %{_datadir}/libvirt/schemas/domaincommon.rng
 %{_datadir}/libvirt/schemas/domainsnapshot.rng
+%{_datadir}/libvirt/schemas/emulatorcapability.rng
 %{_datadir}/libvirt/schemas/interface.rng
 %{_datadir}/libvirt/schemas/network.rng
 %{_datadir}/libvirt/schemas/networkcommon.rng
diff --git a/mingw-libvirt.spec.in b/mingw-libvirt.spec.in
index 1b505e6..ca1db40 100644
--- a/mingw-libvirt.spec.in
+++ b/mingw-libvirt.spec.in
@@ -205,6 +205,7 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt-guests.sh
 %{mingw32_datadir}/libvirt/schemas/domain.rng
 %{mingw32_datadir}/libvirt/schemas/domaincommon.rng
 %{mingw32_datadir}/libvirt/schemas/domainsnapshot.rng
+%{mingw32_datadir}/libvirt/schemas/emulatorcapability.rng
 %{mingw32_datadir}/libvirt/schemas/interface.rng
 %{mingw32_datadir}/libvirt/schemas/network.rng
 %{mingw32_datadir}/libvirt/schemas/networkcommon.rng
@@ -265,6 +266,7 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt-guests.sh
 %{mingw64_datadir}/libvirt/schemas/domain.rng
 %{mingw64_datadir}/libvirt/schemas/domaincommon.rng
 %{mingw64_datadir}/libvirt/schemas/domainsnapshot.rng
+%{mingw64_datadir}/libvirt/schemas/emulatorcapability.rng
 %{mingw64_datadir}/libvirt/schemas/interface.rng
 %{mingw64_datadir}/libvirt/schemas/network.rng
 %{mingw64_datadir}/libvirt/schemas/networkcommon.rng
diff --git a/src/Makefile.am b/src/Makefile.am
index 2b9ac61..9db896d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -251,7 +251,8 @@ DOMAIN_CONF_SOURCES =						\
 		conf/domain_conf.c conf/domain_conf.h		\
 		conf/domain_audit.c conf/domain_audit.h		\
 		conf/domain_nwfilter.c conf/domain_nwfilter.h	\
-		conf/snapshot_conf.c conf/snapshot_conf.h
+		conf/snapshot_conf.c conf/snapshot_conf.h	\
+		conf/viremulator_capabilities.c conf/viremulator_capabilities.h
 
 OBJECT_EVENT_SOURCES =						\
 		conf/object_event.c conf/object_event.h \
diff --git a/src/conf/viremulator_capabilities.c b/src/conf/viremulator_capabilities.c
new file mode 100644
index 0000000..8e7d4af
--- /dev/null
+++ b/src/conf/viremulator_capabilities.c
@@ -0,0 +1,139 @@
+/*
+ * viremulator_capabilities.c: hypervisor capabilities
+ *
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Michal Privoznik <mprivozn at redhat.com>
+ */
+
+#include <config.h>
+
+#include "viremulator_capabilities.h"
+#include "virobject.h"
+#include "viralloc.h"
+#include "virbuffer.h"
+#include "virstring.h"
+
+#define VIR_FROM_THIS VIR_FROM_CAPABILITIES
+
+struct _virEmulatorCapabilities {
+    virObjectLockable parent;
+
+    char *path;                     /* path to emulator binary */
+    char *machine;                  /* machine type */
+    virDomainVirtType virttype;     /* virtualization type */
+
+    void *privateData;
+    virEmulatorCapabilitiesPrivateDataFormatFunc formatFunc;
+};
+
+static virClassPtr virEmulatorCapabilitiesClass;
+
+static void virEmulatorCapabilitiesDispose(void *obj);
+
+static int virEmulatorCapabilitiesOnceInit(void)
+{
+    if (!(virEmulatorCapabilitiesClass = virClassNew(virClassForObjectLockable(),
+                                                     "virEmulatorCapabilities",
+                                                     sizeof(virEmulatorCapabilities),
+                                                     virEmulatorCapabilitiesDispose)))
+        return -1;
+
+    return 0;
+}
+
+VIR_ONCE_GLOBAL_INIT(virEmulatorCapabilities)
+
+
+static void
+virEmulatorCapabilitiesDispose(void *obj)
+{
+    virEmulatorCapabilitiesPtr caps = obj;
+
+    VIR_FREE(caps->path);
+    VIR_FREE(caps->machine);
+}
+
+
+virEmulatorCapabilitiesPtr
+virEmulatorCapabilitiesNew(const char *path,
+                           const char *machine,
+                           virDomainVirtType virttype)
+{
+    virEmulatorCapabilitiesPtr caps = NULL;
+
+    if (virEmulatorCapabilitiesInitialize() < 0)
+        return NULL;
+
+    if (!(caps = virObjectLockableNew(virEmulatorCapabilitiesClass)))
+        return NULL;
+
+    if (VIR_STRDUP(caps->path, path) < 0 ||
+        VIR_STRDUP(caps->machine, machine) < 0)
+        goto error;
+    caps->virttype = virttype;
+
+    return caps;
+ error:
+    virObjectUnref(caps);
+    return NULL;
+}
+
+
+void
+virEmulatorCapabilitiesSetPrivate(virEmulatorCapabilitiesPtr caps,
+                                  void *privateData,
+                                  virEmulatorCapabilitiesPrivateDataFormatFunc formatFunc)
+{
+    if (!caps)
+        return;
+
+    caps->privateData = privateData;
+    caps->formatFunc = formatFunc;
+}
+
+
+static int
+virEmulatorCapabilitiesFormatInternal(virEmulatorCapabilitiesPtr caps,
+                                      virBufferPtr buf)
+{
+    const char *virttype_str = virDomainVirtTypeToString(caps->virttype);
+
+    virBufferAddLit(buf, "<emulatorCapabilities>\n");
+    virBufferAdjustIndent(buf, 2);
+    virBufferAsprintf(buf, "<path>%s</path>\n", caps->path);
+    virBufferAsprintf(buf, "<domain>%s</domain>\n", virttype_str);
+    virBufferAsprintf(buf, "<machine>%s</machine>\n", caps->machine);
+    if (caps->formatFunc)
+        caps->formatFunc(buf, caps->privateData, caps->machine);
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</emulatorCapabilities>\n");
+    return 0;
+}
+
+
+char *
+virEmulatorCapabilitiesFormat(virEmulatorCapabilitiesPtr caps)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    if (virEmulatorCapabilitiesFormatInternal(caps, &buf) < 0)
+        return NULL;
+
+    return virBufferContentAndReset(&buf);
+
+}
diff --git a/src/conf/viremulator_capabilities.h b/src/conf/viremulator_capabilities.h
new file mode 100644
index 0000000..361f765
--- /dev/null
+++ b/src/conf/viremulator_capabilities.h
@@ -0,0 +1,47 @@
+/*
+ * viremulator_capabilities.h: hypervisor capabilities
+ *
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Michal Privoznik <mprivozn at redhat.com>
+ */
+
+#ifndef __VIR_EMULATOR_CAPABILITIES_H
+# define __VIR_EMULATOR_CAPABILITIES_H
+
+# include "domain_conf.h"
+
+typedef int
+(*virEmulatorCapabilitiesPrivateDataFormatFunc)(virBufferPtr buf,
+                                                void *privateData,
+                                                const char *machine);
+
+typedef struct _virEmulatorCapabilities virEmulatorCapabilities;
+typedef virEmulatorCapabilities *virEmulatorCapabilitiesPtr;
+
+virEmulatorCapabilitiesPtr
+virEmulatorCapabilitiesNew(const char *path,
+                           const char *machine,
+                           virDomainVirtType virttype);
+
+void
+virEmulatorCapabilitiesSetPrivate(virEmulatorCapabilitiesPtr caps,
+                                  void *privateData,
+                                  virEmulatorCapabilitiesPrivateDataFormatFunc formatFunc);
+
+char *virEmulatorCapabilitiesFormat(virEmulatorCapabilitiesPtr caps);
+#endif
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 1d29f15..2784610 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -759,6 +759,12 @@ virChrdevFree;
 virChrdevOpen;
 
 
+# conf/viremulator_capabilities.h
+virEmulatorCapabilitiesFormat;
+virEmulatorCapabilitiesNew;
+virEmulatorCapabilitiesSetPrivate;
+
+
 # cpu/cpu.h
 cpuBaseline;
 cpuBaselineXML;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index c999061..e7d9f94 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -125,6 +125,8 @@ EXTRA_DIST =		\
 	sysinfodata \
 	test-lib.sh	\
 	vircaps2xmldata \
+	viremulatorcapabilitiesdata\
+	viremulatorcapabilitiesschematest \
 	vboxsnapshotxmldata \
 	virsh-uriprecedence \
 	virfiledata \
@@ -167,6 +169,7 @@ test_programs = virshtest sockettest \
 	virnetdevbandwidthtest \
 	virkmodtest \
 	vircapstest \
+	viremulatorcapabilitiestest \
 	domainconftest \
 	virhostdevtest \
 	vircaps2xmltest \
@@ -319,7 +322,8 @@ test_scripts = \
 	nodedevschematest \
 	nwfilterschematest \
 	domainsnapshotschematest \
-	secretschematest
+	secretschematest \
+	viremulatorcapabilitiesschematest
 
 if WITH_LIBVIRTD
 test_scripts +=				\
@@ -824,6 +828,10 @@ vircaps2xmltest_SOURCES = \
 	vircaps2xmltest.c testutils.h testutils.c
 vircaps2xmltest_LDADD = $(LDADDS)
 
+viremulatorcapabilitiestest_SOURCES = \
+	viremulatorcapabilitiestest.c testutils.h testutils.c
+viremulatorcapabilitiestest_LDADD = $(LDADDS)
+
 if WITH_LIBVIRTD
 libvirtdconftest_SOURCES = \
 	libvirtdconftest.c testutils.h testutils.c \
diff --git a/tests/viremulatorcapabilitiesdata/viremulatorcaps-basic.xml b/tests/viremulatorcapabilitiesdata/viremulatorcaps-basic.xml
new file mode 100644
index 0000000..a3fd457
--- /dev/null
+++ b/tests/viremulatorcapabilitiesdata/viremulatorcaps-basic.xml
@@ -0,0 +1,5 @@
+<emulatorCapabilities>
+  <path>/bin/emulatorbin</path>
+  <domain>uml</domain>
+  <machine>my-machine-type</machine>
+</emulatorCapabilities>
diff --git a/tests/viremulatorcapabilitiesschematest b/tests/viremulatorcapabilitiesschematest
new file mode 100755
index 0000000..e4dd621
--- /dev/null
+++ b/tests/viremulatorcapabilitiesschematest
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+: ${srcdir=.}
+. $srcdir/test-lib.sh
+. $abs_srcdir/schematestutils.sh
+
+DIRS=""
+DIRS="$DIRS viremulatorcapabilitiesdata"
+SCHEMA="emulatorcapability.rng"
+
+check_schema "$DIRS" "$SCHEMA"
diff --git a/tests/viremulatorcapabilitiestest.c b/tests/viremulatorcapabilitiestest.c
new file mode 100644
index 0000000..448f0cf
--- /dev/null
+++ b/tests/viremulatorcapabilitiestest.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) Red Hat, Inc. 2014
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *      Michal Privoznik <mprivozn at redhat.com>
+ */
+
+#include <config.h>
+#include <stdlib.h>
+
+#include "testutils.h"
+#include "viremulator_capabilities.h"
+
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+static virEmulatorCapabilitiesPtr
+buildVirEmulatorCapabilities(const char *emulatorbin,
+                             const char *machine,
+                             virDomainVirtType type,
+                             void *privateData,
+                             virEmulatorCapabilitiesPrivateDataFormatFunc formatFunc)
+{
+    virEmulatorCapabilitiesPtr emulCaps;
+
+    if (!(emulCaps = virEmulatorCapabilitiesNew(emulatorbin, machine, type)))
+        goto cleanup;
+
+    if (privateData)
+        virEmulatorCapabilitiesSetPrivate(emulCaps, privateData, formatFunc);
+
+ cleanup:
+    return emulCaps;
+}
+
+struct test_virEmulatorCapabilitiesFormatData {
+    const char *filename;
+    const char *emulatorbin;
+    const char *machine;
+    virDomainVirtType type;
+    void *privateData;
+    virEmulatorCapabilitiesPrivateDataFormatFunc formatFunc;
+};
+
+static int
+test_virEmulatorCapabilitiesFormat(const void *opaque)
+{
+    struct test_virEmulatorCapabilitiesFormatData *data =
+        (struct test_virEmulatorCapabilitiesFormatData *) opaque;
+    virEmulatorCapabilitiesPtr emulCaps = NULL;
+    char *path = NULL;
+    char *emulCapsXML = NULL;
+    char *emulCapsFromFile = NULL;
+    int ret = -1;
+
+    if (virAsprintf(&path, "%s/viremulatorcapabilitiesdata/viremulatorcaps-%s.xml",
+                    abs_srcdir, data->filename) < 0)
+        goto cleanup;
+
+    if (virFileReadAll(path, 8192, &emulCapsFromFile) < 0)
+        goto cleanup;
+
+    if (!(emulCaps = buildVirEmulatorCapabilities(data->emulatorbin, data->machine,
+                                                  data->type, data->privateData,
+                                                  data->formatFunc)))
+        goto cleanup;
+
+    if (!(emulCapsXML = virEmulatorCapabilitiesFormat(emulCaps)))
+        goto cleanup;
+
+    if (STRNEQ(emulCapsFromFile, emulCapsXML)) {
+        virtTestDifference(stderr, emulCapsFromFile, emulCapsXML);
+        goto cleanup;
+    }
+
+    ret = 0;
+ cleanup:
+    VIR_FREE(emulCapsFromFile);
+    VIR_FREE(emulCapsXML);
+    VIR_FREE(path);
+    virObjectUnref(emulCaps);
+    return ret;
+}
+
+static int
+mymain(void)
+{
+    int ret = 0;
+
+#define DO_TEST(Filename, Emulatorbin, Machine, Type, ...)                          \
+    do {                                                                            \
+        struct test_virEmulatorCapabilitiesFormatData data = {.filename = Filename, \
+            .emulatorbin = Emulatorbin, .machine = Machine, .type = Type, __VA_ARGS__}; \
+        if (virtTestRun(Filename, test_virEmulatorCapabilitiesFormat, &data) < 0)   \
+        ret = -1;                                                                   \
+    } while (0)
+
+    DO_TEST("basic", "/bin/emulatorbin", "my-machine-type", VIR_DOMAIN_VIRT_UML);
+
+    return ret;
+}
+
+VIRT_TEST_MAIN(mymain)
-- 
1.8.5.5




More information about the libvir-list mailing list