Implement the cpu-max attribute into virConnectGetCapabilities() API
output to allow caller to check maximum number of CPUs to be set for
specified machine type.
Signed-off-by: Michal Novotny <minovotn(a)redhat.com>
---
docs/schemas/capability.rng | 5 +++++
src/conf/capabilities.c | 4 ++++
src/conf/capabilities.h | 1 +
src/qemu/qemu_capabilities.c | 40 +++++++++++++++++++++++++++++++++++++++-
src/qemu/qemu_capabilities.h | 3 ++-
src/qemu/qemu_monitor.h | 1 +
src/qemu/qemu_monitor_json.c | 7 +++++++
7 files changed, 59 insertions(+), 2 deletions(-)
diff --git a/docs/schemas/capability.rng b/docs/schemas/capability.rng
index 106ca73..4f87397 100644
--- a/docs/schemas/capability.rng
+++ b/docs/schemas/capability.rng
@@ -290,6 +290,11 @@
<text/>
</attribute>
</optional>
+ <optional>
+ <attribute name='cpu-max'>
+ <ref name='unsignedInt'/>
+ </attribute>
+ </optional>
<text/>
</element>
</define>
diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
index c7ec92f..ab1bdd3 100644
--- a/src/conf/capabilities.c
+++ b/src/conf/capabilities.c
@@ -860,6 +860,8 @@ virCapabilitiesFormatXML(virCapsPtr caps)
for (j = 0 ; j < caps->guests[i]->arch.defaultInfo.nmachines ; j++) {
virCapsGuestMachinePtr machine =
caps->guests[i]->arch.defaultInfo.machines[j];
virBufferAddLit(&xml, " <machine");
+ if (machine->cpu_max > 0)
+ virBufferAsprintf(&xml, " cpu-max='%d'",
machine->cpu_max);
if (machine->canonical)
virBufferAsprintf(&xml, " canonical='%s'",
machine->canonical);
virBufferAsprintf(&xml, ">%s</machine>\n",
machine->name);
@@ -878,6 +880,8 @@ virCapabilitiesFormatXML(virCapsPtr caps)
for (k = 0 ; k < caps->guests[i]->arch.domains[j]->info.nmachines
; k++) {
virCapsGuestMachinePtr machine =
caps->guests[i]->arch.domains[j]->info.machines[k];
virBufferAddLit(&xml, " <machine");
+ if (machine->cpu_max > 0)
+ virBufferAsprintf(&xml, " cpu-max='%d'",
machine->cpu_max);
if (machine->canonical)
virBufferAsprintf(&xml, " canonical='%s'",
machine->canonical);
virBufferAsprintf(&xml, ">%s</machine>\n",
machine->name);
diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
index abcf6de..16bf3de 100644
--- a/src/conf/capabilities.h
+++ b/src/conf/capabilities.h
@@ -46,6 +46,7 @@ typedef virCapsGuestMachine *virCapsGuestMachinePtr;
struct _virCapsGuestMachine {
char *name;
char *canonical;
+ int cpu_max;
};
typedef struct _virCapsGuestDomainInfo virCapsGuestDomainInfo;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index d10c8aa..a03a643 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;
@@ -1885,9 +1897,11 @@ int virQEMUCapsGetMachineTypesCaps(virQEMUCapsPtr qemuCaps,
goto no_memory;
if (!(mach->canonical = strdup(qemuCaps->machineTypes[i])))
goto no_memory;
+ mach->cpu_max = qemuCaps->machineMaxCpus[i];
} else {
if (!(mach->name = strdup(qemuCaps->machineTypes[i])))
goto no_memory;
+ mach->cpu_max = qemuCaps->machineMaxCpus[i];
}
(*machines)[i] = mach;
}
@@ -1923,6 +1937,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 +2106,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 +2124,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 728add5..8205ff7 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -224,7 +224,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;
--
1.7.11.7