On 10/13/2010 11:53 AM, Eric Blake wrote:
Version 2 of the patch series; this addresses most of the points from v1 (http://thread.gmane.org/gmane.comp.emulators.libvirt/28520).
I'll send an interdiff for how this series differs from v1, if that helps in the review.
Attached. -- Eric Blake eblake@xxxxxxxxxx +1-801-349-2682 Libvirt virtualization library http://libvirt.org
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. <span class="since">Since 0.8.5</span>, the optional attribute <code>current</code> 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. </dd> </dl> 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 <xen/dom0_ops.h> @@ -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 @@ +<domain type='xen' id='6'> + <name>pvtest</name> + <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid> + <memory>430080</memory> + <currentMemory>430080</currentMemory> + <vcpu current='2'>4</vcpu> + <os> + <type>linux</type> + <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel> + <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd> + <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os </cmdline> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>destroy</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <disk type='file' device='disk'> + <driver name='file'/> + <source file='/root/some.img'/> + <target dev='xvda' bus='xen'/> + </disk> + <console type='pty'> + <target type='xen' port='0'/> + </console> + </devices> +</domain> 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 @@ +<domain type='xen'> + <name>XenGuest1</name> + <uuid>c7a5fdb0-cdaf-9455-926a-d65c16db1809</uuid> + <memory>592896</memory> + <currentMemory>403456</currentMemory> + <vcpu current='2'>4</vcpu> + <bootloader>/usr/bin/pygrub</bootloader> + <os> + <type arch='i686' machine='xenpv'>linux</type> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <disk type='block' device='disk'> + <driver name='phy'/> + <source dev='/dev/HostVG/XenGuest1'/> + <target dev='xvda' bus='xen'/> + </disk> + <interface type='bridge'> + <mac address='00:16:3e:66:94:9c'/> + <source bridge='br0'/> + <script path='vif-bridge'/> + </interface> + <console type='pty'> + <target type='xen' port='0'/> + </console> + <input type='mouse' bus='xen'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> + </devices> +</domain> 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 @@ <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os </cmdline> </os> <memory>430080</memory> - <vcpu current='1'>2</vcpu> + <vcpu current='2'>4</vcpu> <on_poweroff>destroy</on_poweroff> <on_reboot>destroy</on_reboot> <on_crash>destroy</on_crash> 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<migrate> optional I<--live> I<--suspend> I<domain-id> I<desturi> I<migrateuri> +=item B<maxvcpus> optional I<type> + +Provide the maximum number of virtual CPUs supported for a guest VM on +this connection. If provided, the I<type> parameter must be a valid +type attribute for the <domain> element of XML. + +=item B<migrate> optional I<--live> I<--suspend> I<domain-id> I<desturi> +I<migrateuri> Migrate domain to another host. Add --live for live migration; --suspend leaves the domain paused on the destination host. The I<desturi> 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<setvcpus> I<domain-id> I<count> optional I<--maximum> I<--persistent> -I<--active> +=item B<setvcpus> I<domain-id> I<count> optional I<--maximum> I<--config> +I<--live> Change the number of virtual CPUs active in the guest domain. Note that I<count> 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<shutdown> I<domain-id> @@ -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<domain-id>. =item B<vcpucount> I<domain-id> optional I<--maximum> I<--current> -I<--persistent> I<--active> +I<--config> I<--live> Print information about the virtual cpu counts of the given I<domain-id>. 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<setvcpus>, 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<vcpuinfo> I<domain-id>
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list