]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
* proxy/libvirt_proxy.c src/proxy_internal.[ch] src/xen_internal.c
authorDaniel Veillard <veillard@redhat.com>
Wed, 31 Oct 2007 09:39:13 +0000 (09:39 +0000)
committerDaniel Veillard <veillard@redhat.com>
Wed, 31 Oct 2007 09:39:13 +0000 (09:39 +0000)
  src/xen_unified.[ch] src/xend_internal.[ch] src/xml.[ch]: last
  patch for the library NUMA support, allow to serialize CPU pinning
  to domain configs (but won't work though proxy access), includes
  many patches from Saori Fukuta.
Daniel

12 files changed:
ChangeLog
proxy/libvirt_proxy.c
src/proxy_internal.c
src/proxy_internal.h
src/xen_internal.c
src/xen_unified.c
src/xen_unified.h
src/xend_internal.c
src/xend_internal.h
src/xm_internal.c
src/xml.c
src/xml.h

index 331ded69e869ddfb0182302ab8db0d77cb6c1b27..e551831cafefd0c920e7d573a752547b184b1c65 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Wed Oct 31 10:36:00 CET 2007 Daniel Veillard <veillard@redhat.com>
+
+       * proxy/libvirt_proxy.c src/proxy_internal.[ch] src/xen_internal.c
+         src/xen_unified.[ch] src/xend_internal.[ch] src/xml.[ch]: last
+         patch for the library NUMA support, allow to serialize CPU pinning
+         to domain configs (but won't work though proxy access), includes
+         many patches from Saori Fukuta.
+
 Fri Oct 26 21:20:44 EST 2007 Daniel P. Berrange <berrange@redhat.com>
 
        * src/libvirt.c: Don't call state driver API if callback is NULL.
index a97b3f9425f060dcc9f77ecf16dafa066747b700..d8092a26eea678fe52d9daeb1243380ecce5ad19 100644 (file)
@@ -614,7 +614,13 @@ retry2:
            if (req->len != sizeof(virProxyPacket))
                goto comm_error;
 
-           xml = xenDaemonDomainDumpXMLByID(conn, request.data.arg, 0);
+            /*
+            * Ideally we should get the CPUs used by the domain
+            * but that information is really node specific and it
+            * rather hard to get from that code path. So proxy
+            * users won't see CPU pinning (last NULL arg)
+            */
+           xml = xenDaemonDomainDumpXMLByID(conn, request.data.arg, 0, NULL);
             if (!xml) {
                 req->data.arg = -1;
                 req->len = sizeof(virProxyPacket);
index aadc0182217133d826fc1efc3b9077d1235ab882..385b12881023135dfac9770dcf95d09aecb0a357 100644 (file)
@@ -37,7 +37,6 @@ static int xenProxyListDomains(virConnectPtr conn, int *ids, int maxids);
 static int xenProxyNumOfDomains(virConnectPtr conn);
 static unsigned long xenProxyDomainGetMaxMemory(virDomainPtr domain);
 static int xenProxyDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info);
-static char *xenProxyDomainDumpXML(virDomainPtr domain, int flags);
 static char *xenProxyDomainGetOSType(virDomainPtr domain);
 
 struct xenUnifiedDriver xenProxyDriver = {
@@ -69,7 +68,6 @@ struct xenUnifiedDriver xenProxyDriver = {
     NULL, /* domainPinVcpu */
     NULL, /* domainGetVcpus */
     NULL, /* domainGetMaxVcpus */
-    xenProxyDomainDumpXML, /* domainDumpXML */
     NULL, /* listDefinedDomains */
     NULL, /* numOfDefinedDomains */
     NULL, /* domainCreate */
@@ -1014,7 +1012,7 @@ xenProxyGetCapabilities (virConnectPtr conn)
  *
  * Returns the XML document on success, NULL otherwise. 
  */
-static char *
+char *
 xenProxyDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED)
 {
     virProxyPacket req;
index 322d39cdf481c55abbe91c75d3389e673a026104..fa8e48abd403ea7829bf66cf39ec714a7f4b2263 100644 (file)
@@ -96,6 +96,8 @@ extern virDomainPtr xenProxyLookupByUUID(virConnectPtr conn,
 extern virDomainPtr xenProxyLookupByName(virConnectPtr conn,
                                          const char *domname);
 
+extern char *       xenProxyDomainDumpXML(virDomainPtr domain,
+                                         int flags);
 #ifdef __cplusplus
 }
 #endif                          /* __cplusplus */
index 0bc956e335ad781cf52178374624c5347e7932fd..3ffac1185f5f183af23519f3a20cc15edfc70e2a 100644 (file)
@@ -704,7 +704,6 @@ struct xenUnifiedDriver xenHypervisorDriver = {
     xenHypervisorPinVcpu, /* domainPinVcpu */
     xenHypervisorGetVcpus, /* domainGetVcpus */
     xenHypervisorGetVcpuMax, /* domainGetMaxVcpus */
-    NULL, /* domainDumpXML */
     NULL, /* listDefinedDomains */
     NULL, /* numOfDefinedDomains */
     NULL, /* domainCreate */
index 760ec5282f84c7d78c297feb22e6933a3006bc25..b4bbd56f1c07de26e878b551526e18849f9539d8 100644 (file)
 #include "xend_internal.h"
 #include "xs_internal.h"
 #include "xm_internal.h"
+#include "xml.h"
 
 static int
 xenUnifiedNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info);
+static int
+xenUnifiedDomainGetMaxVcpus (virDomainPtr dom);
+static int
+xenUnifiedDomainGetVcpus (virDomainPtr dom,
+                          virVcpuInfoPtr info, int maxinfo,
+                          unsigned char *cpumaps, int maplen);
 
 /* The five Xen drivers below us. */
 static struct xenUnifiedDriver *drivers[XEN_UNIFIED_NR_DRIVERS] = {
@@ -113,9 +120,9 @@ int xenNbCells(virConnectPtr conn) {
  * xenNbCpus:
  * @conn: pointer to the hypervisor connection
  *
- * Number of NUMa cells present in the actual Node
+ * Number of CPUs present in the actual Node
  *
- * Returns the number of NUMA cells available on that Node
+ * Returns the number of CPUs available on that Node
  */
 int xenNbCpus(virConnectPtr conn) {
     if (nbNodeCpus < 0)
@@ -123,6 +130,81 @@ int xenNbCpus(virConnectPtr conn) {
     return(nbNodeCpus);
 }
 
+/**
+ * xenDomainUsedCpus:
+ * @dom: the domain
+ *
+ * Analyze which set of CPUs are used by the domain and
+ * return a string providing the ranges.
+ *
+ * Returns the string which needs to be freed by the caller or
+ *         NULL if the domain uses all CPU or in case of error.
+ */
+char *
+xenDomainUsedCpus(virDomainPtr dom)
+{
+    char *res = NULL;
+    int nb_cpu, ncpus;
+    int nb_vcpu;
+    char *cpulist = NULL;
+    unsigned char *cpumap = NULL;
+    size_t cpumaplen;
+    int nb = 0;
+    int n, m;
+    virVcpuInfoPtr cpuinfo = NULL;
+    virNodeInfo nodeinfo;
+
+    if (!VIR_IS_CONNECTED_DOMAIN(dom))
+        return (NULL);
+
+    nb_cpu = xenNbCpus(dom->conn);
+    if (nb_cpu <= 0)
+        return(NULL);
+    nb_vcpu = xenUnifiedDomainGetMaxVcpus(dom);
+    if (nb_vcpu <= 0)
+        return(NULL);
+    if (xenUnifiedNodeGetInfo(dom->conn, &nodeinfo) < 0)
+        return(NULL);
+
+    cpulist = (char *) calloc(nb_cpu, sizeof(char));
+    if (cpulist == NULL)
+        goto done;
+    cpuinfo = malloc(sizeof(virVcpuInfo) * nb_vcpu);
+    if (cpuinfo == NULL)
+        goto done;
+    cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
+    cpumap = (unsigned char *) calloc(nb_vcpu, cpumaplen);
+    if (cpumap == NULL)
+        goto done;
+
+    if ((ncpus = xenUnifiedDomainGetVcpus(dom, cpuinfo, nb_vcpu,
+                                          cpumap, cpumaplen)) >= 0) {
+       for (n = 0 ; n < ncpus ; n++) {
+           for (m = 0 ; m < nb_cpu; m++) {
+               if ((cpulist[m] == 0) &&
+                   (VIR_CPU_USABLE(cpumap, cpumaplen, n, m))) {
+                   cpulist[m] = 1;
+                   nb++;
+                   /* if all CPU are used just return NULL */
+                   if (nb == nb_cpu) 
+                       goto done;
+                       
+               }
+           }
+       }
+        res = virSaveCpuSet(dom->conn, cpulist, nb_cpu);
+    }
+
+done:
+    if (cpulist != NULL)
+        free(cpulist);
+    if (cpumap != NULL)
+        free(cpumap);
+    if (cpuinfo != NULL)
+        free(cpuinfo);
+    return(res);
+}
+
 /*----- Dispatch functions. -----*/
 
 /* These dispatch functions follow the model used historically
@@ -862,19 +944,24 @@ static char *
 xenUnifiedDomainDumpXML (virDomainPtr dom, int flags)
 {
     GET_PRIVATE(dom->conn);
-    int i;
-    char *ret;
 
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] && drivers[i]->domainDumpXML) {
-            ret = drivers[i]->domainDumpXML (dom, flags);
-            if (ret) return ret;
+    if (dom->id == -1 && priv->xendConfigVersion < 3 ) {
+        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
+            return xenXMDomainDumpXML(dom, flags);
+    } else {
+        if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
+            char *cpus, *res;
+            cpus = xenDomainUsedCpus(dom);
+            res = xenDaemonDomainDumpXML(dom, flags, cpus);
+           if (cpus != NULL)
+               free(cpus);
+           return(res);
         }
+        if (priv->opened[XEN_UNIFIED_PROXY_OFFSET])
+            return xenProxyDomainDumpXML(dom, flags);
+    } 
 
-    /* XXX May need to return an error here if sub-drivers didn't
-     * set one.  We really should change these to direct calls to
-     * the sub-drivers at a later date.
-     */
+    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
     return NULL;
 }
 
index 86cc1c0ba5d726f2fb8b41e89ad4d83945bb22ee..212e82680875eb18bf36d4778bd2bbd96eac3bde 100644 (file)
@@ -65,7 +65,6 @@ struct xenUnifiedDriver {
        virDrvDomainPinVcpu             domainPinVcpu;
        virDrvDomainGetVcpus            domainGetVcpus;
        virDrvDomainGetMaxVcpus         domainGetMaxVcpus;
-       virDrvDomainDumpXML             domainDumpXML;
        virDrvListDefinedDomains        listDefinedDomains;
        virDrvNumOfDefinedDomains       numOfDefinedDomains;
        virDrvDomainCreate              domainCreate;
@@ -119,6 +118,7 @@ typedef struct _xenUnifiedPrivate *xenUnifiedPrivatePtr;
 
 int xenNbCells(virConnectPtr conn);
 int xenNbCpus(virConnectPtr conn);
+char *xenDomainUsedCpus(virDomainPtr dom);
 #ifdef __cplusplus
 }
 #endif
index e407a48805246dbef657c058d4cd8c14b40c2ef9..42242d7a5487b0989f0db05e1d26eabbea2afa1c 100644 (file)
@@ -94,7 +94,6 @@ struct xenUnifiedDriver xenDaemonDriver = {
     xenDaemonDomainPinVcpu, /* domainPinVcpu */
     xenDaemonDomainGetVcpus, /* domainGetVcpus */
     NULL, /* domainGetMaxVcpus */
-    xenDaemonDomainDumpXML, /* domainDumpXML */
     xenDaemonListDefinedDomains, /* listDefinedDomains */
     xenDaemonNumOfDefinedDomains, /* numOfDefinedDomains */
     xenDaemonDomainCreate, /* domainCreate */
@@ -1343,6 +1342,7 @@ xend_parse_sexp_desc_os(virConnectPtr xend, struct sexpr *node, virBufferPtr buf
  * @root: the root of the parsed S-Expression
  * @xendConfigVersion: version of xend
  * @flags: a combination of virDomainXMLFlags
+ * @cpus: set of cpus the domain may be pinned to
  *
  * Parse the xend sexp description and turn it into the XML format similar
  * to the one unsed for creation.
@@ -1352,7 +1352,7 @@ xend_parse_sexp_desc_os(virConnectPtr xend, struct sexpr *node, virBufferPtr buf
  */
 static char *
 xend_parse_sexp_desc(virConnectPtr conn, struct sexpr *root,
-                     int xendConfigVersion, int flags)
+                     int xendConfigVersion, int flags, const char *cpus)
 {
     struct sexpr *cur, *node;
     const char *tmp;
@@ -1438,8 +1438,18 @@ xend_parse_sexp_desc(virConnectPtr conn, struct sexpr *root,
     if ((cur_mem >= MIN_XEN_GUEST_SIZE) && (cur_mem != max_mem))
        virBufferVSprintf(&buf, "  <currentMemory>%d</currentMemory>\n",
                          cur_mem);
-    virBufferVSprintf(&buf, "  <vcpu>%d</vcpu>\n",
+    
+    virBufferVSprintf(&buf, "  <vcpu");
+    if (cpus != NULL) {
+       virBufferVSprintf(&buf, " cpuset='%s'", cpus);
+    }
+    virBufferVSprintf(&buf, ">%d</vcpu>\n",
                       sexpr_int(root, "domain/vcpus"));
+    /* TODO if need to output the cpus values,
+     * - parse the cpus values if xend exports
+     * or
+     * - analyze the cpus values extracted by xenDaemonDomainGetVcpus
+     */
     tmp = sexpr_node(root, "domain/on_poweroff");
     if (tmp != NULL)
         virBufferVSprintf(&buf, "  <on_poweroff>%s</on_poweroff>\n", tmp);
@@ -1802,7 +1812,7 @@ xend_parse_domain_sexp(virConnectPtr conn, char *sexpr, int xendConfigVersion) {
   if (!root)
       return NULL;
 
-  data = xend_parse_sexp_desc(conn, root, xendConfigVersion, 0);
+  data = xend_parse_sexp_desc(conn, root, xendConfigVersion, 0, NULL);
 
   sexpr_free(root);
 
@@ -2481,7 +2491,8 @@ xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory)
    dumpxml will work over proxy for inactive domains
    and this can be removed */
 char *
-xenDaemonDomainDumpXMLByID(virConnectPtr conn, int domid, int flags)
+xenDaemonDomainDumpXMLByID(virConnectPtr conn, int domid, int flags,
+                           const char *cpus)
 {
     char *ret = NULL;
     struct sexpr *root;
@@ -2496,14 +2507,16 @@ xenDaemonDomainDumpXMLByID(virConnectPtr conn, int domid, int flags)
 
     priv = (xenUnifiedPrivatePtr) conn->privateData;
 
-    ret = xend_parse_sexp_desc(conn, root, priv->xendConfigVersion, flags);
+    ret = xend_parse_sexp_desc(conn, root, priv->xendConfigVersion,
+                               flags, cpus);
     sexpr_free(root);
 
     return (ret);
 }
 
 char *
-xenDaemonDomainDumpXMLByName(virConnectPtr conn, const char *name, int flags)
+xenDaemonDomainDumpXMLByName(virConnectPtr conn, const char *name, int flags,
+                             const char *cpus)
 {
     char *ret = NULL;
     struct sexpr *root;
@@ -2518,7 +2531,8 @@ xenDaemonDomainDumpXMLByName(virConnectPtr conn, const char *name, int flags)
 
     priv = (xenUnifiedPrivatePtr) conn->privateData;
 
-    ret = xend_parse_sexp_desc(conn, root, priv->xendConfigVersion, flags);
+    ret = xend_parse_sexp_desc(conn, root, priv->xendConfigVersion,
+                               flags, cpus);
     sexpr_free(root);
 
     return (ret);
@@ -2529,6 +2543,8 @@ xenDaemonDomainDumpXMLByName(virConnectPtr conn, const char *name, int flags)
 /**
  * xenDaemonDomainDumpXML:
  * @domain: a domain object
+ * @flags: potential dump flags
+ * @cpus: list of cpu the domain is pinned to.
  *
  * Provide an XML description of the domain.
  *
@@ -2536,7 +2552,7 @@ xenDaemonDomainDumpXMLByName(virConnectPtr conn, const char *name, int flags)
  *         the caller must free() the returned value.
  */
 char *
-xenDaemonDomainDumpXML(virDomainPtr domain, int flags)
+xenDaemonDomainDumpXML(virDomainPtr domain, int flags, const char *cpus)
 {
     xenUnifiedPrivatePtr priv;
 
@@ -2553,9 +2569,11 @@ xenDaemonDomainDumpXML(virDomainPtr domain, int flags)
     }
 
     if (domain->id < 0)
-        return xenDaemonDomainDumpXMLByName(domain->conn, domain->name, flags);
+        return xenDaemonDomainDumpXMLByName(domain->conn, domain->name, flags,
+                                           cpus);
     else
-        return xenDaemonDomainDumpXMLByID(domain->conn, domain->id, flags);
+        return xenDaemonDomainDumpXMLByID(domain->conn, domain->id, flags,
+                                         cpus);
 }
 #endif /* !PROXY */
 
index e16d96cc07f570e21d79ba9da362b6a9be9d7e25..fcf42f922f7689c3412c8272202fb583ad906185 100644 (file)
@@ -110,11 +110,13 @@ int xenDaemonDomainLookupByID(virConnectPtr xend,
 
 char *xenDaemonDomainDumpXMLByID(virConnectPtr xend,
                                 int domid,
-                                int flags);
+                                int flags,
+                                const char *cpus);
 
 char *xenDaemonDomainDumpXMLByName(virConnectPtr xend,
                                   const char *name,
-                                  int flags);
+                                  int flags,
+                                  const char *cpus);
 
 /**
  * \brief Lookup information about the host machine
@@ -196,7 +198,7 @@ int xenDaemonDomainRestore(virConnectPtr conn, const char *filename);
 int xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory);
 int xenDaemonDomainSetMaxMemory(virDomainPtr domain, unsigned long memory);
 int xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info);
-char *xenDaemonDomainDumpXML(virDomainPtr domain, int flags);
+char *xenDaemonDomainDumpXML(virDomainPtr domain, int flags, const char *cpus);
 unsigned long xenDaemonDomainGetMaxMemory(virDomainPtr domain);
 char **xenDaemonListDomainsOld(virConnectPtr xend);
 
index 288359da0926b11dcd0c2dc1a6be51520064a7d6..3dedf7367094e9606e7349b0638b6db946548b2b 100644 (file)
@@ -104,7 +104,6 @@ struct xenUnifiedDriver xenXMDriver = {
     NULL, /* domainPinVcpu */
     NULL, /* domainGetVcpus */
     NULL, /* domainGetMaxVcpus */
-    xenXMDomainDumpXML, /* domainDumpXML */
     xenXMListDefinedDomains, /* listDefinedDomains */
     xenXMNumOfDefinedDomains, /* numOfDefinedDomains */
     xenXMDomainCreate, /* domainCreate */
@@ -660,11 +659,20 @@ char *xenXMDomainFormatXML(virConnectPtr conn, virConfPtr conf) {
             val = MIN_XEN_GUEST_SIZE * 2;
     virBufferVSprintf(buf, "  <memory>%ld</memory>\n", val * 1024);
 
+    virBufferVSprintf(buf, "  <vcpu"); /* DV */
+    if (xenXMConfigGetString(conf, "cpus", &str) == 0) {
+        char *ranges;
 
+       ranges = virConvertCpuSet(conn, str, 0);
+       if (ranges != NULL) {
+           virBufferVSprintf(buf, " cpuset='%s'", ranges);
+           free(ranges);
+       } else
+           virBufferVSprintf(buf, " cpuset='%s'", str);
+    }
     if (xenXMConfigGetInt(conf, "vcpus", &val) < 0)
         val = 1;
-    virBufferVSprintf(buf, "  <vcpu>%ld</vcpu>\n", val);
-
+    virBufferVSprintf(buf, ">%ld</vcpu>\n", val);
 
     if (xenXMConfigGetString(conf, "on_poweroff", &str) < 0)
         str = "destroy";
@@ -1763,6 +1771,7 @@ virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml) {
     virConfPtr conf = NULL;
     int hvm = 0, i;
     xenUnifiedPrivatePtr priv;
+    char *cpus;
 
     doc = xmlReadDoc((const xmlChar *) xml, "domain.xml", NULL,
                      XML_PARSE_NOENT | XML_PARSE_NONET |
@@ -1821,6 +1830,32 @@ virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml) {
                                    "cannot set vcpus config parameter") < 0)
         goto error;
 
+    cpus = virXPathString("string(/domain/vcpu/@cpuset)", ctxt);
+    if (cpus != NULL) {
+        char *ranges;
+
+       ranges = virConvertCpuSet(conn, cpus, 0);
+       if (ranges != NULL) {
+           free(cpus);
+           if (xenXMConfigSetString(conf, "cpus", ranges) < 0) {
+               free(ranges);
+               goto error;
+           }
+           free(ranges);
+       } else {
+           if (xenXMConfigSetString(conf, "cpus", cpus) < 0) {
+               free(cpus);
+               goto error;
+           }
+           free(cpus);
+       }
+    }
+
+    if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "cpus", /* DV */
+                                      "string(/domain/vcpu/@cpuset)", 1,
+                                      "cannot set the cpuset parameter") < 0)
+            goto error;
+
     obj = xmlXPathEval(BAD_CAST "string(/domain/os/type)", ctxt);
     if ((obj != NULL) && (obj->type == XPATH_STRING) &&
         (obj->stringval != NULL) && !strcmp((char*)obj->stringval, "hvm"))
index e87a6e687a342d019d51a7390b77fdb47c26045c..4eca53313e5c7cd9b84996a4e75b84ef46666aae 100644 (file)
--- a/src/xml.c
+++ b/src/xml.c
@@ -135,7 +135,7 @@ parseCpuNumber(const char **str, int maxcpu)
 }
 
 /**
- * saveCpuSet:
+ * virSaveCpuSet:
  * @conn: connection
  * @cpuset: pointer to a char array for the CPU set
  * @maxcpu: number of elements available in @cpuset
@@ -145,8 +145,8 @@ parseCpuNumber(const char **str, int maxcpu)
  * Returns the new string NULL in case of error. The string need to be
  *         freed by the caller.
  */
-static char *
-saveCpuSet(virConnectPtr conn, char *cpuset, int maxcpu)
+char *
+virSaveCpuSet(virConnectPtr conn, char *cpuset, int maxcpu)
 {
     virBufferPtr buf;
     char *ret;
@@ -174,8 +174,6 @@ saveCpuSet(virConnectPtr conn, char *cpuset, int maxcpu)
                 first = 0;
             if (cur == start + 1)
                 virBufferVSprintf(buf, "%d", start);
-            else if (cur == start + 2)
-                virBufferVSprintf(buf, "%d,%d", start, cur - 1);
             else
                 virBufferVSprintf(buf, "%d-%d", start, cur - 1);
             start = -1;
@@ -187,8 +185,6 @@ saveCpuSet(virConnectPtr conn, char *cpuset, int maxcpu)
             virBufferAdd(buf, ",", -1);
         if (maxcpu == start + 1)
             virBufferVSprintf(buf, "%d", start);
-        else if (maxcpu == start + 2)
-            virBufferVSprintf(buf, "%d,%d", start, maxcpu - 1);
         else
             virBufferVSprintf(buf, "%d-%d", start, maxcpu - 1);
     }
@@ -198,6 +194,7 @@ saveCpuSet(virConnectPtr conn, char *cpuset, int maxcpu)
 
 /**
  * virParseCpuSet:
+ * @conn: connection
  * @str: pointer to a CPU set string pointer
  * @sep: potential character used to mark the end of string if not 0
  * @cpuset: pointer to a char array for the CPU set
@@ -300,6 +297,7 @@ virParseCpuSet(virConnectPtr conn, const char **str, char sep,
 
 /**
  * virParseXenCpuTopology:
+ * @conn: connection
  * @xml: XML output buffer
  * @str: the topology string 
  * @maxcpu: number of elements available in @cpuset
@@ -362,7 +360,7 @@ virParseXenCpuTopology(virConnectPtr conn, virBufferPtr xml,
         {
             char *dump;
 
-            dump = saveCpuSet(conn, cpuset, maxcpu);
+            dump = virSaveCpuSet(conn, cpuset, maxcpu);
             if (dump != NULL) {
                 virBufferVSprintf(xml, "           <dump>%s</dump>\n",
                                   dump);
@@ -408,6 +406,45 @@ virParseXenCpuTopology(virConnectPtr conn, virBufferPtr xml,
     return (-1);
 }
 
+/**
+ * virConvertCpuSet:
+ * @conn: connection
+ * @str: pointer to a Xen or user provided CPU set string pointer
+ * @maxcpu: number of CPUs on the node, if 0 4096 will be used
+ *
+ * Parse the given CPU set string and convert it to a range based
+ * string.
+ *
+ * Returns a new string which must be freed by the caller or NULL in
+ *         case of error.
+ */
+char *
+virConvertCpuSet(virConnectPtr conn, const char *str, int maxcpu) {
+    int ret;
+    char *res, *cpuset;
+    const char *cur = str;
+
+    if (str == NULL)
+        return(NULL);
+
+    if (maxcpu <= 0)
+        maxcpu = 4096;
+
+    cpuset = calloc(maxcpu, sizeof(char));
+    if (cpuset == NULL) {
+       virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0);
+       return(NULL);
+    }
+    
+    ret = virParseCpuSet(conn, &cur, 0, cpuset, maxcpu);
+    if (ret < 0) {
+        free(cpuset);
+       return(NULL);
+    }
+    res = virSaveCpuSet(conn, cpuset, maxcpu);
+    free(cpuset);
+    return (res);
+}
 #ifndef PROXY
 
 /************************************************************************
@@ -1603,7 +1640,7 @@ virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name,
             if (cpuset != NULL) {
                 res = virParseCpuSet(conn, &cur, 0, cpuset, maxcpu);
                 if (res > 0) {
-                    ranges = saveCpuSet(conn, cpuset, maxcpu);
+                    ranges = virSaveCpuSet(conn, cpuset, maxcpu);
                     if (ranges != NULL) {
                         virBufferVSprintf(&buf, "(cpus '%s')", ranges);
                         free(ranges);
index ff355ee94be5fa4e727eab988c19d52c032203f6..045ec4e62e9fc95fc7497ba4b7e9dfe3324e1130 100644 (file)
--- a/src/xml.h
+++ b/src/xml.h
@@ -41,6 +41,12 @@ int          virParseCpuSet  (virConnectPtr conn,
                                 char sep,
                                 char *cpuset,
                                 int maxcpu);
+char *          virSaveCpuSet  (virConnectPtr conn,
+                                char *cpuset,
+                                int maxcpu);
+char *         virConvertCpuSet(virConnectPtr conn,
+                                const char *str,
+                                int maxcpu);
 char *         virDomainParseXMLDesc(virConnectPtr conn,
                                 const char *xmldesc,
                                 char **name,