e10da2
From 4617eedfaeee2b187a1f14691d25746ba3ff31b6 Mon Sep 17 00:00:00 2001
e10da2
From: Eric Blake <eblake@redhat.com>
e10da2
Date: Wed, 29 Sep 2010 10:20:07 -0600
e10da2
Subject: [PATCH 07/15] vcpu: support maxvcpu in domain_conf
e10da2
e10da2
Although this patch adds a distinction between maximum vcpus and
e10da2
current vcpus in the XML, the values should be identical for all
e10da2
drivers at this point.  Only in subsequent per-driver patches will
e10da2
a distinction be made.
e10da2
e10da2
In general, virDomainGetInfo should prefer the current vcpus.
e10da2
e10da2
* src/conf/domain_conf.h (_virDomainDef): Adjust vcpus to unsigned
e10da2
short, to match virDomainGetInfo limit.  Add maxvcpus member.
e10da2
* src/conf/domain_conf.c (virDomainDefParseXML)
e10da2
(virDomainDefFormat): parse and print out vcpu details.
e10da2
* src/xen/xend_internal.c (xenDaemonParseSxpr)
e10da2
(xenDaemonFormatSxpr): Manage both vcpu numbers, and require them
e10da2
to be equal for now.
e10da2
* src/xen/xm_internal.c (xenXMDomainConfigParse)
e10da2
(xenXMDomainConfigFormat): Likewise.
e10da2
* src/phyp/phyp_driver.c (phypDomainDumpXML): Likewise.
e10da2
* src/openvz/openvz_conf.c (openvzLoadDomains): Likewise.
e10da2
* src/openvz/openvz_driver.c (openvzDomainDefineXML)
e10da2
(openvzDomainCreateXML, openvzDomainSetVcpusInternal): Likewise.
e10da2
* src/vbox/vbox_tmpl.c (vboxDomainDumpXML, vboxDomainDefineXML):
e10da2
Likewise.
e10da2
* src/xenapi/xenapi_driver.c (xenapiDomainDumpXML): Likewise.
e10da2
* src/xenapi/xenapi_utils.c (createVMRecordFromXml): Likewise.
e10da2
* src/esx/esx_vmx.c (esxVMX_ParseConfig, esxVMX_FormatConfig):
e10da2
Likewise.
e10da2
* src/qemu/qemu_conf.c (qemuBuildSmpArgStr)
e10da2
(qemuParseCommandLineSmp, qemuParseCommandLine): Likewise.
e10da2
* src/qemu/qemu_driver.c (qemudDomainHotplugVcpus): Likewise.
e10da2
* src/opennebula/one_conf.c (xmlOneTemplate): Likewise.
e10da2
---
e10da2
 src/conf/domain_conf.c     |   45 +++++++++++++++++++++++++++++++++++++------
e10da2
 src/conf/domain_conf.h     |    3 +-
e10da2
 src/esx/esx_vmx.c          |   24 ++++++++++++++--------
e10da2
 src/opennebula/one_conf.c  |    9 +++++--
e10da2
 src/openvz/openvz_conf.c   |    7 +++--
e10da2
 src/openvz/openvz_driver.c |   15 +++++++++----
e10da2
 src/phyp/phyp_driver.c     |    2 +-
e10da2
 src/qemu/qemu_conf.c       |   14 +++++++++++-
e10da2
 src/qemu/qemu_driver.c     |    5 ++-
e10da2
 src/vbox/vbox_tmpl.c       |   12 +++++++---
e10da2
 src/xen/xend_internal.c    |    9 ++++---
e10da2
 src/xen/xm_internal.c      |   11 ++++++---
e10da2
 src/xenapi/xenapi_driver.c |    2 +-
e10da2
 src/xenapi/xenapi_utils.c  |    4 +-
e10da2
 14 files changed, 114 insertions(+), 48 deletions(-)
e10da2
e10da2
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
e10da2
index 78d7a6a..a997e06 100644
e10da2
--- a/src/conf/domain_conf.c
e10da2
+++ b/src/conf/domain_conf.c
e10da2
@@ -4203,6 +4203,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
e10da2
     int i, n;
e10da2
     long id = -1;
e10da2
     virDomainDefPtr def;
e10da2
+    unsigned long count;
e10da2
e10da2
     if (VIR_ALLOC(def) < 0) {
e10da2
         virReportOOMError();
e10da2
@@ -4287,8 +4288,37 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
e10da2
                       &def->mem.swap_hard_limit) < 0)
