* src/conf/domain_conf.h (_virDomainDef): Adjust vcpus to unsigned
short, to match virDomainGetInfo limit. Add maxvcpus member.
* src/conf/domain_conf.c (virDomainDefParseXML)
(virDomainDefFormat): parse and print out vcpu details.
* src/xen/xend_internal.c (xenDaemonParseSxpr)
(xenDaemonFormatSxpr): Manage both vcpu numbers, and require them
to be equal for now.
* src/xen/xm_internal.c (xenXMDomainConfigParse)
(xenXMDomainConfigFormat): Likewise.
* src/phyp/phyp_driver.c (phypDomainDumpXML): Likewise.
* src/openvz/openvz_conf.c (openvzLoadDomains): Likewise.
* src/openvz/openvz_driver.c (openvzDomainDefineXML)
(openvzDomainCreateXML, openvzDomainSetVcpusInternal): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainDumpXML, vboxDomainDefineXML):
Likewise.
* src/xenapi/xenapi_driver.c (xenapiDomainDumpXML): Likewise.
* src/xenapi/xenapi_utils.c (createVMRecordFromXml): Likewise.
* src/esx/esx_vmx.c (esxVMX_ParseConfig, esxVMX_FormatConfig):
Likewise.
* src/qemu/qemu_conf.c (qemuBuildSmpArgStr)
(qemuParseCommandLineSmp, qemuParseCommandLine): Likewise.
* src/qemu/qemu_driver.c (qemudDomainHotplugVcpus): Likewise.
* src/opennebula/one_conf.c (xmlOneTemplate): Likewise.
---
Two tightly-related changes. One: virDomainGetInfo implicitly limits
vcpus to a 16-bit number; so there's no need to pretend otherwise
through the rest of the code. Two: add a new maxvcpus member, but
for now, ensure that all domains treat vcpus == maxvcpus at all
times (domains that support hot-unplugging vcpus will be changed
in later patches).
src/conf/domain_conf.c | 35 ++++++++++++++++++++++++++++-------
src/conf/domain_conf.h | 3 ++-
src/esx/esx_vmx.c | 24 +++++++++++++++---------
src/opennebula/one_conf.c | 11 ++++++-----
src/openvz/openvz_conf.c | 7 ++++---
src/openvz/openvz_driver.c | 15 ++++++++++-----
src/phyp/phyp_driver.c | 2 +-
src/qemu/qemu_conf.c | 14 ++++++++++++--
src/qemu/qemu_driver.c | 5 +++--
src/vbox/vbox_tmpl.c | 12 ++++++++----
src/xen/xend_internal.c | 9 +++++----
src/xen/xm_internal.c | 9 ++++++---
src/xenapi/xenapi_driver.c | 2 +-
src/xenapi/xenapi_utils.c | 4 ++--
14 files changed, 103 insertions(+), 49 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index afb06e8..540767f 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4179,6 +4179,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
int i, n;
long id = -1;
virDomainDefPtr def;
+ unsigned long count;
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
@@ -4244,8 +4245,27 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
if (node)
def->hugepage_backed = 1;
- if (virXPathULong("string(./vcpu[1])", ctxt, &def->vcpus) < 0)
- def->vcpus = 1;
+ if (virXPathULong("string(./vcpu[1])", ctxt, &count) < 0)
+ def->maxvcpus = 1;
+ else {
+ def->maxvcpus = count;
+ if (def->maxvcpus != count || count == 0) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid maxvcpus %lu"), count);
+ goto error;
+ }
+ }
+
+ if (virXPathULong("string(./vcpu[1]/@current)", ctxt, &count) < 0)
+ def->vcpus = def->maxvcpus;
+ else {
+ def->vcpus = count;
+ if (def->vcpus != count || count == 0 || def->maxvcpus < count) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid current vcpus %lu"), count);
+ goto error;
+ }
+ }
tmp = virXPathString("string(./vcpu[1]/@cpuset)", ctxt);
if (tmp) {
@@ -6394,17 +6414,18 @@ char *virDomainDefFormat(virDomainDefPtr def,
if (def->cpumask[n] != 1)
allones = 0;
- if (allones) {
- virBufferVSprintf(&buf, " <vcpu>%lu</vcpu>\n",
def->vcpus);
- } else {
+ virBufferAddLit(&buf, " <vcpu");
+ if (!allones) {
char *cpumask = NULL;
if ((cpumask =
virDomainCpuSetFormat(def->cpumask, def->cpumasklen)) == NULL)
goto cleanup;
- virBufferVSprintf(&buf, " <vcpu
cpuset='%s'>%lu</vcpu>\n",
- cpumask, def->vcpus);
+ virBufferVSprintf(&buf, " cpuset='%s'", cpumask);
VIR_FREE(cpumask);
}
+ if (def->vcpus != def->maxvcpus)
+ virBufferVSprintf(&buf, " current='%u'", def->vcpus);
+ virBufferVSprintf(&buf, ">%u</vcpu>\n", def->maxvcpus);
if (def->os.bootloader) {
virBufferEscapeString(&buf, "
<bootloader>%s</bootloader>\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 7195c04..d3d3b5c 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -867,7 +867,8 @@ struct _virDomainDef {
unsigned long memory;
unsigned long maxmem;
unsigned char hugepage_backed;
- unsigned long vcpus;
+ unsigned short vcpus;
+ unsigned short maxvcpus;
int cpumasklen;
char *cpumask;
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
index 59eb3b2..cb0044d 100644
--- a/src/esx/esx_vmx.c
+++ b/src/esx/esx_vmx.c
@@ -50,7 +50,7 @@ def->uuid = <value> <=> uuid.bios =
"<value>"
def->name = <value> <=> displayName =
"<value>"
def->maxmem = <value kilobyte> <=> memsize = "<value
megabyte>" # must be a multiple of 4, defaults to 32
def->memory = <value kilobyte> <=> sched.mem.max = "<value
megabyte>" # defaults to "unlimited" -> def->memory =
def->maxmem
-def->vcpus = <value> <=> numvcpus =
"<value>" # must be 1 or a multiple of 2, defaults to
1
+def->maxvcpus = <value> <=> numvcpus =
"<value>" # must be 1 or a multiple of 2, defaults to
1
def->cpumask = <uint list> <=> sched.cpu.affinity =
"<uint list>"
@@ -1021,7 +1021,7 @@ esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char
*vmx,
goto cleanup;
}
- def->vcpus = numvcpus;
+ def->maxvcpus = def->vcpus = numvcpus;
/* vmx:sched.cpu.affinity -> def:cpumask */
// VirtualMachine:config.cpuAffinity.affinitySet
@@ -2497,16 +2497,22 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps,
virDomainDefPtr def,
(int)(def->memory / 1024));
}
- /* def:vcpus -> vmx:numvcpus */
- if (def->vcpus <= 0 || (def->vcpus % 2 != 0 && def->vcpus != 1))
{
+ /* def:maxvcpus -> vmx:numvcpus */
+ if (def->vcpus != def->maxvcpus) {
+ ESX_ERROR(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("No support for domain XML entry 'vcpu' attribute
"
+ "'current'"));
+ goto cleanup;
+ }
+ if (def->maxvcpus <= 0 || (def->maxvcpus % 2 != 0 &&
def->maxvcpus != 1)) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting domain XML entry 'vcpu' to be an unsigned
"
"integer (1 or a multiple of 2) but found %d"),
- (int)def->vcpus);
+ def->maxvcpus);
goto cleanup;
}
- virBufferVSprintf(&buffer, "numvcpus = \"%d\"\n",
(int)def->vcpus);
+ virBufferVSprintf(&buffer, "numvcpus = \"%d\"\n",
def->maxvcpus);
/* def:cpumask -> vmx:sched.cpu.affinity */
if (def->cpumasklen > 0) {
@@ -2520,11 +2526,11 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps,
virDomainDefPtr def,
}
}
- if (sched_cpu_affinity_length < def->vcpus) {
+ if (sched_cpu_affinity_length < def->maxvcpus) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting domain XML attribute 'cpuset' of entry
"
- "'vcpu' to contains at least %d CPU(s)"),
- (int)def->vcpus);
+ "'vcpu' to contain at least %d CPU(s)"),
+ def->maxvcpus);
goto cleanup;
}
diff --git a/src/opennebula/one_conf.c b/src/opennebula/one_conf.c
index 029d475..f674f9b 100644
--- a/src/opennebula/one_conf.c
+++ b/src/opennebula/one_conf.c
@@ -1,5 +1,7 @@
/*----------------------------------------------------------------------------------*/
-/* Copyright 2002-2009, Distributed Systems Architecture Group, Universidad
+/*
+ * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright 2002-2009, Distributed Systems Architecture Group, Universidad
* Complutense de Madrid (
dsa-research.org)
*
* This library is free software; you can redistribute it and/or
@@ -169,10 +171,9 @@ char* xmlOneTemplate(virDomainDefPtr def)
{
int i;
virBuffer buf= VIR_BUFFER_INITIALIZER;
- virBufferVSprintf(&buf,"#OpenNebula Template automatically generated by
libvirt\nNAME = %s\nCPU = %ld\nMEMORY = %ld\n",
- def->name,
- def->vcpus,
- (def->maxmem)/1024);
+ virBufferVSprintf(&buf, "#OpenNebula Template automatically generated
"
+ "by libvirt\nNAME = %s\nCPU = %d\nMEMORY = %ld\n",
+ def->name, def->maxvcpus, (def->maxmem)/1024);
/*Optional Booting OpenNebula Information:*/
if (def->os.kernel) {
diff --git a/src/openvz/openvz_conf.c b/src/openvz/openvz_conf.c
index ec11bbc..c84a6f3 100644
--- a/src/openvz/openvz_conf.c
+++ b/src/openvz/openvz_conf.c
@@ -507,11 +507,12 @@ int openvzLoadDomains(struct openvz_driver *driver) {
veid);
goto cleanup;
} else if (ret > 0) {
- dom->def->vcpus = strtoI(temp);
+ dom->def->maxvcpus = strtoI(temp);
}
- if (ret == 0 || dom->def->vcpus == 0)
- dom->def->vcpus = openvzGetNodeCPUs();
+ if (ret == 0 || dom->def->maxvcpus == 0)
+ dom->def->maxvcpus = openvzGetNodeCPUs();
+ dom->def->vcpus = dom->def->maxvcpus;
/* XXX load rest of VM config data .... */
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index 547646d..ebeb81d 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -925,8 +925,13 @@ openvzDomainDefineXML(virConnectPtr conn, const char *xml)
if (openvzDomainSetNetworkConfig(conn, vm->def) < 0)
goto cleanup;
- if (vm->def->vcpus > 0) {
- if (openvzDomainSetVcpusInternal(vm, vm->def->vcpus) < 0) {
+ if (vm->def->vcpus != vm->def->maxvcpus) {
+ openvzError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("current vcpu count must equal maximum"));
+ goto cleanup;
+ }
+ if (vm->def->maxvcpus > 0) {
+ if (openvzDomainSetVcpusInternal(vm, vm->def->maxvcpus) < 0) {
openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not set number of virtual cpu"));
goto cleanup;
@@ -1019,8 +1024,8 @@ openvzDomainCreateXML(virConnectPtr conn, const char *xml,
vm->def->id = vm->pid;
vm->state = VIR_DOMAIN_RUNNING;
- if (vm->def->vcpus > 0) {
- if (openvzDomainSetVcpusInternal(vm, vm->def->vcpus) < 0) {
+ if (vm->def->maxvcpus > 0) {
+ if (openvzDomainSetVcpusInternal(vm, vm->def->maxvcpus) < 0) {
openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not set number of virtual cpu"));
goto cleanup;
@@ -1249,7 +1254,7 @@ static int openvzDomainSetVcpusInternal(virDomainObjPtr vm,
return -1;
}
- vm->def->vcpus = nvcpus;
+ vm->def->maxvcpus = vm->def->vcpus = nvcpus;
return 0;
}
diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
index 74c22bb..bf1b45c 100644
--- a/src/phyp/phyp_driver.c
+++ b/src/phyp/phyp_driver.c
@@ -3540,7 +3540,7 @@ phypDomainDumpXML(virDomainPtr dom, int flags)
goto err;
}
- if ((def.vcpus =
+ if ((def.maxvcpus = def.vcpus =
phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0) {
VIR_ERROR0(_("Unable to determine domain's CPU."));
goto err;
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 7a37c70..5169e3c 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -3613,7 +3613,7 @@ qemuBuildSmpArgStr(const virDomainDefPtr def,
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
- virBufferVSprintf(&buf, "%lu", def->vcpus);
+ virBufferVSprintf(&buf, "%u", def->vcpus);
if ((qemuCmdFlags & QEMUD_CMD_FLAG_SMP_TOPOLOGY)) {
/* sockets, cores, and threads are either all zero
@@ -3624,11 +3624,18 @@ qemuBuildSmpArgStr(const virDomainDefPtr def,
virBufferVSprintf(&buf, ",threads=%u",
def->cpu->threads);
}
else {
- virBufferVSprintf(&buf, ",sockets=%lu", def->vcpus);
+ virBufferVSprintf(&buf, ",sockets=%u", def->maxvcpus);
virBufferVSprintf(&buf, ",cores=%u", 1);
virBufferVSprintf(&buf, ",threads=%u", 1);
}
}
+ if (def->vcpus != def->maxvcpus) {
+ virBufferFreeAndReset(&buf);
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("setting current vcpu count less than maximum is "
+ "not supported yet"));
+ return NULL;
+ }
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
@@ -6051,6 +6058,8 @@ qemuParseCommandLineSmp(virDomainDefPtr dom,
}
}
+ dom->maxvcpus = dom->vcpus;
+
if (sockets && cores && threads) {
virCPUDefPtr cpu;
@@ -6120,6 +6129,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
def->id = -1;
def->memory = def->maxmem = 64 * 1024;
+ def->maxvcpus = 1;
def->vcpus = 1;
def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC;
def->features = (1 << VIR_DOMAIN_FEATURE_ACPI)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 943cad4..c31eeb9 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2422,8 +2422,9 @@ qemuDetectVcpuPIDs(struct qemud_driver *driver,
if (ncpupids != vm->def->vcpus) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
- _("got wrong number of vCPU pids from QEMU monitor. got %d,
wanted %d"),
- ncpupids, (int)vm->def->vcpus);
+ _("got wrong number of vCPU pids from QEMU monitor. "
+ "got %d, wanted %d"),
+ ncpupids, vm->def->vcpus);
VIR_FREE(cpupids);
return -1;
}
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 960bcb3..690cbd0 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -2028,7 +2028,7 @@ static char *vboxDomainDumpXML(virDomainPtr dom, int flags) {
def->maxmem = memorySize * 1024;
machine->vtbl->GetCPUCount(machine, &CPUCount);
- def->vcpus = CPUCount;
+ def->maxvcpus = def->vcpus = CPUCount;
/* Skip cpumasklen, cpumask, onReboot, onPoweroff, onCrash */
@@ -4598,11 +4598,15 @@ static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const
char *xml) {
def->memory, (unsigned)rc);
}
- rc = machine->vtbl->SetCPUCount(machine, def->vcpus);
+ if (def->vcpus != def->maxvcpus) {
+ vboxError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("current vcpu count must equal maximum"));
+ }
+ rc = machine->vtbl->SetCPUCount(machine, def->maxvcpus);
if (NS_FAILED(rc)) {
vboxError(VIR_ERR_INTERNAL_ERROR,
- _("could not set the number of virtual CPUs to: %lu,
rc=%08x"),
- def->vcpus, (unsigned)rc);
+ _("could not set the number of virtual CPUs to: %u,
rc=%08x"),
+ def->maxvcpus, (unsigned)rc);
}
#if VBOX_API_VERSION < 3001
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index fce0233..16140d1 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -2188,7 +2188,8 @@ xenDaemonParseSxpr(virConnectPtr conn,
}
}
- def->vcpus = sexpr_int(root, "domain/vcpus");
+ def->maxvcpus = sexpr_int(root, "domain/vcpus");
+ def->vcpus = def->maxvcpus;
tmp = sexpr_node(root, "domain/on_poweroff");
if (tmp != NULL) {
@@ -5644,7 +5645,7 @@ xenDaemonFormatSxprInput(virDomainInputDefPtr input,
*
* Generate an SEXPR representing the domain configuration.
*
- * Returns the 0 terminatedi S-Expr string or NULL in case of error.
+ * Returns the 0 terminated S-Expr string or NULL in case of error.
* the caller must free() the returned value.
*/
char *
@@ -5661,7 +5662,7 @@ xenDaemonFormatSxpr(virConnectPtr conn,
virBufferVSprintf(&buf, "(name '%s')", def->name);
virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)",
def->memory/1024, def->maxmem/1024);
- virBufferVSprintf(&buf, "(vcpus %lu)", def->vcpus);
+ virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus);
if (def->cpumask) {
char *ranges = virDomainCpuSetFormat(def->cpumask, def->cpumasklen);
@@ -5756,7 +5757,7 @@ xenDaemonFormatSxpr(virConnectPtr conn,
else
virBufferVSprintf(&buf, "(kernel '%s')",
def->os.loader);
- virBufferVSprintf(&buf, "(vcpus %lu)", def->vcpus);
+ virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus);
for (i = 0 ; i < def->os.nBootDevs ; i++) {
switch (def->os.bootDevs[i]) {
diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c
index b9cb4c3..e658c19 100644
--- a/src/xen/xm_internal.c
+++ b/src/xen/xm_internal.c
@@ -678,6 +678,7 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
int i;
const char *defaultArch, *defaultMachine;
int vmlocaltime = 0;
+ unsigned long count;
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
@@ -768,9 +769,11 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
def->memory *= 1024;
def->maxmem *= 1024;
-
- if (xenXMConfigGetULong(conf, "vcpus", &def->vcpus, 1) < 0)
+ if (xenXMConfigGetULong(conf, "vcpus", &count, 1) < 0 ||
+ (unsigned short) count != count)
goto cleanup;
+ def->maxvcpus = count;
+ def->vcpus = def->maxvcpus;
if (xenXMConfigGetString(conf, "cpus", &str, NULL) < 0)
goto cleanup;
@@ -2239,7 +2242,7 @@ virConfPtr xenXMDomainConfigFormat(virConnectPtr conn,
if (xenXMConfigSetInt(conf, "memory", def->memory / 1024) < 0)
goto no_memory;
- if (xenXMConfigSetInt(conf, "vcpus", def->vcpus) < 0)
+ if (xenXMConfigSetInt(conf, "vcpus", def->maxvcpus) < 0)
goto no_memory;
if ((def->cpumask != NULL) &&
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
index a5690a0..1e40a25 100644
--- a/src/xenapi/xenapi_driver.c
+++ b/src/xenapi/xenapi_driver.c
@@ -1335,7 +1335,7 @@ xenapiDomainDumpXML (virDomainPtr dom, int flags ATTRIBUTE_UNUSED)
} else {
defPtr->memory = memory;
}
- defPtr->vcpus = xenapiDomainGetMaxVcpus(dom);
+ defPtr->maxvcpus = defPtr->vcpus = xenapiDomainGetMaxVcpus(dom);
enum xen_on_normal_exit action;
if (xen_vm_get_actions_after_shutdown(session, &action, vm)) {
defPtr->onPoweroff = xenapiNormalExitEnum2virDomainLifecycle(action);
diff --git a/src/xenapi/xenapi_utils.c b/src/xenapi/xenapi_utils.c
index 252073c..423f83a 100644
--- a/src/xenapi/xenapi_utils.c
+++ b/src/xenapi/xenapi_utils.c
@@ -510,8 +510,8 @@ createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr def,
else
(*record)->memory_dynamic_max = (*record)->memory_static_max;
- if (def->vcpus) {
- (*record)->vcpus_max = (int64_t) def->vcpus;
+ if (def->maxvcpus) {
+ (*record)->vcpus_max = (int64_t) def->maxvcpus;
(*record)->vcpus_at_startup = (int64_t) def->vcpus;
}
if (def->onPoweroff)
--
1.7.2.3