From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NB8iJ-0007oV-Lg for qemu-devel@nongnu.org; Thu, 19 Nov 2009 10:14:27 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NB8iE-0007l4-OZ for qemu-devel@nongnu.org; Thu, 19 Nov 2009 10:14:27 -0500 Received: from [199.232.76.173] (port=49927 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NB8iE-0007l0-JH for qemu-devel@nongnu.org; Thu, 19 Nov 2009 10:14:22 -0500 Received: from mx1.redhat.com ([209.132.183.28]:36113) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NB8iE-0002Av-1K for qemu-devel@nongnu.org; Thu, 19 Nov 2009 10:14:22 -0500 From: Luiz Capitulino Date: Thu, 19 Nov 2009 13:13:42 -0200 Message-Id: <1258643623-8636-15-git-send-email-lcapitulino@redhat.com> In-Reply-To: <1258643623-8636-1-git-send-email-lcapitulino@redhat.com> References: <1258643623-8636-1-git-send-email-lcapitulino@redhat.com> Subject: [Qemu-devel] [PATCH 14/15] QMP: Introduce qmp-shell List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: aliguori@us.ibm.com, avi@redhat.com This is a very simple shell written in Python which works on top of QMP. Unfortunately it's a bit awkward right now, as the user has to specify the arguments names, for example: (QEMU) info item=version 0.11.50 (QEMU) Also, if the output is not a string or integer, the user is is going to get a low-level dictionary or list. It's worth to note that the shell is broken into two files. One is the shell itself, the other is the QMP class which handles the communication with QEMU. Signed-off-by: Luiz Capitulino --- QMP/qmp-shell | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ QMP/qmp.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 0 deletions(-) create mode 100755 QMP/qmp-shell create mode 100644 QMP/qmp.py diff --git a/QMP/qmp-shell b/QMP/qmp-shell new file mode 100755 index 0000000..2faf79b --- /dev/null +++ b/QMP/qmp-shell @@ -0,0 +1,66 @@ +#!/usr/bin/python +# +# Simple QEMU shell on top of QMP +# +# Usage: +# +# Start QEMU with: +# +# $ qemu [...] -monitor control,unix:./qmp,server +# +# Run the shell: +# +# $ qmp-shell ./qmp +# +# Commands have the following format: +# +# < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ] +# +# For example: +# +# (QEMU) info item=network +# +# Luiz Capitulino + +import qmp +import readline +from sys import argv,exit + +def shell_help(): + print 'bye exit from the shell' + +def main(): + if len(argv) != 2: + print 'qemu-shell ' + exit(1) + + qemu = qmp.QEMUMonitorProtocol(argv[1]) + qemu.connect() + + print 'Connected!' + + while True: + try: + cmd = raw_input('(QEMU) ') + except EOFError: + print + break + if cmd == '': + continue + elif cmd == 'bye': + break + elif cmd == 'help': + shell_help() + else: + try: + resp = qemu.send(cmd) + if resp == None: + print 'Disconnected' + break + print resp + except IndexError: + print '-> command format: ', + print '[arg-name1=arg1] ... [arg-nameN=argN]' + +if __name__ == '__main__': + main() diff --git a/QMP/qmp.py b/QMP/qmp.py new file mode 100644 index 0000000..c56f143 --- /dev/null +++ b/QMP/qmp.py @@ -0,0 +1,54 @@ +import socket, json + +class QMPError(Exception): + pass + +class QMPConnectError(QMPError): + pass + +class QEMUMonitorProtocol: + def connect(self): + self.sock.connect(self.filename) + data = self.__json_read() + if data == None: + raise QMPConnectError + if not data.has_key('QMP'): + raise QMPConnectError + return data['QMP']['capabilities'] + + def send(self, cmdline): + cmd = self.__build_cmd(cmdline) + self.__json_send(cmd) + resp = self.__json_read() + if resp == None: + return + elif resp.has_key('error'): + return resp['error'] + else: + return resp['return'] + + def __build_cmd(self, cmdline): + cmdargs = cmdline.split() + qmpcmd = { 'execute': cmdargs[0], 'arguments': {} } + for arg in cmdargs[1:]: + opt = arg.split('=') + try: + value = int(opt[1]) + except ValueError: + value = opt[1] + qmpcmd['arguments'][opt[0]] = value + return qmpcmd + + def __json_send(self, cmd): + self.sock.send(json.dumps(cmd) + '\n') + + def __json_read(self): + try: + return json.loads(self.sock.recv(1024)) + except ValueError: + return + + def __init__(self, filename): + self.filename = filename + self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + -- 1.6.5.3.148.g785c5