e10da2
         def->mem.swap_hard_limit = 0;
e10da2
e10da2
-    if (virXPathULong("string(./vcpu[1])", ctxt, &def->vcpus) < 0)
e10da2
-        def->vcpus = 1;
e10da2
+    n = virXPathULong("string(./vcpu[1])", ctxt, &count);
e10da2
+    if (n == -2) {
e10da2
+        virDomainReportError(VIR_ERR_XML_ERROR, "%s",
e10da2
+                             _("maximum vcpus must be an integer"));
e10da2
+        goto error;
e10da2
+    } else if (n < 0) {
e10da2
+        def->maxvcpus = 1;
e10da2
+    } else {
e10da2
+        def->maxvcpus = count;
e10da2
+        if (def->maxvcpus != count || count == 0) {
e10da2
+            virDomainReportError(VIR_ERR_XML_ERROR,
e10da2
+                                 _("invalid maxvcpus %lu"), count);
e10da2
+            goto error;
e10da2
+        }
e10da2
+    }
e10da2
+
e10da2
+    n = virXPathULong("string(./vcpu[1]/@current)", ctxt, &count);
e10da2
+    if (n == -2) {
e10da2
+        virDomainReportError(VIR_ERR_XML_ERROR, "%s",
e10da2
+                             _("current vcpus must be an integer"));
e10da2
+        goto error;
e10da2
+    } else if (n < 0) {
e10da2
+        def->vcpus = def->maxvcpus;
e10da2
+    } else {
e10da2
+        def->vcpus = count;
e10da2
+        if (def->vcpus != count || count == 0 || def->maxvcpus < count) {
e10da2
+            virDomainReportError(VIR_ERR_XML_ERROR,
e10da2
+                                 _("invalid current vcpus %lu"), count);
e10da2
+            goto error;
e10da2
+        }
e10da2
+    }
e10da2
e10da2
     tmp = virXPathString("string(./vcpu[1]/@cpuset)", ctxt);
