1 # QEMU Monitor Protocol Python class
3 # Copyright (C) 2009, 2010 Red Hat Inc.
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.
17 class QMPError(Exception):
21 class QMPConnectError(QMPError
):
25 class QMPCapabilitiesError(QMPError
):
29 class QMPTimeoutError(QMPError
):
33 class QEMUMonitorProtocol(object):
35 #: Socket's error class
38 timeout
= socket
.timeout
40 def __init__(self
, address
, server
=False, debug
=False):
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
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
53 self
.__address
= address
55 self
.__sock
= self
.__get
_sock
()
56 self
.__sockfile
= None
58 self
.__sock
.setsockopt(socket
.SOL_SOCKET
, socket
.SO_REUSEADDR
, 1)
59 self
.__sock
.bind(self
.__address
)
63 if isinstance(self
.__address
, tuple):
64 family
= socket
.AF_INET
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
:
73 # Greeting seems ok, negotiate capabilities
74 resp
= self
.cmd('qmp_capabilities')
77 raise QMPCapabilitiesError
79 def __json_read(self
, only_event
=False):
81 data
= self
.__sockfile
.readline()
84 resp
= json
.loads(data
)
87 print >>sys
.stderr
, "QMP:<<< %s" % resp
88 self
.__events
.append(resp
)
93 def __get_events(self
, wait
=False):
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
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)
110 except socket
.error
as err
:
111 if err
[0] == errno
.EAGAIN
:
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
)
122 ret
= self
.__json
_read
(only_event
=True)
123 except socket
.timeout
:
124 raise QMPTimeoutError("Timeout waiting for event")
126 raise QMPConnectError("Error while reading from socket")
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()
143 return self
.__negotiate
_capabilities
()
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
168 print >>sys
.stderr
, "QMP:>>> %s" % qmp_cmd
170 self
.__sock
.sendall(json
.dumps(qmp_cmd
))
171 except socket
.error
as err
:
172 if err
[0] == errno
.EPIPE
:
174 raise socket
.error(err
)
175 resp
= self
.__json
_read
()
177 print >>sys
.stderr
, "QMP:<<< %s" % 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
}
190 qmp_cmd
['arguments'] = args
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
)
201 raise Exception(ret
['error']['desc'])
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
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
)
221 return self
.__events
.pop(0)
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
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
)
241 def clear_events(self
):
243 Clear current list of pending events.
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