This policy suppresses deprecated bits in output, and thus permits "testing the future". Implement it for QMP command query-qmp-schema: suppress information on deprecated commands, events and object type members, i.e. anything that has the special feature flag "deprecated".
Signed-off-by: Markus Armbruster <arm...@redhat.com> --- qapi/introspect.json | 2 +- monitor/monitor-internal.h | 3 - monitor/misc.c | 2 - monitor/qmp-cmds-control.c | 100 +++++++++++++++++++++++---- storage-daemon/qemu-storage-daemon.c | 2 - 5 files changed, 89 insertions(+), 20 deletions(-) diff --git a/qapi/introspect.json b/qapi/introspect.json index 944bb87a20..39bd303778 100644 --- a/qapi/introspect.json +++ b/qapi/introspect.json @@ -49,7 +49,7 @@ ## { 'command': 'query-qmp-schema', 'returns': [ 'SchemaInfo' ], - 'gen': false } # just to simplify qmp_query_json() + 'allow-preconfig': true } ## # @SchemaMetaType: diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h index b39e03b744..8833afaa65 100644 --- a/monitor/monitor-internal.h +++ b/monitor/monitor-internal.h @@ -180,7 +180,4 @@ void help_cmd(Monitor *mon, const char *name); void handle_hmp_command(MonitorHMP *mon, const char *cmdline); int hmp_compare_cmd(const char *name, const char *list); -void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data, - Error **errp); - #endif diff --git a/monitor/misc.c b/monitor/misc.c index e847b58a8c..3fd335e737 100644 --- a/monitor/misc.c +++ b/monitor/misc.c @@ -242,8 +242,6 @@ static void monitor_init_qmp_commands(void) qmp_init_marshal(&qmp_commands); - qmp_register_command(&qmp_commands, "query-qmp-schema", - qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG); qmp_register_command(&qmp_commands, "device_add", qmp_device_add, QCO_NO_OPTIONS); qmp_register_command(&qmp_commands, "object-add", qmp_object_add, diff --git a/monitor/qmp-cmds-control.c b/monitor/qmp-cmds-control.c index 8f04cfa6e6..5b07c7e765 100644 --- a/monitor/qmp-cmds-control.c +++ b/monitor/qmp-cmds-control.c @@ -26,10 +26,14 @@ #include "monitor-internal.h" #include "qemu-version.h" +#include "qapi/compat-policy.h" #include "qapi/error.h" #include "qapi/qapi-commands-control.h" +#include "qapi/qapi-commands-introspect.h" #include "qapi/qapi-emit-events.h" #include "qapi/qapi-introspect.h" +#include "qapi/qapi-visit-introspect.h" +#include "qapi/qobject-input-visitor.h" /* * Accept QMP capabilities in @list for @mon. @@ -153,17 +157,89 @@ EventInfoList *qmp_query_events(Error **errp) return ev_list; } -/* - * Minor hack: generated marshalling suppressed for this command - * ('gen': false in the schema) so we can parse the JSON string - * directly into QObject instead of first parsing it with - * visit_type_SchemaInfoList() into a SchemaInfoList, then marshal it - * to QObject with generated output marshallers, every time. Instead, - * we do it in test-qobject-input-visitor.c, just to make sure - * qapi-gen.py's output actually conforms to the schema. - */ -void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data, - Error **errp) +static void *split_off_generic_list(void *list, + bool (*splitp)(void *elt), + void **part) { - *ret_data = qobject_from_qlit(&qmp_schema_qlit); + GenericList *keep = NULL, **keep_tailp = &keep; + GenericList *split = NULL, **split_tailp = &split; + GenericList *tail; + + for (tail = list; tail; tail = tail->next) { + if (splitp(tail)) { + *split_tailp = tail; + split_tailp = &tail->next; + } else { + *keep_tailp = tail; + keep_tailp = &tail->next; + } + } + + *keep_tailp = *split_tailp = NULL; + *part = split; + return keep; +} + +static bool is_in(const char *s, strList *list) +{ + strList *tail; + + for (tail = list; tail; tail = tail->next) { + if (!strcmp(tail->value, s)) { + return true; + } + } + return false; +} + +static bool is_entity_deprecated(void *link) +{ + return is_in("deprecated", ((SchemaInfoList *)link)->value->features); +} + +static bool is_member_deprecated(void *link) +{ + return is_in("deprecated", + ((SchemaInfoObjectMemberList *)link)->value->features); +} + +static SchemaInfoList *zap_deprecated(SchemaInfoList *schema) +{ + void *to_zap; + SchemaInfoList *tail; + SchemaInfo *ent; + + schema = split_off_generic_list(schema, is_entity_deprecated, &to_zap); + qapi_free_SchemaInfoList(to_zap); + + for (tail = schema; tail; tail = tail->next) { + ent = tail->value; + if (ent->meta_type == SCHEMA_META_TYPE_OBJECT) { + ent->u.object.members + = split_off_generic_list(ent->u.object.members, + is_member_deprecated, &to_zap); + qapi_free_SchemaInfoObjectMemberList(to_zap); + } + } + + return schema; +} + +SchemaInfoList *qmp_query_qmp_schema(Error **errp) +{ + QObject *obj = qobject_from_qlit(&qmp_schema_qlit); + Visitor *v = qobject_input_visitor_new(obj); + SchemaInfoList *schema = NULL; + + /* test_visitor_in_qmp_introspect() ensures this can't fail */ + visit_type_SchemaInfoList(v, NULL, &schema, &error_abort); + g_assert(schema); + + qobject_unref(obj); + visit_free(v); + + if (compat_policy.deprecated_output == COMPAT_POLICY_OUTPUT_HIDE) { + return zap_deprecated(schema); + } + return schema; } diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c index 7e9b0e0d3f..9490099036 100644 --- a/storage-daemon/qemu-storage-daemon.c +++ b/storage-daemon/qemu-storage-daemon.c @@ -142,8 +142,6 @@ static QemuOptsList qemu_object_opts = { static void init_qmp_commands(void) { qmp_init_marshal(&qmp_commands); - qmp_register_command(&qmp_commands, "query-qmp-schema", - qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG); QTAILQ_INIT(&qmp_cap_negotiation_commands); qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities", -- 2.26.2