* [Qemu-devel] [PATCH] qmp: add test tool for QMP @ 2011-11-07 15:11 Anthony Liguori 2011-11-07 16:08 ` Luiz Capitulino 2011-11-08 8:36 ` Mark Wu 0 siblings, 2 replies; 10+ messages in thread From: Anthony Liguori @ 2011-11-07 15:11 UTC (permalink / raw) To: qemu-devel; +Cc: Anthony Liguori, Luiz Capitulino I wrote this quickly to aid in testing. It's similar to qmp-shell with a few important differences: 1) It is not interactive. That makes it useful for scripting. 2) qmp-shell: (QEMU) set_password protocol=vnc password=foo 3) qmp: $ qmp set_password --protocol=vnc --password=foo 4) Extensible, git-style interface. If an invalid command name is passed, it will try to exec qmp-$1. 5) It attempts to pretty print the JSON responses in a shell friendly format such that tools can work with the output. Hope others will also find it useful. Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> --- QMP/qmp | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 120 insertions(+), 0 deletions(-) create mode 100755 QMP/qmp diff --git a/QMP/qmp b/QMP/qmp new file mode 100755 index 0000000..7b2a3c7 --- /dev/null +++ b/QMP/qmp @@ -0,0 +1,120 @@ +#!/usr/bin/python +# +# QMP command line tool +# +# Copyright IBM, Corp. 2011 +# +# Authors: +# Anthony Liguori <aliguori@us.ibm.com> +# +# This work is licensed under the terms of the GNU GPLv2 or later. +# See the COPYING file in the top-level directory. + +import sys, os +from qmp import QEMUMonitorProtocol + +def print_response(rsp, prefix=[]): + if type(rsp) == list: + i = 0 + for item in rsp: + if prefix == []: + prefix = ['item'] + print_response(item, prefix[:-1] + ['%s[%d]' % (prefix[-1], i)]) + i += 1 + elif type(rsp) == dict: + for key in rsp.keys(): + print_response(rsp[key], prefix + [key]) + else: + if len(prefix): + print '%s: %s' % ('.'.join(prefix), rsp) + else: + print '%s' % (rsp) + +def main(args): + path = None + + # Use QMP_PATH if it's set + if os.environ.has_key('QMP_PATH'): + path = os.environ['QMP_PATH'] + + while len(args): + arg = args[0] + + if arg.startswith('--'): + arg = arg[2:] + if arg.find('=') == -1: + value = True + else: + arg, value = arg.split('=', 1) + + if arg in ['path']: + path = value + elif arg in ['help']: + os.execlp('man', 'man', 'qmp') + else: + print 'Unknown argument "%s"' % arg + + args = args[1:] + else: + break + + if not path: + print "QMP path isn't set, use --path or set QMP_PATH" + return 1 + + command, args = args[0], args[1:] + + if command in ['help']: + os.execlp('man', 'man', 'qmp') + + srv = QEMUMonitorProtocol(path) + srv.connect() + + def do_command(srv, cmd, **kwds): + rsp = srv.cmd(cmd, kwds) + if rsp.has_key('error'): + raise Exception(rsp['error']['desc']) + return rsp['return'] + + commands = map(lambda x: x['name'], do_command(srv, 'query-commands')) + + srv.close() + + if command not in commands: + fullcmd = 'qmp-%s' % command + try: + os.environ['QMP_PATH'] = path + os.execvp(fullcmd, [fullcmd] + args) + except OSError, (errno, msg): + if errno == 2: + print 'Command "%s" not found.' % (fullcmd) + return 1 + raise + return 0 + + srv = QEMUMonitorProtocol(path) + srv.connect() + + arguments = {} + for arg in args: + if not arg.startswith('--'): + print 'Unknown argument "%s"' % arg + return 1 + + arg = arg[2:] + if arg.find('=') == -1: + value = True + else: + arg, value = arg.split('=', 1) + + if arg in ['help']: + os.execlp('man', 'man', 'qmp-%s' % command) + return 1 + + arguments[arg] = value + + rsp = do_command(srv, command, **arguments) + print_response(rsp) + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) -- 1.7.4.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH] qmp: add test tool for QMP 2011-11-07 15:11 [Qemu-devel] [PATCH] qmp: add test tool for QMP Anthony Liguori @ 2011-11-07 16:08 ` Luiz Capitulino 2011-11-07 16:09 ` Anthony Liguori 2011-11-08 8:36 ` Mark Wu 1 sibling, 1 reply; 10+ messages in thread From: Luiz Capitulino @ 2011-11-07 16:08 UTC (permalink / raw) To: Anthony Liguori; +Cc: qemu-devel On Mon, 7 Nov 2011 09:11:15 -0600 Anthony Liguori <aliguori@us.ibm.com> wrote: > I wrote this quickly to aid in testing. It's similar to qmp-shell with a few > important differences: > > 1) It is not interactive. That makes it useful for scripting. > > 2) qmp-shell: > > (QEMU) set_password protocol=vnc password=foo > > 3) qmp: > > $ qmp set_password --protocol=vnc --password=foo > > 4) Extensible, git-style interface. If an invalid command name is passed, it > will try to exec qmp-$1. > > 5) It attempts to pretty print the JSON responses in a shell friendly format > such that tools can work with the output. > > Hope others will also find it useful. > > Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> Acked-by: Luiz Capitulino <lcapitulino@redhat.com> > --- > QMP/qmp | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 120 insertions(+), 0 deletions(-) > create mode 100755 QMP/qmp > > diff --git a/QMP/qmp b/QMP/qmp > new file mode 100755 > index 0000000..7b2a3c7 > --- /dev/null > +++ b/QMP/qmp > @@ -0,0 +1,120 @@ > +#!/usr/bin/python > +# > +# QMP command line tool > +# > +# Copyright IBM, Corp. 2011 > +# > +# Authors: > +# Anthony Liguori <aliguori@us.ibm.com> > +# > +# This work is licensed under the terms of the GNU GPLv2 or later. > +# See the COPYING file in the top-level directory. > + > +import sys, os > +from qmp import QEMUMonitorProtocol > + > +def print_response(rsp, prefix=[]): > + if type(rsp) == list: > + i = 0 > + for item in rsp: > + if prefix == []: > + prefix = ['item'] > + print_response(item, prefix[:-1] + ['%s[%d]' % (prefix[-1], i)]) > + i += 1 > + elif type(rsp) == dict: > + for key in rsp.keys(): > + print_response(rsp[key], prefix + [key]) > + else: > + if len(prefix): > + print '%s: %s' % ('.'.join(prefix), rsp) > + else: > + print '%s' % (rsp) > + > +def main(args): > + path = None > + > + # Use QMP_PATH if it's set > + if os.environ.has_key('QMP_PATH'): > + path = os.environ['QMP_PATH'] > + > + while len(args): > + arg = args[0] > + > + if arg.startswith('--'): > + arg = arg[2:] > + if arg.find('=') == -1: > + value = True > + else: > + arg, value = arg.split('=', 1) > + > + if arg in ['path']: > + path = value > + elif arg in ['help']: > + os.execlp('man', 'man', 'qmp') > + else: > + print 'Unknown argument "%s"' % arg > + > + args = args[1:] > + else: > + break > + > + if not path: > + print "QMP path isn't set, use --path or set QMP_PATH" > + return 1 > + > + command, args = args[0], args[1:] > + > + if command in ['help']: > + os.execlp('man', 'man', 'qmp') > + > + srv = QEMUMonitorProtocol(path) > + srv.connect() > + > + def do_command(srv, cmd, **kwds): > + rsp = srv.cmd(cmd, kwds) > + if rsp.has_key('error'): > + raise Exception(rsp['error']['desc']) > + return rsp['return'] > + > + commands = map(lambda x: x['name'], do_command(srv, 'query-commands')) > + > + srv.close() > + > + if command not in commands: > + fullcmd = 'qmp-%s' % command > + try: > + os.environ['QMP_PATH'] = path > + os.execvp(fullcmd, [fullcmd] + args) > + except OSError, (errno, msg): > + if errno == 2: > + print 'Command "%s" not found.' % (fullcmd) > + return 1 > + raise > + return 0 > + > + srv = QEMUMonitorProtocol(path) > + srv.connect() > + > + arguments = {} > + for arg in args: > + if not arg.startswith('--'): > + print 'Unknown argument "%s"' % arg > + return 1 > + > + arg = arg[2:] > + if arg.find('=') == -1: > + value = True > + else: > + arg, value = arg.split('=', 1) > + > + if arg in ['help']: > + os.execlp('man', 'man', 'qmp-%s' % command) > + return 1 > + > + arguments[arg] = value > + > + rsp = do_command(srv, command, **arguments) > + print_response(rsp) > + > +if __name__ == '__main__': > + sys.exit(main(sys.argv[1:])) ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH] qmp: add test tool for QMP 2011-11-07 16:08 ` Luiz Capitulino @ 2011-11-07 16:09 ` Anthony Liguori 2011-11-07 16:30 ` Luiz Capitulino 0 siblings, 1 reply; 10+ messages in thread From: Anthony Liguori @ 2011-11-07 16:09 UTC (permalink / raw) To: Luiz Capitulino; +Cc: Anthony Liguori, qemu-devel On 11/07/2011 10:08 AM, Luiz Capitulino wrote: > On Mon, 7 Nov 2011 09:11:15 -0600 > Anthony Liguori<aliguori@us.ibm.com> wrote: > >> I wrote this quickly to aid in testing. It's similar to qmp-shell with a few >> important differences: >> >> 1) It is not interactive. That makes it useful for scripting. >> >> 2) qmp-shell: >> >> (QEMU) set_password protocol=vnc password=foo >> >> 3) qmp: >> >> $ qmp set_password --protocol=vnc --password=foo >> >> 4) Extensible, git-style interface. If an invalid command name is passed, it >> will try to exec qmp-$1. >> >> 5) It attempts to pretty print the JSON responses in a shell friendly format >> such that tools can work with the output. >> >> Hope others will also find it useful. >> >> Signed-off-by: Anthony Liguori<aliguori@us.ibm.com> > > Acked-by: Luiz Capitulino<lcapitulino@redhat.com> BTW, one thing I'd like to try at some point soon is to generate man pages from qapi-schema.json. If you notice in the script, it does online help by invoking man. Regards, Anthony Liguori > >> --- >> QMP/qmp | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >> 1 files changed, 120 insertions(+), 0 deletions(-) >> create mode 100755 QMP/qmp >> >> diff --git a/QMP/qmp b/QMP/qmp >> new file mode 100755 >> index 0000000..7b2a3c7 >> --- /dev/null >> +++ b/QMP/qmp >> @@ -0,0 +1,120 @@ >> +#!/usr/bin/python >> +# >> +# QMP command line tool >> +# >> +# Copyright IBM, Corp. 2011 >> +# >> +# Authors: >> +# Anthony Liguori<aliguori@us.ibm.com> >> +# >> +# This work is licensed under the terms of the GNU GPLv2 or later. >> +# See the COPYING file in the top-level directory. >> + >> +import sys, os >> +from qmp import QEMUMonitorProtocol >> + >> +def print_response(rsp, prefix=[]): >> + if type(rsp) == list: >> + i = 0 >> + for item in rsp: >> + if prefix == []: >> + prefix = ['item'] >> + print_response(item, prefix[:-1] + ['%s[%d]' % (prefix[-1], i)]) >> + i += 1 >> + elif type(rsp) == dict: >> + for key in rsp.keys(): >> + print_response(rsp[key], prefix + [key]) >> + else: >> + if len(prefix): >> + print '%s: %s' % ('.'.join(prefix), rsp) >> + else: >> + print '%s' % (rsp) >> + >> +def main(args): >> + path = None >> + >> + # Use QMP_PATH if it's set >> + if os.environ.has_key('QMP_PATH'): >> + path = os.environ['QMP_PATH'] >> + >> + while len(args): >> + arg = args[0] >> + >> + if arg.startswith('--'): >> + arg = arg[2:] >> + if arg.find('=') == -1: >> + value = True >> + else: >> + arg, value = arg.split('=', 1) >> + >> + if arg in ['path']: >> + path = value >> + elif arg in ['help']: >> + os.execlp('man', 'man', 'qmp') >> + else: >> + print 'Unknown argument "%s"' % arg >> + >> + args = args[1:] >> + else: >> + break >> + >> + if not path: >> + print "QMP path isn't set, use --path or set QMP_PATH" >> + return 1 >> + >> + command, args = args[0], args[1:] >> + >> + if command in ['help']: >> + os.execlp('man', 'man', 'qmp') >> + >> + srv = QEMUMonitorProtocol(path) >> + srv.connect() >> + >> + def do_command(srv, cmd, **kwds): >> + rsp = srv.cmd(cmd, kwds) >> + if rsp.has_key('error'): >> + raise Exception(rsp['error']['desc']) >> + return rsp['return'] >> + >> + commands = map(lambda x: x['name'], do_command(srv, 'query-commands')) >> + >> + srv.close() >> + >> + if command not in commands: >> + fullcmd = 'qmp-%s' % command >> + try: >> + os.environ['QMP_PATH'] = path >> + os.execvp(fullcmd, [fullcmd] + args) >> + except OSError, (errno, msg): >> + if errno == 2: >> + print 'Command "%s" not found.' % (fullcmd) >> + return 1 >> + raise >> + return 0 >> + >> + srv = QEMUMonitorProtocol(path) >> + srv.connect() >> + >> + arguments = {} >> + for arg in args: >> + if not arg.startswith('--'): >> + print 'Unknown argument "%s"' % arg >> + return 1 >> + >> + arg = arg[2:] >> + if arg.find('=') == -1: >> + value = True >> + else: >> + arg, value = arg.split('=', 1) >> + >> + if arg in ['help']: >> + os.execlp('man', 'man', 'qmp-%s' % command) >> + return 1 >> + >> + arguments[arg] = value >> + >> + rsp = do_command(srv, command, **arguments) >> + print_response(rsp) >> + >> +if __name__ == '__main__': >> + sys.exit(main(sys.argv[1:])) > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH] qmp: add test tool for QMP 2011-11-07 16:09 ` Anthony Liguori @ 2011-11-07 16:30 ` Luiz Capitulino 2011-11-07 16:35 ` Anthony Liguori 0 siblings, 1 reply; 10+ messages in thread From: Luiz Capitulino @ 2011-11-07 16:30 UTC (permalink / raw) To: Anthony Liguori; +Cc: Anthony Liguori, qemu-devel On Mon, 07 Nov 2011 10:09:55 -0600 Anthony Liguori <anthony@codemonkey.ws> wrote: > On 11/07/2011 10:08 AM, Luiz Capitulino wrote: > > On Mon, 7 Nov 2011 09:11:15 -0600 > > Anthony Liguori<aliguori@us.ibm.com> wrote: > > > >> I wrote this quickly to aid in testing. It's similar to qmp-shell with a few > >> important differences: > >> > >> 1) It is not interactive. That makes it useful for scripting. > >> > >> 2) qmp-shell: > >> > >> (QEMU) set_password protocol=vnc password=foo > >> > >> 3) qmp: > >> > >> $ qmp set_password --protocol=vnc --password=foo > >> > >> 4) Extensible, git-style interface. If an invalid command name is passed, it > >> will try to exec qmp-$1. > >> > >> 5) It attempts to pretty print the JSON responses in a shell friendly format > >> such that tools can work with the output. > >> > >> Hope others will also find it useful. > >> > >> Signed-off-by: Anthony Liguori<aliguori@us.ibm.com> > > > > Acked-by: Luiz Capitulino<lcapitulino@redhat.com> > > BTW, one thing I'd like to try at some point soon is to generate man pages from > qapi-schema.json. If you notice in the script, it does online help by invoking man. Yes, I did notice it. I didn't comment on it because I imagined you had plans about it. PS: I don't think this needs to go through my tree. > > Regards, > > Anthony Liguori > > > > >> --- > >> QMP/qmp | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > >> 1 files changed, 120 insertions(+), 0 deletions(-) > >> create mode 100755 QMP/qmp > >> > >> diff --git a/QMP/qmp b/QMP/qmp > >> new file mode 100755 > >> index 0000000..7b2a3c7 > >> --- /dev/null > >> +++ b/QMP/qmp > >> @@ -0,0 +1,120 @@ > >> +#!/usr/bin/python > >> +# > >> +# QMP command line tool > >> +# > >> +# Copyright IBM, Corp. 2011 > >> +# > >> +# Authors: > >> +# Anthony Liguori<aliguori@us.ibm.com> > >> +# > >> +# This work is licensed under the terms of the GNU GPLv2 or later. > >> +# See the COPYING file in the top-level directory. > >> + > >> +import sys, os > >> +from qmp import QEMUMonitorProtocol > >> + > >> +def print_response(rsp, prefix=[]): > >> + if type(rsp) == list: > >> + i = 0 > >> + for item in rsp: > >> + if prefix == []: > >> + prefix = ['item'] > >> + print_response(item, prefix[:-1] + ['%s[%d]' % (prefix[-1], i)]) > >> + i += 1 > >> + elif type(rsp) == dict: > >> + for key in rsp.keys(): > >> + print_response(rsp[key], prefix + [key]) > >> + else: > >> + if len(prefix): > >> + print '%s: %s' % ('.'.join(prefix), rsp) > >> + else: > >> + print '%s' % (rsp) > >> + > >> +def main(args): > >> + path = None > >> + > >> + # Use QMP_PATH if it's set > >> + if os.environ.has_key('QMP_PATH'): > >> + path = os.environ['QMP_PATH'] > >> + > >> + while len(args): > >> + arg = args[0] > >> + > >> + if arg.startswith('--'): > >> + arg = arg[2:] > >> + if arg.find('=') == -1: > >> + value = True > >> + else: > >> + arg, value = arg.split('=', 1) > >> + > >> + if arg in ['path']: > >> + path = value > >> + elif arg in ['help']: > >> + os.execlp('man', 'man', 'qmp') > >> + else: > >> + print 'Unknown argument "%s"' % arg > >> + > >> + args = args[1:] > >> + else: > >> + break > >> + > >> + if not path: > >> + print "QMP path isn't set, use --path or set QMP_PATH" > >> + return 1 > >> + > >> + command, args = args[0], args[1:] > >> + > >> + if command in ['help']: > >> + os.execlp('man', 'man', 'qmp') > >> + > >> + srv = QEMUMonitorProtocol(path) > >> + srv.connect() > >> + > >> + def do_command(srv, cmd, **kwds): > >> + rsp = srv.cmd(cmd, kwds) > >> + if rsp.has_key('error'): > >> + raise Exception(rsp['error']['desc']) > >> + return rsp['return'] > >> + > >> + commands = map(lambda x: x['name'], do_command(srv, 'query-commands')) > >> + > >> + srv.close() > >> + > >> + if command not in commands: > >> + fullcmd = 'qmp-%s' % command > >> + try: > >> + os.environ['QMP_PATH'] = path > >> + os.execvp(fullcmd, [fullcmd] + args) > >> + except OSError, (errno, msg): > >> + if errno == 2: > >> + print 'Command "%s" not found.' % (fullcmd) > >> + return 1 > >> + raise > >> + return 0 > >> + > >> + srv = QEMUMonitorProtocol(path) > >> + srv.connect() > >> + > >> + arguments = {} > >> + for arg in args: > >> + if not arg.startswith('--'): > >> + print 'Unknown argument "%s"' % arg > >> + return 1 > >> + > >> + arg = arg[2:] > >> + if arg.find('=') == -1: > >> + value = True > >> + else: > >> + arg, value = arg.split('=', 1) > >> + > >> + if arg in ['help']: > >> + os.execlp('man', 'man', 'qmp-%s' % command) > >> + return 1 > >> + > >> + arguments[arg] = value > >> + > >> + rsp = do_command(srv, command, **arguments) > >> + print_response(rsp) > >> + > >> +if __name__ == '__main__': > >> + sys.exit(main(sys.argv[1:])) > > > > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH] qmp: add test tool for QMP 2011-11-07 16:30 ` Luiz Capitulino @ 2011-11-07 16:35 ` Anthony Liguori 2011-11-07 16:39 ` Luiz Capitulino 0 siblings, 1 reply; 10+ messages in thread From: Anthony Liguori @ 2011-11-07 16:35 UTC (permalink / raw) To: Luiz Capitulino; +Cc: Anthony Liguori, qemu-devel On 11/07/2011 10:30 AM, Luiz Capitulino wrote: > On Mon, 07 Nov 2011 10:09:55 -0600 > Anthony Liguori<anthony@codemonkey.ws> wrote: > >> On 11/07/2011 10:08 AM, Luiz Capitulino wrote: >>> On Mon, 7 Nov 2011 09:11:15 -0600 >>> Anthony Liguori<aliguori@us.ibm.com> wrote: >>> >>>> I wrote this quickly to aid in testing. It's similar to qmp-shell with a few >>>> important differences: >>>> >>>> 1) It is not interactive. That makes it useful for scripting. >>>> >>>> 2) qmp-shell: >>>> >>>> (QEMU) set_password protocol=vnc password=foo >>>> >>>> 3) qmp: >>>> >>>> $ qmp set_password --protocol=vnc --password=foo >>>> >>>> 4) Extensible, git-style interface. If an invalid command name is passed, it >>>> will try to exec qmp-$1. >>>> >>>> 5) It attempts to pretty print the JSON responses in a shell friendly format >>>> such that tools can work with the output. >>>> >>>> Hope others will also find it useful. >>>> >>>> Signed-off-by: Anthony Liguori<aliguori@us.ibm.com> >>> >>> Acked-by: Luiz Capitulino<lcapitulino@redhat.com> >> >> BTW, one thing I'd like to try at some point soon is to generate man pages from >> qapi-schema.json. If you notice in the script, it does online help by invoking man. > > Yes, I did notice it. I didn't comment on it because I imagined you had plans > about it. > > PS: I don't think this needs to go through my tree. What do you want to do with qmp.py? Do you feel comfortable installing it in $PYTHONPATH and treating it as a supported API? Regards, Anthony Liguori ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH] qmp: add test tool for QMP 2011-11-07 16:35 ` Anthony Liguori @ 2011-11-07 16:39 ` Luiz Capitulino 2011-11-07 17:26 ` Alon Levy 0 siblings, 1 reply; 10+ messages in thread From: Luiz Capitulino @ 2011-11-07 16:39 UTC (permalink / raw) To: Anthony Liguori; +Cc: Anthony Liguori, qemu-devel On Mon, 07 Nov 2011 10:35:51 -0600 Anthony Liguori <anthony@codemonkey.ws> wrote: > On 11/07/2011 10:30 AM, Luiz Capitulino wrote: > > On Mon, 07 Nov 2011 10:09:55 -0600 > > Anthony Liguori<anthony@codemonkey.ws> wrote: > > > >> On 11/07/2011 10:08 AM, Luiz Capitulino wrote: > >>> On Mon, 7 Nov 2011 09:11:15 -0600 > >>> Anthony Liguori<aliguori@us.ibm.com> wrote: > >>> > >>>> I wrote this quickly to aid in testing. It's similar to qmp-shell with a few > >>>> important differences: > >>>> > >>>> 1) It is not interactive. That makes it useful for scripting. > >>>> > >>>> 2) qmp-shell: > >>>> > >>>> (QEMU) set_password protocol=vnc password=foo > >>>> > >>>> 3) qmp: > >>>> > >>>> $ qmp set_password --protocol=vnc --password=foo > >>>> > >>>> 4) Extensible, git-style interface. If an invalid command name is passed, it > >>>> will try to exec qmp-$1. > >>>> > >>>> 5) It attempts to pretty print the JSON responses in a shell friendly format > >>>> such that tools can work with the output. > >>>> > >>>> Hope others will also find it useful. > >>>> > >>>> Signed-off-by: Anthony Liguori<aliguori@us.ibm.com> > >>> > >>> Acked-by: Luiz Capitulino<lcapitulino@redhat.com> > >> > >> BTW, one thing I'd like to try at some point soon is to generate man pages from > >> qapi-schema.json. If you notice in the script, it does online help by invoking man. > > > > Yes, I did notice it. I didn't comment on it because I imagined you had plans > > about it. > > > > PS: I don't think this needs to go through my tree. > > What do you want to do with qmp.py? Do you feel comfortable installing it in > $PYTHONPATH and treating it as a supported API? I probably don't. I coded it as demo in the very beginning of QMP, maybe we should first define what we expect from a QMP Python class then we can see whether it fits or not... I feel it needs to be revamped. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH] qmp: add test tool for QMP 2011-11-07 16:39 ` Luiz Capitulino @ 2011-11-07 17:26 ` Alon Levy 0 siblings, 0 replies; 10+ messages in thread From: Alon Levy @ 2011-11-07 17:26 UTC (permalink / raw) To: Luiz Capitulino; +Cc: Anthony Liguori, qemu-devel On Mon, Nov 07, 2011 at 02:39:29PM -0200, Luiz Capitulino wrote: > On Mon, 07 Nov 2011 10:35:51 -0600 > Anthony Liguori <anthony@codemonkey.ws> wrote: > > > On 11/07/2011 10:30 AM, Luiz Capitulino wrote: > > > On Mon, 07 Nov 2011 10:09:55 -0600 > > > Anthony Liguori<anthony@codemonkey.ws> wrote: > > > > > >> On 11/07/2011 10:08 AM, Luiz Capitulino wrote: > > >>> On Mon, 7 Nov 2011 09:11:15 -0600 > > >>> Anthony Liguori<aliguori@us.ibm.com> wrote: > > >>> > > >>>> I wrote this quickly to aid in testing. It's similar to qmp-shell with a few > > >>>> important differences: > > >>>> > > >>>> 1) It is not interactive. That makes it useful for scripting. > > >>>> > > >>>> 2) qmp-shell: > > >>>> > > >>>> (QEMU) set_password protocol=vnc password=foo > > >>>> > > >>>> 3) qmp: > > >>>> > > >>>> $ qmp set_password --protocol=vnc --password=foo > > >>>> > > >>>> 4) Extensible, git-style interface. If an invalid command name is passed, it > > >>>> will try to exec qmp-$1. > > >>>> > > >>>> 5) It attempts to pretty print the JSON responses in a shell friendly format > > >>>> such that tools can work with the output. > > >>>> > > >>>> Hope others will also find it useful. > > >>>> > > >>>> Signed-off-by: Anthony Liguori<aliguori@us.ibm.com> > > >>> > > >>> Acked-by: Luiz Capitulino<lcapitulino@redhat.com> > > >> > > >> BTW, one thing I'd like to try at some point soon is to generate man pages from > > >> qapi-schema.json. If you notice in the script, it does online help by invoking man. > > > > > > Yes, I did notice it. I didn't comment on it because I imagined you had plans > > > about it. > > > > > > PS: I don't think this needs to go through my tree. > > > > What do you want to do with qmp.py? Do you feel comfortable installing it in > > $PYTHONPATH and treating it as a supported API? > > I probably don't. I coded it as demo in the very beginning of QMP, maybe > we should first define what we expect from a QMP Python class then we > can see whether it fits or not... I feel it needs to be revamped. > It should not blocking, i.e. for event notification. I have a patch that fixes that but breaks tab-completion. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH] qmp: add test tool for QMP 2011-11-07 15:11 [Qemu-devel] [PATCH] qmp: add test tool for QMP Anthony Liguori 2011-11-07 16:08 ` Luiz Capitulino @ 2011-11-08 8:36 ` Mark Wu 2011-11-08 11:56 ` Luiz Capitulino 2011-11-08 13:57 ` Anthony Liguori 1 sibling, 2 replies; 10+ messages in thread From: Mark Wu @ 2011-11-08 8:36 UTC (permalink / raw) To: Anthony Liguori; +Cc: qemu-devel, Luiz Capitulino When I run this tool, I got two python exceptions. It turned out that both of them were caused by wrong usage. Do you think we need add validation for input to handle these cases? Thanks. 1. Not using '=' for path: $ ./QMP/qmp --path monitor-address Traceback (most recent call last): File "./QMP/qmp", line 120, in <module> sys.exit(main(sys.argv[1:])) File "./QMP/qmp", line 71, in main srv.connect() File "/home/mark/work/source/qemu/QMP/qmp.py", line 85, in connect self.__sock.connect(self.__address) File "<string>", line 1, in connect TypeError: argument must be string or read-only character buffer, not bool Proposed patch: @@ -48,7 +48,8 @@ def main(args): arg, value = arg.split('=', 1) if arg in ['path']: - path = value + if isinstance(value, basestring): + path = value 2. No qmp comand given in command line $ ./QMP/qmp --path=monitor-address Traceback (most recent call last): File "./QMP/qmp", line 120, in <module> sys.exit(main(sys.argv[1:])) File "./QMP/qmp", line 65, in main command, args = args[0], args[1:] IndexError: list index out of range @@ -62,11 +63,17 @@ def main(args): print "QMP path isn't set, use --path or set QMP_PATH" return 1 Proposed patch: - command, args = args[0], args[1:] + if len(args): + command, args = args[0], args[1:] + else: + print 'No command found' + print 'Usage: "qmp [--path=monitor-address] qmp-cmd arguments"' + return 1 On 11/07/2011 11:11 PM, Anthony Liguori wrote: > I wrote this quickly to aid in testing. It's similar to qmp-shell with a few > important differences: > > 1) It is not interactive. That makes it useful for scripting. > > 2) qmp-shell: > > (QEMU) set_password protocol=vnc password=foo > > 3) qmp: > > $ qmp set_password --protocol=vnc --password=foo > > 4) Extensible, git-style interface. If an invalid command name is passed, it > will try to exec qmp-$1. > > 5) It attempts to pretty print the JSON responses in a shell friendly format > such that tools can work with the output. > > Hope others will also find it useful. > > Signed-off-by: Anthony Liguori<aliguori@us.ibm.com> > --- > QMP/qmp | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 120 insertions(+), 0 deletions(-) > create mode 100755 QMP/qmp > > diff --git a/QMP/qmp b/QMP/qmp > new file mode 100755 > index 0000000..7b2a3c7 > --- /dev/null > +++ b/QMP/qmp > @@ -0,0 +1,120 @@ > +#!/usr/bin/python > +# > +# QMP command line tool > +# > +# Copyright IBM, Corp. 2011 > +# > +# Authors: > +# Anthony Liguori<aliguori@us.ibm.com> > +# > +# This work is licensed under the terms of the GNU GPLv2 or later. > +# See the COPYING file in the top-level directory. > + > +import sys, os > +from qmp import QEMUMonitorProtocol > + > +def print_response(rsp, prefix=[]): > + if type(rsp) == list: > + i = 0 > + for item in rsp: > + if prefix == []: > + prefix = ['item'] > + print_response(item, prefix[:-1] + ['%s[%d]' % (prefix[-1], i)]) > + i += 1 > + elif type(rsp) == dict: > + for key in rsp.keys(): > + print_response(rsp[key], prefix + [key]) > + else: > + if len(prefix): > + print '%s: %s' % ('.'.join(prefix), rsp) > + else: > + print '%s' % (rsp) > + > +def main(args): > + path = None > + > + # Use QMP_PATH if it's set > + if os.environ.has_key('QMP_PATH'): > + path = os.environ['QMP_PATH'] > + > + while len(args): > + arg = args[0] > + > + if arg.startswith('--'): > + arg = arg[2:] > + if arg.find('=') == -1: > + value = True > + else: > + arg, value = arg.split('=', 1) > + > + if arg in ['path']: > + path = value > + elif arg in ['help']: > + os.execlp('man', 'man', 'qmp') > + else: > + print 'Unknown argument "%s"' % arg > + > + args = args[1:] > + else: > + break > + > + if not path: > + print "QMP path isn't set, use --path or set QMP_PATH" > + return 1 > + > + command, args = args[0], args[1:] > + > + if command in ['help']: > + os.execlp('man', 'man', 'qmp') > + > + srv = QEMUMonitorProtocol(path) > + srv.connect() > + > + def do_command(srv, cmd, **kwds): > + rsp = srv.cmd(cmd, kwds) > + if rsp.has_key('error'): > + raise Exception(rsp['error']['desc']) > + return rsp['return'] > + > + commands = map(lambda x: x['name'], do_command(srv, 'query-commands')) > + > + srv.close() > + > + if command not in commands: > + fullcmd = 'qmp-%s' % command > + try: > + os.environ['QMP_PATH'] = path > + os.execvp(fullcmd, [fullcmd] + args) > + except OSError, (errno, msg): > + if errno == 2: > + print 'Command "%s" not found.' % (fullcmd) > + return 1 > + raise > + return 0 > + > + srv = QEMUMonitorProtocol(path) > + srv.connect() > + > + arguments = {} > + for arg in args: > + if not arg.startswith('--'): > + print 'Unknown argument "%s"' % arg > + return 1 > + > + arg = arg[2:] > + if arg.find('=') == -1: > + value = True > + else: > + arg, value = arg.split('=', 1) > + > + if arg in ['help']: > + os.execlp('man', 'man', 'qmp-%s' % command) > + return 1 > + > + arguments[arg] = value > + > + rsp = do_command(srv, command, **arguments) > + print_response(rsp) > + > +if __name__ == '__main__': > + sys.exit(main(sys.argv[1:])) ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH] qmp: add test tool for QMP 2011-11-08 8:36 ` Mark Wu @ 2011-11-08 11:56 ` Luiz Capitulino 2011-11-08 13:57 ` Anthony Liguori 1 sibling, 0 replies; 10+ messages in thread From: Luiz Capitulino @ 2011-11-08 11:56 UTC (permalink / raw) To: Mark Wu; +Cc: Anthony Liguori, qemu-devel On Tue, 08 Nov 2011 16:36:55 +0800 Mark Wu <wudxw@linux.vnet.ibm.com> wrote: > When I run this tool, I got two python exceptions. It turned out that > both of them were caused by wrong usage. Do you think we need add > validation for input to handle these cases? Yes. > > Thanks. > > 1. Not using '=' for path: > $ ./QMP/qmp --path monitor-address > Traceback (most recent call last): > File "./QMP/qmp", line 120, in <module> > sys.exit(main(sys.argv[1:])) > File "./QMP/qmp", line 71, in main > srv.connect() > File "/home/mark/work/source/qemu/QMP/qmp.py", line 85, in connect > self.__sock.connect(self.__address) > File "<string>", line 1, in connect > TypeError: argument must be string or read-only character buffer, not bool > > Proposed patch: > > @@ -48,7 +48,8 @@ def main(args): > arg, value = arg.split('=', 1) > > if arg in ['path']: > - path = value > + if isinstance(value, basestring): > + path = value > > > 2. No qmp comand given in command line > $ ./QMP/qmp --path=monitor-address > Traceback (most recent call last): > File "./QMP/qmp", line 120, in <module> > sys.exit(main(sys.argv[1:])) > File "./QMP/qmp", line 65, in main > command, args = args[0], args[1:] > IndexError: list index out of range > > @@ -62,11 +63,17 @@ def main(args): > print "QMP path isn't set, use --path or set QMP_PATH" > return 1 > > Proposed patch: > - command, args = args[0], args[1:] > + if len(args): > + command, args = args[0], args[1:] > + else: > + print 'No command found' > + print 'Usage: "qmp [--path=monitor-address] qmp-cmd arguments"' > + return 1 > > > > > > > > > On 11/07/2011 11:11 PM, Anthony Liguori wrote: > > I wrote this quickly to aid in testing. It's similar to qmp-shell with a few > > important differences: > > > > 1) It is not interactive. That makes it useful for scripting. > > > > 2) qmp-shell: > > > > (QEMU) set_password protocol=vnc password=foo > > > > 3) qmp: > > > > $ qmp set_password --protocol=vnc --password=foo > > > > 4) Extensible, git-style interface. If an invalid command name is passed, it > > will try to exec qmp-$1. > > > > 5) It attempts to pretty print the JSON responses in a shell friendly format > > such that tools can work with the output. > > > > Hope others will also find it useful. > > > > Signed-off-by: Anthony Liguori<aliguori@us.ibm.com> > > --- > > QMP/qmp | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > > 1 files changed, 120 insertions(+), 0 deletions(-) > > create mode 100755 QMP/qmp > > > > diff --git a/QMP/qmp b/QMP/qmp > > new file mode 100755 > > index 0000000..7b2a3c7 > > --- /dev/null > > +++ b/QMP/qmp > > @@ -0,0 +1,120 @@ > > +#!/usr/bin/python > > +# > > +# QMP command line tool > > +# > > +# Copyright IBM, Corp. 2011 > > +# > > +# Authors: > > +# Anthony Liguori<aliguori@us.ibm.com> > > +# > > +# This work is licensed under the terms of the GNU GPLv2 or later. > > +# See the COPYING file in the top-level directory. > > + > > +import sys, os > > +from qmp import QEMUMonitorProtocol > > + > > +def print_response(rsp, prefix=[]): > > + if type(rsp) == list: > > + i = 0 > > + for item in rsp: > > + if prefix == []: > > + prefix = ['item'] > > + print_response(item, prefix[:-1] + ['%s[%d]' % (prefix[-1], i)]) > > + i += 1 > > + elif type(rsp) == dict: > > + for key in rsp.keys(): > > + print_response(rsp[key], prefix + [key]) > > + else: > > + if len(prefix): > > + print '%s: %s' % ('.'.join(prefix), rsp) > > + else: > > + print '%s' % (rsp) > > + > > +def main(args): > > + path = None > > + > > + # Use QMP_PATH if it's set > > + if os.environ.has_key('QMP_PATH'): > > + path = os.environ['QMP_PATH'] > > + > > + while len(args): > > + arg = args[0] > > + > > + if arg.startswith('--'): > > + arg = arg[2:] > > + if arg.find('=') == -1: > > + value = True > > + else: > > + arg, value = arg.split('=', 1) > > + > > + if arg in ['path']: > > + path = value > > + elif arg in ['help']: > > + os.execlp('man', 'man', 'qmp') > > + else: > > + print 'Unknown argument "%s"' % arg > > + > > + args = args[1:] > > + else: > > + break > > + > > + if not path: > > + print "QMP path isn't set, use --path or set QMP_PATH" > > + return 1 > > + > > + command, args = args[0], args[1:] > > + > > + if command in ['help']: > > + os.execlp('man', 'man', 'qmp') > > + > > + srv = QEMUMonitorProtocol(path) > > + srv.connect() > > + > > + def do_command(srv, cmd, **kwds): > > + rsp = srv.cmd(cmd, kwds) > > + if rsp.has_key('error'): > > + raise Exception(rsp['error']['desc']) > > + return rsp['return'] > > + > > + commands = map(lambda x: x['name'], do_command(srv, 'query-commands')) > > + > > + srv.close() > > + > > + if command not in commands: > > + fullcmd = 'qmp-%s' % command > > + try: > > + os.environ['QMP_PATH'] = path > > + os.execvp(fullcmd, [fullcmd] + args) > > + except OSError, (errno, msg): > > + if errno == 2: > > + print 'Command "%s" not found.' % (fullcmd) > > + return 1 > > + raise > > + return 0 > > + > > + srv = QEMUMonitorProtocol(path) > > + srv.connect() > > + > > + arguments = {} > > + for arg in args: > > + if not arg.startswith('--'): > > + print 'Unknown argument "%s"' % arg > > + return 1 > > + > > + arg = arg[2:] > > + if arg.find('=') == -1: > > + value = True > > + else: > > + arg, value = arg.split('=', 1) > > + > > + if arg in ['help']: > > + os.execlp('man', 'man', 'qmp-%s' % command) > > + return 1 > > + > > + arguments[arg] = value > > + > > + rsp = do_command(srv, command, **arguments) > > + print_response(rsp) > > + > > +if __name__ == '__main__': > > + sys.exit(main(sys.argv[1:])) > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH] qmp: add test tool for QMP 2011-11-08 8:36 ` Mark Wu 2011-11-08 11:56 ` Luiz Capitulino @ 2011-11-08 13:57 ` Anthony Liguori 1 sibling, 0 replies; 10+ messages in thread From: Anthony Liguori @ 2011-11-08 13:57 UTC (permalink / raw) To: Mark Wu; +Cc: qemu-devel, Luiz Capitulino On 11/08/2011 02:36 AM, Mark Wu wrote: > When I run this tool, I got two python exceptions. It turned out that both of > them were caused by wrong usage. Do you think we need add validation for input > to handle these cases? Definitely. Could you just send out a version of the patch with your changes, a (v2) in the subject, and your Signed-off-by? Thanks! Regards, Anthony Liguori > > Thanks. > > 1. Not using '=' for path: > $ ./QMP/qmp --path monitor-address > Traceback (most recent call last): > File "./QMP/qmp", line 120, in <module> > sys.exit(main(sys.argv[1:])) > File "./QMP/qmp", line 71, in main > srv.connect() > File "/home/mark/work/source/qemu/QMP/qmp.py", line 85, in connect > self.__sock.connect(self.__address) > File "<string>", line 1, in connect > TypeError: argument must be string or read-only character buffer, not bool > > Proposed patch: > > @@ -48,7 +48,8 @@ def main(args): > arg, value = arg.split('=', 1) > > if arg in ['path']: > - path = value > + if isinstance(value, basestring): > + path = value > > > 2. No qmp comand given in command line > $ ./QMP/qmp --path=monitor-address > Traceback (most recent call last): > File "./QMP/qmp", line 120, in <module> > sys.exit(main(sys.argv[1:])) > File "./QMP/qmp", line 65, in main > command, args = args[0], args[1:] > IndexError: list index out of range > > @@ -62,11 +63,17 @@ def main(args): > print "QMP path isn't set, use --path or set QMP_PATH" > return 1 > > Proposed patch: > - command, args = args[0], args[1:] > + if len(args): > + command, args = args[0], args[1:] > + else: > + print 'No command found' > + print 'Usage: "qmp [--path=monitor-address] qmp-cmd arguments"' > + return 1 > > > > > > > > > On 11/07/2011 11:11 PM, Anthony Liguori wrote: >> I wrote this quickly to aid in testing. It's similar to qmp-shell with a few >> important differences: >> >> 1) It is not interactive. That makes it useful for scripting. >> >> 2) qmp-shell: >> >> (QEMU) set_password protocol=vnc password=foo >> >> 3) qmp: >> >> $ qmp set_password --protocol=vnc --password=foo >> >> 4) Extensible, git-style interface. If an invalid command name is passed, it >> will try to exec qmp-$1. >> >> 5) It attempts to pretty print the JSON responses in a shell friendly format >> such that tools can work with the output. >> >> Hope others will also find it useful. >> >> Signed-off-by: Anthony Liguori<aliguori@us.ibm.com> >> --- >> QMP/qmp | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >> 1 files changed, 120 insertions(+), 0 deletions(-) >> create mode 100755 QMP/qmp >> >> diff --git a/QMP/qmp b/QMP/qmp >> new file mode 100755 >> index 0000000..7b2a3c7 >> --- /dev/null >> +++ b/QMP/qmp >> @@ -0,0 +1,120 @@ >> +#!/usr/bin/python >> +# >> +# QMP command line tool >> +# >> +# Copyright IBM, Corp. 2011 >> +# >> +# Authors: >> +# Anthony Liguori<aliguori@us.ibm.com> >> +# >> +# This work is licensed under the terms of the GNU GPLv2 or later. >> +# See the COPYING file in the top-level directory. >> + >> +import sys, os >> +from qmp import QEMUMonitorProtocol >> + >> +def print_response(rsp, prefix=[]): >> + if type(rsp) == list: >> + i = 0 >> + for item in rsp: >> + if prefix == []: >> + prefix = ['item'] >> + print_response(item, prefix[:-1] + ['%s[%d]' % (prefix[-1], i)]) >> + i += 1 >> + elif type(rsp) == dict: >> + for key in rsp.keys(): >> + print_response(rsp[key], prefix + [key]) >> + else: >> + if len(prefix): >> + print '%s: %s' % ('.'.join(prefix), rsp) >> + else: >> + print '%s' % (rsp) >> + >> +def main(args): >> + path = None >> + >> + # Use QMP_PATH if it's set >> + if os.environ.has_key('QMP_PATH'): >> + path = os.environ['QMP_PATH'] >> + >> + while len(args): >> + arg = args[0] >> + >> + if arg.startswith('--'): >> + arg = arg[2:] >> + if arg.find('=') == -1: >> + value = True >> + else: >> + arg, value = arg.split('=', 1) >> + >> + if arg in ['path']: >> + path = value >> + elif arg in ['help']: >> + os.execlp('man', 'man', 'qmp') >> + else: >> + print 'Unknown argument "%s"' % arg >> + >> + args = args[1:] >> + else: >> + break >> + >> + if not path: >> + print "QMP path isn't set, use --path or set QMP_PATH" >> + return 1 >> + >> + command, args = args[0], args[1:] >> + >> + if command in ['help']: >> + os.execlp('man', 'man', 'qmp') >> + >> + srv = QEMUMonitorProtocol(path) >> + srv.connect() >> + >> + def do_command(srv, cmd, **kwds): >> + rsp = srv.cmd(cmd, kwds) >> + if rsp.has_key('error'): >> + raise Exception(rsp['error']['desc']) >> + return rsp['return'] >> + >> + commands = map(lambda x: x['name'], do_command(srv, 'query-commands')) >> + >> + srv.close() >> + >> + if command not in commands: >> + fullcmd = 'qmp-%s' % command >> + try: >> + os.environ['QMP_PATH'] = path >> + os.execvp(fullcmd, [fullcmd] + args) >> + except OSError, (errno, msg): >> + if errno == 2: >> + print 'Command "%s" not found.' % (fullcmd) >> + return 1 >> + raise >> + return 0 >> + >> + srv = QEMUMonitorProtocol(path) >> + srv.connect() >> + >> + arguments = {} >> + for arg in args: >> + if not arg.startswith('--'): >> + print 'Unknown argument "%s"' % arg >> + return 1 >> + >> + arg = arg[2:] >> + if arg.find('=') == -1: >> + value = True >> + else: >> + arg, value = arg.split('=', 1) >> + >> + if arg in ['help']: >> + os.execlp('man', 'man', 'qmp-%s' % command) >> + return 1 >> + >> + arguments[arg] = value >> + >> + rsp = do_command(srv, command, **arguments) >> + print_response(rsp) >> + >> +if __name__ == '__main__': >> + sys.exit(main(sys.argv[1:])) > > ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-11-08 13:57 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-11-07 15:11 [Qemu-devel] [PATCH] qmp: add test tool for QMP Anthony Liguori 2011-11-07 16:08 ` Luiz Capitulino 2011-11-07 16:09 ` Anthony Liguori 2011-11-07 16:30 ` Luiz Capitulino 2011-11-07 16:35 ` Anthony Liguori 2011-11-07 16:39 ` Luiz Capitulino 2011-11-07 17:26 ` Alon Levy 2011-11-08 8:36 ` Mark Wu 2011-11-08 11:56 ` Luiz Capitulino 2011-11-08 13:57 ` Anthony Liguori
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).