@@ -46,6 +46,41 @@
'*default-value': 'any' } }
##
+# @ObjectPropertyValue:
+#
+# @name: the name of the property
+#
+# @type: the type of the property, as described in @ObjectPropertyInfo
+#
+# @value: the value of the property
+#
+# @error: error message if value cannot be fetched
+#
+# Since 10.0
+##
+{ 'struct': 'ObjectPropertyValue',
+ 'data': { 'name': 'str',
+ 'type': 'str',
+ '*value': 'any',
+ '*error': 'str' } }
+
+##
+# @ObjectNode:
+#
+# @name: the name of the node
+#
+# @children: child nodes
+#
+# @properties: properties of the node
+#
+# Since 10.0
+##
+{ 'struct': 'ObjectNode',
+ 'data': { 'name': 'str',
+ 'children': [ 'ObjectNode' ],
+ 'properties': [ 'ObjectPropertyValue' ] }}
+
+##
# @qom-list:
#
# This command will list any properties of a object given a path in
@@ -126,6 +161,30 @@
'allow-preconfig': true }
##
+# @qom-tree-get:
+#
+# This command returns a tree of objects and their properties,
+# rooted at the specified path.
+#
+# @path: The absolute or partial path within the object model, as
+# described in @qom-get
+#
+# Errors:
+# - If path is not valid or is ambiguous, returns an error.
+# - If a property cannot be read, returns an error message in the
+# corresponding @ObjectPropertyValue.
+#
+# Returns: A tree of @ObjectNode. Each node contains its name, list
+# of properties, and list of child nodes.
+#
+# Since 10.0
+##
+{ 'command': 'qom-tree-get',
+ 'data': { 'path': 'str' },
+ 'returns': 'ObjectNode',
+ 'allow-preconfig': true }
+
+##
# @qom-set:
#
# This command will set a property from a object model path.
@@ -69,6 +69,75 @@ ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
return props;
}
+static void qom_list_add_property_value(Object *obj, ObjectProperty *prop,
+ ObjectPropertyValueList **props)
+{
+ ObjectPropertyValue *item = g_new0(ObjectPropertyValue, 1);
+ Error *err = NULL;
+
+ QAPI_LIST_PREPEND(*props, item);
+
+ item->name = g_strdup(prop->name);
+ item->type = g_strdup(prop->type);
+ item->value = object_property_get_qobject(obj, prop->name, &err);
+
+ if (!item->value) {
+ item->error = g_strdup(error_get_pretty(err));
+ error_free(err);
+ }
+}
+
+static ObjectNode *qom_tree_get(const char *path, Error **errp)
+{
+ Object *obj;
+ ObjectProperty *prop;
+ ObjectNode *result, *child;
+ ObjectPropertyIterator iter;
+
+ obj = qom_resolve_path(path, errp);
+ if (obj == NULL) {
+ return NULL;
+ }
+
+ result = g_new0(ObjectNode, 1);
+
+ object_property_iter_init(&iter, obj);
+ while ((prop = object_property_iter_next(&iter))) {
+ if (strstart(prop->type, "child<", NULL)) {
+ g_autofree char *child_path = g_strdup_printf("%s/%s",
+ path, prop->name);
+ child = qom_tree_get(child_path, errp);
+ if (!child) {
+ qapi_free_ObjectNode(result);
+ return NULL;
+ }
+ child->name = g_strdup(prop->name);
+ QAPI_LIST_PREPEND(result->children, child);
+ } else {
+ qom_list_add_property_value(obj, prop, &result->properties);
+ }
+ }
+
+ return result;
+}
+
+ObjectNode *qmp_qom_tree_get(const char *path, Error **errp)
+{
+ ObjectNode *result = qom_tree_get(path, errp);
+
+ if (result) {
+ /* Strip the path prefix if any */
+ const char *basename = strrchr(path, '/');
+
+ if (!basename || !basename[1]) {
+ result->name = g_strdup(path);
+ } else {
+ result->name = g_strdup(basename + 1);
+ }
+ }
+ return result;
+}
+
void qmp_qom_set(const char *path, const char *property, QObject *value,
Error **errp)
{
Define the qom-tree-get QAPI command, which fetches an entire tree of properties and values with a single QAPI call. This is much faster than using qom-list plus qom-get for every node and property of the tree. See qom.json for details. Signed-off-by: Steve Sistare <steven.sistare@oracle.com> --- qapi/qom.json | 59 ++++++++++++++++++++++++++++++++++++++++++++++ qom/qom-qmp-cmds.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+)