>From 2b39fe0f380eea6a96de3589b3d148673d28c1ff Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Fri, 7 Jun 2013 18:02:21 +0800 Subject: [PATCH] full introspection support for QMP Signed-off-by: Amos Kong --- qapi-schema.json | 6 ++++++ qmp-commands.hx | 23 +++++++++++++++++++++++ qmp.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ scripts/qapi-commands.py | 2 +- scripts/qapi-types.py | 42 +++++++++++++++++++++++++++++++++++++++++- scripts/qapi-visit.py | 2 +- scripts/qapi.py | 13 ++++++++++++- 7 files changed, 130 insertions(+), 4 deletions(-) diff --git a/qapi-schema.json b/qapi-schema.json index ef1f657..128cc58 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -3618,3 +3618,9 @@ '*cpuid-input-ecx': 'int', 'cpuid-register': 'X86CPURegister32', 'features': 'int' } } + +{ 'type': 'SchemaData', + 'data': { 'type': 'str', 'name': 'str', '*data': 'str', '*returns': 'str' } } + +{ 'command': 'query-qmp-schema', 'data': { '*type': 'str', '*name': 'str' }, + 'returns': ['SchemaData'] } diff --git a/qmp-commands.hx b/qmp-commands.hx index ffd130e..fc56fba 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -2932,3 +2932,26 @@ Example: <- { "return": {} } EQMP + + { + .name = "query-qmp-schema", + .args_type = "type:s?,name:s?", + .mhandler.cmd_new = qmp_marshal_input_query_qmp_schema, + }, + + +SQMP +query-qmp-schema +---------------- + +query qmp schema information + +Example: + +-> { "execute": "query-qmp-schema", "arguments": { "name" : "query-name" }} +<- { "return": [ + "{ 'command': 'query-name', 'returns': 'NameInfo' }" + ] + } + +EQMP \ No newline at end of file diff --git a/qmp.c b/qmp.c index 4c149b3..c062f88 100644 --- a/qmp.c +++ b/qmp.c @@ -25,6 +25,7 @@ #include "sysemu/blockdev.h" #include "qom/qom-qobject.h" #include "hw/boards.h" +#include "qmp-schema.h" NameInfo *qmp_query_name(Error **errp) { @@ -486,6 +487,51 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) return arch_query_cpu_definitions(errp); } +SchemaDataList * qmp_query_qmp_schema(bool has_type, const char * type, + bool has_name, const char * name, + Error **errp) +{ + SchemaDataList *list = NULL, *last_entry, *entry; + SchemaData *info; + int i; + + for (i = 0; qmp_schema_table[i].type; i++) { + if (has_type && strcmp(type, qmp_schema_table[i].type)) { + continue; + } + if (has_name && strcmp(name, qmp_schema_table[i].name)) { + continue; + } + + info = g_malloc0(sizeof(*info)); + info->type = g_strdup(qmp_schema_table[i].type); + info->name = g_strdup(qmp_schema_table[i].name); + + if (qmp_schema_table[i].data && strlen(qmp_schema_table[i].data) > 0) { + info->has_data = true; + } + info->data = g_strdup(qmp_schema_table[i].data); + + if (qmp_schema_table[i].returns && strlen(qmp_schema_table[i].returns) > 0) { + info->has_returns = true; + } + info->returns = g_strdup(qmp_schema_table[i].returns); + + entry = malloc(sizeof(SchemaDataList *)); + entry->value = info; + entry->next = NULL; + + if (!list) { + list = entry; + } else { + last_entry->next = entry; + } + last_entry = entry; + } + + return list; +} + void qmp_add_client(const char *protocol, const char *fdname, bool has_skipauth, bool skipauth, bool has_tls, bool tls, Error **errp) diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index e06332b..d15d04f 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -437,7 +437,7 @@ except os.error, e: if e.errno != errno.EEXIST: raise -exprs = parse_schema(sys.stdin) +exprs = parse_schema(sys.stdin)[0] commands = filter(lambda expr: expr.has_key('command'), exprs) commands = filter(lambda expr: not expr.has_key('gen'), commands) diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index ddcfed9..30e7e56 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -15,6 +15,7 @@ import sys import os import getopt import errno +import re def generate_fwd_struct(name, members, builtin_type=False): if builtin_type: @@ -303,7 +304,46 @@ fdecl.write(mcgen(''' ''', guard=guardname(h_file))) -exprs = parse_schema(sys.stdin) +exprs_all = parse_schema(sys.stdin) + +schema_table = """ +/* convert qapi-schema.json to a string table */ + +struct qmp_schem { +const char *type; +const char *name; +const char *data; +const char *returns; +} qmp_schema_table[] = { +""" + +for i in exprs_all[1]: + print i + + data = returns = "" + type = i.keys()[0] + name = i[type] + for k in i.keys(): + if isinstance(i[k], OrderedDict): + ret = {} + for key in i[k]: + ret[key] = i[k][key] + i[k] = ret + + if i.has_key('data'): + data = i['data'] + if i.has_key('returns'): + returns = i['returns'] + + schema_table += '{"%s", "%s", "%s", "%s"},\n' % (type, name, data, returns) + +schema_table += '{NULL, NULL, NULL } };\n' + +f = open("qmp-schema.h", "w") +f.write(schema_table) +f.close() + +exprs = exprs_all[0] exprs = filter(lambda expr: not expr.has_key('gen'), exprs) fdecl.write(guardstart("QAPI_TYPES_BUILTIN_STRUCT_DECL")) diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index 6cac05a..70f80eb 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -334,7 +334,7 @@ fdecl.write(mcgen(''' ''', prefix=prefix, guard=guardname(h_file))) -exprs = parse_schema(sys.stdin) +exprs = parse_schema(sys.stdin)[0] # to avoid header dependency hell, we always generate declarations # for built-in types in our header files and simply guard them diff --git a/scripts/qapi.py b/scripts/qapi.py index 02ad668..076b5dc 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -80,6 +80,7 @@ def evaluate(string): def parse_schema(fp): exprs = [] + raw_exprs = [] expr = '' expr_eval = None @@ -91,6 +92,11 @@ def parse_schema(fp): expr += line elif expr: expr_eval = evaluate(expr) + + for name in ['command', 'type', 'enum', 'union']: + if expr_eval.has_key(name): + raw_exprs.append(expr_eval) + if expr_eval.has_key('enum'): add_enum(expr_eval['enum']) elif expr_eval.has_key('union'): @@ -102,13 +108,18 @@ def parse_schema(fp): if expr: expr_eval = evaluate(expr) + + for name in ['command', 'type', 'enum', 'union']: + if expr_eval.has_key(name): + raw_exprs.append(expr_eval) + if expr_eval.has_key('enum'): add_enum(expr_eval['enum']) elif expr_eval.has_key('union'): add_enum('%sKind' % expr_eval['union']) exprs.append(expr_eval) - return exprs + return exprs, raw_exprs def parse_args(typeinfo): for member in typeinfo: -- 1.8.1.4