[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH v4 02/11] XML parsing/formating code for CPU flags



Signed-off-by: Jiri Denemark <jdenemar redhat com>
---
 include/libvirt/virterror.h |    1 +
 proxy/Makefile.am           |    1 +
 src/Makefile.am             |    9 +-
 src/conf/capabilities.c     |   31 ++++-
 src/conf/capabilities.h     |    6 +
 src/conf/cpu_conf.c         |  368 +++++++++++++++++++++++++++++++++++++++++++
 src/conf/cpu_conf.h         |  119 ++++++++++++++
 src/conf/domain_conf.c      |   15 ++
 src/conf/domain_conf.h      |    2 +
 src/libvirt_private.syms    |    9 +
 src/util/virterror.c        |    3 +
 11 files changed, 561 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/proxy/Makefile.am b/proxy/Makefile.am
index 42f6a81..97d6e5a 100644
--- a/proxy/Makefile.am
+++ b/proxy/Makefile.am
@@ -25,6 +25,7 @@ libvirt_proxy_SOURCES = libvirt_proxy.c \
             @top_srcdir@/src/conf/capabilities.c \
             @top_srcdir@/src/conf/storage_encryption_conf.c \
             @top_srcdir@/src/conf/domain_conf.c \
+            @top_srcdir@/src/conf/cpu_conf.c \
             @top_srcdir@/src/xen/xend_internal.c \
 	    @top_srcdir@/src/xen/xen_hypervisor.c \
 	    @top_srcdir@/src/xen/sexpr.c  \
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..f7edb09
--- /dev/null
+++ b/src/conf/cpu_conf.c
@@ -0,0 +1,368 @@
+/*
+ * 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 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);
+}
+
+
+#ifndef PROXY
+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;
+}
+#endif
+
+
+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..e95afaa
--- /dev/null
+++ b/src/conf/cpu_conf.h
@@ -0,0 +1,119 @@
+/*
+ * 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 redhat com>
+ */
+
+#ifndef __VIR_CPU_CONF_H__
+#define __VIR_CPU_CONF_H__
+
+#include "util.h"
+#include "buf.h"
+#ifndef PROXY
+#include "xml.h"
+#endif
+
+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);
+
+#ifndef PROXY
+virCPUDefPtr
+virCPUDefParseXML(virConnectPtr conn,
+                  const xmlNodePtr node,
+                  xmlXPathContextPtr ctxt,
+                  enum virCPUType mode);
+#endif
+
+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);
 }
-- 
1.6.5.7


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]