e10da2
     if (tmp) {
e10da2
@@ -6462,17 +6492,18 @@ char *virDomainDefFormat(virDomainDefPtr def,
e10da2
         if (def->cpumask[n] != 1)
e10da2
             allones = 0;
e10da2
e10da2
-    if (allones) {
e10da2
-        virBufferAsprintf(&buf, "  <vcpu>%lu</vcpu>\n", def->vcpus);
e10da2
-    } else {
e10da2
+    virBufferAddLit(&buf, "  
e10da2
+    if (!allones) {
e10da2
         char *cpumask = NULL;
e10da2
         if ((cpumask =
e10da2
              virDomainCpuSetFormat(def->cpumask, def->cpumasklen)) == NULL)
e10da2
             goto cleanup;
e10da2
-        virBufferAsprintf(&buf, "  <vcpu cpuset='%s'>%lu</vcpu>\n",
e10da2
-                          cpumask, def->vcpus);
e10da2
+        virBufferAsprintf(&buf, " cpuset='%s'", cpumask);
e10da2
         VIR_FREE(cpumask);
e10da2
     }
e10da2
+    if (def->vcpus != def->maxvcpus)
e10da2
+        virBufferAsprintf(&buf, " current='%u'", def->vcpus);
e10da2
+    virBufferAsprintf(&buf, ">%u</vcpu>\n", def->maxvcpus);
e10da2
e10da2
     if (def->os.bootloader) {
e10da2
         virBufferEscapeString(&buf, "  <bootloader>%s</bootloader>\n",
e10da2
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
e10da2
index db09c23..5499f28 100644
e10da2
--- a/src/conf/domain_conf.h
e10da2
+++ b/src/conf/domain_conf.h
e10da2
@@ -885,7 +885,8 @@ struct _virDomainDef {
e10da2
         unsigned long min_guarantee;
e10da2
         unsigned long swap_hard_limit;
e10da2
     } mem;
e10da2
-    unsigned long vcpus;
e10da2
+    unsigned short vcpus;
e10da2
+    unsigned short maxvcpus;
e10da2
     int cpumasklen;
e10da2
     char *cpumask;
e10da2
e10da2
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
e10da2
index 7ec8c0e..0a26614 100644
e10da2
--- a/src/esx/esx_vmx.c
e10da2
+++ b/src/esx/esx_vmx.c
e10da2
@@ -50,7 +50,7 @@ def->uuid = <value>               <=>   uuid.bios = "<value>"
e10da2
 def->name = <value>               <=>   displayName = "<value>"
e10da2
 def->mem.max_balloon = <value kilobyte>    <=>   memsize = "<value megabyte>"            # must be a multiple of 4, defaults to 32
e10da2
 def->mem.cur_balloon = <value kilobyte>    <=>   sched.mem.max = "<value megabyte>"      # defaults to "unlimited" -> def->mem.cur_balloon = def->mem.max_balloon
e10da2
-def->vcpus = <value>              <=>   numvcpus = "<value>"                    # must be 1 or a multiple of 2, defaults to 1
e10da2
+def->maxvcpus = <value>           <=>   numvcpus = "<value>"                    # must be 1 or a multiple of 2, defaults to 1
e10da2
 def->cpumask = <uint list>        <=>   sched.cpu.affinity = "<uint list>"
e10da2
e10da2
e10da2
@@ -1075,7 +1075,7 @@ esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char *vmx,
e10da2
         goto cleanup;
e10da2
     }
e10da2
e10da2
-    def->vcpus = numvcpus;
e10da2
+    def->maxvcpus = def->vcpus = numvcpus;
e10da2
e10da2
     /* vmx:sched.cpu.affinity -> def:cpumask */
e10da2
     // VirtualMachine:config.cpuAffinity.affinitySet
e10da2
@@ -2609,16 +2609,22 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
e10da2
                           (int)(def->mem.cur_balloon / 1024));
e10da2
     }
e10da2
e10da2
-    /* def:vcpus -> vmx:numvcpus */
e10da2
-    if (def->vcpus <= 0 || (def->vcpus % 2 != 0 && def->vcpus != 1)) {
e10da2
+    /* def:maxvcpus -> vmx:numvcpus */
e10da2
+    if (def->vcpus != def->maxvcpus) {
e10da2
+        ESX_ERROR(VIR_ERR_CONFIG_UNSUPPORTED,
e10da2
+                  _("No support for domain XML entry 'vcpu' attribute "
e10da2
+                    "'current'"));
e10da2
+        goto cleanup;
e10da2
+    }
e10da2
+    if (def->maxvcpus <= 0 || (def->maxvcpus % 2 != 0 && def->maxvcpus != 1)) {
e10da2
         ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
e10da2
                   _("Expecting domain XML entry 'vcpu' to be an unsigned "
e10da2
                     "integer (1 or a multiple of 2) but found %d"),
e10da2
-                  (int)def->vcpus);
e10da2
+                  def->maxvcpus);
e10da2
         goto cleanup;
e10da2
     }
e10da2
e10da2
-    virBufferAsprintf(&buffer, "numvcpus = \"%d\"\n", (int)def->vcpus);
e10da2
+    virBufferAsprintf(&buffer, "numvcpus = \"%d\"\n", def->maxvcpus);
e10da2
e10da2
     /* def:cpumask -> vmx:sched.cpu.affinity */
e10da2
     if (def->cpumasklen > 0) {
e10da2
@@ -2632,11 +2638,11 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
e10da2
             }
e10da2
         }
e10da2
e10da2
-        if (sched_cpu_affinity_length < def->vcpus) {
e10da2
+        if (sched_cpu_affinity_length < def->maxvcpus) {
e10da2
             ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
e10da2
                       _("Expecting domain XML attribute 'cpuset' of entry "
e10da2
-                        "'vcpu' to contains at least %d CPU(s)"),
e10da2
-                      (int)def->vcpus);
e10da2
+                        "'vcpu' to contain at least %d CPU(s)"),
e10da2
+                      def->maxvcpus);
e10da2
             goto cleanup;
e10da2
         }
e10da2
e10da2
diff --git a/src/opennebula/one_conf.c b/src/opennebula/one_conf.c
e10da2
index 44e28dc..2079c51 100644
e10da2
--- a/src/opennebula/one_conf.c
e10da2
+++ b/src/opennebula/one_conf.c
e10da2
@@ -1,5 +1,7 @@
e10da2
 /*----------------------------------------------------------------------------------*/
