* src/qemu/qemu_driver.c (qemudDomainSetVcpusFlags)
(qemudDomainGetVcpusFlags): Support all feasible flag
combinations.
---
Aargh - my ISP SMTP server said that 11 emails is the limit for one
session, so I have to resend the last two of my series (and figure out
how to config git to use multiple sessions to avoid that problem in
the future).
Anyways, this is the meat of the patch series, in converting qemu
0.12+ to remember whether vcpus have been hot-unplugged below the
maximum, in order to boot that way the next time around. I'm a bit
fuzzy on whether I used all the driver internals correctly, especially
on how and when vm->newDef should be created for managing persistent
state separately from live state, so a careful review is appreciated,
and I'll probably need a v2.
src/qemu/qemu_driver.c | 90 ++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 75 insertions(+), 15 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index c31eeb9..4b1519d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5908,9 +5908,22 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
int max;
int ret = -1;
- if (flags != VIR_DOMAIN_VCPU_ACTIVE) {
- qemuReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"),
- flags);
+ virCheckFlags(VIR_DOMAIN_VCPU_ACTIVE |
+ VIR_DOMAIN_VCPU_PERSISTENT |
+ 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)) {
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("invalid flag combination: (0x%x)"), flags);
+ return -1;
+ }
+ if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("argument out of range: %d"), nvcpus);
return -1;
}
@@ -5929,7 +5942,7 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
if (qemuDomainObjBeginJob(vm) < 0)
goto cleanup;
- if (!virDomainObjIsActive(vm)) {
+ if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_VCPU_ACTIVE)) {
qemuReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not running"));
goto endjob;
@@ -5948,6 +5961,11 @@ 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) {
+ max = vm->def->maxvcpus;
+ }
+
if (nvcpus > max) {
qemuReportError(VIR_ERR_INVALID_ARG,
_("requested vcpus is greater than max allowable"
@@ -5955,7 +5973,39 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
goto endjob;
}
- ret = qemudDomainHotplugVcpus(vm, 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;
+ }
+ 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;
+ }
+ break;
+
+ case VIR_DOMAIN_VCPU_ACTIVE:
+ ret = qemudDomainHotplugVcpus(vm, nvcpus);
+ break;
+
+ case VIR_DOMAIN_VCPU_ACTIVE | VIR_DOMAIN_VCPU_PERSISTENT:
+ ret = qemudDomainHotplugVcpus(vm, nvcpus);
+ if (ret == 0 && vm->newDef)
+ vm->newDef->vcpus = nvcpus;
+ break;
+ }
endjob:
if (qemuDomainObjEndJob(vm) == 0)
@@ -6134,12 +6184,18 @@ qemudDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
{
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
- const char *type;
+ virDomainDefPtr def;
int ret = -1;
- if (flags != (VIR_DOMAIN_VCPU_ACTIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
- qemuReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"),
- flags);
+ virCheckFlags(VIR_DOMAIN_VCPU_ACTIVE |
+ VIR_DOMAIN_VCPU_PERSISTENT |
+ 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)) {
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("invalid flag combination: (0x%x)"), flags);
return -1;
}
@@ -6155,14 +6211,18 @@ qemudDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
goto cleanup;
}
- if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
- qemuReportError(VIR_ERR_INTERNAL_ERROR,
- _("unknown virt type in domain definition
'%d'"),
- vm->def->virtType);
- goto cleanup;
+ if (flags & VIR_DOMAIN_VCPU_ACTIVE) {
+ if (!virDomainObjIsActive(vm)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain not active"));
+ goto cleanup;
+ }
+ def = vm->def;
+ } else {
+ def = vm->newDef ? vm->newDef : vm->def;
}
- ret = qemudGetMaxVCPUs(NULL, type);
+ ret = (flags & VIR_DOMAIN_VCPU_MAXIMUM) ? def->maxvcpus : def->vcpus;
cleanup:
if (vm)
--
1.7.2.3