Add a new qemuMonitorGetObjectProperty() method to support invocation
of the 'qom-get' JSON monitor command with a provided path, property, and
expected data type return. The qemuMonitorObjectProperty is similar to
virTypedParameter; however, a future patch will extend it a bit to include
a void pointer to balloon driver statistic data.
The provided test will execute a qom-get on "/machine/i440fx" which will
return a property "realized".
---
src/qemu/qemu_monitor.c | 23 ++++++++++++
src/qemu/qemu_monitor.h | 33 +++++++++++++++++
src/qemu/qemu_monitor_json.c | 86 ++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 6 ++++
tests/qemumonitorjsontest.c | 48 +++++++++++++++++++++++++
5 files changed, 196 insertions(+)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index f175250..6737a63 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3468,6 +3468,29 @@ void qemuMonitorListPathFree(qemuMonitorListPathPtr paths)
}
+int qemuMonitorGetObjectProperty(qemuMonitorPtr mon,
+ const char *path,
+ const char *property,
+ qemuMonitorObjectPropertyPtr prop)
+{
+ VIR_DEBUG("mon=%p path=%s property=%s prop=%p type=%d",
+ mon, path, property, prop, prop->type);
+ if (!mon) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("monitor must not be NULL"));
+ return -1;
+ }
+
+ if (!mon->json) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("JSON monitor is required"));
+ return -1;
+ }
+
+ return qemuMonitorJSONGetObjectProperty(mon, path, property, prop);
+}
+
+
int qemuMonitorGetObjectProps(qemuMonitorPtr mon,
const char *type,
char ***props)
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 2e92f8c..cc22123 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -694,6 +694,39 @@ int qemuMonitorGetObjectListPaths(qemuMonitorPtr mon,
void qemuMonitorListPathFree(qemuMonitorListPathPtr paths);
+/* Flags for the 'type' field in _qemuMonitorObjectProperty */
+typedef enum {
+ QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN=1,
+ QEMU_MONITOR_OBJECT_PROPERTY_INT,
+ QEMU_MONITOR_OBJECT_PROPERTY_LONG,
+ QEMU_MONITOR_OBJECT_PROPERTY_UINT,
+ QEMU_MONITOR_OBJECT_PROPERTY_ULONG,
+ QEMU_MONITOR_OBJECT_PROPERTY_DOUBLE,
+ QEMU_MONITOR_OBJECT_PROPERTY_STRING,
+
+ QEMU_MONITOR_OBJECT_PROPERTY_LAST
+} qemuMonitorObjectPropertyType;
+
+typedef struct _qemuMonitorObjectProperty qemuMonitorObjectProperty;
+typedef qemuMonitorObjectProperty *qemuMonitorObjectPropertyPtr;
+struct _qemuMonitorObjectProperty {
+ int type; /* qemuMonitorObjectPropertyType */
+ union {
+ bool b;
+ int i;
+ long long l;
+ unsigned int ui;
+ unsigned long long ul;
+ double d;
+ char *str;
+ } val;
+};
+
+int qemuMonitorGetObjectProperty(qemuMonitorPtr mon,
+ const char *path,
+ const char *property,
+ qemuMonitorObjectPropertyPtr prop);
+
int qemuMonitorGetObjectProps(qemuMonitorPtr mon,
const char *type,
char ***props);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 7d0cc85..a725903 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -4626,6 +4626,92 @@ cleanup:
return ret;
}
+
+int qemuMonitorJSONGetObjectProperty(qemuMonitorPtr mon,
+ const char *path,
+ const char *property,
+ qemuMonitorObjectPropertyPtr prop)
+{
+ int ret;
+ virJSONValuePtr cmd;
+ virJSONValuePtr reply = NULL;
+ virJSONValuePtr data;
+ const char *tmp;
+
+ if (!(cmd = qemuMonitorJSONMakeCommand("qom-get",
+ "s:path", path,
+ "s:property", property,
+ NULL)))
+ return -1;
+
+ ret = qemuMonitorJSONCommand(mon, cmd, &reply);
+
+ if (ret == 0)
+ ret = qemuMonitorJSONCheckError(cmd, reply);
+
+ if (ret < 0)
+ goto cleanup;
+
+ ret = -1;
+
+ if (!(data = virJSONValueObjectGet(reply, "return"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("qom-get reply was missing return data"));
+ goto cleanup;
+ }
+
+ switch (prop->type) {
+ /* Simple cases of boolean, int, long, uint, ulong, double, and string
+ * will receive return value as part of {"return": xxx} statement
+ */
+ case QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN:
+ ret = virJSONValueGetBoolean(data, &prop->val.b);
+ break;
+ case QEMU_MONITOR_OBJECT_PROPERTY_INT:
+ ret = virJSONValueGetNumberInt(data, &prop->val.i);
+ break;
+ case QEMU_MONITOR_OBJECT_PROPERTY_LONG:
+ ret = virJSONValueGetNumberLong(data, &prop->val.l);
+ break;
+ case QEMU_MONITOR_OBJECT_PROPERTY_UINT:
+ ret = virJSONValueGetNumberUint(data, &prop->val.ui);
+ break;
+ case QEMU_MONITOR_OBJECT_PROPERTY_ULONG:
+ ret = virJSONValueGetNumberUlong(data, &prop->val.ul);
+ break;
+ case QEMU_MONITOR_OBJECT_PROPERTY_DOUBLE:
+ ret = virJSONValueGetNumberDouble(data, &prop->val.d);
+ break;
+ case QEMU_MONITOR_OBJECT_PROPERTY_STRING:
+ tmp = virJSONValueGetString(data);
+ if (tmp && VIR_STRDUP(prop->val.str, tmp) < 0)
+ goto cleanup;
+ if (tmp)
+ ret = 0;
+ break;
+ case QEMU_MONITOR_OBJECT_PROPERTY_LAST:
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("qom-get invalid object property type %d"),
+ prop->type);
+ goto cleanup;
+ }
+
+ if (ret == -1) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("qom-get reply was missing return data"));
+ goto cleanup;
+ }
+
+ ret = 0;
+cleanup:
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+
+ return ret;
+}
+
+
int qemuMonitorJSONGetObjectProps(qemuMonitorPtr mon,
const char *type,
char ***props)
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 20a2364..63807df 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -338,6 +338,12 @@ int qemuMonitorJSONGetObjectListPaths(qemuMonitorPtr mon,
qemuMonitorListPathPtr **paths)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+int qemuMonitorJSONGetObjectProperty(qemuMonitorPtr mon,
+ const char *path,
+ const char *property,
+ qemuMonitorObjectPropertyPtr prop)
+ ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
+
int qemuMonitorJSONGetObjectProps(qemuMonitorPtr mon,
const char *type,
char ***props)
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
index ab8a73d..4544676 100644
--- a/tests/qemumonitorjsontest.c
+++ b/tests/qemumonitorjsontest.c
@@ -671,6 +671,53 @@ cleanup:
}
+/*
+ * This test will use a path to /machine/i440fx which should exist in order
+ * to ensure that the qom-get property fetch works properly. The following
+ * is the execution and expected return:
+ *
+ *
+ * { "execute": "qom-get","arguments": \
+ * { "path": "/machine/i440fx","property":
"realized"}}
+ * {"return": true}
+ */
+static int
+testQemuMonitorJSONGetObjectProperty(const void *data)
+{
+ const virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
+ qemuMonitorTestPtr test = qemuMonitorTestNew(true, xmlopt);
+ int ret = -1;
+ qemuMonitorObjectProperty prop;
+
+ if (!test)
+ return -1;
+
+ if (qemuMonitorTestAddItem(test, "qom-get",
+ "{ \"return\": true }") < 0)
+ goto cleanup;
+
+ /* Present with path and property */
+ memset(&prop, 0, sizeof(qemuMonitorObjectProperty));
+ prop.type = QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN;
+ if (qemuMonitorGetObjectProperty(qemuMonitorTestGetMonitor(test),
+ "/machine/i440fx",
+ "realized",
+ &prop) < 0)
+ goto cleanup;
+
+ if (!prop.val.b) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ "expected true, but false returned");
+ goto cleanup;
+ }
+
+ ret = 0;
+cleanup:
+ qemuMonitorTestFree(test);
+ return ret;
+}
+
+
static int
mymain(void)
{
@@ -700,6 +747,7 @@ mymain(void)
DO_TEST(GetTPMModels);
DO_TEST(GetCommandLineOptionParameters);
DO_TEST(GetListPaths);
+ DO_TEST(GetObjectProperty);
virObjectUnref(xmlopt);
--
1.8.1.4