diff options
author | Markus Armbruster <armbru@redhat.com> | 2021-03-18 16:55:15 +0100 |
---|---|---|
committer | Markus Armbruster <armbru@redhat.com> | 2021-03-19 16:05:11 +0100 |
commit | 2df68d777c7abfb80a260021b3db3283f37843a1 (patch) | |
tree | 54d28f0cae1d53c7ebbdd6b9058f121b9f11e155 /monitor | |
parent | 624fa80c8c199229af7ff42eb20b5b2ab851e4ee (diff) |
qapi: Implement deprecated-output=hide for QMP introspection
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 <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20210318155519.1224118-8-armbru@redhat.com>
Diffstat (limited to 'monitor')
-rw-r--r-- | monitor/qmp-cmds-control.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/monitor/qmp-cmds-control.c b/monitor/qmp-cmds-control.c index d152fd7e59..6e581713a3 100644 --- a/monitor/qmp-cmds-control.c +++ b/monitor/qmp-cmds-control.c @@ -134,6 +134,74 @@ CommandInfoList *qmp_query_commands(Error **errp) return list; } +static void *split_off_generic_list(void *list, + bool (*splitp)(void *elt), + void **part) +{ + 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); @@ -147,5 +215,8 @@ SchemaInfoList *qmp_query_qmp_schema(Error **errp) qobject_unref(obj); visit_free(v); + if (compat_policy.deprecated_output == COMPAT_POLICY_OUTPUT_HIDE) { + return zap_deprecated(schema); + } return schema; } |