From patchwork Wed Nov 9 05:55:33 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Wu X-Patchwork-Id: 124478 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 620451007D8 for ; Wed, 9 Nov 2011 16:56:11 +1100 (EST) Received: from localhost ([::1]:50515 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RO18h-00027q-9h for incoming@patchwork.ozlabs.org; Wed, 09 Nov 2011 00:55:59 -0500 Received: from eggs.gnu.org ([140.186.70.92]:50184) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RO18b-00027d-56 for qemu-devel@nongnu.org; Wed, 09 Nov 2011 00:55:54 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RO18Z-0002XP-Ns for qemu-devel@nongnu.org; Wed, 09 Nov 2011 00:55:53 -0500 Received: from e23smtp06.au.ibm.com ([202.81.31.148]:41097) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RO18Z-0002XI-61 for qemu-devel@nongnu.org; Wed, 09 Nov 2011 00:55:51 -0500 Received: from d23relay03.au.ibm.com (d23relay03.au.ibm.com [202.81.31.245]) by e23smtp06.au.ibm.com (8.14.4/8.13.1) with ESMTP id pA95sPfm029275 for ; Wed, 9 Nov 2011 16:54:25 +1100 Received: from d23av01.au.ibm.com (d23av01.au.ibm.com [9.190.234.96]) by d23relay03.au.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id pA95tkNb1507340 for ; Wed, 9 Nov 2011 16:55:46 +1100 Received: from d23av01.au.ibm.com (loopback [127.0.0.1]) by d23av01.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id pA95tkUK003566 for ; Wed, 9 Nov 2011 16:55:46 +1100 Received: from oc4654482034.ibm.com ([9.115.122.153]) by d23av01.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id pA95tjHh003547; Wed, 9 Nov 2011 16:55:45 +1100 Received: by oc4654482034.ibm.com (Postfix, from userid 500) id 21DCD44C88; Wed, 9 Nov 2011 13:55:43 +0800 (CST) From: Mark Wu To: Anthony Liguori , Luiz Capitulino Date: Wed, 9 Nov 2011 13:55:33 +0800 Message-Id: <1320818133-8930-1-git-send-email-wudxw@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.1 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-Received-From: 202.81.31.148 Cc: qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH v2] qmp: add test tool for QMP X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Anthony 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 Signed-off-by: Mark Wu Acked-by: Luiz Capitulino --- QMP/qmp | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 126 insertions(+), 0 deletions(-) create mode 100755 QMP/qmp diff --git a/QMP/qmp b/QMP/qmp new file mode 100755 index 0000000..1db3c7f --- /dev/null +++ b/QMP/qmp @@ -0,0 +1,126 @@ +#!/usr/bin/python +# +# QMP command line tool +# +# Copyright IBM, Corp. 2011 +# +# Authors: +# Anthony Liguori +# +# 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']: + if type(value) == str: + 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=qmp-monitor-address or set QMP_PATH" + return 1 + + if len(args): + command, args = args[0], args[1:] + else: + print 'No command found' + print 'Usage: "qmp [--path=qmp-monitor-address] qmp-cmd arguments"' + return 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:]))