aboutsummaryrefslogtreecommitdiff
path: root/QMP
diff options
context:
space:
mode:
Diffstat (limited to 'QMP')
-rw-r--r--QMP/README51
-rw-r--r--QMP/qmp-events.txt26
-rwxr-xr-xQMP/qmp-shell72
-rw-r--r--QMP/qmp-spec.txt192
-rw-r--r--QMP/qmp.py72
-rwxr-xr-xQMP/vm-info32
6 files changed, 445 insertions, 0 deletions
diff --git a/QMP/README b/QMP/README
new file mode 100644
index 000000000..50c31f20c
--- /dev/null
+++ b/QMP/README
@@ -0,0 +1,51 @@
+ QEMU Monitor Protocol
+ =====================
+
+Introduction
+-------------
+
+The QEMU Monitor Protocol (QMP) is a JSON[1] based protocol for QEMU.
+
+By using it applications can control QEMU in reliable and "parseable" way,
+QMP also provides asynchronous events support.
+
+For more information, please, refer to the following files:
+
+o qmp-spec.txt QEMU Monitor Protocol current draft specification
+o qmp-events.txt List of available asynchronous events
+
+There are also two simple Python scripts available:
+
+o qmp-shell A shell
+o vm-info Show some informations about the Virtal Machine
+
+[1] http://www.json.org
+
+Usage
+-----
+
+To enable QMP, QEMU has to be started in "control mode". This is done
+by passing the flag "control" to the "-monitor" command-line option.
+
+For example:
+
+$ qemu [...] -monitor control,tcp:localhost:4444,server
+
+Will start QEMU in control mode, waiting for a client TCP connection
+on localhost port 4444.
+
+To manually test it you can connect with telnet and issue commands:
+
+$ telnet localhost 4444
+Trying ::1...
+Connected to localhost.
+Escape character is '^]'.
+{"QMP": {"capabilities": []}}
+{ "execute": "query-version" }
+{"return": "0.11.50"}
+
+Contact
+-------
+
+http://www.linux-kvm.org/page/MonitorProtocol
+Luiz Fernando N. Capitulino <lcapitulino@redhat.com>
diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
new file mode 100644
index 000000000..682a5e53a
--- /dev/null
+++ b/QMP/qmp-events.txt
@@ -0,0 +1,26 @@
+ QEMU Monitor Protocol: Events
+ =============================
+
+1 SHUTDOWN
+-----------
+
+Description: Issued when the Virtual Machine is powered down.
+Data: None.
+
+2 RESET
+-------
+
+Description: Issued when the Virtual Machine is reseted.
+Data: None.
+
+3 STOP
+------
+
+Description: Issued when the Virtual Machine is stopped.
+Data: None.
+
+4 DEBUG
+-------
+
+Description: Issued when the Virtual Machine enters debug mode.
+Data: None.
diff --git a/QMP/qmp-shell b/QMP/qmp-shell
new file mode 100755
index 000000000..f89b9af87
--- /dev/null
+++ b/QMP/qmp-shell
@@ -0,0 +1,72 @@
+#!/usr/bin/python
+#
+# Simple QEMU shell on top of QMP
+#
+# Copyright (C) 2009 Red Hat Inc.
+#
+# Authors:
+# Luiz Capitulino <lcapitulino@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2. See
+# the COPYING file in the top-level directory.
+#
+# 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
+
+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 <unix-socket>'
+ 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: <command-name> ',
+ print '[arg-name1=arg1] ... [arg-nameN=argN]'
+
+if __name__ == '__main__':
+ main()
diff --git a/QMP/qmp-spec.txt b/QMP/qmp-spec.txt
new file mode 100644
index 000000000..8429789a9
--- /dev/null
+++ b/QMP/qmp-spec.txt
@@ -0,0 +1,192 @@
+ QEMU Monitor Protocol Draft Specification - Version 0.1
+
+1. Introduction
+===============
+
+This document specifies the QEMU Monitor Protocol (QMP), a JSON-based protocol
+which is available for applications to control QEMU at the machine-level.
+
+To enable QMP support, QEMU has to be run in "control mode". This is done by
+starting QEMU with the appropriate command-line options. Please, refer to the
+QEMU manual page for more information.
+
+2. Protocol Specification
+=========================
+
+This section details the protocol format. For the purpose of this document
+"Client" is any application which is communicating with QEMU in control mode,
+and "Server" is QEMU itself.
+
+JSON data structures, when mentioned in this document, are always in the
+following format:
+
+ json-DATA-STRUCTURE-NAME
+
+Where DATA-STRUCTURE-NAME is any valid JSON data structure, as defined by
+the JSON standard:
+
+http://www.ietf.org/rfc/rfc4627.txt
+
+For convenience, json-objects mentioned in this document will have its members
+in a certain order. However, in real protocol usage json-objects members can
+be in ANY order, thus no particular order should be assumed.
+
+2.1 General Definitions
+-----------------------
+
+2.1.1 All interactions transmitted by the Server are json-objects, always
+ terminating with CRLF
+
+2.1.2 All json-objects members are mandatory when not specified otherwise
+
+2.2 Server Greeting
+-------------------
+
+Right when connected the Server will issue a greeting message, which signals
+that the connection has been successfully established and that the Server is
+waiting for commands.
+
+The format is:
+
+{ "QMP": { "capabilities": json-array } }
+
+ Where,
+
+- The "capabilities" member specify the availability of features beyond the
+ baseline specification
+
+2.3 Issuing Commands
+--------------------
+
+The format for command execution is:
+
+{ "execute": json-string, "arguments": json-object, "id": json-value }
+
+ Where,
+
+- The "execute" member identifies the command to be executed by the Server
+- The "arguments" member is used to pass any arguments required for the
+ execution of the command, it is optional when no arguments are required
+- The "id" member is a transaction identification associated with the
+ command execution, it is optional and will be part of the response if
+ provided
+
+2.4 Commands Responses
+----------------------
+
+There are two possible responses which the Server will issue as the result
+of a command execution: success or error.
+
+2.4.1 success
+-------------
+
+The success response is issued when the command execution has finished
+without errors.
+
+The format is:
+
+{ "return": json-value, "id": json-value }
+
+ Where,
+
+- The "return" member contains the command returned data, which is defined
+ in a per-command basis or "OK" if the command does not return data
+- The "id" member contains the transaction identification associated
+ with the command execution (if issued by the Client)
+
+2.4.2 error
+-----------
+
+The error response is issued when the command execution could not be
+completed because of an error condition.
+
+The format is:
+
+{ "error": { "class": json-string, "data": json-value }, "id": json-value }
+
+ Where,
+
+- The "class" member contains the error class name (eg. "ServiceUnavailable")
+- The "data" member contains specific error data and is defined in a
+ per-command basis, it will be an empty json-object if the error has no data
+- The "id" member contains the transaction identification associated with
+ the command execution (if issued by the Client)
+
+NOTE: Some errors can occur before the Server is able to read the "id" member,
+in these cases the "id" member will not be part of the error response, even
+if provided by the client.
+
+2.5 Asynchronous events
+-----------------------
+
+As a result of state changes, the Server may send messages unilaterally
+to the Client at any time. They are called 'asynchronous events'.
+
+The format is:
+
+{ "event": json-string, "data": json-value,
+ "timestamp": { "seconds": json-number, "microseconds": json-number } }
+
+ Where,
+
+- The "event" member contains the event's name
+- The "data" member contains event specific data, which is defined in a
+ per-event basis, it is optional
+- The "timestamp" member contains the exact time of when the event ocurred
+ in the Server. It is a fixed json-object with time in seconds and
+ microseconds
+
+For a listing of supported asynchronous events, please, refer to the
+qmp-events.txt file.
+
+3. QMP Examples
+===============
+
+This section provides some examples of real QMP usage, in all of them
+'C' stands for 'Client' and 'S' stands for 'Server'.
+
+3.1 Server greeting
+-------------------
+
+S: {"QMP": {"capabilities": []}}
+
+3.2 Simple 'stop' execution
+---------------------------
+
+C: { "execute": "stop" }
+S: {"return": "OK"}
+
+3.3 KVM information
+-------------------
+
+C: {"execute": "query-kvm", "id": "example"}
+S: {"return": "enabled", "id": "example"}
+
+3.4 Parsing error
+------------------
+
+C: { "execute": }
+S: {"error": {"class": "JSONParsing", "data": {}}}
+
+3.5 Powerdown event
+-------------------
+
+S: {"timestamp": {"seconds": 1258551470, "microseconds": 802384}, "event":
+"POWERDOWN"}
+
+4. Notes to Client implementors
+-------------------------------
+
+4.1 It is recommended to always start the Server in pause mode, thus the
+ Client is able to perform any setup procedure without the risk of
+ race conditions and related problems
+
+4.2 It is recommended to always check the capabilities json-array, issued
+ with the greeting message, at connection time
+
+4.3 Json-objects or json-arrays mentioned in this document are not fixed
+ and no particular size or number of members/elements should be assumed.
+ New members/elements can be added at any time.
+
+4.4 No particular order of json-objects members should be assumed, they
+ can change at any time
diff --git a/QMP/qmp.py b/QMP/qmp.py
new file mode 100644
index 000000000..d9da603be
--- /dev/null
+++ b/QMP/qmp.py
@@ -0,0 +1,72 @@
+# QEMU Monitor Protocol Python class
+#
+# Copyright (C) 2009 Red Hat Inc.
+#
+# Authors:
+# Luiz Capitulino <lcapitulino@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2. See
+# the COPYING file in the top-level directory.
+
+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 close(self):
+ self.sock.close()
+
+ def send_raw(self, line):
+ self.sock.send(str(line))
+ return self.__json_read()
+
+ 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):
+ # XXX: We have to send any additional char, otherwise
+ # the Server won't read our input
+ self.sock.send(json.dumps(cmd) + ' ')
+
+ 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)
diff --git a/QMP/vm-info b/QMP/vm-info
new file mode 100755
index 000000000..b150d8240
--- /dev/null
+++ b/QMP/vm-info
@@ -0,0 +1,32 @@
+#!/usr/bin/python
+#
+# Print Virtual Machine information
+#
+# Usage:
+#
+# Start QEMU with:
+#
+# $ qemu [...] -monitor control,unix:./qmp,server
+#
+# Run vm-info:
+#
+# $ vm-info ./qmp
+#
+# Luiz Capitulino <lcapitulino@redhat.com>
+
+import qmp
+from sys import argv,exit
+
+def main():
+ if len(argv) != 2:
+ print 'vm-info <unix-socket>'
+ exit(1)
+
+ qemu = qmp.QEMUMonitorProtocol(argv[1])
+ qemu.connect()
+
+ for cmd in [ 'version', 'hpet', 'kvm', 'status', 'uuid', 'balloon' ]:
+ print cmd + ': ' + str(qemu.send('query-' + cmd))
+
+if __name__ == '__main__':
+ main()