[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