Skip to content

Commit

Permalink
qmp: add test tool for QMP
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Mark Wu <[email protected]>
Signed-off-by: Luiz Capitulino <[email protected]>
  • Loading branch information
Mark Wu authored and Luiz Capitulino committed Dec 6, 2011
1 parent 4b389b5 commit 1c1d46c
Showing 1 changed file with 126 additions and 0 deletions.
126 changes: 126 additions & 0 deletions QMP/qmp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#!/usr/bin/python
#
# QMP command line tool
#
# Copyright IBM, Corp. 2011
#
# Authors:
# Anthony Liguori <[email protected]>
#
# 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:]))

0 comments on commit 1c1d46c

Please sign in to comment.