From 2fc215dd2ad4b88c1054da804c4c45b3d4e5c2fa Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Wed, 22 Feb 2017 16:01:30 +0100 Subject: [PATCH] qemu: Store more types in qemuMonitorCPUModelInfo While query-cpu-model-expansion returns only boolean features on s390, but x86_64 reports some integer and string properties which we are interested in. Signed-off-by: Jiri Denemark --- src/qemu/qemu_capabilities.c | 98 ++++++++++++++----- src/qemu/qemu_monitor.c | 25 ++++- src/qemu/qemu_monitor.h | 27 ++++- src/qemu/qemu_monitor_json.c | 40 ++++++-- .../caps_2.9.0.x86_64.xml | 7 ++ 5 files changed, 161 insertions(+), 36 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 0e9c81b6b0..d92aa95428 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3082,14 +3082,16 @@ virQEMUCapsInitCPUModelS390(virQEMUCapsPtr qemuCaps, cpu->nfeatures = 0; for (i = 0; i < modelInfo->nprops; i++) { - if (VIR_STRDUP(cpu->features[i].name, modelInfo->props[i].name) < 0) - return -1; + virCPUFeatureDefPtr feature = cpu->features + cpu->nfeatures; + qemuMonitorCPUPropertyPtr prop = modelInfo->props + i; - if (modelInfo->props[i].supported) - cpu->features[i].policy = VIR_CPU_FEATURE_REQUIRE; - else - cpu->features[i].policy = VIR_CPU_FEATURE_DISABLE; + if (prop->type != QEMU_MONITOR_CPU_PROPERTY_BOOLEAN) + continue; + if (VIR_STRDUP(feature->name, prop->name) < 0) + return -1; + feature->policy = prop->value.boolean ? VIR_CPU_FEATURE_REQUIRE + : VIR_CPU_FEATURE_DISABLE; cpu->nfeatures++; } @@ -3195,30 +3197,59 @@ virQEMUCapsLoadHostCPUModelInfo(virQEMUCapsPtr qemuCaps, hostCPU->nprops = n; for (i = 0; i < n; i++) { - hostCPU->props[i].name = virXMLPropString(nodes[i], "name"); - if (!hostCPU->props[i].name) { + qemuMonitorCPUPropertyPtr prop = hostCPU->props + i; + int type; + + ctxt->node = nodes[i]; + + if (!(prop->name = virXMLPropString(ctxt->node, "name"))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing 'name' attribute for a host CPU" " model property in QEMU capabilities cache")); goto cleanup; } - if (!(str = virXMLPropString(nodes[i], "value"))) { + if (!(str = virXMLPropString(ctxt->node, "type")) || + (type = qemuMonitorCPUPropertyTypeFromString(str)) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("missing 'value' attribute for a host CPU" - " model property in QEMU capabilities cache")); - goto cleanup; - } - if (STREQ(str, "true")) { - hostCPU->props[i].supported = true; - } else if (STREQ(str, "false")) { - hostCPU->props[i].supported = false; - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("invalid boolean value: '%s'"), str); + _("missing or invalid CPU model property type " + "in QEMU capabilities cache")); goto cleanup; } VIR_FREE(str); + + prop->type = type; + switch (prop->type) { + case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN: + if (virXPathBoolean("./@value='true'", ctxt)) + prop->value.boolean = true; + break; + + case QEMU_MONITOR_CPU_PROPERTY_STRING: + prop->value.string = virXMLPropString(ctxt->node, "value"); + if (!prop->value.string) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("invalid string value for '%s' host CPU " + "model property in QEMU capabilities cache"), + prop->name); + goto cleanup; + } + break; + + case QEMU_MONITOR_CPU_PROPERTY_NUMBER: + if (virXPathLongLong("string(./@value)", ctxt, + &prop->value.number) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("invalid number value for '%s' host CPU " + "model property in QEMU capabilities cache"), + prop->name); + goto cleanup; + } + break; + + case QEMU_MONITOR_CPU_PROPERTY_LAST: + break; + } } } @@ -3560,9 +3591,30 @@ virQEMUCapsFormatHostCPUModelInfo(virQEMUCapsPtr qemuCaps, virBufferAdjustIndent(buf, 2); for (i = 0; i < model->nprops; i++) { - virBufferAsprintf(buf, "\n", - model->props[i].name, - model->props[i].supported ? "true" : "false"); + qemuMonitorCPUPropertyPtr prop = model->props + i; + + virBufferAsprintf(buf, "name, + qemuMonitorCPUPropertyTypeToString(prop->type)); + + switch (prop->type) { + case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN: + virBufferAsprintf(buf, "value='%s'", + prop->value.boolean ? "true" : "false"); + break; + + case QEMU_MONITOR_CPU_PROPERTY_STRING: + virBufferEscapeString(buf, "value='%s'", prop->value.string); + break; + + case QEMU_MONITOR_CPU_PROPERTY_NUMBER: + virBufferAsprintf(buf, "value='%lld'", prop->value.number); + break; + + case QEMU_MONITOR_CPU_PROPERTY_LAST: + break; + } + virBufferAddLit(buf, "/>\n"); } virBufferAdjustIndent(buf, -2); diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index b15207a693..4c3f7a20fe 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3661,8 +3661,11 @@ qemuMonitorCPUModelInfoFree(qemuMonitorCPUModelInfoPtr model_info) if (!model_info) return; - for (i = 0; i < model_info->nprops; i++) + for (i = 0; i < model_info->nprops; i++) { VIR_FREE(model_info->props[i].name); + if (model_info->props[i].type == QEMU_MONITOR_CPU_PROPERTY_STRING) + VIR_FREE(model_info->props[i].value.string); + } VIR_FREE(model_info->props); VIR_FREE(model_info->name); @@ -3691,7 +3694,25 @@ qemuMonitorCPUModelInfoCopy(const qemuMonitorCPUModelInfo *orig) if (VIR_STRDUP(copy->props[i].name, orig->props[i].name) < 0) goto error; - copy->props[i].supported = orig->props[i].supported; + copy->props[i].type = orig->props[i].type; + switch (orig->props[i].type) { + case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN: + copy->props[i].value.boolean = orig->props[i].value.boolean; + break; + + case QEMU_MONITOR_CPU_PROPERTY_STRING: + if (VIR_STRDUP(copy->props[i].value.string, + orig->props[i].value.string) < 0) + goto error; + break; + + case QEMU_MONITOR_CPU_PROPERTY_NUMBER: + copy->props[i].value.number = orig->props[i].value.number; + break; + + case QEMU_MONITOR_CPU_PROPERTY_LAST: + break; + } } return copy; diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 8811d85017..20d59b052d 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -921,16 +921,35 @@ int qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon, qemuMonitorCPUDefInfoPtr **cpus); void qemuMonitorCPUDefInfoFree(qemuMonitorCPUDefInfoPtr cpu); +typedef enum { + QEMU_MONITOR_CPU_PROPERTY_BOOLEAN, + QEMU_MONITOR_CPU_PROPERTY_STRING, + QEMU_MONITOR_CPU_PROPERTY_NUMBER, + + QEMU_MONITOR_CPU_PROPERTY_LAST +} qemuMonitorCPUPropertyType; + +VIR_ENUM_DECL(qemuMonitorCPUProperty) + +typedef struct _qemuMonitorCPUProperty qemuMonitorCPUProperty; +typedef qemuMonitorCPUProperty *qemuMonitorCPUPropertyPtr; +struct _qemuMonitorCPUProperty { + char *name; + qemuMonitorCPUPropertyType type; + union { + bool boolean; + char *string; + long long number; + } value; +}; + typedef struct _qemuMonitorCPUModelInfo qemuMonitorCPUModelInfo; typedef qemuMonitorCPUModelInfo *qemuMonitorCPUModelInfoPtr; struct _qemuMonitorCPUModelInfo { char *name; size_t nprops; - struct { - char *name; - bool supported; - } *props; + qemuMonitorCPUPropertyPtr props; }; int qemuMonitorGetCPUModelExpansion(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 69fe340bed..e3bef3eb64 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -4977,24 +4977,50 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon, return ret; } + +VIR_ENUM_IMPL(qemuMonitorCPUProperty, + QEMU_MONITOR_CPU_PROPERTY_LAST, + "boolean", "string", "number") + static int qemuMonitorJSONParseCPUModelProperty(const char *key, virJSONValue *value, void *opaque) { qemuMonitorCPUModelInfoPtr machine_model = opaque; - size_t n = machine_model->nprops; - bool supported; + qemuMonitorCPUPropertyPtr prop; - if (virJSONValueGetBoolean(value, &supported) < 0) - return 0; + prop = machine_model->props + machine_model->nprops; - if (VIR_STRDUP(machine_model->props[n].name, key) < 0) - return -1; + switch ((virJSONType) value->type) { + case VIR_JSON_TYPE_STRING: + if (VIR_STRDUP(prop->value.string, virJSONValueGetString(value)) < 0) + return -1; + prop->type = QEMU_MONITOR_CPU_PROPERTY_STRING; + break; + + case VIR_JSON_TYPE_NUMBER: + /* Ignore numbers which cannot be parsed as unsigned long long */ + if (virJSONValueGetNumberLong(value, &prop->value.number) < 0) + return 0; + prop->type = QEMU_MONITOR_CPU_PROPERTY_NUMBER; + break; - machine_model->props[n].supported = supported; + case VIR_JSON_TYPE_BOOLEAN: + virJSONValueGetBoolean(value, &prop->value.boolean); + prop->type = QEMU_MONITOR_CPU_PROPERTY_BOOLEAN; + break; + + case VIR_JSON_TYPE_OBJECT: + case VIR_JSON_TYPE_ARRAY: + case VIR_JSON_TYPE_NULL: + return 0; + } machine_model->nprops++; + if (VIR_STRDUP(prop->name, key) < 0) + return -1; + return 0; } diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml index 64da511c78..3cce40c688 100644 --- a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml @@ -223,11 +223,13 @@ + + @@ -243,6 +245,7 @@ + @@ -288,6 +291,7 @@ + @@ -298,6 +302,7 @@ + @@ -335,6 +340,7 @@ + @@ -364,6 +370,7 @@ + -- GitLab