[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH RFC v5 30/32] qapi: New QMP command query-qmp-sc
From: |
Markus Armbruster |
Subject: |
Re: [Qemu-devel] [PATCH RFC v5 30/32] qapi: New QMP command query-qmp-schema for QMP introspection |
Date: |
Fri, 11 Sep 2015 09:02:15 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux) |
Michael Roth <address@hidden> writes:
> Quoting Markus Armbruster (2015-09-07 05:16:41)
>> qapi/introspect.json defines the introspection schema. It's designed
>> for QMP introspection, but should do for similar uses, such as QGA.
>>
>> The introspection schema does not reflect all the rules and
>> restrictions that apply to QAPI schemata. A valid QAPI schema has an
>> introspection value conforming to the introspection schema, but the
>> converse is not true.
>>
>> Introspection lowers away a number of schema details, and makes
>> implicit things explicit:
>>
>> * The built-in types are declared with their JSON type.
>>
>> TODO Should we map all the integer types to just int?
>>
>> * Implicit type definitions are made explicit, and given
>> auto-generated names:
>>
>> - Array types, named by appending "List" to the name of their
>> element type, like in generated C.
>>
>> - The enumeration types implicitly defined by simple union types,
>> named by appending "Kind" to the name of their simple union type,
>> like in generated C.
>>
>> - Types that don't occur in generated C. Their names start with ':'
>> so they don't clash with the user's names.
>>
>> * All type references are by name.
>>
>> * The struct and union types are generalized into an object type.
>>
>> * Base types are flattened.
>>
>> * Commands take a single argument and return a single result.
>>
>> Dictionary argument or list result is an implicit type definition.
>>
>> The empty object type is used when a command takes no arguments or
>> produces no results.
>>
>> The argument is always of object type, but the introspection schema
>> doesn't reflect that.
>>
>> The 'gen': false directive is omitted as implementation detail.
>>
>> The 'success-response' directive is omitted as well for now, even
>> though it's not an implementation detail, because it's not used by
>> QMP.
>>
>> * Events carry a single data value.
>>
>> Implicit type definition and empty object type use, just like for
>> commands.
>>
>> The value is of object type, but the introspection schema doesn't
>> reflect that.
>>
>> * Types not used by commands or events are omitted.
>>
>> Indirect use counts as use.
>>
>> * Optional members have a default, which can only be null right now
>>
>> Instead of a mandatory "optional" flag, we have an optional default.
>> No default means mandatory, default null means optional without
>> default value. Non-null is available for optional with default
>> (possible future extension).
>>
>> * Clients should *not* look up types by name, because type names are
>> not ABI. Look up the command or event you're interested in, then
>> follow the references.
>>
>> TODO Should we hide the type names to eliminate the temptation?
>>
>> New generator scripts/qapi-introspect.py computes an introspection
>> value for its input, and generates a C variable holding it.
>>
>> It can generate awfully long lines. Marked TODO.
>
> Would be good if we could get this is for initial merge to help
> with debugging if anything pops up.
Unlikely, to be honest. Patches depending on this series have been
piling up. I'd be okay with delaying follow-up QAPI work some more, but
not work on other subsystems, especially not user-visible goodies.
Work-arounds:
* Take the C string from qmp-introspect.c, unquote it to get actual
string contents, feed it to your favourite JSON pretty printer. I've
used Python's pprint.
* Run query-qmp-schema, feed the result to your favourite JSON pretty
printer.
* Likewise, using the QMP monitor's integrated pretty printer, e.g.
with --qmp-pretty.
>> A new test-qmp-input-visitor test case feeds its result for both
>> tests/qapi-schema/qapi-schema-test.json and qapi-schema.json to a
>> QmpInputVisitor to verify it actually conforms to the schema.
>>
>> New QMP command query-qmp-schema takes its return value from that
>> variable. Its reply is some 85KiBytes for me right now.
>>
>> If this turns out to be too much, we have a couple of options:
>>
>> * We can use shorter names in the JSON. Not the QMP style.
>>
>> * Optionally return the sub-schema for commands and events given as
>> arguments.
>>
>> Right now qmp_query_schema() sends the string literal computed by
>> qmp-introspect.py. To compute sub-schema at run time, we'd have to
>> duplicate parts of qapi-introspect.py in C. Unattractive.
>>
>> * Let clients cache the output of query-qmp-schema.
>>
>> It changes only on QEMU upgrades, i.e. rarely. Provide a command
>> query-qmp-schema-hash. Clients can have a cache indexed by hash,
>> and re-query the schema only when they don't have it cached. Even
>> simpler: put the hash in the QMP greeting.
>
> Would probably be easier for management to build up their own structure
> for querying caps, so I think a computed hash seems best. But I don't
> think either is something that couldn't be added later if need be.
I also think a hash is the way to go, and I'd like to provide one early,
but I don't want to delay this series for it.
[...]
>> diff --git a/monitor.c b/monitor.c
>> index e083716..ddf6cb5 100644
>> --- a/monitor.c
>> +++ b/monitor.c
>> @@ -74,6 +74,7 @@
>> #include "block/qapi.h"
>> #include "qapi/qmp-event.h"
>> #include "qapi-event.h"
>> +#include "qmp-introspect.h"
>> #include "sysemu/block-backend.h"
>>
>> /* for hmp_info_irq/pic */
>> @@ -928,6 +929,20 @@ 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-qmp-input-visitor.c, just to make sure
>> + * qapi-introspect.py's output actually conforms to the schema.
>> + */
>> +static void qmp_query_schema(QDict *qdict, QObject **ret_data, Error **errp)
>> +{
>> + *ret_data = qobject_from_json(qmp_schema_json);
>> +}
>
> What if we still did 'gen': false, manually ran it through input/output
> visitors, but then cached the result? I think the unit test approach
> is reasonable, but currently we only test the input visitor, whereas
> QmpOutputVisitor would come into play for the wire response if we
> ever moved to using a C-based schema visitor (for querying individual
> fields for instance)
Could be explored in a follow-up patch.
>> +
>> /* set the current CPU defined by the user */
>> int monitor_set_cpu(int cpu_index)
>> {
>> diff --git a/qapi-schema.json b/qapi-schema.json
>> index d874c11..8c77220 100644
>> --- a/qapi-schema.json
>> +++ b/qapi-schema.json
>> @@ -14,6 +14,9 @@
>> # Tracing commands
>> { 'include': 'qapi/trace.json' }
>>
>> +# QAPI introspection
>> +{ 'include': 'qapi/introspect.json' }
>> +
>> ##
>> # @LostTickPolicy:
>> #
>> diff --git a/qapi/introspect.json b/qapi/introspect.json
>> new file mode 100644
>> index 0000000..5b4713b
>> --- /dev/null
>> +++ b/qapi/introspect.json
>> @@ -0,0 +1,276 @@
>> +# -*- Mode: Python -*-
>> +#
>> +# QAPI/QMP introspection
>> +#
>> +# Copyright (C) 2015 Red Hat, Inc.
>> +#
>> +# Authors:
>> +# Markus Armbruster <address@hidden>
>> +#
>> +# This work is licensed under the terms of the GNU GPL, version 2 or later.
>> +# See the COPYING file in the top-level directory.
>> +
>> +##
>> +# @query-qmp-schema
>> +#
>> +# Command query-qmp-schema exposes the QMP wire ABI as an array of
>> +# SchemaInfo. This lets QMP clients figure out what commands and
>> +# events are available in this QEMU, and their parameters and results.
>> +#
>> +# However, the SchemaInfo can't reflect all the rules and restrictions
>> +# that apply to QMP. It's interface introspection (figuring out
>> +# what's there), not interface specification. The specification is in
>> +# the QAPI schema.
>
> Thanks, the clarification here and in the documentation addresses my
> concerns.
Thanks for making me improve the docs :)
>> +#
>> +# Returns: array of @SchemaInfo, where each element describes an
>> +# entity in the ABI: command, event, type, ...
>> +#
>> +# Note: the QAPI schema is also used to help define *internal*
>> +# interfaces, by defining QAPI types. These are not part of the QMP
>> +# wire ABI, and therefore not returned by this command.
>> +#
>> +# Since: 2.5
>> +##
>> +{ 'command': 'query-qmp-schema',
>> + 'returns': [ 'SchemaInfo' ],
>> + 'gen': false } # just to simplify qmp_query_json()
>> +
>> +##
>> +# @SchemaMetaType
>> +#
>> +# This is a @SchemaInfo's meta type, i.e. the kind of entity it
>> +# describes.
>> +#
>> +# @builtin: a predefined type such as 'int' or 'bool'.
>> +#
>> +# @enum: an enumeration type
>> +#
>> +# @array: an array type
>> +#
>> +# @object: an object type (struct or union)
>> +#
>> +# @alternate: an alternate type
>> +#
>> +# @command: a QMP command
>> +#
>> +# @event: a QMP event
>> +#
>> +# Since: 2.5
>> +##
>> +{ 'enum': 'SchemaMetaType',
>> + 'data': [ 'builtin', 'enum', 'array', 'object', 'alternate',
>> + 'command', 'event' ] }
>> +
>
>
> Small nit, don't we usually put type definitions before the
> commands that reference them?
Yes, we do, but I've never been a fan of slavish define before use. It
tends to produce documents I need to read partly backwards. I prefer to
order things in a way that optimizes readability in strict forward
direction.
We had generator bugs around forward references, but I fixed them, and
added test cases (commit 8c3f8e7).
- [Qemu-devel] [PATCH RFC v5 21/32] qapi-commands: Rearrange code, (continued)
Re: [Qemu-devel] [PATCH RFC v5 00/32] qapi: QMP introspection, Markus Armbruster, 2015/09/11
Re: [Qemu-devel] [PATCH RFC v5 00/32] qapi: QMP introspection, Markus Armbruster, 2015/09/15