linux-user: in poll(), if nfds is 0, pfd can be NULL
[qemu/ar7.git] / scripts / qmp / qmp.py
blob1d38e3e9e787dc59cf4972ad1efda88c7aaa6fd6
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
15 class QMPError(Exception):
16 pass
18 class QMPConnectError(QMPError):
19 pass
21 class QMPCapabilitiesError(QMPError):
22 pass
24 class QMPTimeoutError(QMPError):
25 pass
27 class QEMUMonitorProtocol:
28 def __init__(self, address, server=False):
29 """
30 Create a QEMUMonitorProtocol class.
32 @param address: QEMU address, can be either a unix socket path (string)
33 or a tuple in the form ( address, port ) for a TCP
34 connection
35 @param server: server mode listens on the socket (bool)
36 @raise socket.error on socket connection errors
37 @note No connection is established, this is done by the connect() or
38 accept() methods
39 """
40 self.__events = []
41 self.__address = address
42 self.__sock = self.__get_sock()
43 if server:
44 self.__sock.bind(self.__address)
45 self.__sock.listen(1)
47 def __get_sock(self):
48 if isinstance(self.__address, tuple):
49 family = socket.AF_INET
50 else:
51 family = socket.AF_UNIX
52 return socket.socket(family, socket.SOCK_STREAM)
54 def __negotiate_capabilities(self):
55 greeting = self.__json_read()
56 if greeting is None or not greeting.has_key('QMP'):
57 raise QMPConnectError
58 # Greeting seems ok, negotiate capabilities
59 resp = self.cmd('qmp_capabilities')
60 if "return" in resp:
61 return greeting
62 raise QMPCapabilitiesError
64 def __json_read(self, only_event=False):
65 while True:
66 data = self.__sockfile.readline()
67 if not data:
68 return
69 resp = json.loads(data)
70 if 'event' in resp:
71 self.__events.append(resp)
72 if not only_event:
73 continue
74 return resp
76 error = socket.error
78 def __get_events(self, wait=False):
79 """
80 Check for new events in the stream and cache them in __events.
82 @param wait (bool): block until an event is available.
83 @param wait (float): If wait is a float, treat it as a timeout value.
85 @raise QMPTimeoutError: If a timeout float is provided and the timeout
86 period elapses.
87 @raise QMPConnectError: If wait is True but no events could be retrieved
88 or if some other error occurred.
89 """
91 # Check for new events regardless and pull them into the cache:
92 self.__sock.setblocking(0)
93 try:
94 self.__json_read()
95 except socket.error, err:
96 if err[0] == errno.EAGAIN:
97 # No data available
98 pass
99 self.__sock.setblocking(1)
101 # Wait for new events, if needed.
102 # if wait is 0.0, this means "no wait" and is also implicitly false.
103 if not self.__events and wait:
104 if isinstance(wait, float):
105 self.__sock.settimeout(wait)
106 try:
107 ret = self.__json_read(only_event=True)
108 except socket.timeout:
109 raise QMPTimeoutError("Timeout waiting for event")
110 except:
111 raise QMPConnectError("Error while reading from socket")
112 if ret is None:
113 raise QMPConnectError("Error while reading from socket")
114 self.__sock.settimeout(None)
116 def connect(self, negotiate=True):
118 Connect to the QMP Monitor and perform capabilities negotiation.
120 @return QMP greeting dict
121 @raise socket.error on socket connection errors
122 @raise QMPConnectError if the greeting is not received
123 @raise QMPCapabilitiesError if fails to negotiate capabilities
125 self.__sock.connect(self.__address)
126 self.__sockfile = self.__sock.makefile()
127 if negotiate:
128 return self.__negotiate_capabilities()
130 def accept(self):
132 Await connection from QMP Monitor and perform capabilities negotiation.
134 @return QMP greeting dict
135 @raise socket.error on socket connection errors
136 @raise QMPConnectError if the greeting is not received
137 @raise QMPCapabilitiesError if fails to negotiate capabilities
139 self.__sock, _ = self.__sock.accept()
140 self.__sockfile = self.__sock.makefile()
141 return self.__negotiate_capabilities()
143 def cmd_obj(self, qmp_cmd):
145 Send a QMP command to the QMP Monitor.
147 @param qmp_cmd: QMP command to be sent as a Python dict
148 @return QMP response as a Python dict or None if the connection has
149 been closed
151 try:
152 self.__sock.sendall(json.dumps(qmp_cmd))
153 except socket.error, err:
154 if err[0] == errno.EPIPE:
155 return
156 raise socket.error(err)
157 return self.__json_read()
159 def cmd(self, name, args=None, id=None):
161 Build a QMP command and send it to the QMP Monitor.
163 @param name: command name (string)
164 @param args: command arguments (dict)
165 @param id: command id (dict, list, string or int)
167 qmp_cmd = { 'execute': name }
168 if args:
169 qmp_cmd['arguments'] = args
170 if id:
171 qmp_cmd['id'] = id
172 return self.cmd_obj(qmp_cmd)
174 def command(self, cmd, **kwds):
175 ret = self.cmd(cmd, kwds)
176 if ret.has_key('error'):
177 raise Exception(ret['error']['desc'])
178 return ret['return']
180 def pull_event(self, wait=False):
182 Get and delete the first available QMP event.
184 @param wait (bool): block until an event is available.
185 @param wait (float): If wait is a float, treat it as a timeout value.
187 @raise QMPTimeoutError: If a timeout float is provided and the timeout
188 period elapses.
189 @raise QMPConnectError: If wait is True but no events could be retrieved
190 or if some other error occurred.
192 @return The first available QMP event, or None.
194 self.__get_events(wait)
196 if self.__events:
197 return self.__events.pop(0)
198 return None
200 def get_events(self, wait=False):
202 Get a list of available QMP events.
204 @param wait (bool): block until an event is available.
205 @param wait (float): If wait is a float, treat it as a timeout value.
207 @raise QMPTimeoutError: If a timeout float is provided and the timeout
208 period elapses.
209 @raise QMPConnectError: If wait is True but no events could be retrieved
210 or if some other error occurred.
212 @return The list of available QMP events.
214 self.__get_events(wait)
215 return self.__events
217 def clear_events(self):
219 Clear current list of pending events.
221 self.__events = []
223 def close(self):
224 self.__sock.close()
225 self.__sockfile.close()
227 timeout = socket.timeout
229 def settimeout(self, timeout):
230 self.__sock.settimeout(timeout)
232 def get_sock_fd(self):
233 return self.__sock.fileno()
235 def is_scm_available(self):
236 return self.__sock.family == socket.AF_UNIX