QEMU reports whether 'query-hotpluggable-cpus' is supported for a given machine type. Extract and cache the information using the capability cache. --- src/qemu/qemu_capabilities.c | 29 ++++++++++++- src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_monitor.h | 1 + src/qemu/qemu_monitor_json.c | 3 ++ tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml | 54 ++++++++++++------------ 5 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 0cb9baa..8e0dafc 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -348,6 +348,7 @@ struct virQEMUCapsMachineType { char *name; char *alias; unsigned int maxCpus; + bool hotplugCpus; }; /* * Update the XML parser/formatter when adding more @@ -547,6 +548,7 @@ virQEMUCapsParseMachineTypesStr(const char *output, } /* When parsing from command line we don't have information about maxCpus */ qemuCaps->machineTypes[qemuCaps->nmachineTypes-1].maxCpus = 0; + qemuCaps->machineTypes[qemuCaps->nmachineTypes-1].hotplugCpus = false; } while ((p = next)); @@ -2043,6 +2045,7 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps) VIR_STRDUP(ret->machineTypes[i].alias, qemuCaps->machineTypes[i].alias) < 0) goto error; ret->machineTypes[i].maxCpus = qemuCaps->machineTypes[i].maxCpus; + ret->machineTypes[i].hotplugCpus = qemuCaps->machineTypes[i].hotplugCpus; } return ret; @@ -2346,6 +2349,20 @@ int virQEMUCapsGetMachineMaxCpus(virQEMUCapsPtr qemuCaps, } +bool virQEMUCapsGetMachineHotplugCpus(virQEMUCapsPtr qemuCaps, + const char *name) +{ + size_t i; + + for (i = 0; i < qemuCaps->nmachineTypes; i++) { + if (STREQ_NULLABLE(qemuCaps->machineTypes[i].name, name)) + return qemuCaps->machineTypes[i].hotplugCpus; + } + + return false; +} + + /** * virQEMUCapsSetGICCapabilities: * @qemuCaps: QEMU capabilities @@ -2500,6 +2517,7 @@ virQEMUCapsProbeQMPMachineTypes(virQEMUCapsPtr qemuCaps, goto cleanup; mach->maxCpus = machines[i]->maxCpus; + mach->hotplugCpus = machines[i]->hotplugCpus; if (machines[i]->isDefault) defIdx = qemuCaps->nmachineTypes - 1; @@ -2758,7 +2776,7 @@ int virQEMUCapsProbeQMP(virQEMUCapsPtr qemuCaps, * ... * <cpu name="pentium3"/> * ... - * <machine name="pc-1.0" alias="pc" maxCpus="4"/> + * <machine name="pc-1.0" alias="pc" hotplugCpus='yes' maxCpus="4"/> * ... * </qemuCaps> */ @@ -2915,6 +2933,11 @@ virQEMUCapsLoadCache(virQEMUCapsPtr qemuCaps, const char *filename, goto cleanup; } VIR_FREE(str); + + str = virXMLPropString(nodes[i], "hotplugCpus"); + if (STREQ_NULLABLE(str, "yes")) + qemuCaps->machineTypes[i].hotplugCpus = true; + VIR_FREE(str); } } VIR_FREE(nodes); @@ -3048,6 +3071,8 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps, if (qemuCaps->machineTypes[i].alias) virBufferEscapeString(&buf, " alias='%s'", qemuCaps->machineTypes[i].alias); + if (qemuCaps->machineTypes[i].hotplugCpus) + virBufferAddLit(&buf, " hotplugCpus='yes'"); virBufferAsprintf(&buf, " maxCpus='%u'/>\n", qemuCaps->machineTypes[i].maxCpus); } @@ -3836,6 +3861,8 @@ virQEMUCapsFilterByMachineType(virQEMUCapsPtr qemuCaps, virQEMUCapsClear(qemuCaps, filter->flags[j]); } + if (!virQEMUCapsGetMachineHotplugCpus(qemuCaps, machineType)) + virQEMUCapsClear(qemuCaps, QEMU_CAPS_QUERY_HOTPLUGGABLE_CPUS); } diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index e2d8d2c..f06e10c 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -428,6 +428,8 @@ const char *virQEMUCapsGetCanonicalMachine(virQEMUCapsPtr qemuCaps, const char *name); int virQEMUCapsGetMachineMaxCpus(virQEMUCapsPtr qemuCaps, const char *name); +bool virQEMUCapsGetMachineHotplugCpus(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 826991f..417091c 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -854,6 +854,7 @@ struct _qemuMonitorMachineInfo { bool isDefault; char *alias; unsigned int maxCpus; + bool hotplugCpus; }; int qemuMonitorGetMachines(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index f39cda4..d61b64f 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -4840,6 +4840,9 @@ int qemuMonitorJSONGetMachines(qemuMonitorPtr mon, _("query-machines reply has malformed 'cpu-max' data")); goto cleanup; } + + ignore_value(virJSONValueObjectGetBoolean(child, "hotpluggable-cpus", + &info->hotplugCpus)); } ret = n; diff --git a/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml index 07aa08e..c767fb2 100644 --- a/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml @@ -226,31 +226,31 @@ <cpu name='core2duo'/> <cpu name='phenom'/> <cpu name='qemu64'/> - <machine name='pc-i440fx-2.7' alias='pc' maxCpus='255'/> - <machine name='pc-0.12' maxCpus='255'/> - <machine name='pc-i440fx-2.4' maxCpus='255'/> - <machine name='pc-1.3' maxCpus='255'/> - <machine name='pc-q35-2.7' alias='q35' maxCpus='255'/> - <machine name='pc-q35-2.6' maxCpus='255'/> - <machine name='pc-i440fx-1.7' maxCpus='255'/> - <machine name='pc-i440fx-1.6' maxCpus='255'/> - <machine name='pc-0.11' maxCpus='255'/> - <machine name='pc-i440fx-2.3' maxCpus='255'/> - <machine name='pc-0.10' maxCpus='255'/> - <machine name='pc-1.2' maxCpus='255'/> - <machine name='pc-i440fx-2.2' maxCpus='255'/> - <machine name='isapc' maxCpus='1'/> - <machine name='pc-q35-2.5' maxCpus='255'/> - <machine name='pc-0.15' maxCpus='255'/> - <machine name='pc-i440fx-1.5' maxCpus='255'/> - <machine name='pc-0.14' maxCpus='255'/> - <machine name='pc-i440fx-2.6' maxCpus='255'/> - <machine name='pc-i440fx-1.4' maxCpus='255'/> - <machine name='pc-i440fx-2.5' maxCpus='255'/> - <machine name='pc-1.1' maxCpus='255'/> - <machine name='pc-i440fx-2.1' maxCpus='255'/> - <machine name='pc-1.0' maxCpus='255'/> - <machine name='pc-i440fx-2.0' maxCpus='255'/> - <machine name='pc-q35-2.4' maxCpus='255'/> - <machine name='pc-0.13' maxCpus='255'/> + <machine name='pc-i440fx-2.7' alias='pc' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-0.12' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-i440fx-2.4' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-1.3' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-q35-2.7' alias='q35' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-q35-2.6' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-i440fx-1.7' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-i440fx-1.6' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-0.11' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-i440fx-2.3' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-0.10' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-1.2' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-i440fx-2.2' hotplugCpus='yes' maxCpus='255'/> + <machine name='isapc' hotplugCpus='yes' maxCpus='1'/> + <machine name='pc-q35-2.5' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-0.15' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-i440fx-1.5' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-0.14' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-i440fx-2.6' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-i440fx-1.4' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-i440fx-2.5' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-1.1' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-i440fx-2.1' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-1.0' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-i440fx-2.0' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-q35-2.4' hotplugCpus='yes' maxCpus='255'/> + <machine name='pc-0.13' hotplugCpus='yes' maxCpus='255'/> </qemuCaps> -- 2.9.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list