Merge remote-tracking branch 'remotes/berrange/tags/pull-qio-2017-10-04-1' into staging
[qemu/kevin.git] / scripts / qmp / qmp.py
blobef12e8a1a0eddcb864f965d4819b15890e2aeec9
1 # QEMU Monitor Protocol Python class
3 # Copyright (C) 2009, 2010 Red Hat Inc.
5 # Authors:
6 # Luiz Capitulino <lcapitulino@redhat.com>
8 # This work is licensed under the terms of the GNU GPL, version 2. See
9 # the COPYING file in the top-level directory.
11 import json
12 import errno
13 import socket
14 import sys
17 class QMPError(Exception):
18 pass
21 class QMPConnectError(QMPError):
22 pass
25 class QMPCapabilitiesError(QMPError):
26 pass
29 class QMPTimeoutError(QMPError):
30 pass
33 class QEMUMonitorProtocol(object):
35 #: Socket's error class
36 error = socket.error
37 #: Socket's timeout
38 timeout = socket.timeout
40 def __init__(self, address, server=False, debug=False):
41 """
42 Create a QEMUMonitorProtocol class.
44 @param address: QEMU address, can be either a unix socket path (string)
45 or a tuple in the form ( address, port ) for a TCP
46 connection
47 @param server: server mode listens on the socket (bool)
48 @raise socket.error on socket connection errors
49 @note No connection is established, this is done by the connect() or
50 accept() methods
51 """
52 self.__events = []
53 self.__address = address
54 self._debug = debug
55 self.__sock = self.__get_sock()
56 self.__sockfile = None
57 if server:
58 self.__sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
59 self.__sock.bind(self.__address)
60 self.__sock.listen(1)
62 def __get_sock(self):
63 if isinstance(self.__address, tuple):
64 family = socket.AF_INET
65 else:
66 family = socket.AF_UNIX
67 return socket.socket(family, socket.SOCK_STREAM)
69 def __negotiate_capabilities(self):
70 greeting = self.__json_read()
71 if greeting is None or "QMP" not in greeting:
72 raise QMPConnectError
73 # Greeting seems ok, negotiate capabilities
74 resp = self.cmd('qmp_capabilities')
75 if "return" in resp:
76 return greeting
77 raise QMPCapabilitiesError
79 def __json_read(self, only_event=False):
80 while True:
81 data = self.__sockfile.readline()
82 if not data:
83 return
84 resp = json.loads(data)
85 if 'event' in resp:
86 if self._debug:
87 print >>sys.stderr, "QMP:<<< %s" % resp
88 self.__events.append(resp)
89 if not only_event:
90 continue
91 return resp
93 def __get_events(self, wait=False):
94 """
95 Check for new events in the stream and cache them in __events.
97 @param wait (bool): block until an event is available.
98 @param wait (float): If wait is a float, treat it as a timeout value.
100 @raise QMPTimeoutError: If a timeout float is provided and the timeout
101 period elapses.
102 @raise QMPConnectError: If wait is True but no events could be
103 retrieved or if some other error occurred.
106 # Check for new events regardless and pull them into the cache:
107 self.__sock.setblocking(0)
108 try:
109 self.__json_read()
110 except socket.error as err:
111 if err[0] == errno.EAGAIN:
112 # No data available
113 pass
114 self.__sock.setblocking(1)
116 # Wait for new events, if needed.
117 # if wait is 0.0, this means "no wait" and is also implicitly false.
118 if not self.__events and wait:
119 if isinstance(wait, float):
120 self.__sock.settimeout(wait)
121 try:
122 ret = self.__json_read(only_event=True)
123 except socket.timeout:
124 raise QMPTimeoutError("Timeout waiting for event")
125 except:
126 raise QMPConnectError("Error while reading from socket")
127 if ret is None:
128 raise QMPConnectError("Error while reading from socket")
129 self.__sock.settimeout(None)
131 def connect(self, negotiate=True):
133 Connect to the QMP Monitor and perform capabilities negotiation.
135 @return QMP greeting dict
136 @raise socket.error on socket connection errors
137 @raise QMPConnectError if the greeting is not received
138 @raise QMPCapabilitiesError if fails to negotiate capabilities
140 self.__sock.connect(self.__address)
141 self.__sockfile = self.__sock.makefile()
142 if negotiate:
143 return self.__negotiate_capabilities()
145 def accept(self):
147 Await connection from QMP Monitor and perform capabilities negotiation.
149 @return QMP greeting dict
150 @raise socket.error on socket connection errors
151 @raise QMPConnectError if the greeting is not received
152 @raise QMPCapabilitiesError if fails to negotiate capabilities
154 self.__sock.settimeout(15)
155 self.__sock, _ = self.__sock.accept()
156 self.__sockfile = self.__sock.makefile()
157 return self.__negotiate_capabilities()
159 def cmd_obj(self, qmp_cmd):
161 Send a QMP command to the QMP Monitor.
163 @param qmp_cmd: QMP command to be sent as a Python dict
164 @return QMP response as a Python dict or None if the connection has
165 been closed
167 if self._debug:
168 print >>sys.stderr, "QMP:>>> %s" % qmp_cmd
169 try:
170 self.__sock.sendall(json.dumps(qmp_cmd))
171 except socket.error as err:
172 if err[0] == errno.EPIPE:
173 return
174 raise socket.error(err)
175 resp = self.__json_read()
176 if self._debug:
177 print >>sys.stderr, "QMP:<<< %s" % resp
178 return resp
180 def cmd(self, name, args=None, cmd_id=None):
182 Build a QMP command and send it to the QMP Monitor.
184 @param name: command name (string)
185 @param args: command arguments (dict)
186 @param cmd_id: command id (dict, list, string or int)
188 qmp_cmd = {'execute': name}
189 if args:
190 qmp_cmd['arguments'] = args
191 if cmd_id:
192 qmp_cmd['id'] = cmd_id
193 return self.cmd_obj(qmp_cmd)
195 def command(self, cmd, **kwds):
197 Build and send a QMP command to the monitor, report errors if any
199 ret = self.cmd(cmd, kwds)
200 if "error" in ret:
201 raise Exception(ret['error']['desc'])
202 return ret['return']
204 def pull_event(self, wait=False):
206 Pulls a single event.
208 @param wait (bool): block until an event is available.
209 @param wait (float): If wait is a float, treat it as a timeout value.
211 @raise QMPTimeoutError: If a timeout float is provided and the timeout
212 period elapses.
213 @raise QMPConnectError: If wait is True but no events could be
214 retrieved or if some other error occurred.
216 @return The first available QMP event, or None.
218 self.__get_events(wait)
220 if self.__events:
221 return self.__events.pop(0)
222 return None
224 def get_events(self, wait=False):
226 Get a list of available QMP events.
228 @param wait (bool): block until an event is available.
229 @param wait (float): If wait is a float, treat it as a timeout value.
231 @raise QMPTimeoutError: If a timeout float is provided and the timeout
232 period elapses.
233 @raise QMPConnectError: If wait is True but no events could be
234 retrieved or if some other error occurred.
236 @return The list of available QMP events.
238 self.__get_events(wait)
239 return self.__events
241 def clear_events(self):
243 Clear current list of pending events.
245 self.__events = []
247 def close(self):
248 self.__sock.close()
249 self.__sockfile.close()
251 def settimeout(self, timeout):
252 self.__sock.settimeout(timeout)
254 def get_sock_fd(self):
255 return self.__sock.fileno()
257 def is_scm_available(self):
258 return self.__sock.family == socket.AF_UNIX