Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/Makefile.am | 1 +
src/conf/domain_capabilities.c | 217 +++++++++++++++++++++++++++++++++++++++++
src/conf/domain_capabilities.h | 89 +++++++++++++++++
src/libvirt_private.syms | 5 +
4 files changed, 312 insertions(+)
create mode 100644 src/conf/domain_capabilities.c
create mode 100644 src/conf/domain_capabilities.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 2b9ac61..e81af0c 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 0000000..896aba9
--- /dev/null
+++ b/src/conf/domain_capabilities.c
@@ -0,0 +1,217 @@
+/*
+ * 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(a)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;
+}
+
+
+#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)
+
+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;
+
+ val = (valToStr)(i);
+ virBufferAsprintf(buf, "<value>%s</value>\n", val);
+ }
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</enum>\n");
+
+ ret = 0;
+ cleanup:
+ return ret;
+}
+
+#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, "<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);
+ virBufferAsprintf(buf, "<arch>%s</arch>\n", arch_str);
+
+ if (caps->maxvcpus)
+ virBufferAsprintf(buf, "<vcpu>%d</vcpu>\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, "</emulatorCapabilities>\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 0000000..b42d11f
--- /dev/null
+++ b/src/conf/domain_capabilities.h
@@ -0,0 +1,89 @@
+/*
+ * 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(a)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);
+
+char * virDomainCapsFormat(virDomainCapsPtr const caps);
+#endif /* __DOMAIN_CAPABILITIES_H__ */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 1e1dd84..6c583b0 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -130,6 +130,11 @@ virDomainAuditStop;
virDomainAuditVcpu;
+# conf/domain_capabilities.h
+virDomainCapsFormat;
+virDomainCapsNew;
+
+
# conf/domain_conf.h
virBlkioDeviceArrayClear;
virDiskNameToBusDeviceIndex;
--
1.8.5.5