--- /dev/null
+<?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>Domain capabilities XML format</h1>
+
+ <ul id="toc"></ul>
+
+ <h2><a name="Overview">Overview</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 qemus.</p>
+
+ <p>The main difference between <code
+ class="docref">virConnectGetCapabilities</code> 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>
+
+ <p>While the <a href="formatcaps.html">Driver Capabilities</a> provides the
+ host capabilities (e.g NUMA topology, security models in effect, etc.), the
+ Domain Capabilities provides the hypervisor specific capabilities for
+ Management Applications to query and make decisions regarding what to
+ utilize.</p>
+
+ <p>The Domain Capabilities can provide information such as the correct
+ combination of devices and drivers that are supported. Knowing which host
+ and hypervisor specific options are available or supported would allow the
+ management application to choose an appropriate mode for a pass-through
+ host device as well as which adapter to utilize.</p>
+
+ <h2><a name="elements">Element and attribute overview</a></h2>
+
+ <p> A new query interface was added to the virConnect API's to retrieve the
+ XML listing of the set of domain capabilities (<span class="since">Since
+ 1.2.7</span>):</p>
+
+<pre>
+ <code class="docref">virConnectGetDomainCapabilities</code>
+</pre>
+
+ <p>The root element that emulator capability XML document starts with has
+ name <code>domainCapabilities</code>. It contains at least four direct
+ child elements:</p>
+
+<pre>
+<domainCapabilities>
+ <path>/usr/bin/qemu-system-x86_64</path>
+ <domain>kvm</domain>
+ <machine>pc-i440fx-2.1</machine>
+ <arch>x86_64</arch>
+ ...
+</domainCapabilities>
+</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>
+
+ <dt>arch</dt>
+ <dd>The domain's <a href="formatdomain.html#elementsOSBIOS">
+ architecture</a>.</dd>
+
+ </dl>
+
+ <h3><a name="elementsCPUAllocation">CPU Allocation</a></h3>
+
+ <p>Before any devices capability occurs, there might be a info on domain
+ wide capabilities, e.g. virtual CPUs:</p>
+
+<pre>
+<domainCapabilities>
+ ...
+ <vcpu max='255'/>
+ ...
+</domainCapabilities>
+</pre>
+
+ <dl>
+ <dt>vcpu</dt>
+ <dd>The maximum number of supported virtual CPUs</dd>
+ </dl>
+
+ <h3><a name="elementsDevices">Devices</a></h3>
+
+ <p>
+ The final set of XML elements describe the supported devices and their
+ capabilities. All devices occur as children of the main
+ <code>devices</code> element.
+ </p>
+
+<pre>
+<domainCapabilities>
+ ...
+ <devices>
+ <disk supported='yes'>
+ <enum name='diskDevice'>
+ <value>disk</value>
+ <value>cdrom</value>
+ <value>floppy</value>
+ <value>lun</value>
+ </enum>
+ ...
+ </disk>
+ <hostdev supported='no'/>
+ </devices>
+</domainCapabilities>
+</pre>
+
+ <p>Reported capabilities are expressed as an enumerated list of available
+ options for each of the element or attribute. For example, the
+ <disk/> element has an attribute <code>device</code> which can
+ support the values <code>disk</code>, <code>cdrom</code>,
+ <code>floppy</code>, or <code>lun</code>.</p>
+
+ <h4><a name="elementsDisks">Hard drives, floppy disks, CDROMs</a></h4>
+ <p>Disk capabilities are exposed under <code>disk</code> element. For
+ instance:</p>
+
+<pre>
+<domainCapabilities>
+ ...
+ <devices>
+ <disk supported='yes'>
+ <enum name='diskDevice'>
+ <value>disk</value>
+ <value>cdrom</value>
+ <value>floppy</value>
+ <value>lun</value>
+ </enum>
+ <enum name='bus'>
+ <value>ide</value>
+ <value>fdc</value>
+ <value>scsi</value>
+ <value>virtio</value>
+ <value>xen</value>
+ <value>usb</value>
+ <value>uml</value>
+ <value>sata</value>
+ <value>sd</value>
+ </enum>
+ </disk>
+ ...
+ </devices>
+</domainCapabilities>
+</pre>
+
+ <dl>
+ <dt>diskDevice</dt>
+ <dd>Options for the <code>device</code> attribute of the <disk/>
+ element.</dd>
+
+ <dt>bus</dt>
+ <dd>Options for the <code>bus</code> attribute of the <target/>
+ element for a <disk/>.</dd>
+ </dl>
+
+ <h4><a name="elementsHostDev">Host device assignment</a></h4>
+ <p>Some host devices can be passed through to a guest (e.g. USB, PCI and
+ SCSI). Well, only if the following is enabled:</p>
+
+<pre>
+<domainCapabilities>
+ ...
+ <devices>
+ <hostdev supported='yes'>
+ <enum name='mode'>
+ <value>subsystem</value>
+ <value>capabilities</value>
+ </enum>
+ <enum name='startupPolicy'>
+ <value>default</value>
+ <value>mandatory</value>
+ <value>requisite</value>
+ <value>optional</value>
+ </enum>
+ <enum name='subsysType'>
+ <value>usb</value>
+ <value>pci</value>
+ <value>scsi</value>
+ </enum>
+ <enum name='capsType'>
+ <value>storage</value>
+ <value>misc</value>
+ <value>net</value>
+ </enum>
+ <enum name='pciBackend'>
+ <value>default</value>
+ <value>kvm</value>
+ <value>vfio</value>
+ <value>xen</value>
+ </enum>
+ </hostdev>
+ </devices>
+</domainCapabilities>
+</pre>
+
+ <dl>
+ <dt>mode</dt>
+ <dd>Options for the <code>mode</code> attribute of the <hostdev/>
+ element.</dd>
+
+ <dt>startupPolicy</dt>
+ <dd>Options for the <code>startupPolicy</code> attribute of the
+ <hostdev/> element.</dd>
+
+ <dt>subsysType</dt>
+ <dd>Options for the <code>type</code> attribute of the <hostdev/>
+ element in case of <code>mode="subsystem"</code>.</dd>
+
+ <dt>capsType</dt>
+ <dd>Options for the <code>type</code> attribute of the <hostdev/>
+ element in case of <code>mode="capabilities"</code>.</dd>
+
+ <dt>pciBackend</dt>
+ <dd>Options for the <code>name</code> attribute of the <driver/>
+ element.</dd>
+ </dl>
+ </body>
+</html>
basictypes.rng \
capability.rng \
domain.rng \
+ domaincaps.rng \
domaincommon.rng \
domainsnapshot.rng \
interface.rng \
--- /dev/null
+<?xml version="1.0"?>
+<!-- A Relax NG schema for the libvirt domain 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='domainCapabilities'/>
+ </start>
+
+
+ <define name='domainCapabilities'>
+ <element name='domainCapabilities'>
+ <interleave>
+ <element name='path'>
+ <ref name="absFilePath"/>
+ </element>
+ <element name='domain'>
+ <text/>
+ </element>
+ <element name='machine'>
+ <text/>
+ </element>
+ <element name='arch'>
+ <text/>
+ </element>
+ <optional>
+ <ref name='vcpu'/>
+ </optional>
+ <optional>
+ <ref name='devices'/>
+ </optional>
+ </interleave>
+ </element>
+ </define>
+
+ <define name='vcpu'>
+ <element name='vcpu'>
+ <attribute name='max'>
+ <ref name='unsignedInt'/>
+ </attribute>
+ <empty/>
+ </element>
+ </define>
+
+ <define name='devices'>
+ <element name='devices'>
+ <interleave>
+ <ref name='disk'/>
+ <ref name='hostdev'/>
+ </interleave>
+ </element>
+ </define>
+
+ <define name='disk'>
+ <element name='disk'>
+ <ref name='supported'/>
+ <ref name='enum'/>
+ </element>
+ </define>
+
+ <define name='hostdev'>
+ <element name='hostdev'>
+ <ref name='supported'/>
+ <ref name='enum'/>
+ </element>
+ </define>
+
+ <define name='supported'>
+ <attribute name='supported'>
+ <choice>
+ <value>yes</value>
+ <value>no</value>
+ </choice>
+ </attribute>
+ </define>
+
+ <define name='enum'>
+ <zeroOrMore>
+ <element name='enum'>
+ <attribute name='name'>
+ <text/>
+ </attribute>
+ <zeroOrMore>
+ <element name='value'>
+ <text/>
+ </element>
+ </zeroOrMore>
+ </element>
+ </zeroOrMore>
+ </define>
+</grammar>
<a href="formatcaps.html">Capabilities</a>
<span>The driver capabilities XML format</span>
</li>
+ <li>
+ <a href="formatdomaincaps.html">Domain capabilities</a>
+ <span>The domain capabilities XML format</span>
+ </li>
<li>
<a href="formatnode.html">Node Devices</a>
<span>The host device XML format</span>
%{_datadir}/libvirt/schemas/basictypes.rng
%{_datadir}/libvirt/schemas/capability.rng
%{_datadir}/libvirt/schemas/domain.rng
+%{_datadir}/libvirt/schemas/domaincaps.rng
%{_datadir}/libvirt/schemas/domaincommon.rng
%{_datadir}/libvirt/schemas/domainsnapshot.rng
%{_datadir}/libvirt/schemas/interface.rng
%{mingw32_datadir}/libvirt/schemas/basictypes.rng
%{mingw32_datadir}/libvirt/schemas/capability.rng
%{mingw32_datadir}/libvirt/schemas/domain.rng
+%{mingw32_datadir}/libvirt/schemas/domaincaps.rng
%{mingw32_datadir}/libvirt/schemas/domaincommon.rng
%{mingw32_datadir}/libvirt/schemas/domainsnapshot.rng
%{mingw32_datadir}/libvirt/schemas/interface.rng
%{mingw64_datadir}/libvirt/schemas/basictypes.rng
%{mingw64_datadir}/libvirt/schemas/capability.rng
%{mingw64_datadir}/libvirt/schemas/domain.rng
+%{mingw64_datadir}/libvirt/schemas/domaincaps.rng
%{mingw64_datadir}/libvirt/schemas/domaincommon.rng
%{mingw64_datadir}/libvirt/schemas/domainsnapshot.rng
%{mingw64_datadir}/libvirt/schemas/interface.rng
src/conf/cpu_conf.c
src/conf/device_conf.c
src/conf/domain_addr.c
+src/conf/domain_capabilities.c
src/conf/domain_conf.c
src/conf/domain_event.c
src/conf/interface_conf.c
DOMAIN_CONF_SOURCES = \
conf/capabilities.c conf/capabilities.h \
conf/domain_addr.c conf/domain_addr.h \
+ conf/domain_capabilities.c conf/domain_capabilities.h \
conf/domain_conf.c conf/domain_conf.h \
conf/domain_audit.c conf/domain_audit.h \
conf/domain_nwfilter.c conf/domain_nwfilter.h \
--- /dev/null
+/*
+ * domain_capabilities.c: domain capabilities XML processing
+ *
+ * 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@redhat.com>
+ */
+
+#include <config.h>
+
+#include "domain_capabilities.h"
+#include "domain_conf.h"
+#include "viralloc.h"
+#include "virstring.h"
+
+#define VIR_FROM_THIS VIR_FROM_CAPABILITIES
+
+static virClassPtr virDomainCapsClass;
+
+static void virDomainCapsDispose(void *obj);
+
+static int virDomainCapsOnceInit(void)
+{
+ if (!(virDomainCapsClass = virClassNew(virClassForObjectLockable(),
+ "virDomainCapsClass",
+ sizeof(virDomainCaps),
+ virDomainCapsDispose)))
+ return -1;
+ return 0;
+}
+
+
+VIR_ONCE_GLOBAL_INIT(virDomainCaps)
+
+
+static void
+virDomainCapsDispose(void *obj)
+{
+ virDomainCapsPtr caps = obj;
+
+ VIR_FREE(caps->path);
+ VIR_FREE(caps->machine);
+}
+
+
+virDomainCapsPtr
+virDomainCapsNew(const char *path,
+ const char *machine,
+ virArch arch,
+ virDomainVirtType virttype)
+{
+ virDomainCapsPtr caps = NULL;
+
+ if (virDomainCapsInitialize() < 0)
+ return NULL;
+
+ if (!(caps = virObjectLockableNew(virDomainCapsClass)))
+ return NULL;
+
+ if (VIR_STRDUP(caps->path, path) < 0 ||
+ VIR_STRDUP(caps->machine, machine) < 0)
+ goto error;
+ caps->arch = arch;
+ caps->virttype = virttype;
+
+ return caps;
+ error:
+ virObjectUnref(caps);
+ return NULL;
+}
+
+
+int
+virDomainCapsEnumSet(virDomainCapsEnumPtr capsEnum,
+ const char *capsEnumName,
+ size_t nvalues,
+ unsigned int *values)
+{
+ int ret = -1;
+ size_t i;
+
+ for (i = 0; i < nvalues; i++) {
+ unsigned int val = 1 << values[i];
+
+ if (!val) {
+ /* Integer overflow */
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("integer overflow on %s. Please contact the "
+ "libvirt development team at libvir-list@redhat.com"),
+ capsEnumName);
+ goto cleanup;
+ }
+
+ capsEnum->values |= val;
+ }
+
+ ret = 0;
+ cleanup:
+ return ret;
+}
+
+
+void
+virDomainCapsEnumClear(virDomainCapsEnumPtr capsEnum)
+{
+ capsEnum->values = 0;
+}
+
+
+static int
+virDomainCapsEnumFormat(virBufferPtr buf,
+ virDomainCapsEnumPtr capsEnum,
+ const char *capsEnumName,
+ virDomainCapsValToStr valToStr)
+{
+ int ret = -1;
+ size_t i;
+
+ virBufferAsprintf(buf, "<enum name='%s'", capsEnumName);
+ if (!capsEnum->values) {
+ virBufferAddLit(buf, "/>\n");
+ ret = 0;
+ goto cleanup;
+ }
+ virBufferAddLit(buf, ">\n");
+ virBufferAdjustIndent(buf, 2);
+
+ for (i = 0; i < sizeof(capsEnum->values) * CHAR_BIT; i++) {
+ const char *val;
+
+ if (!(capsEnum->values & (1 << i)))
+ continue;
+
+ if ((val = (valToStr)(i)))
+ virBufferAsprintf(buf, "<value>%s</value>\n", val);
+ }
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</enum>\n");
+
+ ret = 0;
+ cleanup:
+ return ret;
+}
+
+#define FORMAT_PROLOGUE(item) \
+ do { \
+ virBufferAsprintf(buf, "<" #item " supported='%s'%s\n", \
+ item->device.supported ? "yes" : "no", \
+ item->device.supported ? ">" : "/>"); \
+ if (!item->device.supported) \
+ return; \
+ virBufferAdjustIndent(buf, 2); \
+ } while (0)
+
+#define FORMAT_EPILOGUE(item) \
+ do { \
+ virBufferAdjustIndent(buf, -2); \
+ virBufferAddLit(buf, "</" #item ">\n"); \
+ } while (0)
+
+#define ENUM_PROCESS(master, capsEnum, valToStr) \
+ do { \
+ virDomainCapsEnumFormat(buf, &master->capsEnum, \
+ #capsEnum, valToStr); \
+ } while (0)
+
+static void
+virDomainCapsDeviceDiskFormat(virBufferPtr buf,
+ virDomainCapsDeviceDiskPtr const disk)
+{
+ FORMAT_PROLOGUE(disk);
+
+ ENUM_PROCESS(disk, diskDevice, virDomainDiskDeviceTypeToString);
+ ENUM_PROCESS(disk, bus, virDomainDiskBusTypeToString);
+
+ FORMAT_EPILOGUE(disk);
+}
+
+
+static void
+virDomainCapsDeviceHostdevFormat(virBufferPtr buf,
+ virDomainCapsDeviceHostdevPtr const hostdev)
+{
+ FORMAT_PROLOGUE(hostdev);
+
+ ENUM_PROCESS(hostdev, mode, virDomainHostdevModeTypeToString);
+ ENUM_PROCESS(hostdev, startupPolicy, virDomainStartupPolicyTypeToString);
+ ENUM_PROCESS(hostdev, subsysType, virDomainHostdevSubsysTypeToString);
+ ENUM_PROCESS(hostdev, capsType, virDomainHostdevCapsTypeToString);
+ ENUM_PROCESS(hostdev, pciBackend, virDomainHostdevSubsysPCIBackendTypeToString);
+
+ FORMAT_EPILOGUE(hostdev);
+}
+
+
+static int
+virDomainCapsFormatInternal(virBufferPtr buf,
+ virDomainCapsPtr const caps)
+{
+ const char *virttype_str = virDomainVirtTypeToString(caps->virttype);
+ const char *arch_str = virArchToString(caps->arch);
+
+ virBufferAddLit(buf, "<domainCapabilities>\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);
+ virBufferAsprintf(buf, "<arch>%s</arch>\n", arch_str);
+
+ if (caps->maxvcpus)
+ virBufferAsprintf(buf, "<vcpu max='%d'/>\n", caps->maxvcpus);
+
+ virBufferAddLit(buf, "<devices>\n");
+ virBufferAdjustIndent(buf, 2);
+
+ virDomainCapsDeviceDiskFormat(buf, &caps->disk);
+ virDomainCapsDeviceHostdevFormat(buf, &caps->hostdev);
+
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</devices>\n");
+
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</domainCapabilities>\n");
+ return 0;
+}
+
+
+char *
+virDomainCapsFormat(virDomainCapsPtr const caps)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+ if (virDomainCapsFormatInternal(&buf, caps) < 0) {
+ virBufferFreeAndReset(&buf);
+ return NULL;
+ }
+
+ return virBufferContentAndReset(&buf);
+}
--- /dev/null
+/*
+ * domain_capabilities.h: domain capabilities XML processing
+ *
+ * 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@redhat.com>
+ */
+
+#ifndef __DOMAIN_CAPABILITIES_H__
+# define __DOMAIN_CAPABILITIES_H__
+
+# include "internal.h"
+# include "domain_conf.h"
+
+typedef const char * (*virDomainCapsValToStr)(int value);
+
+typedef struct _virDomainCaps virDomainCaps;
+typedef virDomainCaps *virDomainCapsPtr;
+
+typedef struct _virDomainCapsEnum virDomainCapsEnum;
+typedef virDomainCapsEnum *virDomainCapsEnumPtr;
+struct _virDomainCapsEnum {
+ unsigned int values; /* Bitmask of values supported in the corresponding enum */
+};
+
+typedef struct _virDomainCapsDevice virDomainCapsDevice;
+typedef virDomainCapsDevice *virDomainCapsDevicePtr;
+struct _virDomainCapsDevice {
+ bool supported; /* true if <devtype> is supported by hypervisor */
+};
+
+typedef struct _virDomainCapsDeviceDisk virDomainCapsDeviceDisk;
+typedef virDomainCapsDeviceDisk *virDomainCapsDeviceDiskPtr;
+struct _virDomainCapsDeviceDisk {
+ virDomainCapsDevice device;
+ virDomainCapsEnum diskDevice; /* Info about virDomainDiskDevice enum values */
+ virDomainCapsEnum bus; /* Info about virDomainDiskBus enum values */
+ /* add new fields here */
+};
+
+typedef struct _virDomainCapsDeviceHostdev virDomainCapsDeviceHostdev;
+typedef virDomainCapsDeviceHostdev *virDomainCapsDeviceHostdevPtr;
+struct _virDomainCapsDeviceHostdev {
+ virDomainCapsDevice device;
+ virDomainCapsEnum mode; /* Info about virDomainHostdevMode */
+ virDomainCapsEnum startupPolicy; /* Info about virDomainStartupPolicy */
+ virDomainCapsEnum subsysType; /* Info about virDomainHostdevSubsysType */
+ virDomainCapsEnum capsType; /* Info about virDomainHostdevCapsType */
+ virDomainCapsEnum pciBackend; /* Info about virDomainHostdevSubsysPCIBackendType */
+ /* add new fields here */
+};
+
+struct _virDomainCaps {
+ virObjectLockable parent;
+
+ char *path; /* path to emulator binary */
+ virDomainVirtType virttype; /* virtualization type */
+ char *machine; /* machine type */
+ virArch arch; /* domain architecture */
+
+ /* Some machine specific info */
+ int maxvcpus;
+
+ virDomainCapsDeviceDisk disk;
+ virDomainCapsDeviceHostdev hostdev;
+ /* add new domain devices here */
+};
+
+virDomainCapsPtr virDomainCapsNew(const char *path,
+ const char *machine,
+ virArch arch,
+ virDomainVirtType virttype);
+
+# define VIR_DOMAIN_CAPS_ENUM_SET(capsEnum, ...) \
+ do { \
+ unsigned int __values[] = {__VA_ARGS__}; \
+ size_t __nvalues = ARRAY_CARDINALITY(__values); \
+ virDomainCapsEnumSet(&(capsEnum), #capsEnum, \
+ __nvalues, __values); \
+ } while (0)
+
+int virDomainCapsEnumSet(virDomainCapsEnumPtr capsEnum,
+ const char *capsEnumName,
+ size_t nvalues,
+ unsigned int *values);
+void virDomainCapsEnumClear(virDomainCapsEnumPtr capsEnum);
+
+char * virDomainCapsFormat(virDomainCapsPtr const caps);
+#endif /* __DOMAIN_CAPABILITIES_H__ */
virDomainAuditVcpu;
+# conf/domain_capabilities.h
+virDomainCapsEnumClear;
+virDomainCapsEnumSet;
+virDomainCapsFormat;
+virDomainCapsNew;
+
+
# conf/domain_conf.h
virBlkioDeviceArrayClear;
virDiskNameToBusDeviceIndex;
commanddata \
confdata \
cputestdata \
+ domaincapsschemadata \
+ domaincapsschematest \
domainconfdata \
domainschemadata \
domainschematest \
virnetdevbandwidthtest \
virkmodtest \
vircapstest \
+ domaincapstest \
domainconftest \
virhostdevtest \
vircaps2xmltest \
networkschematest \
storagepoolschematest \
storagevolschematest \
+ domaincapsschematest \
domainschematest \
nodedevschematest \
nwfilterschematest \
vircaps2xmltest.c testutils.h testutils.c
vircaps2xmltest_LDADD = $(LDADDS)
+domaincapstest_SOURCES = \
+ domaincapstest.c testutils.h testutils.c
+domaincapstest_LDADD = $(LDADDS)
+
if WITH_LIBVIRTD
libvirtdconftest_SOURCES = \
libvirtdconftest.c testutils.h testutils.c \
--- /dev/null
+<domainCapabilities>
+ <path>/bin/emulatorbin</path>
+ <domain>uml</domain>
+ <machine>my-machine-type</machine>
+ <arch>x86_64</arch>
+ <devices>
+ <disk supported='no'/>
+ <hostdev supported='no'/>
+ </devices>
+</domainCapabilities>
--- /dev/null
+<domainCapabilities>
+ <path>/bin/emulatorbin</path>
+ <domain>kvm</domain>
+ <machine>my-machine-type</machine>
+ <arch>x86_64</arch>
+ <vcpu max='255'/>
+ <devices>
+ <disk supported='yes'>
+ <enum name='diskDevice'>
+ <value>disk</value>
+ <value>cdrom</value>
+ <value>floppy</value>
+ <value>lun</value>
+ </enum>
+ <enum name='bus'>
+ <value>ide</value>
+ <value>fdc</value>
+ <value>scsi</value>
+ <value>virtio</value>
+ <value>xen</value>
+ <value>usb</value>
+ <value>uml</value>
+ <value>sata</value>
+ <value>sd</value>
+ </enum>
+ </disk>
+ <hostdev supported='yes'>
+ <enum name='mode'>
+ <value>subsystem</value>
+ <value>capabilities</value>
+ </enum>
+ <enum name='startupPolicy'>
+ <value>default</value>
+ <value>mandatory</value>
+ <value>requisite</value>
+ <value>optional</value>
+ </enum>
+ <enum name='subsysType'>
+ <value>usb</value>
+ <value>pci</value>
+ <value>scsi</value>
+ </enum>
+ <enum name='capsType'>
+ <value>storage</value>
+ <value>misc</value>
+ <value>net</value>
+ </enum>
+ <enum name='pciBackend'>
+ <value>default</value>
+ <value>kvm</value>
+ <value>vfio</value>
+ <value>xen</value>
+ </enum>
+ </hostdev>
+ </devices>
+</domainCapabilities>
--- /dev/null
+#!/bin/sh
+
+: ${srcdir=.}
+. $srcdir/test-lib.sh
+. $abs_srcdir/schematestutils.sh
+
+DIRS=""
+DIRS="$DIRS domaincapsschemadata"
+SCHEMA="domaincaps.rng"
+
+check_schema "$DIRS" "$SCHEMA"
--- /dev/null
+/*
+ * 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@redhat.com>
+ */
+
+#include <config.h>
+#include <stdlib.h>
+
+#include "testutils.h"
+#include "domain_capabilities.h"
+
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+typedef void (*virDomainCapsFill)(virDomainCapsPtr domCaps,
+ void *opaque);
+
+#define SET_ALL_BITS(x) \
+ memset(&(x.values), 0xff, sizeof(x.values))
+
+static void
+fillAll(virDomainCapsPtr domCaps,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ virDomainCapsDeviceDiskPtr disk = &domCaps->disk;
+ virDomainCapsDeviceHostdevPtr hostdev = &domCaps->hostdev;
+ domCaps->maxvcpus = 255;
+
+ disk->device.supported = true;
+ SET_ALL_BITS(disk->diskDevice);
+ SET_ALL_BITS(disk->bus);
+
+ hostdev->device.supported = true;
+ SET_ALL_BITS(hostdev->mode);
+ SET_ALL_BITS(hostdev->startupPolicy);
+ SET_ALL_BITS(hostdev->subsysType);
+ SET_ALL_BITS(hostdev->capsType);
+ SET_ALL_BITS(hostdev->pciBackend);
+}
+
+static virDomainCapsPtr
+buildVirDomainCaps(const char *emulatorbin,
+ const char *machine,
+ virArch arch,
+ virDomainVirtType type,
+ virDomainCapsFill fillFunc,
+ void *opaque)
+{
+ virDomainCapsPtr domCaps;
+
+ if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, type)))
+ goto cleanup;
+
+ if (fillFunc)
+ fillFunc(domCaps, opaque);
+
+ cleanup:
+ return domCaps;
+}
+
+struct test_virDomainCapsFormatData {
+ const char *filename;
+ const char *emulatorbin;
+ const char *machine;
+ virArch arch;
+ virDomainVirtType type;
+ virDomainCapsFill fillFunc;
+ void *opaque;
+};
+
+static int
+test_virDomainCapsFormat(const void *opaque)
+{
+ struct test_virDomainCapsFormatData *data =
+ (struct test_virDomainCapsFormatData *) opaque;
+ virDomainCapsPtr domCaps = NULL;
+ char *path = NULL;
+ char *domCapsXML = NULL;
+ char *domCapsFromFile = NULL;
+ int ret = -1;
+
+ if (virAsprintf(&path, "%s/domaincapsschemadata/domaincaps-%s.xml",
+ abs_srcdir, data->filename) < 0)
+ goto cleanup;
+
+ if (virFileReadAll(path, 8192, &domCapsFromFile) < 0)
+ goto cleanup;
+
+ if (!(domCaps = buildVirDomainCaps(data->emulatorbin, data->machine,
+ data->arch, data->type,
+ data->fillFunc, data->opaque)))
+ goto cleanup;
+
+ if (!(domCapsXML = virDomainCapsFormat(domCaps)))
+ goto cleanup;
+
+ if (STRNEQ(domCapsFromFile, domCapsXML)) {
+ virtTestDifference(stderr, domCapsFromFile, domCapsXML);
+ goto cleanup;
+ }
+
+ ret = 0;
+ cleanup:
+ VIR_FREE(domCapsFromFile);
+ VIR_FREE(domCapsXML);
+ VIR_FREE(path);
+ virObjectUnref(domCaps);
+ return ret;
+}
+
+static int
+mymain(void)
+{
+ int ret = 0;
+
+#define DO_TEST(Filename, Emulatorbin, Machine, Arch, Type, ...) \
+ do { \
+ struct test_virDomainCapsFormatData data = {.filename = Filename, \
+ .emulatorbin = Emulatorbin, .machine = Machine, .arch = Arch, \
+ .type = Type, __VA_ARGS__}; \
+ if (virtTestRun(Filename, test_virDomainCapsFormat, &data) < 0) \
+ ret = -1; \
+ } while (0)
+
+ DO_TEST("basic", "/bin/emulatorbin", "my-machine-type",
+ VIR_ARCH_X86_64, VIR_DOMAIN_VIRT_UML);
+ DO_TEST("full", "/bin/emulatorbin", "my-machine-type",
+ VIR_ARCH_X86_64, VIR_DOMAIN_VIRT_KVM, .fillFunc = fillAll);
+
+ return ret;
+}
+
+VIRT_TEST_MAIN(mymain)