diff --git c/docs/formatdomain.html.in w/docs/formatdomain.html.in
index 0f5066a..174cd1f 100644
--- c/docs/formatdomain.html.in
+++ w/docs/formatdomain.html.in
@@ -222,7 +222,7 @@
a range of CPU numbers, or a caret followed by a CPU number to
be excluded from a previous range. Since
0.8.5, the optional attribute current
can
- be used to specify that fewer than the maximum number of
+ be used to specify whether fewer than the maximum number of
virtual CPUs should be enabled.
diff --git c/include/libvirt/libvirt.h.in w/include/libvirt/libvirt.h.in
index 0361455..d0cc4c0 100644
--- c/include/libvirt/libvirt.h.in
+++ w/include/libvirt/libvirt.h.in
@@ -915,13 +915,14 @@ struct _virVcpuInfo {
};
typedef virVcpuInfo *virVcpuInfoPtr;
+/* Flags for controlling virtual CPU hot-plugging. */
typedef enum {
/* Must choose at least one of these two bits; SetVcpus can choose both */
- VIR_DOMAIN_VCPU_ACTIVE = (1 << 0), /* Affect active domain */
- VIR_DOMAIN_VCPU_PERSISTENT = (1 << 1), /* Affect next boot */
+ VIR_DOMAIN_VCPU_LIVE = (1 << 0), /* Affect active domain */
+ VIR_DOMAIN_VCPU_CONFIG = (1 << 1), /* Affect next boot */
/* Additional flags to be bit-wise OR'd in */
- VIR_DOMAIN_VCPU_MAXIMUM = (1 << 2), /* Max rather than current count */
+ VIR_DOMAIN_VCPU_MAXIMUM = (1 << 2), /* Max rather than current count */
} virDomainVcpuFlags;
int virDomainSetVcpus (virDomainPtr domain,
diff --git c/src/conf/domain_conf.c w/src/conf/domain_conf.c
index e4f0402..dba0b12 100644
--- c/src/conf/domain_conf.c
+++ w/src/conf/domain_conf.c
@@ -4268,23 +4268,33 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
&def->mem.swap_hard_limit) < 0)
def->mem.swap_hard_limit = 0;
- if (virXPathULong("string(./vcpu[1])", ctxt, &count) < 0)
+ n = virXPathULong("string(./vcpu[1])", ctxt, &count);
+ if (n == -2) {
+ virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+ _("maximum vcpus must be an integer"));
+ goto error;
+ } else if (n < 0) {
def->maxvcpus = 1;
- else {
+ } else {
def->maxvcpus = count;
if (def->maxvcpus != count || count == 0) {
- virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ virDomainReportError(VIR_ERR_XML_ERROR,
_("invalid maxvcpus %lu"), count);
goto error;
}
}
- if (virXPathULong("string(./vcpu[1]/@current)", ctxt, &count) < 0)
+ n = virXPathULong("string(./vcpu[1]/@current)", ctxt, &count);
+ if (n == -2) {
+ virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+ _("current vcpus must be an integer"));
+ goto error;
+ } else if (n < 0) {
def->vcpus = def->maxvcpus;
- else {
+ } else {
def->vcpus = count;
if (def->vcpus != count || count == 0 || def->maxvcpus < count) {
- virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ virDomainReportError(VIR_ERR_XML_ERROR,
_("invalid current vcpus %lu"), count);
goto error;
}
diff --git c/src/esx/esx_driver.c w/src/esx/esx_driver.c
index cab2f63..465da45 100644
--- c/src/esx/esx_driver.c
+++ w/src/esx/esx_driver.c
@@ -2393,7 +2393,7 @@ esxDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus,
esxVI_ManagedObjectReference *task = NULL;
esxVI_TaskInfoState taskInfoState;
- if (flags != VIR_DOMAIN_VCPU_ACTIVE) {
+ if (flags != VIR_DOMAIN_VCPU_LIVE) {
ESX_ERROR(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
return -1;
}
@@ -2460,7 +2460,7 @@ esxDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus,
static int
esxDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus)
{
- return esxDomainSetVcpusFlags(domain, nvcpus, VIR_DOMAIN_VCPU_ACTIVE);
+ return esxDomainSetVcpusFlags(domain, nvcpus, VIR_DOMAIN_VCPU_LIVE);
}
@@ -2472,7 +2472,7 @@ esxDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
esxVI_ObjectContent *hostSystem = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
- if (flags != (VIR_DOMAIN_VCPU_ACTIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
+ if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
ESX_ERROR(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
return -1;
}
@@ -2525,7 +2525,7 @@ esxDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
static int
esxDomainGetMaxVcpus(virDomainPtr domain)
{
- return esxDomainGetVcpusFlags(domain, (VIR_DOMAIN_VCPU_ACTIVE |
+ return esxDomainGetVcpusFlags(domain, (VIR_DOMAIN_VCPU_LIVE |
VIR_DOMAIN_VCPU_MAXIMUM));
}
diff --git c/src/libvirt.c w/src/libvirt.c
index def1f74..c9f93c6 100644
--- c/src/libvirt.c
+++ w/src/libvirt.c
@@ -5178,7 +5178,9 @@ error:
* This function requires privileged access to the hypervisor.
*
* This command only changes the runtime configuration of the domain,
- * so can only be called on an active domain.
+ * so can only be called on an active domain. It is hypervisor-dependent
+ * whether it also affects persistent configuration; for more control,
+ * use virDomainSetVcpusFlags().
*
* Returns 0 in case of success, -1 in case of failure.
*/
@@ -5233,13 +5235,13 @@ error:
* does not support it or if growing the number is arbitrary limited.
* This function requires privileged access to the hypervisor.
*
- * @flags must include VIR_DOMAIN_VCPU_ACTIVE to affect a running
- * domain (which will fail if domain is not active), or
- * VIR_DOMAIN_VCPU_PERSISTENT to affect the next boot via the XML
+ * @flags must include VIR_DOMAIN_VCPU_LIVE to affect a running
+ * domain (which may fail if domain is not active), or
+ * VIR_DOMAIN_VCPU_CONFIG to affect the next boot via the XML
* description of the domain. Both flags may be set.
*
* If @flags includes VIR_DOMAIN_VCPU_MAXIMUM, then
- * VIR_DOMAIN_VCPU_ACTIVE must be clear, and only the maximum virtual
+ * VIR_DOMAIN_VCPU_LIVE must be clear, and only the maximum virtual
* CPU limit is altered; generally, this value must be less than or
* equal to virConnectGetMaxVcpus(). Otherwise, this call affects the
* current virtual CPU limit, which must be less than or equal to the
@@ -5267,7 +5269,9 @@ virDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus,
goto error;
}
- if (nvcpus < 1) {
+ /* Perform some argument validation common to all implementations. */
+ if (nvcpus < 1 || (unsigned short) nvcpus != nvcpus ||
+ (flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0) {
virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
goto error;
}
@@ -5324,6 +5328,11 @@ virDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
return (-1);
}
+ /* Exactly one of these two flags should be set. */
+ if (!(flags & VIR_DOMAIN_VCPU_LIVE) == !(flags & VIR_DOMAIN_VCPU_CONFIG)) {
+ virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ goto error;
+ }
conn = domain->conn;
if (conn->driver->domainGetVcpusFlags) {
@@ -5476,9 +5485,9 @@ error:
*
* Provides the maximum number of virtual CPUs supported for
* the guest VM. If the guest is inactive, this is basically
- * the same as virConnectGetMaxVcpus. If the guest is running
+ * the same as virConnectGetMaxVcpus(). If the guest is running
* this will reflect the maximum number of virtual CPUs the
- * guest was booted with.
+ * guest was booted with. For more details, see virDomainGetVcpusFlags().
*
* Returns the maximum of virtual CPU or -1 in case of error.
*/
diff --git c/src/openvz/openvz_driver.c w/src/openvz/openvz_driver.c
index c3eb099..b7c2754 100644
--- c/src/openvz/openvz_driver.c
+++ w/src/openvz/openvz_driver.c
@@ -1219,7 +1219,7 @@ static int
openvzDomainGetVcpusFlags(virDomainPtr dom ATTRIBUTE_UNUSED,
unsigned int flags)
{
- if (flags != (VIR_DOMAIN_VCPU_ACTIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
+ if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
openvzError(VIR_ERR_INVALID_ARG, _("unsupported flags (0x%x)"), flags);
return -1;
}
@@ -1229,7 +1229,7 @@ openvzDomainGetVcpusFlags(virDomainPtr dom ATTRIBUTE_UNUSED,
static int openvzDomainGetMaxVcpus(virDomainPtr dom)
{
- return openvzDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_ACTIVE |
+ return openvzDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
VIR_DOMAIN_VCPU_MAXIMUM));
}
@@ -1265,7 +1265,7 @@ static int openvzDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
struct openvz_driver *driver = dom->conn->privateData;
int ret = -1;
- if (flags != VIR_DOMAIN_VCPU_ACTIVE) {
+ if (flags != VIR_DOMAIN_VCPU_LIVE) {
openvzError(VIR_ERR_INVALID_ARG, _("unsupported flags (0x%x)"), flags);
return -1;
}
@@ -1298,7 +1298,7 @@ cleanup:
static int
openvzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
{
- return openvzDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_ACTIVE);
+ return openvzDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
}
static virDrvOpenStatus openvzOpen(virConnectPtr conn,
diff --git c/src/phyp/phyp_driver.c w/src/phyp/phyp_driver.c
index 95fcaca..3d0ed11 100644
--- c/src/phyp/phyp_driver.c
+++ w/src/phyp/phyp_driver.c
@@ -1502,7 +1502,7 @@ phypDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
phyp_driverPtr phyp_driver = dom->conn->privateData;
char *managed_system = phyp_driver->managed_system;
- if (flags != (VIR_DOMAIN_VCPU_ACTIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
+ if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
PHYP_ERROR(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
return -1;
}
@@ -1513,7 +1513,7 @@ phypDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
static int
phypGetLparCPUMAX(virDomainPtr dom)
{
- return phypDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_ACTIVE |
+ return phypDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
VIR_DOMAIN_VCPU_MAXIMUM));
}
@@ -3859,7 +3859,7 @@ phypDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
unsigned int amount = 0;
virBuffer buf = VIR_BUFFER_INITIALIZER;
- if (flags != VIR_DOMAIN_VCPU_ACTIVE) {
+ if (flags != VIR_DOMAIN_VCPU_LIVE) {
PHYP_ERROR(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
return -1;
}
@@ -3912,7 +3912,7 @@ phypDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
static int
phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus)
{
- return phypDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_ACTIVE);
+ return phypDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
}
static virDrvOpenStatus
diff --git c/src/qemu/qemu_conf.c w/src/qemu/qemu_conf.c
index f8aa5ca..e2ac59f 100644
--- c/src/qemu/qemu_conf.c
+++ w/src/qemu/qemu_conf.c
@@ -3723,7 +3723,7 @@ qemuBuildSmpArgStr(const virDomainDefPtr def,
}
} else if (def->vcpus != def->maxvcpus) {
virBufferFreeAndReset(&buf);
- // FIXME - consider hot-unplugging cpus after boot
+ /* FIXME - consider hot-unplugging cpus after boot for older qemu */
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("setting current vcpu count less than maximum is "
"not supported with this QEMU binary"));
diff --git c/src/qemu/qemu_driver.c w/src/qemu/qemu_driver.c
index 4a8d166..69f3d92 100644
--- c/src/qemu/qemu_driver.c
+++ w/src/qemu/qemu_driver.c
@@ -5940,19 +5940,20 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
{
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
+ virDomainDefPtr def;
const char * type;
int max;
int ret = -1;
- virCheckFlags(VIR_DOMAIN_VCPU_ACTIVE |
- VIR_DOMAIN_VCPU_PERSISTENT |
+ virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_CONFIG |
VIR_DOMAIN_VCPU_MAXIMUM, -1);
- /* At least one of ACTIVE or PERSISTENT must be set. MAXIMUM
- * requires exactly PERSISTENT. */
- if ((flags & (VIR_DOMAIN_VCPU_ACTIVE | VIR_DOMAIN_VCPU_PERSISTENT)) == 0 ||
- (flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_ACTIVE)) ==
- (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_ACTIVE)) {
+ /* At least one of LIVE or CONFIG must be set. MAXIMUM cannot be
+ * mixed with LIVE. */
+ if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0 ||
+ (flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) ==
+ (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) {
qemuReportError(VIR_ERR_INVALID_ARG,
_("invalid flag combination: (0x%x)"), flags);
return -1;
@@ -5978,7 +5979,7 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
if (qemuDomainObjBeginJob(vm) < 0)
goto cleanup;
- if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_VCPU_ACTIVE)) {
+ if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_VCPU_LIVE)) {
qemuReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not running"));
goto endjob;
@@ -5997,8 +5998,8 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
goto endjob;
}
- if ((flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_ACTIVE)) ==
- VIR_DOMAIN_VCPU_ACTIVE && vm->def->maxvcpus < max) {
+ if ((flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) ==
+ VIR_DOMAIN_VCPU_LIVE && vm->def->maxvcpus < max) {
max = vm->def->maxvcpus;
}
@@ -6010,33 +6011,43 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
}
switch (flags) {
- case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_PERSISTENT:
- if (!vm->newDef)
- qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("no persistent state"));
- else {
- vm->newDef->maxvcpus = nvcpus;
- if (nvcpus < vm->newDef->vcpus)
- vm->newDef->vcpus = nvcpus;
- ret = 0;
+ case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_CONFIG:
+ def = vm->def;
+ if (virDomainObjIsActive(vm)) {
+ if (vm->newDef)
+ def = vm->newDef;
+ else{
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("no persistent state"));
+ goto endjob;
+ }
}
+ def->maxvcpus = nvcpus;
+ if (nvcpus < vm->newDef->vcpus)
+ def->vcpus = nvcpus;
+ ret = 0;
break;
- case VIR_DOMAIN_VCPU_PERSISTENT:
- if (!vm->newDef)
- qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("no persistent state"));
- else {
- vm->newDef->vcpus = nvcpus;
- ret = 0;
+ case VIR_DOMAIN_VCPU_CONFIG:
+ def = vm->def;
+ if (virDomainObjIsActive(vm)) {
+ if (vm->newDef)
+ def = vm->newDef;
+ else {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("no persistent state"));
+ goto endjob;
+ }
}
+ def->vcpus = nvcpus;
+ ret = 0;
break;
- case VIR_DOMAIN_VCPU_ACTIVE:
+ case VIR_DOMAIN_VCPU_LIVE:
ret = qemudDomainHotplugVcpus(vm, nvcpus);
break;
- case VIR_DOMAIN_VCPU_ACTIVE | VIR_DOMAIN_VCPU_PERSISTENT:
+ case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG:
ret = qemudDomainHotplugVcpus(vm, nvcpus);
if (ret == 0 && vm->newDef)
vm->newDef->vcpus = nvcpus;
@@ -6056,7 +6067,7 @@ cleanup:
static int
qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
{
- return qemudDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_ACTIVE);
+ return qemudDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
}
@@ -6223,13 +6234,12 @@ qemudDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
virDomainDefPtr def;
int ret = -1;
- virCheckFlags(VIR_DOMAIN_VCPU_ACTIVE |
- VIR_DOMAIN_VCPU_PERSISTENT |
+ virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_CONFIG |
VIR_DOMAIN_VCPU_MAXIMUM, -1);
- /* Exactly one of ACTIVE or PERSISTENT must be set. */
- if (!(flags & VIR_DOMAIN_VCPU_ACTIVE) ==
- !(flags & VIR_DOMAIN_VCPU_PERSISTENT)) {
+ /* Exactly one of LIVE or CONFIG must be set. */
+ if (!(flags & VIR_DOMAIN_VCPU_LIVE) == !(flags & VIR_DOMAIN_VCPU_CONFIG)) {
qemuReportError(VIR_ERR_INVALID_ARG,
_("invalid flag combination: (0x%x)"), flags);
return -1;
@@ -6247,7 +6257,7 @@ qemudDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
goto cleanup;
}
- if (flags & VIR_DOMAIN_VCPU_ACTIVE) {
+ if (flags & VIR_DOMAIN_VCPU_LIVE) {
if (!virDomainObjIsActive(vm)) {
qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("domain not active"));
@@ -6269,7 +6279,7 @@ cleanup:
static int
qemudDomainGetMaxVcpus(virDomainPtr dom)
{
- return qemudDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_ACTIVE |
+ return qemudDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
VIR_DOMAIN_VCPU_MAXIMUM));
}
diff --git c/src/test/test_driver.c w/src/test/test_driver.c
index 3da75db..a9d3d89 100644
--- c/src/test/test_driver.c
+++ w/src/test/test_driver.c
@@ -450,6 +450,7 @@ testDomainUpdateVCPUs(virConnectPtr conn,
goto cleanup;
}
+ dom->def->vcpus = nvcpus;
ret = 0;
cleanup:
return ret;
@@ -2032,18 +2033,57 @@ cleanup:
static int
testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
{
- if (flags != (VIR_DOMAIN_VCPU_ACTIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
- testError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
+ testConnPtr privconn = domain->conn->privateData;
+ virDomainObjPtr vm;
+ virDomainDefPtr def;
+ int ret = -1;
+
+ virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_CONFIG |
+ VIR_DOMAIN_VCPU_MAXIMUM, -1);
+
+ /* Exactly one of LIVE or CONFIG must be set. */
+ if (!(flags & VIR_DOMAIN_VCPU_LIVE) == !(flags & VIR_DOMAIN_VCPU_CONFIG)) {
+ testError(VIR_ERR_INVALID_ARG,
+ _("invalid flag combination: (0x%x)"), flags);
return -1;
}
- return testGetMaxVCPUs(domain->conn, "test");
+ testDriverLock(privconn);
+ vm = virDomainFindByUUID(&privconn->domains, domain->uuid);
+ testDriverUnlock(privconn);
+
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(domain->uuid, uuidstr);
+ testError(VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
+ goto cleanup;
+ }
+
+ if (flags & VIR_DOMAIN_VCPU_LIVE) {
+ if (!virDomainObjIsActive(vm)) {
+ testError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain not active"));
+ goto cleanup;
+ }
+ def = vm->def;
+ } else {
+ def = vm->newDef ? vm->newDef : vm->def;
+ }
+
+ ret = (flags & VIR_DOMAIN_VCPU_MAXIMUM) ? def->maxvcpus : def->vcpus;
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ return ret;
}
static int
testDomainGetMaxVcpus(virDomainPtr domain)
{
- return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_VCPU_ACTIVE |
+ return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_VCPU_LIVE |
VIR_DOMAIN_VCPU_MAXIMUM));
}
@@ -2053,21 +2093,30 @@ testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
{
testConnPtr privconn = domain->conn->privateData;
virDomainObjPtr privdom = NULL;
+ virDomainDefPtr def;
int ret = -1, maxvcpus;
- if (flags != VIR_DOMAIN_VCPU_ACTIVE) {
- testError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
+ virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_CONFIG |
+ VIR_DOMAIN_VCPU_MAXIMUM, -1);
+
+ /* At least one of LIVE or CONFIG must be set. MAXIMUM cannot be
+ * mixed with LIVE. */
+ if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0 ||
+ (flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) ==
+ (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) {
+ testError(VIR_ERR_INVALID_ARG,
+ _("invalid flag combination: (0x%x)"), flags);
+ return -1;
+ }
+ if (!nrCpus || (maxvcpus = testGetMaxVCPUs(domain->conn, NULL)) < nrCpus) {
+ testError(VIR_ERR_INVALID_ARG,
+ _("argument out of range: %d"), nrCpus);
return -1;
}
-
- /* Do this first before locking */
- maxvcpus = testDomainGetMaxVcpus(domain);
- if (maxvcpus < 0)
- goto cleanup;
testDriverLock(privconn);
- privdom = virDomainFindByName(&privconn->domains,
- domain->name);
+ privdom = virDomainFindByUUID(&privconn->domains, domain->uuid);
testDriverUnlock(privconn);
if (privdom == NULL) {
@@ -2075,13 +2124,17 @@ testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
goto cleanup;
}
- if (!virDomainObjIsActive(privdom)) {
+ if (!virDomainObjIsActive(privdom) && (flags & VIR_DOMAIN_VCPU_LIVE)) {
testError(VIR_ERR_OPERATION_INVALID,
"%s", _("cannot hotplug vcpus for an inactive domain"));
goto cleanup;
}
- /* We allow more cpus in guest than host */
+ /* We allow more cpus in guest than host, but not more than the
+ * domain's starting limit. */
+ if ((flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) ==
+ VIR_DOMAIN_VCPU_LIVE && privdom->def->maxvcpus < maxvcpus)
+ maxvcpus = privdom->def->maxvcpus;
if (nrCpus > maxvcpus) {
testError(VIR_ERR_INVALID_ARG,
"requested cpu amount exceeds maximum (%d > %d)",
@@ -2089,12 +2142,49 @@ testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
goto cleanup;
}
- /* Update VCPU state for the running domain */
- if (testDomainUpdateVCPUs(domain->conn, privdom, nrCpus, 0) < 0)
- goto cleanup;
+ switch (flags) {
+ case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_CONFIG:
+ def = privdom->def;
+ if (virDomainObjIsActive(privdom)) {
+ if (privdom->newDef)
+ def = privdom->newDef;
+ else {
+ testError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("no persistent state"));
+ goto cleanup;
+ }
+ }
+ def->maxvcpus = nrCpus;
+ if (nrCpus < def->vcpus)
+ def->vcpus = nrCpus;
+ ret = 0;
+ break;
- privdom->def->vcpus = nrCpus;
- ret = 0;
+ case VIR_DOMAIN_VCPU_CONFIG:
+ def = privdom->def;
+ if (virDomainObjIsActive(privdom)) {
+ if (privdom->newDef)
+ def = privdom->newDef;
+ else {
+ testError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("no persistent state"));
+ goto cleanup;
+ }
+ }
+ def->vcpus = nrCpus;
+ ret = 0;
+ break;
+
+ case VIR_DOMAIN_VCPU_LIVE:
+ ret = testDomainUpdateVCPUs(domain->conn, privdom, nrCpus, 0);
+ break;
+
+ case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG:
+ ret = testDomainUpdateVCPUs(domain->conn, privdom, nrCpus, 0);
+ if (ret == 0 && privdom->newDef)
+ privdom->newDef->vcpus = nrCpus;
+ break;
+ }
cleanup:
if (privdom)
@@ -2105,7 +2195,7 @@ cleanup:
static int
testSetVcpus(virDomainPtr domain, unsigned int nrCpus)
{
- return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_VCPU_ACTIVE);
+ return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_VCPU_LIVE);
}
static int testDomainGetVcpus(virDomainPtr domain,
diff --git c/src/vbox/vbox_tmpl.c w/src/vbox/vbox_tmpl.c
index 3bb9431..5a859a4 100644
--- c/src/vbox/vbox_tmpl.c
+++ w/src/vbox/vbox_tmpl.c
@@ -1849,7 +1849,7 @@ vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
PRUint32 CPUCount = nvcpus;
nsresult rc;
- if (flags != VIR_DOMAIN_VCPU_ACTIVE) {
+ if (flags != VIR_DOMAIN_VCPU_LIVE) {
vboxError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
return -1;
}
@@ -1898,7 +1898,7 @@ cleanup:
static int
vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
{
- return vboxDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_ACTIVE);
+ return vboxDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
}
static int
@@ -1908,7 +1908,7 @@ vboxDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
ISystemProperties *systemProperties = NULL;
PRUint32 maxCPUCount = 0;
- if (flags != (VIR_DOMAIN_VCPU_ACTIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
+ if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
vboxError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
return -1;
}
@@ -1933,7 +1933,7 @@ vboxDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
static int
vboxDomainGetMaxVcpus(virDomainPtr dom)
{
- return vboxDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_ACTIVE |
+ return vboxDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
VIR_DOMAIN_VCPU_MAXIMUM));
}
diff --git c/src/xen/proxy_internal.c w/src/xen/proxy_internal.c
index 335dfc4..3e122f4 100644
--- c/src/xen/proxy_internal.c
+++ w/src/xen/proxy_internal.c
@@ -70,7 +70,6 @@ struct xenUnifiedDriver xenProxyDriver = {
NULL, /* domainSetVcpus */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
- NULL, /* domainGetMaxVcpus */
NULL, /* listDefinedDomains */
NULL, /* numOfDefinedDomains */
NULL, /* domainCreate */
diff --git c/src/xen/xen_driver.c w/src/xen/xen_driver.c
index 5c73afd..fe2ff86 100644
--- c/src/xen/xen_driver.c
+++ w/src/xen/xen_driver.c
@@ -1075,7 +1075,7 @@ xenUnifiedDomainSetVcpusFlags (virDomainPtr dom, unsigned int nvcpus,
GET_PRIVATE(dom->conn);
int i;
- if (flags != VIR_DOMAIN_VCPU_ACTIVE) {
+ if (flags != VIR_DOMAIN_VCPU_LIVE) {
xenUnifiedError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"),
flags);
return -1;
@@ -1102,7 +1102,7 @@ xenUnifiedDomainSetVcpusFlags (virDomainPtr dom, unsigned int nvcpus,
static int
xenUnifiedDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus)
{
- return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_ACTIVE);
+ return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
}
static int
@@ -1142,27 +1142,40 @@ static int
xenUnifiedDomainGetVcpusFlags (virDomainPtr dom, unsigned int flags)
{
GET_PRIVATE(dom->conn);
- int i, ret;
+ int ret;
- if (flags != (VIR_DOMAIN_VCPU_ACTIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
- xenUnifiedError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"),
- flags);
+ virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_CONFIG |
+ VIR_DOMAIN_VCPU_MAXIMUM, -1);
+
+ /* Exactly one of LIVE or CONFIG must be set. */
+ if (!(flags & VIR_DOMAIN_VCPU_LIVE) == !(flags & VIR_DOMAIN_VCPU_CONFIG)) {
+ xenUnifiedError(VIR_ERR_INVALID_ARG,
+ _("invalid flag combination: (0x%x)"), flags);
return -1;
}
- for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
- if (priv->opened[i] && drivers[i]->domainGetMaxVcpus) {
- ret = drivers[i]->domainGetMaxVcpus (dom);
- if (ret != 0) return ret;
- }
+ if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
+ ret = xenDaemonDomainGetVcpusFlags(dom, flags);
+ if (ret != -2)
+ return ret;
+ }
+ if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
+ ret = xenXMDomainGetVcpusFlags(dom, flags);
+ if (ret != -2)
+ return ret;
+ }
+ if (flags == (VIR_DOMAIN_VCPU_CONFIG | VIR_DOMAIN_VCPU_MAXIMUM))
+ return xenHypervisorGetVcpuMax(dom);
+ xenUnifiedError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
return -1;
}
static int
xenUnifiedDomainGetMaxVcpus (virDomainPtr dom)
{
- return xenUnifiedDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_ACTIVE |
+ return xenUnifiedDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
VIR_DOMAIN_VCPU_MAXIMUM));
}
diff --git c/src/xen/xen_driver.h w/src/xen/xen_driver.h
index 3e7c1d0..bb68f6a 100644
--- c/src/xen/xen_driver.h
+++ w/src/xen/xen_driver.h
@@ -1,7 +1,7 @@
/*
* xen_unified.c: Unified Xen driver.
*
- * Copyright (C) 2007 Red Hat, Inc.
+ * Copyright (C) 2007, 2010 Red Hat, Inc.
*
* See COPYING.LIB for the License of this software
*
@@ -87,7 +87,6 @@ struct xenUnifiedDriver {
virDrvDomainSetVcpus domainSetVcpus;
virDrvDomainPinVcpu domainPinVcpu;
virDrvDomainGetVcpus domainGetVcpus;
- virDrvDomainGetMaxVcpus domainGetMaxVcpus;
virDrvListDefinedDomains listDefinedDomains;
virDrvNumOfDefinedDomains numOfDefinedDomains;
virDrvDomainCreate domainCreate;
diff --git c/src/xen/xen_hypervisor.c w/src/xen/xen_hypervisor.c
index 6246513..32f3683 100644
--- c/src/xen/xen_hypervisor.c
+++ w/src/xen/xen_hypervisor.c
@@ -787,7 +787,6 @@ struct xenUnifiedDriver xenHypervisorDriver = {
xenHypervisorSetVcpus, /* domainSetVcpus */
xenHypervisorPinVcpu, /* domainPinVcpu */
xenHypervisorGetVcpus, /* domainGetVcpus */
- xenHypervisorGetVcpuMax, /* domainGetMaxVcpus */
NULL, /* listDefinedDomains */
NULL, /* numOfDefinedDomains */
NULL, /* domainCreate */
diff --git c/src/xen/xen_inotify.c w/src/xen/xen_inotify.c
index d24b20f..9b95d67 100644
--- c/src/xen/xen_inotify.c
+++ w/src/xen/xen_inotify.c
@@ -74,7 +74,6 @@ struct xenUnifiedDriver xenInotifyDriver = {
NULL, /* domainSetVcpus */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
- NULL, /* domainGetMaxVcpus */
NULL, /* listDefinedDomains */
NULL, /* numOfDefinedDomains */
NULL, /* domainCreate */
diff --git c/src/xen/xend_internal.c w/src/xen/xend_internal.c
index 02f8f5f..e887e9d 100644
--- c/src/xen/xend_internal.c
+++ w/src/xen/xend_internal.c
@@ -44,6 +44,7 @@
#include "xen_hypervisor.h"
#include "xs_internal.h" /* To extract VNC port & Serial console TTY */
#include "memory.h"
+#include "count-one-bits.h"
/* required for cpumap_t */
#include
@@ -2191,8 +2192,9 @@ xenDaemonParseSxpr(virConnectPtr conn,
}
def->maxvcpus = sexpr_int(root, "domain/vcpus");
-// def->vcpus = sexpr_int(root, "domain/vcpu_avail");
- def->vcpus = def->maxvcpus;
+ def->vcpus = count_one_bits(sexpr_int(root, "domain/vcpu_avail"));
+ if (!def->vcpus || def->maxvcpus < def->vcpus)
+ def->vcpus = def->maxvcpus;
tmp = sexpr_node(root, "domain/on_poweroff");
if (tmp != NULL) {
@@ -2434,7 +2436,7 @@ sexpr_to_xend_domain_info(virDomainPtr domain, const struct sexpr *root,
virDomainInfoPtr info)
{
const char *flags;
-
+ int vcpus;
if ((root == NULL) || (info == NULL))
return (-1);
@@ -2465,8 +2467,11 @@ sexpr_to_xend_domain_info(virDomainPtr domain, const struct sexpr *root,
info->state = VIR_DOMAIN_NOSTATE;
}
info->cpuTime = sexpr_float(root, "domain/cpu_time") * 1000000000;
-// info->nrVirtCpu = sexpr_int(root, "domain/vcpu_avail");
- info->nrVirtCpu = sexpr_int(root, "domain/vcpus");
+ vcpus = sexpr_int(root, "domain/vcpus");
+ info->nrVirtCpu = count_one_bits(sexpr_int(root, "domain/vcpu_avail"));
+ if (!info->nrVirtCpu || vcpus < info->nrVirtCpu)
+ info->nrVirtCpu = vcpus;
+
return (0);
}
@@ -3615,6 +3620,58 @@ xenDaemonDomainPinVcpu(virDomainPtr domain, unsigned int vcpu,
}
/**
+ * xenDaemonDomainGetVcpusFlags:
+ * @domain: pointer to domain object
+ * @flags: bitwise-ORd from virDomainVcpuFlags
+ *
+ * Extract information about virtual CPUs of domain according to flags.
+ *
+ * Returns the number of vcpus on success, -1 if an error message was
+ * issued, and -2 if the unified driver should keep trying.
+
+ */
+int
+xenDaemonDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
+{
+ struct sexpr *root;
+ int ret;
+ xenUnifiedPrivatePtr priv;
+
+ if (domain == NULL || domain->conn == NULL || domain->name == NULL) {
+ virXendError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return -1;
+ }
+
+ priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+
+ /* If xendConfigVersion is 2, then we can only report _LIVE (and
+ * xm_internal reports _CONFIG). If it is 3, then _LIVE and
+ * _CONFIG are always in sync for a running system. */
+ if (domain->id < 0 && priv->xendConfigVersion < 3)
+ return -2;
+ if (domain->id < 0 && (flags & VIR_DOMAIN_VCPU_LIVE)) {
+ virXendError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain not active"));
+ return -1;
+ }
+
+ root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
+ if (root == NULL)
+ return -1;
+
+ ret = sexpr_int(root, "domain/vcpus");
+ if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM)) {
+ int vcpus = count_one_bits(sexpr_int(root, "domain/vcpu_avail"));
+ if (vcpus)
+ ret = MIN(vcpus, ret);
+ }
+ if (!ret)
+ ret = -2;
+ sexpr_free(root);
+ return ret;
+}
+
+/**
* virDomainGetVcpus:
* @domain: pointer to domain object, or NULL for Domain0
* @info: pointer to an array of virVcpuInfo structures (OUT)
@@ -5083,7 +5140,6 @@ struct xenUnifiedDriver xenDaemonDriver = {
xenDaemonDomainSetVcpus, /* domainSetVcpus */
xenDaemonDomainPinVcpu, /* domainPinVcpu */
xenDaemonDomainGetVcpus, /* domainGetVcpus */
- NULL, /* domainGetMaxVcpus */
xenDaemonListDefinedDomains, /* listDefinedDomains */
xenDaemonNumOfDefinedDomains,/* numOfDefinedDomains */
xenDaemonDomainCreate, /* domainCreate */
@@ -5669,9 +5725,10 @@ xenDaemonFormatSxpr(virConnectPtr conn,
virBufferVSprintf(&buf, "(name '%s')", def->name);
virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)",
def->mem.cur_balloon/1024, def->mem.max_balloon/1024);
-// virBufferVSprintf(&buf, "(vcpus %u)(vcpu_avail %u)", def->maxvcpus,
-// def->vcpus);
virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus);
+ /* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is 32. */
+ if (def->vcpus < def->maxvcpus)
+ virBufferVSprintf(&buf, "(vcpu_avail %u)", (1U << def->vcpus) - 1);
if (def->cpumask) {
char *ranges = virDomainCpuSetFormat(def->cpumask, def->cpumasklen);
@@ -5766,9 +5823,10 @@ xenDaemonFormatSxpr(virConnectPtr conn,
else
virBufferVSprintf(&buf, "(kernel '%s')", def->os.loader);
-// virBufferVSprintf(&buf, "(vcpus %u)(vcpu_avail %u)",
-// def->maxvcpus, def->vcpus);
virBufferVSprintf(&buf, "(vcpus %u)", def->maxvcpus);
+ if (def->vcpus < def->maxvcpus)
+ virBufferVSprintf(&buf, "(vcpu_avail %u)",
+ (1U << def->vcpus) - 1);
for (i = 0 ; i < def->os.nBootDevs ; i++) {
switch (def->os.bootDevs[i]) {
diff --git c/src/xen/xend_internal.h w/src/xen/xend_internal.h
index c757716..923cebd 100644
--- c/src/xen/xend_internal.h
+++ w/src/xen/xend_internal.h
@@ -155,6 +155,8 @@ int xenDaemonDomainPinVcpu (virDomainPtr domain,
unsigned int vcpu,
unsigned char *cpumap,
int maplen);
+int xenDaemonDomainGetVcpusFlags (virDomainPtr domain,
+ unsigned int flags);
int xenDaemonDomainGetVcpus (virDomainPtr domain,
virVcpuInfoPtr info,
int maxinfo,
diff --git c/src/xen/xm_internal.c w/src/xen/xm_internal.c
index 01485a5..9194c0d 100644
--- c/src/xen/xm_internal.c
+++ w/src/xen/xm_internal.c
@@ -46,6 +46,7 @@
#include "util.h"
#include "memory.h"
#include "logging.h"
+#include "count-one-bits.h"
#define VIR_FROM_THIS VIR_FROM_XENXM
@@ -105,7 +106,6 @@ struct xenUnifiedDriver xenXMDriver = {
xenXMDomainSetVcpus, /* domainSetVcpus */
xenXMDomainPinVcpu, /* domainPinVcpu */
NULL, /* domainGetVcpus */
- NULL, /* domainGetMaxVcpus */
xenXMListDefinedDomains, /* listDefinedDomains */
xenXMNumOfDefinedDomains, /* numOfDefinedDomains */
xenXMDomainCreate, /* domainCreate */
@@ -772,14 +772,12 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
def->mem.max_balloon *= 1024;
if (xenXMConfigGetULong(conf, "vcpus", &count, 1) < 0 ||
- (unsigned short) count != count)
+ MAX_VIRT_CPUS < count)
goto cleanup;
def->maxvcpus = count;
-// if (xenXMConfigGetULong(conf, "vcpu_avail", &count, 1) < 0 ||
-// (unsigned short) count != count)
-// goto cleanup;
-// def->vcpus = count;
- def->vcpus = def->maxvcpus;
+ if (xenXMConfigGetULong(conf, "vcpu_avail", &count, -1) < 0)
+ goto cleanup;
+ def->vcpus = MIN(count_one_bits(count), def->maxvcpus);
if (xenXMConfigGetString(conf, "cpus", &str, NULL) < 0)
goto cleanup;
@@ -1657,7 +1655,7 @@ int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus) {
if (!(entry = virHashLookup(priv->configCache, filename)))
goto cleanup;
- entry->def->vcpus = vcpus;
+ entry->def->maxvcpus = entry->def->vcpus = vcpus;
/* If this fails, should we try to undo our changes to the
* in-memory representation of the config file. I say not!
@@ -1672,6 +1670,53 @@ cleanup:
}
/**
+ * xenXMDomainGetVcpusFlags:
+ * @domain: pointer to domain object
+ * @flags: bitwise-ORd from virDomainVcpuFlags
+ *
+ * Extract information about virtual CPUs of domain according to flags.
+ *
+ * Returns the number of vcpus on success, -1 if an error message was
+ * issued, and -2 if the unified driver should keep trying.
+ */
+int
+xenXMDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
+{
+ xenUnifiedPrivatePtr priv;
+ const char *filename;
+ xenXMConfCachePtr entry;
+ int ret = -2;
+
+ if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+ xenXMError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return -1;
+ }
+
+ if (domain->id != -1)
+ return -2;
+ if (flags & VIR_DOMAIN_VCPU_LIVE) {
+ xenXMError(VIR_ERR_OPERATION_FAILED, "%s", _("domain not active"));
+ return -1;
+ }
+
+ priv = domain->conn->privateData;
+ xenUnifiedLock(priv);
+
+ if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
+ goto cleanup;
+
+ if (!(entry = virHashLookup(priv->configCache, filename)))
+ goto cleanup;
+
+ ret = ((flags & VIR_DOMAIN_VCPU_MAXIMUM) ? entry->def->maxvcpus
+ : entry->def->vcpus);
+
+cleanup:
+ xenUnifiedUnlock(priv);
+ return ret;
+}
+
+/**
* xenXMDomainPinVcpu:
* @domain: pointer to domain object
* @vcpu: virtual CPU number (reserved)
@@ -2250,8 +2295,9 @@ virConfPtr xenXMDomainConfigFormat(virConnectPtr conn,
if (xenXMConfigSetInt(conf, "vcpus", def->maxvcpus) < 0)
goto no_memory;
-// if (xenXMConfigSetInt(conf, "vcpu_avail", def->vcpus) < 0)
-// goto no_memory;
+ if (def->vcpus < def->maxvcpus &&
+ xenXMConfigSetInt(conf, "vcpu_avail", (1U << def->vcpus) - 1) < 0)
+ goto no_memory;
if ((def->cpumask != NULL) &&
((cpus = virDomainCpuSetFormat(def->cpumask,
diff --git c/src/xen/xm_internal.h w/src/xen/xm_internal.h
index 3ad3456..3295fbd 100644
--- c/src/xen/xm_internal.h
+++ w/src/xen/xm_internal.h
@@ -45,6 +45,7 @@ int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory);
int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory);
unsigned long xenXMDomainGetMaxMemory(virDomainPtr domain);
int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus);
+int xenXMDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags);
int xenXMDomainPinVcpu(virDomainPtr domain, unsigned int vcpu,
unsigned char *cpumap, int maplen);
virDomainPtr xenXMDomainLookupByName(virConnectPtr conn, const char *domname);
diff --git c/src/xen/xs_internal.c w/src/xen/xs_internal.c
index 9296f25..434904c 100644
--- c/src/xen/xs_internal.c
+++ w/src/xen/xs_internal.c
@@ -70,7 +70,6 @@ struct xenUnifiedDriver xenStoreDriver = {
NULL, /* domainSetVcpus */
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
- NULL, /* domainGetMaxVcpus */
NULL, /* listDefinedDomains */
NULL, /* numOfDefinedDomains */
NULL, /* domainCreate */
diff --git c/src/xenapi/xenapi_driver.c w/src/xenapi/xenapi_driver.c
index 7ce4b8a..5ccdede 100644
--- c/src/xenapi/xenapi_driver.c
+++ w/src/xenapi/xenapi_driver.c
@@ -1006,7 +1006,7 @@ xenapiDomainSetVcpusFlags (virDomainPtr dom, unsigned int nvcpus,
xen_vm_set *vms;
xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
- if (flags != VIR_DOMAIN_VCPU_ACTIVE) {
+ if (flags != VIR_DOMAIN_VCPU_LIVE) {
xenapiError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"),
flags);
return -1;
@@ -1039,7 +1039,7 @@ xenapiDomainSetVcpusFlags (virDomainPtr dom, unsigned int nvcpus,
static int
xenapiDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus)
{
- return xenapiDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_ACTIVE);
+ return xenapiDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
}
/*
@@ -1178,7 +1178,7 @@ xenapiDomainGetVcpusFlags (virDomainPtr dom, unsigned int flags)
enum xen_vm_power_state state;
xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session;
- if (flags != (VIR_DOMAIN_VCPU_ACTIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
+ if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
xenapiError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"),
flags);
return -1;
@@ -1215,7 +1215,7 @@ xenapiDomainGetVcpusFlags (virDomainPtr dom, unsigned int flags)
static int
xenapiDomainGetMaxVcpus (virDomainPtr dom)
{
- return xenapiDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_ACTIVE |
+ return xenapiDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
VIR_DOMAIN_VCPU_MAXIMUM));
}
diff --git c/src/xenapi/xenapi_utils.c w/src/xenapi/xenapi_utils.c
index c917813..a7e2a4b 100644
--- c/src/xenapi/xenapi_utils.c
+++ w/src/xenapi/xenapi_utils.c
@@ -512,7 +512,7 @@ createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr def,
if (def->maxvcpus) {
(*record)->vcpus_max = (int64_t) def->maxvcpus;
- (*record)->vcpus_at_startup = (int64_t) def->maxvcpus; // FIXME
+ (*record)->vcpus_at_startup = (int64_t) def->vcpus;
}
if (def->onPoweroff)
(*record)->actions_after_shutdown = actionShutdownLibvirt2XenapiEnum(def->onPoweroff);
diff --git c/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.sexpr w/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.sexpr
new file mode 100644
index 0000000..2be6822
--- /dev/null
+++ w/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.sexpr
@@ -0,0 +1 @@
+(domain (domid 6)(name 'pvtest')(memory 420)(maxmem 420)(vcpus 4)(vcpu_avail 3)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w'))))
diff --git c/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.xml w/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.xml
new file mode 100644
index 0000000..0d6bf11
--- /dev/null
+++ w/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.xml
@@ -0,0 +1,27 @@
+
+ pvtest
+ 596a5d21-71f4-8fb2-e068-e2386a5c413e
+ 430080
+ 430080
+ 4
+
+ linux
+ /var/lib/xen/vmlinuz.2Dn2YT
+ /var/lib/xen/initrd.img.0u-Vhq
+ method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os
+
+
+ destroy
+ destroy
+ destroy
+
+
+
+
+
+
+
+
+
+
+
diff --git c/tests/sexpr2xmltest.c w/tests/sexpr2xmltest.c
index d62b44f..f100dd8 100644
--- c/tests/sexpr2xmltest.c
+++ w/tests/sexpr2xmltest.c
@@ -132,6 +132,7 @@ mymain(int argc, char **argv)
DO_TEST("pv-vfb-type-crash", "pv-vfb-type-crash", 3);
DO_TEST("fv-autoport", "fv-autoport", 3);
DO_TEST("pv-bootloader", "pv-bootloader", 1);
+ DO_TEST("pv-vcpus", "pv-vcpus", 1);
DO_TEST("disk-file", "disk-file", 2);
DO_TEST("disk-block", "disk-block", 2);
diff --git c/tests/xmconfigdata/test-paravirt-vcpu.cfg w/tests/xmconfigdata/test-paravirt-vcpu.cfg
new file mode 100644
index 0000000..24c78f4
--- /dev/null
+++ w/tests/xmconfigdata/test-paravirt-vcpu.cfg
@@ -0,0 +1,17 @@
+name = "XenGuest1"
+uuid = "c7a5fdb0-cdaf-9455-926a-d65c16db1809"
+maxmem = 579
+memory = 394
+vcpus = 4
+vcpu_avail = 3
+bootloader = "/usr/bin/pygrub"
+on_poweroff = "destroy"
+on_reboot = "restart"
+on_crash = "restart"
+sdl = 0
+vnc = 1
+vncunused = 1
+vnclisten = "127.0.0.1"
+vncpasswd = "123poi"
+disk = [ "phy:/dev/HostVG/XenGuest1,xvda,w" ]
+vif = [ "mac=00:16:3e:66:94:9c,bridge=br0,script=vif-bridge" ]
diff --git c/tests/xmconfigdata/test-paravirt-vcpu.xml w/tests/xmconfigdata/test-paravirt-vcpu.xml
new file mode 100644
index 0000000..0be9456
--- /dev/null
+++ w/tests/xmconfigdata/test-paravirt-vcpu.xml
@@ -0,0 +1,32 @@
+
+ XenGuest1
+ c7a5fdb0-cdaf-9455-926a-d65c16db1809
+ 592896
+ 403456
+ 4
+ /usr/bin/pygrub
+
+ linux
+
+
+ destroy
+ restart
+ restart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git c/tests/xmconfigtest.c w/tests/xmconfigtest.c
index 221b322..ea00747 100644
--- c/tests/xmconfigtest.c
+++ w/tests/xmconfigtest.c
@@ -210,6 +210,7 @@ mymain(int argc, char **argv)
DO_TEST("paravirt-new-pvfb-vncdisplay", 3);
DO_TEST("paravirt-net-e1000", 3);
DO_TEST("paravirt-net-vifname", 3);
+ DO_TEST("paravirt-vcpu", 2);
DO_TEST("fullvirt-old-cdrom", 1);
DO_TEST("fullvirt-new-cdrom", 2);
DO_TEST("fullvirt-utc", 2);
diff --git c/tests/xml2sexprdata/xml2sexpr-pv-vcpus.sexpr w/tests/xml2sexprdata/xml2sexpr-pv-vcpus.sexpr
new file mode 100644
index 0000000..e886545
--- /dev/null
+++ w/tests/xml2sexprdata/xml2sexpr-pv-vcpus.sexpr
@@ -0,0 +1 @@
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 4)(vcpu_avail 3)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w'))))
\ No newline at end of file
diff --git c/tests/xml2sexprdata/xml2sexpr-pv-vcpus.xml w/tests/xml2sexprdata/xml2sexpr-pv-vcpus.xml
index a11f713..d061e11 100644
--- c/tests/xml2sexprdata/xml2sexpr-pv-vcpus.xml
+++ w/tests/xml2sexprdata/xml2sexpr-pv-vcpus.xml
@@ -8,7 +8,7 @@
method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os
430080
- 2
+ 4
destroy
destroy
destroy
diff --git c/tests/xml2sexprtest.c w/tests/xml2sexprtest.c
index 77cf760..9cf8d39 100644
--- c/tests/xml2sexprtest.c
+++ w/tests/xml2sexprtest.c
@@ -118,6 +118,7 @@ mymain(int argc, char **argv)
DO_TEST("pv-vfb-new", "pv-vfb-new", "pvtest", 3);
DO_TEST("pv-vfb-new-auto", "pv-vfb-new-auto", "pvtest", 3);
DO_TEST("pv-bootloader", "pv-bootloader", "pvtest", 1);
+ DO_TEST("pv-vcpus", "pv-vcpus", "pvtest", 1);
DO_TEST("disk-file", "disk-file", "pvtest", 2);
DO_TEST("disk-block", "disk-block", "pvtest", 2);
diff --git c/tools/virsh.c w/tools/virsh.c
index 2f553ba..496853e 100644
--- c/tools/virsh.c
+++ w/tools/virsh.c
@@ -2280,11 +2280,44 @@ cmdFreecell(vshControl *ctl, const vshCmd *cmd)
}
/*
+ * "maxvcpus" command
+ */
+static const vshCmdInfo info_maxvcpus[] = {
+ {"help", N_("connection vcpu maximum")},
+ {"desc", N_("Show maximum number of virtual CPUs for guests on this connection.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_maxvcpus[] = {
+ {"type", VSH_OT_STRING, 0, N_("domain type")},
+ {NULL, 0, 0, NULL}
+};
+
+static int
+cmdMaxvcpus(vshControl *ctl, const vshCmd *cmd)
+{
+ char *type;
+ int vcpus;
+
+ type = vshCommandOptString(cmd, "type", NULL);
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return FALSE;
+
+ vcpus = virConnectGetMaxVcpus(ctl->conn, type);
+ if (vcpus < 0)
+ return FALSE;
+ vshPrint(ctl, "%d\n", vcpus);
+
+ return TRUE;
+}
+
+/*
* "vcpucount" command
*/
static const vshCmdInfo info_vcpucount[] = {
{"help", N_("domain vcpu counts")},
- {"desc", N_("Returns the number of domain virtual CPUs.")},
+ {"desc", N_("Returns the number of virtual CPUs used by the domain.")},
{NULL, NULL}
};
@@ -2292,8 +2325,8 @@ static const vshCmdOptDef opts_vcpucount[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"maximum", VSH_OT_BOOL, 0, N_("get maximum cap on vcpus")},
{"current", VSH_OT_BOOL, 0, N_("get current vcpu usage")},
- {"persistent", VSH_OT_BOOL, 0, N_("get value to be used on next boot")},
- {"active", VSH_OT_BOOL, 0, N_("get value from running domain")},
+ {"config", VSH_OT_BOOL, 0, N_("get value to be used on next boot")},
+ {"live", VSH_OT_BOOL, 0, N_("get value from running domain")},
{NULL, 0, 0, NULL}
};
@@ -2304,9 +2337,9 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd)
int ret = TRUE;
int maximum = vshCommandOptBool(cmd, "maximum");
int current = vshCommandOptBool(cmd, "current");
- int persistent = vshCommandOptBool(cmd, "persistent");
- int active = vshCommandOptBool(cmd, "active");
- bool all = maximum + current + persistent + active == 0;
+ int config = vshCommandOptBool(cmd, "config");
+ int live = vshCommandOptBool(cmd, "live");
+ bool all = maximum + current + config + live == 0;
int count;
if (maximum && current) {
@@ -2314,18 +2347,20 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd)
_("--maximum and --current cannot both be specified"));
return FALSE;
}
- if (persistent && active) {
+ if (config && live) {
vshError(ctl, "%s",
- _("--persistent and --active cannot both be specified"));
+ _("--config and --live cannot both be specified"));
return FALSE;
}
- if (maximum + current + persistent + active == 1) {
+ /* We want one of each pair of mutually exclusive options; that
+ * is, use of flags requires exactly two options. */
+ if (maximum + current + config + live == 1) {
vshError(ctl,
_("when using --%s, either --%s or --%s must be specified"),
- maximum ? "maximum" : current ? "current"
- : persistent ? "persistent" : "active",
- maximum + current ? "persistent" : "maximum",
- maximum + current ? "active" : "current");
+ (maximum ? "maximum" : current ? "current"
+ : config ? "config" : "live"),
+ maximum + current ? "config" : "maximum",
+ maximum + current ? "live" : "current");
return FALSE;
}
@@ -2338,9 +2373,9 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd)
/* In all cases, try the new API first; if it fails because we are
* talking to an older client, try a fallback API before giving
* up. */
- if (all || (maximum && persistent)) {
+ if (all || (maximum && config)) {
count = virDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_MAXIMUM |
- VIR_DOMAIN_VCPU_PERSISTENT));
+ VIR_DOMAIN_VCPU_CONFIG));
if (count < 0 && (last_error->code == VIR_ERR_NO_SUPPORT
|| last_error->code == VIR_ERR_INVALID_ARG)) {
char *tmp;
@@ -2357,7 +2392,7 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd)
virshReportError(ctl);
ret = FALSE;
} else if (all) {
- vshPrint(ctl, "%-12s %-12s %3d\n", _("maximum"), _("persistent"),
+ vshPrint(ctl, "%-12s %-12s %3d\n", _("maximum"), _("config"),
count);
} else {
vshPrint(ctl, "%d\n", count);
@@ -2366,9 +2401,9 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd)
last_error = NULL;
}
- if (all || (maximum && active)) {
+ if (all || (maximum && live)) {
count = virDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_MAXIMUM |
- VIR_DOMAIN_VCPU_ACTIVE));
+ VIR_DOMAIN_VCPU_LIVE));
if (count < 0 && (last_error->code == VIR_ERR_NO_SUPPORT
|| last_error->code == VIR_ERR_INVALID_ARG)) {
count = virDomainGetMaxVcpus(dom);
@@ -2378,7 +2413,7 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd)
virshReportError(ctl);
ret = FALSE;
} else if (all) {
- vshPrint(ctl, "%-12s %-12s %3d\n", _("maximum"), _("active"),
+ vshPrint(ctl, "%-12s %-12s %3d\n", _("maximum"), _("live"),
count);
} else {
vshPrint(ctl, "%d\n", count);
@@ -2387,8 +2422,8 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd)
last_error = NULL;
}
- if (all || (current && persistent)) {
- count = virDomainGetVcpusFlags(dom, VIR_DOMAIN_VCPU_PERSISTENT);
+ if (all || (current && config)) {
+ count = virDomainGetVcpusFlags(dom, VIR_DOMAIN_VCPU_CONFIG);
if (count < 0 && (last_error->code == VIR_ERR_NO_SUPPORT
|| last_error->code == VIR_ERR_INVALID_ARG)) {
char *tmp, *end;
@@ -2415,7 +2450,7 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd)
virshReportError(ctl);
ret = FALSE;
} else if (all) {
- vshPrint(ctl, "%-12s %-12s %3d\n", _("current"), _("persistent"),
+ vshPrint(ctl, "%-12s %-12s %3d\n", _("current"), _("config"),
count);
} else {
vshPrint(ctl, "%d\n", count);
@@ -2424,8 +2459,8 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd)
last_error = NULL;
}
- if (all || (current && active)) {
- count = virDomainGetVcpusFlags(dom, VIR_DOMAIN_VCPU_ACTIVE);
+ if (all || (current && live)) {
+ count = virDomainGetVcpusFlags(dom, VIR_DOMAIN_VCPU_LIVE);
if (count < 0 && (last_error->code == VIR_ERR_NO_SUPPORT
|| last_error->code == VIR_ERR_INVALID_ARG)) {
virDomainInfo info;
@@ -2437,7 +2472,7 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd)
virshReportError(ctl);
ret = FALSE;
} else if (all) {
- vshPrint(ctl, "%-12s %-12s %3d\n", _("current"), _("active"),
+ vshPrint(ctl, "%-12s %-12s %3d\n", _("current"), _("live"),
count);
} else {
vshPrint(ctl, "%d\n", count);
@@ -2685,8 +2720,8 @@ static const vshCmdOptDef opts_setvcpus[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"count", VSH_OT_DATA, VSH_OFLAG_REQ, N_("number of virtual CPUs")},
{"maximum", VSH_OT_BOOL, 0, N_("set maximum limit on next boot")},
- {"persistent", VSH_OT_BOOL, 0, N_("affect next boot")},
- {"active", VSH_OT_BOOL, 0, N_("affect running domain")},
+ {"config", VSH_OT_BOOL, 0, N_("affect next boot")},
+ {"live", VSH_OT_BOOL, 0, N_("affect running domain")},
{NULL, 0, 0, NULL}
};
@@ -2697,11 +2732,11 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd)
int count;
int ret = TRUE;
int maximum = vshCommandOptBool(cmd, "maximum");
- int persistent = vshCommandOptBool(cmd, "persistent");
- int active = vshCommandOptBool(cmd, "active");
+ int config = vshCommandOptBool(cmd, "config");
+ int live = vshCommandOptBool(cmd, "live");
int flags = ((maximum ? VIR_DOMAIN_VCPU_MAXIMUM : 0) |
- (persistent ? VIR_DOMAIN_VCPU_PERSISTENT : 0) |
- (active ? VIR_DOMAIN_VCPU_ACTIVE : 0));
+ (config ? VIR_DOMAIN_VCPU_CONFIG : 0) |
+ (live ? VIR_DOMAIN_VCPU_LIVE : 0));
if (!vshConnectionUsability(ctl, ctl->conn))
return FALSE;
@@ -9721,6 +9756,7 @@ static const vshCmdDef commands[] = {
{"freecell", cmdFreecell, opts_freecell, info_freecell},
{"hostname", cmdHostname, NULL, info_hostname},
{"list", cmdList, opts_list, info_list},
+ {"maxvcpus", cmdMaxvcpus, opts_maxvcpus, info_maxvcpus},
{"migrate", cmdMigrate, opts_migrate, info_migrate},
{"migrate-setmaxdowntime", cmdMigrateSetMaxDowntime, opts_migrate_setmaxdowntime, info_migrate_setmaxdowntime},
diff --git c/tools/virsh.pod w/tools/virsh.pod
index d52aef7..9634b21 100644
--- c/tools/virsh.pod
+++ w/tools/virsh.pod
@@ -436,7 +436,14 @@ Remove the managed save file for a domain if it exists. The next time the
domain is started it will not restore to its previous state but instead will
do a full boot.
-=item B optional I<--live> I<--suspend> I I I
+=item B optional I
+
+Provide the maximum number of virtual CPUs supported for a guest VM on
+this connection. If provided, the I parameter must be a valid
+type attribute for the element of XML.
+
+=item B optional I<--live> I<--suspend> I I
+I
Migrate domain to another host. Add --live for live migration; --suspend
leaves the domain paused on the destination host. The I is the
@@ -506,8 +513,8 @@ Change the maximum memory allocation limit in the guest domain. This should
not change the current memory use. The memory limit is specified in
kilobytes.
-=item B I I optional I<--maximum> I<--persistent>
-I<--active>
+=item B I I optional I<--maximum> I<--config>
+I<--live>
Change the number of virtual CPUs active in the guest domain. Note that
I may be limited by host, hypervisor or limit coming from the
@@ -516,14 +523,15 @@ original description of domain.
For Xen, you can only adjust the virtual CPUs of a running domain if
the domain is paravirtualized.
-If I<--persistent> is specified, the change will only affect the next
-boot of a domain. If I<--active> is specified, the domain must be
+If I<--config> is specified, the change will only affect the next
+boot of a domain. If I<--live> is specified, the domain must be
running, and the change takes place immediately. Both flags may be
-specified, if supported by the hypervisor; and I<--active> is implied
-when neither flag is given.
+specified, if supported by the hypervisor. If neither flag is given,
+then I<--live> is implied and it is up to the hypervisor whether
+I<--config> is also implied.
-If I<--maximum> is specified, then you must use I<--persistent> and
-avoid I<--active>; this flag controls the maximum limit of vcpus that
+If I<--maximum> is specified, then you must use I<--config> and
+avoid I<--live>; this flag controls the maximum limit of vcpus that
can be hot-plugged the next time the domain is booted.
=item B I
@@ -565,7 +573,7 @@ Undefine the configuration for an inactive domain. Since it's not running
the domain name or UUID must be used as the I.
=item B I optional I<--maximum> I<--current>
-I<--persistent> I<--active>
+I<--config> I<--live>
Print information about the virtual cpu counts of the given
I. If no flags are specified, all possible counts are
@@ -574,9 +582,9 @@ numeric value requested.
I<--maximum> requests information on the maximum cap of vcpus that a
domain can add via B, while I<--current> shows the current
-usage; these two flags cannot both be specified. I<--persistent>
+usage; these two flags cannot both be specified. I<--config>
requests information regarding the next time the domain will be
-booted, while I<--active> requires a running domain and lists current
+booted, while I<--live> requires a running domain and lists current
values; these two flags cannot both be specified.
=item B I