diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in new file mode 100644 index 0000000000..66b6017742 --- /dev/null +++ b/docs/formatdomaincaps.html.in @@ -0,0 +1,232 @@ + + + + +

Domain capabilities XML format

+ + + +

Overview

+ +

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.

+ +

The main difference between virConnectGetCapabilities 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.

+ +

While the Driver Capabilities 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.

+ +

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.

+ +

Element and attribute overview

+ +

A new query interface was added to the virConnect API's to retrieve the + XML listing of the set of domain capabilities (Since + 1.2.7):

+ +
+    virConnectGetDomainCapabilities
+
+ +

The root element that emulator capability XML document starts with has + name domainCapabilities. It contains at least four direct + child elements:

+ +
+<domainCapabilities>
+  <path>/usr/bin/qemu-system-x86_64</path>
+  <domain>kvm</domain>
+  <machine>pc-i440fx-2.1</machine>
+  <arch>x86_64</arch>
+  ...
+</domainCapabilities>
+
+
+
path
+
The full path to the emulator binary.
+ +
domain
+
Describes the virtualization + type (or so called domain type).
+ +
machine
+
The domain's machine + type.
+ +
arch
+
The domain's + architecture.
+ +
+ +

CPU Allocation

+ +

Before any devices capability occurs, there might be a info on domain + wide capabilities, e.g. virtual CPUs:

+ +
+<domainCapabilities>
+  ...
+  <vcpu max='255'/>
+  ...
+</domainCapabilities>
+
+ +
+
vcpu
+
The maximum number of supported virtual CPUs
+
+ +

Devices

+ +

+ The final set of XML elements describe the supported devices and their + capabilities. All devices occur as children of the main + devices element. +

+ +
+<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>
+
+ +

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 device which can + support the values disk, cdrom, + floppy, or lun.

+ +

Hard drives, floppy disks, CDROMs

+

Disk capabilities are exposed under disk element. For + instance:

+ +
+<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>
+
+ +
+
diskDevice
+
Options for the device attribute of the <disk/> + element.
+ +
bus
+
Options for the bus attribute of the <target/> + element for a <disk/>.
+
+ +

Host device assignment

+

Some host devices can be passed through to a guest (e.g. USB, PCI and + SCSI). Well, only if the following is enabled:

