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 + + + + + + + + + +