From cd159d0954f65df61864a85e355acdf7ae7fe0f9 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 12 Feb 2014 11:05:13 +0800 Subject: QMP: Allow dot separated dict path arguments in qmp-shell As another convenience to allow using commands that expect a dict as argument, this patch adds support for foo.bar=value syntax, similar to command line argument style: (QEMU) blockdev-add options.driver=file options.id=drive1 options.filename=... Signed-off-by: Fam Zheng Reviewed-by: Eric Blake Reviewed-by: Stefan Hajnoczi Signed-off-by: Luiz Capitulino --- scripts/qmp/qmp-shell | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell index d374b35..e0e848b 100755 --- a/scripts/qmp/qmp-shell +++ b/scripts/qmp/qmp-shell @@ -112,13 +112,29 @@ class QMPShell(qmp.QEMUMonitorProtocol): value = json.loads(opt[1]) else: value = opt[1] - qmpcmd['arguments'][opt[0]] = value + optpath = opt[0].split('.') + parent = qmpcmd['arguments'] + curpath = [] + for p in optpath[:-1]: + curpath.append(p) + d = parent.get(p, {}) + if type(d) is not dict: + raise QMPShellError('Cannot use "%s" as both leaf and non-leaf key' % '.'.join(curpath)) + parent[p] = d + parent = d + if optpath[-1] in parent: + if type(parent[optpath[-1]]) is dict: + raise QMPShellError('Cannot use "%s" as both leaf and non-leaf key' % '.'.join(curpath)) + else: + raise QMPShellError('Cannot set "%s" multiple times' % opt[0]) + parent[optpath[-1]] = value return qmpcmd def _execute_cmd(self, cmdline): try: qmpcmd = self.__build_cmd(cmdline) - except: + except Exception, e: + print 'Error while parsing command line: %s' % e print 'command format: ', print '[arg-name1=arg1] ... [arg-nameN=argN]' return True -- cgit v1.1 From 4864512389b06389501e60d965edb8defb66a0fc Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Mon, 24 Feb 2014 13:45:01 +0800 Subject: qmp: Check for returned data from __json_read in get_events When QEMU process aborts and socket is closed, qmp client will not detect it. When this happens, some qemu-iotests scripts will enter an endless loop waiting for qmp events. It's better we raise an exception in qmp.py to catch this and make the test script stop. Signed-off-by: Fam Zheng Reviewed-by: Stefan Hajnoczi Signed-off-by: Luiz Capitulino --- scripts/qmp/qmp.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/qmp/qmp.py b/scripts/qmp/qmp.py index 5c97175..20b6ec7 100644 --- a/scripts/qmp/qmp.py +++ b/scripts/qmp/qmp.py @@ -171,7 +171,12 @@ class QEMUMonitorProtocol: pass self.__sock.setblocking(1) if not self.__events and wait: - self.__json_read(only_event=True) + ret = self.__json_read(only_event=True) + if ret == None: + # We are in blocking mode, if don't get anything, something + # went wrong + raise QMPConnectError("Error while reading from socket") + return self.__events def clear_events(self): -- cgit v1.1 From 678e48a2e43d1cafbb510c60d7597897b0d90256 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sat, 1 Mar 2014 08:40:34 +0100 Subject: qapi: Fix licensing of scripts The scripts carry this copyright notice: # This work is licensed under the terms of the GNU GPLv2. # See the COPYING.LIB file in the top-level directory. The sentences contradict each other, as COPYING.LIB contains the LGPL 2.1. Michael Roth says this was a simple pasto, and he meant to refer COPYING. Let's fix that. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Signed-off-by: Luiz Capitulino --- scripts/qapi-commands.py | 4 ++-- scripts/qapi-types.py | 4 ++-- scripts/qapi-visit.py | 4 ++-- scripts/qapi.py | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index b12b696..38c2347 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -7,8 +7,8 @@ # Anthony Liguori # Michael Roth # -# This work is licensed under the terms of the GNU GPLv2. -# See the COPYING.LIB file in the top-level directory. +# This work is licensed under the terms of the GNU GPL, version 2. +# See the COPYING file in the top-level directory. from ordereddict import OrderedDict from qapi import * diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index 4a1652b..2c6e0dc 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -6,8 +6,8 @@ # Authors: # Anthony Liguori # -# This work is licensed under the terms of the GNU GPLv2. -# See the COPYING.LIB file in the top-level directory. +# This work is licensed under the terms of the GNU GPL, version 2. +# See the COPYING file in the top-level directory. from ordereddict import OrderedDict from qapi import * diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index 65f1a54..b2a1c1c 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -7,8 +7,8 @@ # Anthony Liguori # Michael Roth # -# This work is licensed under the terms of the GNU GPLv2. -# See the COPYING.LIB file in the top-level directory. +# This work is licensed under the terms of the GNU GPL, version 2. +# See the COPYING file in the top-level directory. from ordereddict import OrderedDict from qapi import * diff --git a/scripts/qapi.py b/scripts/qapi.py index 9b3de4c..f3c2a20 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -8,8 +8,8 @@ # Anthony Liguori # Markus Armbruster # -# This work is licensed under the terms of the GNU GPLv2. -# See the COPYING.LIB file in the top-level directory. +# This work is licensed under the terms of the GNU GPL, version 2. +# See the COPYING file in the top-level directory. from ordereddict import OrderedDict import sys -- cgit v1.1 From a105acbce3954cb31ab30cae04f489dfe07cfd02 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sat, 1 Mar 2014 08:40:35 +0100 Subject: qapi: Drop nonsensical header guard in generated qapi-visit.c Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Signed-off-by: Luiz Capitulino --- scripts/qapi-visit.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'scripts') diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index b2a1c1c..97e9b11 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -494,10 +494,8 @@ fdecl.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DECL")) # have the functions defined, so we use -b option to provide control # over these cases if do_builtins: - fdef.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DEF")) for typename in builtin_types: fdef.write(generate_visit_list(typename, None)) - fdef.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DEF")) for expr in exprs: if expr.has_key('type'): -- cgit v1.1 From 56bed4135f139721d42992da3924786282bb0286 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sat, 1 Mar 2014 08:40:36 +0100 Subject: qapi: Drop unused code in qapi-commands.py Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Signed-off-by: Luiz Capitulino --- scripts/qapi-commands.py | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'scripts') diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index 38c2347..9734ab0 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -23,13 +23,6 @@ def type_visitor(name): else: return 'visit_type_%s' % name -def generate_decl_enum(name, members, genlist=True): - return mcgen(''' - -void %(visitor)s(Visitor *m, %(name)s * obj, const char *name, Error **errp); -''', - visitor=type_visitor(name)) - def generate_command_decl(name, args, ret_type): arglist="" for argname, argtype, optional, structured in parse_args(args): @@ -76,19 +69,6 @@ def gen_marshal_output_call(name, ret_type): return "" return "qmp_marshal_output_%s(retval, ret, errp);" % c_fun(name) -def gen_visitor_output_containers_decl(ret_type): - ret = "" - push_indent() - if ret_type: - ret += mcgen(''' -QmpOutputVisitor *mo; -QapiDeallocVisitor *md; -Visitor *v; -''') - pop_indent() - - return ret - def gen_visitor_input_containers_decl(args): ret = "" -- cgit v1.1 From 949ceeb31b84dce43e4619b6d7f02cac0e62e1e1 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sat, 1 Mar 2014 08:40:37 +0100 Subject: qapi: Clean up null checking in generated visitors Visitors get passed a pointer to the visited object. The generated visitors try to cope with this pointer being null in some places, for instance like this: visit_start_optional(m, obj ? &(*obj)->has_name : NULL, "name", &err); visit_start_optional() passes its second argument to Visitor method start_optional. Three out of three methods dereference it unconditionally. I fail to see how this pointer could legitimately be null. All this useless null checking is highly redundant, which Coverity duly reports. About 200 times. Remove the useless null checks. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Signed-off-by: Luiz Capitulino --- scripts/qapi-visit.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index 97e9b11..c6de9ae 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -47,9 +47,9 @@ static void visit_type_%(full_name)s_fields(Visitor *m, %(name)s ** obj, Error * if base: ret += mcgen(''' -visit_start_implicit_struct(m, obj ? (void**) &(*obj)->%(c_name)s : NULL, sizeof(%(type)s), &err); +visit_start_implicit_struct(m, (void**) &(*obj)->%(c_name)s, sizeof(%(type)s), &err); if (!err) { - visit_type_%(type)s_fields(m, obj ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, &err); + visit_type_%(type)s_fields(m, &(*obj)->%(c_prefix)s%(c_name)s, &err); error_propagate(errp, err); err = NULL; visit_end_implicit_struct(m, &err); @@ -61,8 +61,8 @@ if (!err) { for argname, argentry, optional, structured in parse_args(members): if optional: ret += mcgen(''' -visit_start_optional(m, obj ? &(*obj)->%(c_prefix)shas_%(c_name)s : NULL, "%(name)s", &err); -if (obj && (*obj)->%(prefix)shas_%(c_name)s) { +visit_start_optional(m, &(*obj)->%(c_prefix)shas_%(c_name)s, "%(name)s", &err); +if ((*obj)->%(prefix)shas_%(c_name)s) { ''', c_prefix=c_var(field_prefix), prefix=field_prefix, c_name=c_var(argname), name=argname) @@ -72,7 +72,7 @@ if (obj && (*obj)->%(prefix)shas_%(c_name)s) { ret += generate_visit_struct_body(full_name, argname, argentry) else: ret += mcgen(''' -visit_type_%(type)s(m, obj ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, "%(name)s", &err); +visit_type_%(type)s(m, &(*obj)->%(c_prefix)s%(c_name)s, "%(name)s", &err); ''', c_prefix=c_var(field_prefix), prefix=field_prefix, type=type_name(argentry), c_name=c_var(argname), @@ -121,7 +121,7 @@ visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); ret += mcgen(''' if (!err) { - if (!obj || *obj) { + if (*obj) { visit_type_%(name)s_fields(m, obj, &err); error_propagate(errp, err); err = NULL; @@ -273,7 +273,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** if (!error_is_set(errp)) { visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); if (!err) { - if (obj && *obj) { + if (*obj) { ''', name=name) -- cgit v1.1