[libvirt] [PATCH v3] qemu: Implement CPUs check against machine type's cpu-max
Michal Novotny
minovotn at redhat.com
Mon Apr 22 10:57:29 UTC 2013
ping?
On 04/17/2013 04:15 PM, Michal Novotny wrote:
> 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 at redhat.com>
> ---
> src/qemu/qemu_capabilities.c | 38 +++++++++++++++++++++++++++++++++++++-
> src/qemu/qemu_capabilities.h | 3 ++-
> src/qemu/qemu_monitor.h | 1 +
> src/qemu/qemu_monitor_json.c | 7 +++++++
> src/qemu/qemu_process.c | 27 +++++++++++++++++++++++++++
> 5 files changed, 74 insertions(+), 2 deletions(-)
>
> diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
> index d10c8aa..bbfe85f 100644
> --- a/src/qemu/qemu_capabilities.c
> +++ b/src/qemu/qemu_capabilities.c
> @@ -243,6 +243,7 @@ struct _virQEMUCaps {
> size_t nmachineTypes;
> char **machineTypes;
> char **machineAliases;
> + int *machineMaxCpus;
> };
>
> struct _virQEMUCapsCache {
> @@ -322,6 +323,7 @@ virQEMUCapsSetDefaultMachine(virQEMUCapsPtr qemuCaps,
> {
> char *name = qemuCaps->machineTypes[defIdx];
> char *alias = qemuCaps->machineAliases[defIdx];
> + int cpu_max = qemuCaps->machineMaxCpus[defIdx];
>
> memmove(qemuCaps->machineTypes + 1,
> qemuCaps->machineTypes,
> @@ -329,8 +331,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] = cpu_max;
> }
>
> /* Format is:
> @@ -377,7 +383,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);
> goto no_memory;
> @@ -390,6 +397,8 @@ virQEMUCapsParseMachineTypesStr(const char *output,
> qemuCaps->machineTypes[qemuCaps->nmachineTypes-1] = name;
> qemuCaps->machineAliases[qemuCaps->nmachineTypes-1] = NULL;
> }
> + /* Value 0 means "unknown" as it's not exposed by QEMU binary */
> + qemuCaps->machineMaxCpus[qemuCaps->nmachineTypes-1] = 0;
> } while ((p = next));
>
>
> @@ -1718,6 +1727,8 @@ 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 (!(ret->machineTypes[i] = strdup(qemuCaps->machineTypes[i])))
> @@ -1725,6 +1736,7 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps)
> if (qemuCaps->machineAliases[i] &&
> !(ret->machineAliases[i] = strdup(qemuCaps->machineAliases[i])))
> goto no_memory;
> + ret->machineMaxCpus[i] = qemuCaps->machineMaxCpus[i];
> }
>
> return ret;
> @@ -1923,6 +1935,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)
> @@ -2073,6 +2104,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 (machines[i]->alias) {
> @@ -2087,6 +2122,7 @@ virQEMUCapsProbeQMPMachineTypes(virQEMUCapsPtr qemuCaps,
> }
> if (machines[i]->isDefault)
> defIdx = i;
> + qemuCaps->machineMaxCpus[i] = machines[i]->cpu_max;
> }
> qemuCaps->nmachineTypes = nmachines;
>
> diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
> index 4e76799..bd97e8d 100644
> --- a/src/qemu/qemu_capabilities.h
> +++ b/src/qemu/qemu_capabilities.h
> @@ -223,7 +223,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);
> diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
> index f39f009..c097953 100644
> --- a/src/qemu/qemu_monitor.h
> +++ b/src/qemu/qemu_monitor.h
> @@ -650,6 +650,7 @@ struct _qemuMonitorMachineInfo {
> char *name;
> bool isDefault;
> char *alias;
> + int cpu_max;
> };
>
> int qemuMonitorGetMachines(qemuMonitorPtr mon,
> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index 6fdd650..adbd865 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -4024,6 +4024,13 @@ int qemuMonitorJSONGetMachines(qemuMonitorPtr mon,
> goto cleanup;
> }
> }
> +
> + if (virJSONValueObjectHasKey(child, "cpu-max") &&
> + virJSONValueObjectGetNumberInt(child, "cpu-max", &info->cpu_max) < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("query-machines reply has malformed 'cpu-max' data"));
> + goto cleanup;
> + }
> }
>
> ret = n;
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index ce9f501..9eae8f6 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -3266,6 +3266,30 @@ qemuSetUnprivSGIO(virDomainDiskDefPtr disk)
> return ret;
> }
>
> +static bool
> +qemuValidateCpuMax(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
> +{
> + int cpu_max;
> +
> + cpu_max = virQEMUCapsGetMachineMaxCpus(qemuCaps, def->os.machine);
> + if (!cpu_max)
> + return true;
> +
> + if (def->vcpus > cpu_max) {
> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> + "%s", _("CPUs greater than specified machine type limit"));
> + return false;
> + }
> +
> + if (def->maxvcpus > cpu_max) {
> + 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,
> @@ -3481,6 +3505,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;
>
--
Michal Novotny <minovotn at redhat.com>, RHCE, Red Hat
Virtualization | libvirt-php bindings | php-virt-control.org
More information about the libvir-list
mailing list