[libvirt] [PATCH v3 02/13] XML parsing/formating code for CPU flags
Daniel Veillard
veillard at redhat.com
Wed Dec 16 15:17:57 UTC 2009
On Wed, Dec 16, 2009 at 12:03:59AM +0100, Jiri Denemark wrote:
>
> Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
> ---
> include/libvirt/virterror.h | 1 +
> src/Makefile.am | 9 +-
> src/conf/capabilities.c | 31 ++++-
> src/conf/capabilities.h | 6 +
> src/conf/cpu_conf.c | 366 +++++++++++++++++++++++++++++++++++++++++++
> src/conf/cpu_conf.h | 116 ++++++++++++++
> src/conf/domain_conf.c | 15 ++
> src/conf/domain_conf.h | 2 +
> src/libvirt_private.syms | 9 +
> src/util/virterror.c | 3 +
> 10 files changed, 555 insertions(+), 3 deletions(-)
> create mode 100644 src/conf/cpu_conf.c
> create mode 100644 src/conf/cpu_conf.h
>
> diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
> index 8548a8d..30f88e8 100644
> --- a/include/libvirt/virterror.h
> +++ b/include/libvirt/virterror.h
> @@ -68,6 +68,7 @@ typedef enum {
> VIR_FROM_ESX, /* Error from ESX driver */
> VIR_FROM_PHYP, /* Error from IBM power hypervisor */
> VIR_FROM_SECRET, /* Error from secret storage */
> + VIR_FROM_CPU, /* Error from CPU driver */
> } virErrorDomain;
>
>
> diff --git a/src/Makefile.am b/src/Makefile.am
> index b639915..432a66e 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -114,6 +114,9 @@ NODE_DEVICE_CONF_SOURCES = \
> ENCRYPTION_CONF_SOURCES = \
> conf/storage_encryption_conf.c conf/storage_encryption_conf.h
>
> +CPU_CONF_SOURCES = \
> + conf/cpu_conf.c conf/cpu_conf.h
> +
> CONF_SOURCES = \
> $(DOMAIN_CONF_SOURCES) \
> $(DOMAIN_EVENT_SOURCES) \
> @@ -122,7 +125,8 @@ CONF_SOURCES = \
> $(STORAGE_CONF_SOURCES) \
> $(ENCRYPTION_CONF_SOURCES) \
> $(INTERFACE_CONF_SOURCES) \
> - $(SECRET_CONF_SOURCES)
> + $(SECRET_CONF_SOURCES) \
> + $(CPU_CONF_SOURCES)
>
> # The remote RPC driver, covering domains, storage, networks, etc
> REMOTE_DRIVER_SOURCES = \
> @@ -831,7 +835,8 @@ libvirt_lxc_SOURCES = \
> $(UTIL_SOURCES) \
> $(NODE_INFO_SOURCES) \
> $(ENCRYPTION_CONF_SOURCES) \
> - $(DOMAIN_CONF_SOURCES)
> + $(DOMAIN_CONF_SOURCES) \
> + $(CPU_CONF_SOURCES)
> libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(COVERAGE_LDCFLAGS) $(CAPNG_LIBS) $(YAJL_LIBS)
> libvirt_lxc_LDADD = $(LIBXML_LIBS) $(NUMACTL_LIBS) ../gnulib/lib/libgnu.la
> libvirt_lxc_CFLAGS = \
> diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
> index 476bba6..47976af 100644
> --- a/src/conf/capabilities.c
> +++ b/src/conf/capabilities.c
> @@ -27,6 +27,7 @@
> #include "buf.h"
> #include "memory.h"
> #include "util.h"
> +#include "cpu_conf.h"
>
> /**
> * virCapabilitiesNew:
> @@ -171,6 +172,8 @@ virCapabilitiesFree(virCapsPtr caps) {
> VIR_FREE(caps->host.arch);
> VIR_FREE(caps->host.secModel.model);
> VIR_FREE(caps->host.secModel.doi);
> + virCPUDefFree(caps->host.cpu);
> +
> VIR_FREE(caps);
> }
>
> @@ -263,6 +266,27 @@ virCapabilitiesAddHostNUMACell(virCapsPtr caps,
> return 0;
> }
>
> +
> +/**
> + * virCapabilitiesSetHostCPU:
> + * @caps: capabilities to extend
> + * @cpu: CPU definition
> + *
> + * Sets host CPU specification
> + */
> +int
> +virCapabilitiesSetHostCPU(virCapsPtr caps,
> + virCPUDefPtr cpu)
> +{
> + if (cpu == NULL)
> + return -1;
> +
> + caps->host.cpu = cpu;
> +
> + return 0;
> +}
> +
> +
> /**
> * virCapabilitiesAllocMachines:
> * @machines: machine variants for emulator ('pc', or 'isapc', etc)
> @@ -653,6 +677,10 @@ virCapabilitiesFormatXML(virCapsPtr caps)
> }
> virBufferAddLit(&xml, " </features>\n");
> }
> +
> + virCPUDefFormatBuf(NULL, &xml, caps->host.cpu, " ",
> + VIR_CPU_FORMAT_EMBEDED);
> +
> virBufferAddLit(&xml, " </cpu>\n");
>
> if (caps->host.offlineMigrate) {
> @@ -750,7 +778,8 @@ virCapabilitiesFormatXML(virCapsPtr caps)
> for (j = 0 ; j < caps->guests[i]->nfeatures ; j++) {
> if (STREQ(caps->guests[i]->features[j]->name, "pae") ||
> STREQ(caps->guests[i]->features[j]->name, "nonpae") ||
> - STREQ(caps->guests[i]->features[j]->name, "ia64_be")) {
> + STREQ(caps->guests[i]->features[j]->name, "ia64_be") ||
> + STREQ(caps->guests[i]->features[j]->name, "cpuselection")) {
> virBufferVSprintf(&xml, " <%s/>\n",
> caps->guests[i]->features[j]->name);
> } else {
> diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
> index f8cbae6..8c20cd4 100644
> --- a/src/conf/capabilities.h
> +++ b/src/conf/capabilities.h
> @@ -27,6 +27,7 @@
> #include "internal.h"
> #include "util.h"
> #include "buf.h"
> +#include "cpu_conf.h"
>
> #include <libxml/xpath.h>
>
> @@ -108,6 +109,7 @@ struct _virCapsHost {
> int nnumaCell;
> virCapsHostNUMACellPtr *numaCell;
> virCapsHostSecModel secModel;
> + virCPUDefPtr cpu;
> };
>
> typedef struct _virCaps virCaps;
> @@ -166,6 +168,10 @@ virCapabilitiesAddHostNUMACell(virCapsPtr caps,
> const int *cpus);
>
>
> +extern int
> +virCapabilitiesSetHostCPU(virCapsPtr caps,
> + virCPUDefPtr cpu);
> +
>
> extern virCapsGuestMachinePtr *
> virCapabilitiesAllocMachines(const char *const *names,
> diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c
> new file mode 100644
> index 0000000..8286eb6
> --- /dev/null
> +++ b/src/conf/cpu_conf.c
> @@ -0,0 +1,366 @@
> +/*
> + * cpu_conf.h: CPU XML handling
> + *
> + * Copyright (C) 2009 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, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + *
> + * Authors:
> + * Jiri Denemark <jdenemar at redhat.com>
> + */
> +
> +#include <config.h>
> +
> +#include "c-ctype.h"
> +#include "virterror_internal.h"
> +#include "memory.h"
> +#include "util.h"
> +#include "buf.h"
> +#include "cpu_conf.h"
> +
> +#define VIR_FROM_THIS VIR_FROM_CPU
> +
> +#define virCPUReportError(conn, code, fmt...) \
> + virReportErrorHelper(conn, VIR_FROM_CPU, code, __FILE__, \
> + __FUNCTION__, __LINE__, fmt)
> +
> +VIR_ENUM_IMPL(virCPUMatch, VIR_CPU_MATCH_LAST,
> + "minimum",
> + "exact",
> + "strict")
> +
> +VIR_ENUM_IMPL(virCPUFeaturePolicy, VIR_CPU_FEATURE_LAST,
> + "force",
> + "require",
> + "optional",
> + "disable",
> + "forbid")
> +
> +
> +void
> +virCPUDefFree(virCPUDefPtr def)
> +{
> + unsigned int i;
> +
> + if (!def)
> + return;
> +
> + VIR_FREE(def->model);
> + VIR_FREE(def->arch);
> +
> + for (i = 0 ; i < def->nfeatures ; i++)
> + VIR_FREE(def->features[i].name);
> + VIR_FREE(def->features);
> +
> + VIR_FREE(def);
> +}
> +
> +
> +virCPUDefPtr
> +virCPUDefParseXML(virConnectPtr conn,
> + const xmlNodePtr node,
> + xmlXPathContextPtr ctxt,
> + enum virCPUType mode)
> +{
> + virCPUDefPtr def;
> + xmlNodePtr *nodes = NULL;
> + char *match;
> + int n;
> + unsigned int i;
> +
> + if (VIR_ALLOC(def) < 0) {
> + virReportOOMError(conn);
> + return NULL;
> + }
> +
> + match = virXMLPropString(node, "match");
> +
> + if (mode == VIR_CPU_TYPE_AUTO)
> + def->type = (match == NULL) ? VIR_CPU_TYPE_HOST : VIR_CPU_TYPE_GUEST;
> + else
> + def->type = mode;
> +
> + if (def->type == VIR_CPU_TYPE_GUEST) {
> + if ((def->match = virCPUMatchTypeFromString(match)) < 0) {
> + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR,
> + "%s", _("Invalid match attribute for CPU specification"));
> + goto error;
> + }
> + }
> +
> + if (def->type == VIR_CPU_TYPE_HOST) {
> + def->arch = virXPathString(conn, "string(./arch[1])", ctxt);
> + if (!def->arch) {
> + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR,
> + "%s", _("Missing CPU architecture"));
> + goto error;
> + }
> + }
> +
> + if (!(def->model = virXPathString(conn, "string(./model[1])", ctxt))) {
> + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR,
> + "%s", _("Missing CPU model name"));
> + goto error;
> + }
> +
> + if (virXPathNode(conn, "./topology[1]", ctxt)) {
> + int ret;
> + unsigned long ul;
> +
> + ret = virXPathULong(conn, "string(./topology[1]/@sockets)",
> + ctxt, &ul);
> + if (ret < 0) {
> + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR,
> + "%s", _("Missing 'sockets' attribute in CPU topology"));
> + goto error;
> + }
> + def->sockets = (unsigned int) ul;
> +
> + ret = virXPathULong(conn, "string(./topology[1]/@cores)",
> + ctxt, &ul);
> + if (ret < 0) {
> + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR,
> + "%s", _("Missing 'cores' attribute in CPU topology"));
> + goto error;
> + }
> + def->cores = (unsigned int) ul;
> +
> + ret = virXPathULong(conn, "string(./topology[1]/@threads)",
> + ctxt, &ul);
> + if (ret < 0) {
> + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR,
> + "%s", _("Missing 'threads' attribute in CPU topology"));
> + goto error;
> + }
> + def->threads = (unsigned int) ul;
> +
> + if (!def->sockets || !def->cores || !def->threads) {
> + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR,
> + "%s", _("Invalid CPU topology"));
> + goto error;
> + }
> + }
> +
> + n = virXPathNodeSet(conn, "./feature", ctxt, &nodes);
> + if (n < 0)
> + goto error;
> +
> + if (n > 0) {
> + if (VIR_ALLOC_N(def->features, n) < 0)
> + goto no_memory;
> + def->nfeatures = n;
> + }
> +
> + for (i = 0 ; i < n ; i++) {
> + char *name;
> + int policy; /* enum virDomainCPUFeaturePolicy */
> + unsigned int j;
> +
> + if (def->type == VIR_CPU_TYPE_GUEST) {
> + char *strpolicy;
> +
> + strpolicy = virXMLPropString(nodes[i], "policy");
> + policy = virCPUFeaturePolicyTypeFromString(strpolicy);
> + VIR_FREE(strpolicy);
> +
> + if (policy < 0) {
> + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR,
> + "%s", _("Invalid CPU feature policy"));
> + goto error;
> + }
> + }
> + else
> + policy = -1;
> +
> + if (!(name = virXMLPropString(nodes[i], "name")) || *name == 0) {
> + VIR_FREE(name);
> + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR,
> + "%s", _("Invalid CPU feature name"));
> + goto error;
> + }
> +
> + for (j = 0 ; j < i ; j++) {
> + if (STREQ(name, def->features[j].name)) {
> + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR,
> + _("CPU feature `%s' specified more than once"),
> + name);
> + VIR_FREE(name);
> + goto error;
> + }
> + }
> +
> + def->features[i].name = name;
> + def->features[i].policy = policy;
> + }
> +
> +cleanup:
> + VIR_FREE(match);
> + VIR_FREE(nodes);
> +
> + return def;
> +
> +no_memory:
> + virReportOOMError(conn);
> +
> +error:
> + virCPUDefFree(def);
> + def = NULL;
> + goto cleanup;
> +}
> +
> +
> +char *
> +virCPUDefFormat(virConnectPtr conn,
> + virCPUDefPtr def,
> + const char *indent,
> + int flags)
> +{
> + virBuffer buf = VIR_BUFFER_INITIALIZER;
> + char *tmp;
> +
> + if (virCPUDefFormatBuf(conn, &buf, def, indent, flags) < 0)
> + goto cleanup;
> +
> + if (virBufferError(&buf))
> + goto no_memory;
> +
> + return virBufferContentAndReset(&buf);
> +
> +no_memory:
> + virReportOOMError(conn);
> +cleanup:
> + tmp = virBufferContentAndReset(&buf);
> + VIR_FREE(tmp);
> + return NULL;
> +}
> +
> +
> +int
> +virCPUDefFormatBuf(virConnectPtr conn,
> + virBufferPtr buf,
> + virCPUDefPtr def,
> + const char *indent,
> + int flags)
> +{
> + unsigned int i;
> +
> + if (!def)
> + return 0;
> +
> + if (indent == NULL)
> + indent = "";
> +
> + if (!def->model) {
> + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR,
> + "%s", _("Missing CPU model"));
> + return -1;
> + }
> +
> + if (!(flags & VIR_CPU_FORMAT_EMBEDED)) {
> + if (def->type == VIR_CPU_TYPE_GUEST) {
> + const char *match;
> + if (!(match = virCPUMatchTypeToString(def->match))) {
> + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR,
> + _("Unexpected CPU match policy %d"), def->match);
> + return -1;
> + }
> +
> + virBufferVSprintf(buf, "%s<cpu match='%s'>\n", indent, match);
> + }
> + else
> + virBufferVSprintf(buf, "%s<cpu>\n", indent);
> +
> + if (def->arch)
> + virBufferVSprintf(buf, "%s <arch>%s</arch>\n", indent, def->arch);
> + }
> +
> + virBufferVSprintf(buf, "%s <model>%s</model>\n", indent, def->model);
> +
> + if (def->sockets && def->cores && def->threads) {
> + virBufferVSprintf(buf, "%s <topology", indent);
> + virBufferVSprintf(buf, " sockets='%u'", def->sockets);
> + virBufferVSprintf(buf, " cores='%u'", def->cores);
> + virBufferVSprintf(buf, " threads='%u'", def->threads);
> + virBufferAddLit(buf, "/>\n");
> + }
> +
> + for (i = 0 ; i < def->nfeatures ; i++) {
> + virCPUFeatureDefPtr feature = def->features + i;
> +
> + if (!feature->name) {
> + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR,
> + "%s", _("Missing CPU feature name"));
> + return -1;
> + }
> +
> + if (def->type == VIR_CPU_TYPE_GUEST) {
> + const char *policy;
> +
> + policy = virCPUFeaturePolicyTypeToString(feature->policy);
> + if (!policy) {
> + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR,
> + _("Unexpected CPU feature policy %d"), feature->policy);
> + return -1;
> + }
> + virBufferVSprintf(buf, "%s <feature policy='%s' name='%s'/>\n",
> + indent, policy, feature->name);
> + }
> + else {
> + virBufferVSprintf(buf, "%s <feature name='%s'/>\n",
> + indent, feature->name);
> + }
> + }
> +
> + if (!(flags & VIR_CPU_FORMAT_EMBEDED))
> + virBufferVSprintf(buf, "%s</cpu>\n", indent);
> +
> + return 0;
> +}
> +
> +
> +int
> +virCPUDefAddFeature(virConnectPtr conn,
> + virCPUDefPtr def,
> + const char *name,
> + int policy)
> +{
> + int i;
> +
> + for (i = 0 ; i < def->nfeatures ; i++) {
> + if (STREQ(name, def->features[i].name)) {
> + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR,
> + _("CPU feature `%s' specified more than once"), name);
> + return -1;
> + }
> + }
> +
> + if (VIR_REALLOC_N(def->features, def->nfeatures + 1) < 0)
> + goto no_memory;
> +
> + if (def->type == VIR_CPU_TYPE_HOST)
> + policy = -1;
> +
> + if (!(def->features[def->nfeatures].name = strdup(name)))
> + goto no_memory;
> +
> + def->features[def->nfeatures].policy = policy;
> + def->nfeatures++;
> +
> + return 0;
> +
> +no_memory:
> + virReportOOMError(conn);
> + return -1;
> +}
> diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h
> new file mode 100644
> index 0000000..c71fbbb
> --- /dev/null
> +++ b/src/conf/cpu_conf.h
> @@ -0,0 +1,116 @@
> +/*
> + * cpu_conf.h: CPU XML handling
> + *
> + * Copyright (C) 2009 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, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + *
> + * Authors:
> + * Jiri Denemark <jdenemar at redhat.com>
> + */
> +
> +#ifndef __VIR_CPU_CONF_H__
> +#define __VIR_CPU_CONF_H__
> +
> +#include "util.h"
> +#include "buf.h"
> +#include "xml.h"
> +
> +
> +enum virCPUType {
> + VIR_CPU_TYPE_HOST,
> + VIR_CPU_TYPE_GUEST,
> + VIR_CPU_TYPE_AUTO
> +};
> +
> +enum virCPUMatch {
> + VIR_CPU_MATCH_MINIMUM,
> + VIR_CPU_MATCH_EXACT,
> + VIR_CPU_MATCH_STRICT,
> +
> + VIR_CPU_MATCH_LAST
> +};
> +
> +VIR_ENUM_DECL(virCPUMatch)
> +
> +enum virCPUFeaturePolicy {
> + VIR_CPU_FEATURE_FORCE,
> + VIR_CPU_FEATURE_REQUIRE,
> + VIR_CPU_FEATURE_OPTIONAL,
> + VIR_CPU_FEATURE_DISABLE,
> + VIR_CPU_FEATURE_FORBID,
> +
> + VIR_CPU_FEATURE_LAST
> +};
> +
> +VIR_ENUM_DECL(virCPUFeaturePolicy)
> +
> +typedef struct _virCPUFeatureDef virCPUFeatureDef;
> +typedef virCPUFeatureDef *virCPUFeatureDefPtr;
> +struct _virCPUFeatureDef {
> + char *name;
> + int policy; /* enum virCPUFeaturePolicy */
> +};
> +
> +typedef struct _virCPUDef virCPUDef;
> +typedef virCPUDef *virCPUDefPtr;
> +struct _virCPUDef {
> + int type; /* enum virCPUType */
> + int match; /* enum virCPUMatch */
> + char *arch;
> + char *model;
> + unsigned int sockets;
> + unsigned int cores;
> + unsigned int threads;
> + unsigned int nfeatures;
> + virCPUFeatureDefPtr features;
> +};
> +
> +
> +void
> +virCPUDefFree(virCPUDefPtr def);
> +
> +virCPUDefPtr
> +virCPUDefParseXML(virConnectPtr conn,
> + const xmlNodePtr node,
> + xmlXPathContextPtr ctxt,
> + enum virCPUType mode);
> +
> +enum virCPUFormatFlags {
> + VIR_CPU_FORMAT_EMBEDED = (1 << 0) /* embed into existing <cpu/> element
> + * in host capabilities */
> +};
> +
> +
> +char *
> +virCPUDefFormat(virConnectPtr conn,
> + virCPUDefPtr def,
> + const char *indent,
> + int flags);
> +
> +int
> +virCPUDefFormatBuf(virConnectPtr conn,
> + virBufferPtr buf,
> + virCPUDefPtr def,
> + const char *indent,
> + int flags);
> +
> +int
> +virCPUDefAddFeature(virConnectPtr conn,
> + virCPUDefPtr cpu,
> + const char *name,
> + int policy);
> +
> +#endif /* __VIR_CPU_CONF_H__ */
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 5e94edf..0b4fe8b 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -601,6 +601,8 @@ void virDomainDefFree(virDomainDefPtr def)
>
> virSecurityLabelDefFree(def);
>
> + virCPUDefFree(def->cpu);
> +
> VIR_FREE(def);
> }
>
> @@ -3360,6 +3362,16 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn,
> if (virSecurityLabelDefParseXML(conn, def, ctxt, flags) == -1)
> goto error;
>
> + if ((node = virXPathNode(conn, "./cpu[1]", ctxt)) != NULL) {
> + xmlNodePtr oldnode = ctxt->node;
> + ctxt->node = node;
> + def->cpu = virCPUDefParseXML(conn, node, ctxt, VIR_CPU_TYPE_GUEST);
> + ctxt->node = oldnode;
> +
> + if (def->cpu == NULL)
> + goto error;
> + }
> +
> return def;
>
> no_memory:
> @@ -4660,6 +4672,9 @@ char *virDomainDefFormat(virConnectPtr conn,
> virBufferAddLit(&buf, " </features>\n");
> }
>
> + if (virCPUDefFormatBuf(conn, &buf, def->cpu, " ", 0) < 0)
> + goto cleanup;
> +
> virBufferVSprintf(&buf, " <clock offset='%s'/>\n",
> def->localtime ? "localtime" : "utc");
>
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index ac39dcd..a807e9d 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -31,6 +31,7 @@
> #include "internal.h"
> #include "capabilities.h"
> #include "storage_encryption_conf.h"
> +#include "cpu_conf.h"
> #include "util.h"
> #include "threads.h"
> #include "hash.h"
> @@ -635,6 +636,7 @@ struct _virDomainDef {
> virDomainChrDefPtr console;
> virSecurityLabelDef seclabel;
> virDomainWatchdogDefPtr watchdog;
> + virCPUDefPtr cpu;
> };
>
> /* Guest VM runtime state */
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index e5ba365..9acd062 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -35,6 +35,7 @@ virCapabilitiesSetEmulatorRequired;
> virCapabilitiesIsEmulatorRequired;
> virCapabilitiesAllocMachines;
> virCapabilitiesFreeMachines;
> +virCapabilitiesSetHostCPU;
>
>
> # conf.h
> @@ -70,6 +71,14 @@ virCgroupGetFreezerState;
> virCgroupSetFreezerState;
>
>
> +# cpu_conf.h
> +virCPUDefFree;
> +virCPUDefParseXML;
> +virCPUDefFormat;
> +virCPUDefFormatBuf;
> +virCPUDefAddFeature;
> +
> +
> # datatypes.h
> virGetDomain;
> virGetInterface;
> diff --git a/src/util/virterror.c b/src/util/virterror.c
> index 3ff02ba..b1a96f8 100644
> --- a/src/util/virterror.c
> +++ b/src/util/virterror.c
> @@ -172,6 +172,9 @@ static const char *virErrorDomainName(virErrorDomain domain) {
> case VIR_FROM_SECRET:
> dom = "Secret Storage ";
> break;
> + case VIR_FROM_CPU:
> + dom = "CPU ";
> + break;
> }
> return(dom);
> }
ACK, I was wondering for a bit about the need for a new set of files,
but it's a good idea to keep modules smaller,
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
More information about the libvir-list
mailing list