e10da2
-/* Copyright 2002-2009, Distributed Systems Architecture Group, Universidad
e10da2
+/*
e10da2
+ * Copyright (C) 2010 Red Hat, Inc.
e10da2
+ * Copyright 2002-2009, Distributed Systems Architecture Group, Universidad
e10da2
  * Complutense de Madrid (dsa-research.org)
e10da2
  *
e10da2
  * This library is free software; you can redistribute it and/or
e10da2
@@ -169,9 +171,10 @@ char* xmlOneTemplate(virDomainDefPtr def)
e10da2
 {
e10da2
     int i;
e10da2
     virBuffer buf= VIR_BUFFER_INITIALIZER;
e10da2
-    virBufferAsprintf(&buf,"#OpenNebula Template automatically generated by libvirt\nNAME = %s\nCPU = %ld\nMEMORY = %ld\n",
e10da2
+    virBufferAsprintf(&buf,"#OpenNebula Template automatically generated "
e10da2
+                      "by libvirt\nNAME = %s\nCPU = %d\nMEMORY = %ld\n",
e10da2
                       def->name,
e10da2
-                      def->vcpus,
e10da2
+                      def->maxvcpus,
e10da2
                       (def->mem.max_balloon)/1024);
e10da2
e10da2
     /*Optional Booting OpenNebula Information:*/
e10da2
diff --git a/src/openvz/openvz_conf.c b/src/openvz/openvz_conf.c
e10da2
index ec11bbc..c84a6f3 100644
e10da2
--- a/src/openvz/openvz_conf.c
e10da2
+++ b/src/openvz/openvz_conf.c
e10da2
@@ -507,11 +507,12 @@ int openvzLoadDomains(struct openvz_driver *driver) {
e10da2
                         veid);
e10da2
             goto cleanup;
e10da2
         } else if (ret > 0) {
e10da2
-            dom->def->vcpus = strtoI(temp);
e10da2
+            dom->def->maxvcpus = strtoI(temp);
e10da2
         }
e10da2
e10da2
-        if (ret == 0 || dom->def->vcpus == 0)
e10da2
-            dom->def->vcpus = openvzGetNodeCPUs();
e10da2
+        if (ret == 0 || dom->def->maxvcpus == 0)
e10da2
+            dom->def->maxvcpus = openvzGetNodeCPUs();
e10da2
+        dom->def->vcpus = dom->def->maxvcpus;
e10da2
e10da2
         /* XXX load rest of VM config data .... */
e10da2
e10da2
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
e10da2
index 0f3cfdf..b7c2754 100644
e10da2
--- a/src/openvz/openvz_driver.c
e10da2
+++ b/src/openvz/openvz_driver.c
e10da2
@@ -925,8 +925,13 @@ openvzDomainDefineXML(virConnectPtr conn, const char *xml)
e10da2
     if (openvzDomainSetNetworkConfig(conn, vm->def) < 0)
e10da2
         goto cleanup;
