mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
qemu: Implement support for VIR_DOMAIN_VCPU_AGENT in qemuDomainSetVcpusFlags
This patch adds support for agent-based cpu disabling and enabling to qemuDomainSetVcpusFlags() API.
This commit is contained in:
parent
c6afcb052c
commit
d47eff88fe
@ -3712,6 +3712,68 @@ unsupported:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuDomainPrepareAgentVCPUs(unsigned int nvcpus,
|
||||||
|
qemuAgentCPUInfoPtr cpuinfo,
|
||||||
|
int ncpuinfo)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int nonline = 0;
|
||||||
|
int nofflinable = 0;
|
||||||
|
|
||||||
|
/* count the active and offlinable cpus */
|
||||||
|
for (i = 0; i < ncpuinfo; i++) {
|
||||||
|
if (cpuinfo[i].online)
|
||||||
|
nonline++;
|
||||||
|
|
||||||
|
if (cpuinfo[i].offlinable && cpuinfo[i].online)
|
||||||
|
nofflinable++;
|
||||||
|
|
||||||
|
/* This shouldn't happen, but we can't trust the guest agent */
|
||||||
|
if (!cpuinfo[i].online && !cpuinfo[i].offlinable) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Invalid data provided by guest agent"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the guest agent reported less cpus than requested */
|
||||||
|
if (nvcpus > ncpuinfo) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("guest agent reports less cpu than requested"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not enough offlinable CPUs to support the request */
|
||||||
|
if (nvcpus < nonline - nofflinable) {
|
||||||
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||||
|
_("Cannot offline enough CPUs"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ncpuinfo; i++) {
|
||||||
|
if (nvcpus < nonline) {
|
||||||
|
/* unplug */
|
||||||
|
if (cpuinfo[i].offlinable && cpuinfo[i].online) {
|
||||||
|
cpuinfo[i].online = false;
|
||||||
|
nonline--;
|
||||||
|
}
|
||||||
|
} else if (nvcpus > nonline) {
|
||||||
|
/* plug */
|
||||||
|
if (!cpuinfo[i].online) {
|
||||||
|
cpuinfo[i].online = true;
|
||||||
|
nonline++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* done */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qemuDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
|
qemuDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
@ -3723,10 +3785,14 @@ qemuDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
|
|||||||
bool maximum;
|
bool maximum;
|
||||||
virQEMUDriverConfigPtr cfg = NULL;
|
virQEMUDriverConfigPtr cfg = NULL;
|
||||||
virCapsPtr caps = NULL;
|
virCapsPtr caps = NULL;
|
||||||
|
qemuAgentCPUInfoPtr cpuinfo = NULL;
|
||||||
|
int ncpuinfo;
|
||||||
|
qemuDomainObjPrivatePtr priv;
|
||||||
|
|
||||||
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
|
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
|
||||||
VIR_DOMAIN_AFFECT_CONFIG |
|
VIR_DOMAIN_AFFECT_CONFIG |
|
||||||
VIR_DOMAIN_VCPU_MAXIMUM, -1);
|
VIR_DOMAIN_VCPU_MAXIMUM |
|
||||||
|
VIR_DOMAIN_VCPU_AGENT, -1);
|
||||||
|
|
||||||
if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
|
if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
|
||||||
virReportError(VIR_ERR_INVALID_ARG,
|
virReportError(VIR_ERR_INVALID_ARG,
|
||||||
@ -3741,6 +3807,8 @@ qemuDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
|
|||||||
if (!(vm = qemuDomObjFromDomain(dom)))
|
if (!(vm = qemuDomObjFromDomain(dom)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
priv = vm->privateData;
|
||||||
|
|
||||||
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
|
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
@ -3766,6 +3834,39 @@ qemuDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
|
|||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & VIR_DOMAIN_VCPU_AGENT) {
|
||||||
|
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||||
|
_("chainging of maximum vCPU count isn't supported "
|
||||||
|
"via guest agent"));
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemuDomainObjEnterAgent(vm);
|
||||||
|
ncpuinfo = qemuAgentGetVCPUs(priv->agent, &cpuinfo);
|
||||||
|
qemuDomainObjExitAgent(vm);
|
||||||
|
|
||||||
|
if (ncpuinfo < 0)
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
|
if (qemuDomainPrepareAgentVCPUs(nvcpus, cpuinfo, ncpuinfo) < 0)
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
|
qemuDomainObjEnterAgent(vm);
|
||||||
|
ret = qemuAgentSetVCPUs(priv->agent, cpuinfo, ncpuinfo);
|
||||||
|
qemuDomainObjExitAgent(vm);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
|
if (ret < ncpuinfo) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("failed to set state of cpu %d via guest agent"),
|
||||||
|
cpuinfo[ret-1].id);
|
||||||
|
ret = -1;
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
|
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
|
||||||
if (qemuDomainHotplugVcpus(driver, vm, nvcpus) < 0)
|
if (qemuDomainHotplugVcpus(driver, vm, nvcpus) < 0)
|
||||||
goto endjob;
|
goto endjob;
|
||||||
@ -3783,6 +3884,7 @@ qemuDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
|
|||||||
if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
|
if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
|
||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
@ -3794,6 +3896,7 @@ cleanup:
|
|||||||
if (vm)
|
if (vm)
|
||||||
virObjectUnlock(vm);
|
virObjectUnlock(vm);
|
||||||
virObjectUnref(caps);
|
virObjectUnref(caps);
|
||||||
|
VIR_FREE(cpuinfo);
|
||||||
virObjectUnref(cfg);
|
virObjectUnref(cfg);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user