Add a new qemuMonitorGetObjectListPaths() method to support invocation
of the 'qom-list' JSON monitor command with a provided path.
The returned list of paired data fields of "name" and "type" that can
be used to peruse QOM configuration data and eventually utilize for the
balloon statistics.
The test does a "{"execute":"qom-list", "arguments": {
"path": "/"}}" which
returns "{"return": [{"name": "machine",
"type": "child<container>"},
{"name": "type", "type": "string"}]}"
resulting in a return of an array
of 2 elements with [0].name="machine",
[0].type="child<container>". The [1]
entry appears to be a header that could be used some day via a command such
as "virsh qemuobject --list" to format output.
---
src/qemu/qemu_monitor.c | 33 ++++++++++++++++
src/qemu/qemu_monitor.h | 15 +++++++
src/qemu/qemu_monitor_json.c | 93 ++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 6 +++
tests/qemumonitorjsontest.c | 77 ++++++++++++++++++++++++++++++++++++
5 files changed, 224 insertions(+)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 091e239..f175250 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3435,6 +3435,39 @@ int qemuMonitorGetObjectTypes(qemuMonitorPtr mon,
}
+int qemuMonitorGetObjectListPaths(qemuMonitorPtr mon,
+ const char *path,
+ qemuMonitorListPathPtr **paths)
+{
+ VIR_DEBUG("mon=%p paths=%p",
+ mon, paths);
+
+ 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 qemuMonitorJSONGetObjectListPaths(mon, path, paths);
+}
+
+
+void qemuMonitorListPathFree(qemuMonitorListPathPtr paths)
+{
+ if (!paths)
+ return;
+ VIR_FREE(paths->name);
+ VIR_FREE(paths->type);
+ VIR_FREE(paths);
+}
+
+
int qemuMonitorGetObjectProps(qemuMonitorPtr mon,
const char *type,
char ***props)
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 86ef635..2e92f8c 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -679,6 +679,21 @@ int qemuMonitorGetKVMState(qemuMonitorPtr mon,
int qemuMonitorGetObjectTypes(qemuMonitorPtr mon,
char ***types);
+
+typedef struct _qemuMonitorListPath qemuMonitorListPath;
+typedef qemuMonitorListPath *qemuMonitorListPathPtr;
+
+struct _qemuMonitorListPath {
+ char *name;
+ char *type;
+};
+
+int qemuMonitorGetObjectListPaths(qemuMonitorPtr mon,
+ const char *path,
+ qemuMonitorListPathPtr **paths);
+
+void qemuMonitorListPathFree(qemuMonitorListPathPtr paths);
+
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 c0d7960..7d0cc85 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -4533,6 +4533,99 @@ cleanup:
}
+int qemuMonitorJSONGetObjectListPaths(qemuMonitorPtr mon,
+ const char *path,
+ qemuMonitorListPathPtr **paths)
+{
+ int ret;
+ virJSONValuePtr cmd;
+ virJSONValuePtr reply = NULL;
+ virJSONValuePtr data;
+ qemuMonitorListPathPtr *pathlist = NULL;
+ int n = 0;
+ size_t i;
+
+ *paths = NULL;
+
+ if (!(cmd = qemuMonitorJSONMakeCommand("qom-list",
+ "s:path", path,
+ 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-list reply was missing return data"));
+ goto cleanup;
+ }
+
+ if ((n = virJSONValueArraySize(data)) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("qom-list reply data was not an array"));
+ goto cleanup;
+ }
+
+ /* null-terminated list */
+ if (VIR_ALLOC_N(pathlist, n + 1) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ for (i = 0; i < n; i++) {
+ virJSONValuePtr child = virJSONValueArrayGet(data, i);
+ const char *tmp;
+ qemuMonitorListPathPtr info;
+
+ if (VIR_ALLOC(info) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ pathlist[i] = info;
+
+ if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("qom-list reply data was missing
'name'"));
+ goto cleanup;
+ }
+
+ if (VIR_STRDUP(info->name, tmp) < 0)
+ goto cleanup;
+
+ if (virJSONValueObjectHasKey(child, "type")) {
+ if (!(tmp = virJSONValueObjectGetString(child, "type"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("qom-list reply has malformed 'type'
data"));
+ goto cleanup;
+ }
+ if (VIR_STRDUP(info->type, tmp) < 0)
+ goto cleanup;
+ }
+ }
+
+ ret = n;
+ *paths = pathlist;
+
+cleanup:
+ if (ret < 0 && pathlist) {
+ for (i = 0; i < n; i++)
+ qemuMonitorListPathFree(pathlist[i]);
+ VIR_FREE(pathlist);
+ }
+ 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 d79b86b..20a2364 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -332,6 +332,12 @@ int qemuMonitorJSONGetKVMState(qemuMonitorPtr mon,
int qemuMonitorJSONGetObjectTypes(qemuMonitorPtr mon,
char ***types)
ATTRIBUTE_NONNULL(2);
+
+int qemuMonitorJSONGetObjectListPaths(qemuMonitorPtr mon,
+ const char *path,
+ qemuMonitorListPathPtr **paths)
+ ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+
int qemuMonitorJSONGetObjectProps(qemuMonitorPtr mon,
const char *type,
char ***props)
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
index acc94ca..ab8a73d 100644
--- a/tests/qemumonitorjsontest.c
+++ b/tests/qemumonitorjsontest.c
@@ -595,6 +595,82 @@ cleanup:
}
+/*
+ * This test will request to return a list of paths for "/". It should be
+ * a simple list of 1 real element that being the "machine". The following
+ * is the execution and expected return:
+ *
+ * {"execute":"qom-list", "arguments": { "path":
"/"}}"
+ * {"return": [{"name": "machine", "type":
"child<container>"}, \
+ * {"name": "type", "type":
"string"}]}
+ */
+static int
+testQemuMonitorJSONGetListPaths(const void *data)
+{
+ const virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
+ qemuMonitorTestPtr test = qemuMonitorTestNew(true, xmlopt);
+ int ret = -1;
+ qemuMonitorListPathPtr *paths;
+ int npaths = 0;
+ int i;
+
+ if (!test)
+ return -1;
+
+ if (qemuMonitorTestAddItem(test, "qom-list",
+ "{ "
+ " \"return\": [ "
+ " {\"name\": \"machine\",
"
+ " \"type\":
\"child<container>\"}, "
+ " {\"name\": \"type\", "
+ " \"type\": \"string\"} "
+ " ]"
+ "}") < 0)
+ goto cleanup;
+
+ /* present with path */
+ if ((npaths = qemuMonitorGetObjectListPaths(qemuMonitorTestGetMonitor(test),
+ "/",
+ &paths)) < 0)
+ goto cleanup;
+
+ if (npaths != 2) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "npaths was %d, expected 1", npaths);
+ goto cleanup;
+ }
+
+#define CHECK(i, wantname, wanttype) \
+ do { \
+ if (STRNEQ(paths[i]->name, (wantname))) { \
+ virReportError(VIR_ERR_INTERNAL_ERROR, \
+ "name was %s, expected %s", \
+ paths[i]->name, (wantname)); \
+ goto cleanup; \
+ } \
+ if (STRNEQ_NULLABLE(paths[i]->type, (wanttype))) { \
+ virReportError(VIR_ERR_INTERNAL_ERROR, \
+ "type was %s, expected %s", \
+ NULLSTR(paths[i]->type), (wanttype)); \
+ goto cleanup; \
+ } \
+ } while (0)
+
+ CHECK(0, "machine", "child<container>");
+
+#undef CHECK
+
+ ret = 0;
+
+cleanup:
+ qemuMonitorTestFree(test);
+ for (i = 0; i < npaths; i++)
+ qemuMonitorListPathFree(paths[i]);
+ VIR_FREE(paths);
+ return ret;
+}
+
+
static int
mymain(void)
{
@@ -623,6 +699,7 @@ mymain(void)
DO_TEST(GetCommands);
DO_TEST(GetTPMModels);
DO_TEST(GetCommandLineOptionParameters);
+ DO_TEST(GetListPaths);
virObjectUnref(xmlopt);
--
1.8.1.4