e10da2
e10da2
-    if (vm->def->vcpus > 0) {
e10da2
-        if (openvzDomainSetVcpusInternal(vm, vm->def->vcpus) < 0) {
e10da2
+    if (vm->def->vcpus != vm->def->maxvcpus) {
e10da2
+        openvzError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
e10da2
+                    _("current vcpu count must equal maximum"));
e10da2
+        goto cleanup;
e10da2
+    }
e10da2
+    if (vm->def->maxvcpus > 0) {
e10da2
+        if (openvzDomainSetVcpusInternal(vm, vm->def->maxvcpus) < 0) {
e10da2
             openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
e10da2
                         _("Could not set number of virtual cpu"));
e10da2
              goto cleanup;
e10da2
@@ -1019,8 +1024,8 @@ openvzDomainCreateXML(virConnectPtr conn, const char *xml,
e10da2
     vm->def->id = vm->pid;
e10da2
     vm->state = VIR_DOMAIN_RUNNING;
e10da2
e10da2
-    if (vm->def->vcpus > 0) {
e10da2
-        if (openvzDomainSetVcpusInternal(vm, vm->def->vcpus) < 0) {
e10da2
+    if (vm->def->maxvcpus > 0) {
e10da2
+        if (openvzDomainSetVcpusInternal(vm, vm->def->maxvcpus) < 0) {
e10da2
             openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
e10da2
                         _("Could not set number of virtual cpu"));
e10da2
             goto cleanup;
e10da2
@@ -1249,7 +1254,7 @@ static int openvzDomainSetVcpusInternal(virDomainObjPtr vm,
e10da2
         return -1;
e10da2
     }
e10da2
e10da2
-    vm->def->vcpus = nvcpus;
e10da2
+    vm->def->maxvcpus = vm->def->vcpus = nvcpus;
e10da2
     return 0;
e10da2
 }
e10da2
e10da2
diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
e10da2
index e284ae0..3d0ed11 100644
e10da2
--- a/src/phyp/phyp_driver.c
e10da2
+++ b/src/phyp/phyp_driver.c
e10da2
@@ -3540,7 +3540,7 @@ phypDomainDumpXML(virDomainPtr dom, int flags)
e10da2
         goto err;
e10da2
     }
e10da2
e10da2
-    if ((def.vcpus =
e10da2
+    if ((def.maxvcpus = def.vcpus =
e10da2
          phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0) {
e10da2
         VIR_ERROR0(_("Unable to determine domain's CPU."));
e10da2
         goto err;
e10da2
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
e10da2
index 83c0f83..38c8351 100644
e10da2
--- a/src/qemu/qemu_conf.c
e10da2
+++ b/src/qemu/qemu_conf.c
e10da2
@@ -3711,7 +3711,7 @@ qemuBuildSmpArgStr(const virDomainDefPtr def,
e10da2
 {
e10da2
     virBuffer buf = VIR_BUFFER_INITIALIZER;
e10da2
e10da2
-    virBufferAsprintf(&buf, "%lu", def->vcpus);
e10da2
+    virBufferAsprintf(&buf, "%u", def->vcpus);
e10da2
e10da2
     if ((qemuCmdFlags & QEMUD_CMD_FLAG_SMP_TOPOLOGY)) {
e10da2
         /* sockets, cores, and threads are either all zero
e10da2
@@ -3722,11 +3722,18 @@ qemuBuildSmpArgStr(const virDomainDefPtr def,
e10da2
             virBufferAsprintf(&buf, ",threads=%u", def->cpu->threads);
e10da2
         }
e10da2
         else {
e10da2
-            virBufferAsprintf(&buf, ",sockets=%lu", def->vcpus);
e10da2
+            virBufferAsprintf(&buf, ",sockets=%u", def->maxvcpus);
e10da2
             virBufferAsprintf(&buf, ",cores=%u", 1);
e10da2
             virBufferAsprintf(&buf, ",threads=%u", 1);
e10da2
         }
e10da2
     }
e10da2
+    if (def->vcpus != def->maxvcpus) {
e10da2
+        virBufferFreeAndReset(&buf;;
e10da2
+        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
e10da2
+                        _("setting current vcpu count less than maximum is "
e10da2
+                          "not supported yet"));
e10da2
+        return NULL;
e10da2
+    }
e10da2
e10da2
     if (virBufferError(&buf)) {
e10da2
         virBufferFreeAndReset(&buf;;
e10da2
@@ -6178,6 +6185,8 @@ qemuParseCommandLineSmp(virDomainDefPtr dom,
e10da2
         }
e10da2
     }
e10da2
e10da2
+    dom->maxvcpus = dom->vcpus;
e10da2
+
e10da2
     if (sockets && cores && threads) {
e10da2
         virCPUDefPtr cpu;
e10da2
e10da2
@@ -6247,6 +6256,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
e10da2
e10da2
     def->id = -1;
e10da2
     def->mem.cur_balloon = def->mem.max_balloon = 64 * 1024;
e10da2
+    def->maxvcpus = 1;
e10da2
     def->vcpus = 1;
e10da2
     def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC;
e10da2
     def->features = (1 << VIR_DOMAIN_FEATURE_ACPI)
e10da2
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
e10da2
index 7a2ea8f..c66dc04 100644
e10da2
--- a/src/qemu/qemu_driver.c
e10da2
+++ b/src/qemu/qemu_driver.c
e10da2
@@ -2425,8 +2425,9 @@ qemuDetectVcpuPIDs(struct qemud_driver *driver,
e10da2
e10da2
     if (ncpupids != vm->def->vcpus) {
e10da2
         qemuReportError(VIR_ERR_INTERNAL_ERROR,
e10da2
-                        _("got wrong number of vCPU pids from QEMU monitor. got %d, wanted %d"),
e10da2
-                        ncpupids, (int)vm->def->vcpus);
e10da2
+                        _("got wrong number of vCPU pids from QEMU monitor. "
e10da2
+                          "got %d, wanted %d"),
e10da2
+                        ncpupids, vm->def->vcpus);
e10da2
         VIR_FREE(cpupids);
e10da2
         return -1;
e10da2
     }
e10da2
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
e10da2
index 0cbe8b3..5a859a4 100644
e10da2
--- a/src/vbox/vbox_tmpl.c
e10da2
+++ b/src/vbox/vbox_tmpl.c
e10da2
@@ -2028,7 +2028,7 @@ static char *vboxDomainDumpXML(virDomainPtr dom, int flags) {
e10da2
             def->mem.max_balloon = memorySize * 1024;
e10da2
e10da2
             machine->vtbl->GetCPUCount(machine, &CPUCount);
e10da2
-            def->vcpus = CPUCount;
e10da2
+            def->maxvcpus = def->vcpus = CPUCount;
e10da2
e10da2
             /* Skip cpumasklen, cpumask, onReboot, onPoweroff, onCrash */
e10da2
e10da2
@@ -4598,11 +4598,15 @@ static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml) {
e10da2
                   def->mem.cur_balloon, (unsigned)rc);
e10da2
     }
e10da2
e10da2
-    rc = machine->vtbl->SetCPUCount(machine, def->vcpus);
e10da2
+    if (def->vcpus != def->maxvcpus) {
e10da2
+        vboxError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
e10da2
+                    _("current vcpu count must equal maximum"));
e10da2
+    }
e10da2
+    rc = machine->vtbl->SetCPUCount(machine, def->maxvcpus);
e10da2
     if (NS_FAILED(rc)) {
e10da2
         vboxError(VIR_ERR_INTERNAL_ERROR,
e10da2
-                  _("could not set the number of virtual CPUs to: %lu, rc=%08x"),
e10da2
-                  def->vcpus, (unsigned)rc);
e10da2
+                  _("could not set the number of virtual CPUs to: %u, rc=%08x"),
e10da2
+                  def->maxvcpus, (unsigned)rc);
e10da2
     }
e10da2
e10da2
 #if VBOX_API_VERSION < 3001
e10da2
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
e10da2
index 5ffc3c8..456b477 100644
e10da2
--- a/src/xen/xend_internal.c
e10da2
+++ b/src/xen/xend_internal.c
e10da2
@@ -2190,7 +2190,8 @@ xenDaemonParseSxpr(virConnectPtr conn,
e10da2
         }
e10da2
     }
e10da2
e10da2
-    def->vcpus = sexpr_int(root, "domain/vcpus");
e10da2
+    def->maxvcpus = sexpr_int(root, "domain/vcpus");
e10da2
+    def->vcpus = def->maxvcpus;
e10da2
e10da2
     tmp = sexpr_node(root, "domain/on_poweroff");
e10da2
     if (tmp != NULL) {
e10da2
@@ -5649,7 +5650,7 @@ xenDaemonFormatSxprInput(virDomainInputDefPtr input,
e10da2
  *
e10da2
  * Generate an SEXPR representing the domain configuration.
e10da2
  *
e10da2
- * Returns the 0 terminatedi S-Expr string or NULL in case of error.
e10da2
+ * Returns the 0 terminated S-Expr string or NULL in case of error.
e10da2
  *         the caller must free() the returned value.
e10da2
  */
e10da2
 char *
e10da2
@@ -5666,7 +5667,7 @@ xenDaemonFormatSxpr(virConnectPtr conn,
e10da2
     virBufferAsprintf(&buf, "(name '%s')", def->name);
e10da2
     virBufferAsprintf(&buf, "(memory %lu)(maxmem %lu)",
e10da2
                       def->mem.cur_balloon/1024, def->mem.max_balloon/1024);
e10da2
-    virBufferAsprintf(&buf, "(vcpus %lu)", def->vcpus);
e10da2
+    virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus);
e10da2
e10da2
     if (def->cpumask) {
e10da2
         char *ranges = virDomainCpuSetFormat(def->cpumask, def->cpumasklen);
e10da2
@@ -5761,7 +5762,7 @@ xenDaemonFormatSxpr(virConnectPtr conn,
e10da2
             else
e10da2
                 virBufferAsprintf(&buf, "(kernel '%s')", def->os.loader);
e10da2
e10da2
-            virBufferAsprintf(&buf, "(vcpus %lu)", def->vcpus);
e10da2
+            virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus);
e10da2
e10da2
             for (i = 0 ; i < def->os.nBootDevs ; i++) {
e10da2
                 switch (def->os.bootDevs[i]) {
e10da2
diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c
e10da2
index 8e42a1c..bf20a64 100644
e10da2
--- a/src/xen/xm_internal.c
e10da2
+++ b/src/xen/xm_internal.c
e10da2
@@ -678,6 +678,7 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
e10da2
     int i;
e10da2
     const char *defaultArch, *defaultMachine;
e10da2
     int vmlocaltime = 0;
e10da2
+    unsigned long count;
e10da2
e10da2
     if (VIR_ALLOC(def) < 0) {
e10da2
         virReportOOMError();
e10da2
@@ -770,9 +771,11 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
e10da2
     def->mem.cur_balloon *= 1024;
e10da2
     def->mem.max_balloon *= 1024;
e10da2
e10da2
-
e10da2
-    if (xenXMConfigGetULong(conf, "vcpus", &def->vcpus, 1) < 0)
e10da2
+    if (xenXMConfigGetULong(conf, "vcpus", &count, 1) < 0 ||
e10da2
+        (unsigned short) count != count)
e10da2
         goto cleanup;
e10da2
+    def->maxvcpus = count;
e10da2
+    def->vcpus = def->maxvcpus;
e10da2
e10da2
     if (xenXMConfigGetString(conf, "cpus", &str, NULL) < 0)
e10da2
         goto cleanup;
e10da2
@@ -1650,7 +1653,7 @@ int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus) {
e10da2
     if (!(entry = virHashLookup(priv->configCache, filename)))
e10da2
         goto cleanup;
e10da2
e10da2
-    entry->def->vcpus = vcpus;
e10da2
+    entry->def->maxvcpus = entry->def->vcpus = vcpus;
e10da2
e10da2
     /* If this fails, should we try to undo our changes to the
e10da2
      * in-memory representation of the config file. I say not!
e10da2
@@ -2241,7 +2244,7 @@ virConfPtr xenXMDomainConfigFormat(virConnectPtr conn,
e10da2
     if (xenXMConfigSetInt(conf, "memory", def->mem.cur_balloon / 1024) < 0)
e10da2
         goto no_memory;
e10da2
e10da2
-    if (xenXMConfigSetInt(conf, "vcpus", def->vcpus) < 0)
e10da2
+    if (xenXMConfigSetInt(conf, "vcpus", def->maxvcpus) < 0)
e10da2
         goto no_memory;
e10da2
e10da2
     if ((def->cpumask != NULL) &&
e10da2
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
e10da2
index 7d4ab8d..5ccdede 100644
e10da2
--- a/src/xenapi/xenapi_driver.c
e10da2
+++ b/src/xenapi/xenapi_driver.c
e10da2
@@ -1335,7 +1335,7 @@ xenapiDomainDumpXML (virDomainPtr dom, int flags ATTRIBUTE_UNUSED)
e10da2
     } else {
e10da2
         defPtr->mem.cur_balloon = memory;
e10da2
     }
e10da2
-    defPtr->vcpus = xenapiDomainGetMaxVcpus(dom);
e10da2
+    defPtr->maxvcpus = defPtr->vcpus = xenapiDomainGetMaxVcpus(dom);
e10da2
     enum xen_on_normal_exit action;
e10da2
     if (xen_vm_get_actions_after_shutdown(session, &action, vm)) {
e10da2
         defPtr->onPoweroff = xenapiNormalExitEnum2virDomainLifecycle(action);
e10da2
diff --git a/src/xenapi/xenapi_utils.c b/src/xenapi/xenapi_utils.c
e10da2
index be55491..a7e2a4b 100644
e10da2
--- a/src/xenapi/xenapi_utils.c
e10da2
+++ b/src/xenapi/xenapi_utils.c
e10da2
@@ -510,8 +510,8 @@ createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr def,
e10da2
     else
e10da2
         (*record)->memory_dynamic_max = (*record)->memory_static_max;
e10da2
e10da2
-    if (def->vcpus) {
e10da2
-        (*record)->vcpus_max = (int64_t) def->vcpus;
e10da2
+    if (def->maxvcpus) {
e10da2
+        (*record)->vcpus_max = (int64_t) def->maxvcpus;
e10da2
         (*record)->vcpus_at_startup = (int64_t) def->vcpus;
e10da2
     }
e10da2
     if (def->onPoweroff)
e10da2
-- 
e10da2
1.7.2.3
e10da2