+ +
+<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>
+
+ +
+
mode
+
Options for the mode attribute of the <hostdev/> + element.
+ +
startupPolicy
+
Options for the startupPolicy attribute of the + <hostdev/> element.
+ +
subsysType
+
Options for the type attribute of the <hostdev/> + element in case of mode="subsystem".
+ +
capsType
+
Options for the type attribute of the <hostdev/> + element in case of mode="capabilities".
+ +
pciBackend
+
Options for the name attribute of the <driver/> + element.
+
+ + diff --git a/docs/schemas/Makefile.am b/docs/schemas/Makefile.am index d71c327f05..0e14dc6c92 100644 --- a/docs/schemas/Makefile.am +++ b/docs/schemas/Makefile.am @@ -19,6 +19,7 @@ schema_DATA = \ basictypes.rng \ capability.rng \ domain.rng \ + domaincaps.rng \ domaincommon.rng \ domainsnapshot.rng \ interface.rng \ diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng new file mode 100644 index 0000000000..627b69998d --- /dev/null +++ b/docs/schemas/domaincaps.rng @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + yes + no + + + + + + + + + + + + + + + + + + + diff --git a/docs/sitemap.html.in b/docs/sitemap.html.in index 78e84e310c..1e918692d8 100644 --- a/docs/sitemap.html.in +++ b/docs/sitemap.html.in @@ -174,6 +174,10 @@ Capabilities The driver capabilities XML format +
  • + Domain capabilities + The domain capabilities XML format +
  • Node Devices The host device XML format diff --git a/libvirt.spec.in b/libvirt.spec.in index 8b9a1f80b3..8802746913 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -2164,6 +2164,7 @@ exit 0 %{_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 diff --git a/mingw-libvirt.spec.in b/mingw-libvirt.spec.in index 91c2dc2554..a555f9cd92 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/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 @@ -265,6 +266,7 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt-guests.sh %{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 diff --git a/po/POTFILES.in b/po/POTFILES.in index d338151cae..64a987ecab 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -16,6 +16,7 @@ src/conf/capabilities.c 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 diff --git a/src/Makefile.am b/src/Makefile.am index 047d4c6c2e..e2f76a7496 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -248,6 +248,7 @@ NETDEV_CONF_SOURCES = \ 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 \ diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c new file mode 100644 index 0000000000..df190eb108 --- /dev/null +++ b/src/conf/domain_capabilities.c @@ -0,0 +1,254 @@ +/* + * 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 + * . + * + * Author: Michal Privoznik + */ + +#include + +#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, "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, "%s\n", val); + } + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\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, "\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, "\n"); + virBufferAdjustIndent(buf, 2); + + virBufferAsprintf(buf, "%s\n", caps->path); + virBufferAsprintf(buf, "%s\n", virttype_str); + virBufferAsprintf(buf, "%s\n", caps->machine); + virBufferAsprintf(buf, "%s\n", arch_str); + + if (caps->maxvcpus) + virBufferAsprintf(buf, "\n", caps->maxvcpus); + + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, 2); + + virDomainCapsDeviceDiskFormat(buf, &caps->disk); + virDomainCapsDeviceHostdevFormat(buf, &caps->hostdev); + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\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); +} diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h new file mode 100644 index 0000000000..731e66f8a4 --- /dev/null +++ b/src/conf/domain_capabilities.h @@ -0,0 +1,103 @@ +/* + * 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 + * . + * + * Author: Michal Privoznik + */ + +#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 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__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index cc5fd325af..e3164403df 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -130,6 +130,13 @@ virDomainAuditStop; virDomainAuditVcpu; +# conf/domain_capabilities.h +virDomainCapsEnumClear; +virDomainCapsEnumSet; +virDomainCapsFormat; +virDomainCapsNew; + + # conf/domain_conf.h virBlkioDeviceArrayClear; virDiskNameToBusDeviceIndex; diff --git a/tests/Makefile.am b/tests/Makefile.am index 025b847c8b..97af0d9d37 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -74,6 +74,8 @@ EXTRA_DIST = \ commanddata \ confdata \ cputestdata \ + domaincapsschemadata \ + domaincapsschematest \ domainconfdata \ domainschemadata \ domainschematest \ @@ -167,6 +169,7 @@ test_programs = virshtest sockettest \ virnetdevbandwidthtest \ virkmodtest \ vircapstest \ + domaincapstest \ domainconftest \ virhostdevtest \ vircaps2xmltest \ @@ -318,6 +321,7 @@ test_scripts = \ networkschematest \ storagepoolschematest \ storagevolschematest \ + domaincapsschematest \ domainschematest \ nodedevschematest \ nwfilterschematest \ @@ -827,6 +831,10 @@ vircaps2xmltest_SOURCES = \ 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 \ diff --git a/tests/domaincapsschemadata/domaincaps-basic.xml b/tests/domaincapsschemadata/domaincaps-basic.xml new file mode 100644 index 0000000000..99635199b4 --- /dev/null +++ b/tests/domaincapsschemadata/domaincaps-basic.xml @@ -0,0 +1,10 @@ + + /bin/emulatorbin + uml + my-machine-type + x86_64 + + + + + diff --git a/tests/domaincapsschemadata/domaincaps-full.xml b/tests/domaincapsschemadata/domaincaps-full.xml new file mode 100644 index 0000000000..58dd4cbdb0 --- /dev/null +++ b/tests/domaincapsschemadata/domaincaps-full.xml @@ -0,0 +1,56 @@ + + /bin/emulatorbin + kvm + my-machine-type + x86_64 + + + + + disk + cdrom + floppy + lun + + + ide + fdc + scsi + virtio + xen + usb + uml + sata + sd + + + + + subsystem + capabilities + + + default + mandatory + requisite + optional + + + usb + pci + scsi + + + storage + misc + net + + + default + kvm + vfio + xen + + + + diff --git a/tests/domaincapsschematest b/tests/domaincapsschematest new file mode 100755 index 0000000000..9baf44a473 --- /dev/null +++ b/tests/domaincapsschematest @@ -0,0 +1,11 @@ +#!/bin/sh + +: ${srcdir=.} +. $srcdir/test-lib.sh +. $abs_srcdir/schematestutils.sh + +DIRS="" +DIRS="$DIRS domaincapsschemadata" +SCHEMA="domaincaps.rng" + +check_schema "$DIRS" "$SCHEMA" diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c new file mode 100644 index 0000000000..6cdd086dcb --- /dev/null +++ b/tests/domaincapstest.c @@ -0,0 +1,149 @@ +/* + * 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 + * . + * + * Authors: + * Michal Privoznik + */ + +#include +#include + +#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)