mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
qemu: Implement CPUs check against machine type's cpu-max
Implement check whether (maximum) vCPUs doesn't exceed machine type's cpu-max settings. On older versions of QEMU the check is disabled. Signed-off-by: Michal Novotny <minovotn@redhat.com>
This commit is contained in:
parent
034d322978
commit
ff96888991
@ -290,6 +290,11 @@
|
||||
<text/>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name='maxCpus'>
|
||||
<ref name='unsignedInt'/>
|
||||
</attribute>
|
||||
</optional>
|
||||
<text/>
|
||||
</element>
|
||||
</define>
|
||||
|
@ -853,6 +853,8 @@ virCapabilitiesFormatXML(virCapsPtr caps)
|
||||
virBufferAddLit(&xml, " <machine");
|
||||
if (machine->canonical)
|
||||
virBufferAsprintf(&xml, " canonical='%s'", machine->canonical);
|
||||
if (machine->maxCpus > 0)
|
||||
virBufferAsprintf(&xml, " maxCpus='%d'", machine->maxCpus);
|
||||
virBufferAsprintf(&xml, ">%s</machine>\n", machine->name);
|
||||
}
|
||||
|
||||
@ -871,6 +873,8 @@ virCapabilitiesFormatXML(virCapsPtr caps)
|
||||
virBufferAddLit(&xml, " <machine");
|
||||
if (machine->canonical)
|
||||
virBufferAsprintf(&xml, " canonical='%s'", machine->canonical);
|
||||
if (machine->maxCpus > 0)
|
||||
virBufferAsprintf(&xml, " maxCpus='%d'", machine->maxCpus);
|
||||
virBufferAsprintf(&xml, ">%s</machine>\n", machine->name);
|
||||
}
|
||||
virBufferAddLit(&xml, " </domain>\n");
|
||||
|
@ -46,6 +46,7 @@ typedef virCapsGuestMachine *virCapsGuestMachinePtr;
|
||||
struct _virCapsGuestMachine {
|
||||
char *name;
|
||||
char *canonical;
|
||||
unsigned int maxCpus;
|
||||
};
|
||||
|
||||
typedef struct _virCapsGuestDomainInfo virCapsGuestDomainInfo;
|
||||
|
@ -256,6 +256,7 @@ struct _virQEMUCaps {
|
||||
size_t nmachineTypes;
|
||||
char **machineTypes;
|
||||
char **machineAliases;
|
||||
unsigned int *machineMaxCpus;
|
||||
};
|
||||
|
||||
struct _virQEMUCapsCache {
|
||||
@ -335,6 +336,7 @@ virQEMUCapsSetDefaultMachine(virQEMUCapsPtr qemuCaps,
|
||||
{
|
||||
char *name = qemuCaps->machineTypes[defIdx];
|
||||
char *alias = qemuCaps->machineAliases[defIdx];
|
||||
unsigned int maxCpus = qemuCaps->machineMaxCpus[defIdx];
|
||||
|
||||
memmove(qemuCaps->machineTypes + 1,
|
||||
qemuCaps->machineTypes,
|
||||
@ -342,8 +344,12 @@ virQEMUCapsSetDefaultMachine(virQEMUCapsPtr qemuCaps,
|
||||
memmove(qemuCaps->machineAliases + 1,
|
||||
qemuCaps->machineAliases,
|
||||
sizeof(qemuCaps->machineAliases[0]) * defIdx);
|
||||
memmove(qemuCaps->machineMaxCpus + 1,
|
||||
qemuCaps->machineMaxCpus,
|
||||
sizeof(qemuCaps->machineMaxCpus[0]) * defIdx);
|
||||
qemuCaps->machineTypes[0] = name;
|
||||
qemuCaps->machineAliases[0] = alias;
|
||||
qemuCaps->machineMaxCpus[0] = maxCpus;
|
||||
}
|
||||
|
||||
/* Format is:
|
||||
@ -390,7 +396,8 @@ virQEMUCapsParseMachineTypesStr(const char *output,
|
||||
}
|
||||
|
||||
if (VIR_REALLOC_N(qemuCaps->machineTypes, qemuCaps->nmachineTypes + 1) < 0 ||
|
||||
VIR_REALLOC_N(qemuCaps->machineAliases, qemuCaps->nmachineTypes + 1) < 0) {
|
||||
VIR_REALLOC_N(qemuCaps->machineAliases, qemuCaps->nmachineTypes + 1) < 0 ||
|
||||
VIR_REALLOC_N(qemuCaps->machineMaxCpus, qemuCaps->nmachineTypes + 1) < 0) {
|
||||
VIR_FREE(name);
|
||||
VIR_FREE(canonical);
|
||||
virReportOOMError();
|
||||
@ -404,6 +411,8 @@ virQEMUCapsParseMachineTypesStr(const char *output,
|
||||
qemuCaps->machineTypes[qemuCaps->nmachineTypes-1] = name;
|
||||
qemuCaps->machineAliases[qemuCaps->nmachineTypes-1] = NULL;
|
||||
}
|
||||
/* When parsing from command line we don't have information about maxCpus */
|
||||
qemuCaps->machineMaxCpus[qemuCaps->nmachineTypes-1] = 0;
|
||||
} while ((p = next));
|
||||
|
||||
|
||||
@ -1764,11 +1773,14 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps)
|
||||
goto no_memory;
|
||||
if (VIR_ALLOC_N(ret->machineAliases, qemuCaps->nmachineTypes) < 0)
|
||||
goto no_memory;
|
||||
if (VIR_ALLOC_N(ret->machineMaxCpus, qemuCaps->nmachineTypes) < 0)
|
||||
goto no_memory;
|
||||
ret->nmachineTypes = qemuCaps->nmachineTypes;
|
||||
for (i = 0; i < qemuCaps->nmachineTypes; i++) {
|
||||
if (VIR_STRDUP(ret->machineTypes[i], qemuCaps->machineTypes[i]) < 0 ||
|
||||
VIR_STRDUP(ret->machineAliases[i], qemuCaps->machineAliases[i]) < 0)
|
||||
goto error;
|
||||
ret->machineMaxCpus[i] = qemuCaps->machineMaxCpus[i];
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -1792,6 +1804,7 @@ void virQEMUCapsDispose(void *obj)
|
||||
}
|
||||
VIR_FREE(qemuCaps->machineTypes);
|
||||
VIR_FREE(qemuCaps->machineAliases);
|
||||
VIR_FREE(qemuCaps->machineMaxCpus);
|
||||
|
||||
for (i = 0; i < qemuCaps->ncpuDefinitions; i++) {
|
||||
VIR_FREE(qemuCaps->cpuDefinitions[i]);
|
||||
@ -1932,6 +1945,7 @@ int virQEMUCapsGetMachineTypesCaps(virQEMUCapsPtr qemuCaps,
|
||||
if (VIR_STRDUP(mach->name, qemuCaps->machineTypes[i]) < 0)
|
||||
goto error;
|
||||
}
|
||||
mach->maxCpus = qemuCaps->machineMaxCpus[i];
|
||||
(*machines)[i] = mach;
|
||||
}
|
||||
|
||||
@ -1966,6 +1980,25 @@ const char *virQEMUCapsGetCanonicalMachine(virQEMUCapsPtr qemuCaps,
|
||||
}
|
||||
|
||||
|
||||
int virQEMUCapsGetMachineMaxCpus(virQEMUCapsPtr qemuCaps,
|
||||
const char *name)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!name)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < qemuCaps->nmachineTypes; i++) {
|
||||
if (!qemuCaps->machineMaxCpus[i])
|
||||
continue;
|
||||
if (STREQ(qemuCaps->machineTypes[i], name))
|
||||
return qemuCaps->machineMaxCpus[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
|
||||
qemuMonitorPtr mon)
|
||||
@ -2083,6 +2116,10 @@ virQEMUCapsProbeQMPMachineTypes(virQEMUCapsPtr qemuCaps,
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
if (VIR_ALLOC_N(qemuCaps->machineMaxCpus, nmachines) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (i = 0; i < nmachines; i++) {
|
||||
if (VIR_STRDUP(qemuCaps->machineAliases[i], machines[i]->alias) < 0 ||
|
||||
@ -2090,6 +2127,7 @@ virQEMUCapsProbeQMPMachineTypes(virQEMUCapsPtr qemuCaps,
|
||||
goto cleanup;
|
||||
if (machines[i]->isDefault)
|
||||
defIdx = i;
|
||||
qemuCaps->machineMaxCpus[i] = machines[i]->maxCpus;
|
||||
}
|
||||
qemuCaps->nmachineTypes = nmachines;
|
||||
|
||||
|
@ -234,7 +234,8 @@ size_t virQEMUCapsGetMachineTypes(virQEMUCapsPtr qemuCaps,
|
||||
char ***names);
|
||||
const char *virQEMUCapsGetCanonicalMachine(virQEMUCapsPtr qemuCaps,
|
||||
const char *name);
|
||||
|
||||
int virQEMUCapsGetMachineMaxCpus(virQEMUCapsPtr qemuCaps,
|
||||
const char *name);
|
||||
int virQEMUCapsGetMachineTypesCaps(virQEMUCapsPtr qemuCaps,
|
||||
size_t *nmachines,
|
||||
virCapsGuestMachinePtr **machines);
|
||||
|
@ -654,6 +654,7 @@ struct _qemuMonitorMachineInfo {
|
||||
char *name;
|
||||
bool isDefault;
|
||||
char *alias;
|
||||
unsigned int maxCpus;
|
||||
};
|
||||
|
||||
int qemuMonitorGetMachines(qemuMonitorPtr mon,
|
||||
|
@ -4042,6 +4042,12 @@ int qemuMonitorJSONGetMachines(qemuMonitorPtr mon,
|
||||
if (VIR_STRDUP(info->alias, tmp) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
if (virJSONValueObjectHasKey(child, "cpu-max") &&
|
||||
virJSONValueObjectGetNumberUint(child, "cpu-max", &info->maxCpus) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("query-machines reply has malformed 'cpu-max' data"));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
ret = n;
|
||||
|
@ -3330,6 +3330,24 @@ error:
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
qemuValidateCpuMax(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
|
||||
{
|
||||
unsigned int maxCpus;
|
||||
|
||||
maxCpus = virQEMUCapsGetMachineMaxCpus(qemuCaps, def->os.machine);
|
||||
if (!maxCpus)
|
||||
return true;
|
||||
|
||||
if (def->maxvcpus > maxCpus) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
"%s", _("Maximum CPUs greater than specified machine type limit"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int qemuProcessStart(virConnectPtr conn,
|
||||
virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm,
|
||||
@ -3519,6 +3537,9 @@ int qemuProcessStart(virConnectPtr conn,
|
||||
vm->def->emulator)))
|
||||
goto cleanup;
|
||||
|
||||
if (!qemuValidateCpuMax(vm->def, priv->qemuCaps))
|
||||
goto cleanup;
|
||||
|
||||
if (qemuAssignDeviceAliases(vm->def, priv->qemuCaps) < 0)
|
||||
goto cleanup;
|
||||
|
||||
|
@ -33,18 +33,18 @@
|
||||
<arch name='i686'>
|
||||
<wordsize>32</wordsize>
|
||||
<emulator>/usr/bin/qemu</emulator>
|
||||
<machine>pc-0.11</machine>
|
||||
<machine canonical='pc-0.11'>pc</machine>
|
||||
<machine>pc-0.10</machine>
|
||||
<machine>isapc</machine>
|
||||
<machine maxCpus='255'>pc-0.11</machine>
|
||||
<machine canonical='pc-0.11' maxCpus='255'>pc</machine>
|
||||
<machine maxCpus='255'>pc-0.10</machine>
|
||||
<machine maxCpus='1'>isapc</machine>
|
||||
<domain type='qemu'>
|
||||
</domain>
|
||||
<domain type='kvm'>
|
||||
<emulator>/usr/bin/qemu-kvm</emulator>
|
||||
<machine>pc-0.11</machine>
|
||||
<machine canonical='pc-0.11'>pc</machine>
|
||||
<machine>pc-0.10</machine>
|
||||
<machine>isapc</machine>
|
||||
<machine maxCpus='255'>pc-0.11</machine>
|
||||
<machine canonical='pc-0.11' maxCpus='255'>pc</machine>
|
||||
<machine maxCpus='255'>pc-0.10</machine>
|
||||
<machine maxCpus='1'>isapc</machine>
|
||||
</domain>
|
||||
</arch>
|
||||
<features>
|
||||
|
Loading…
Reference in New Issue
Block a user