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.
15 class QMPError(Exception):
18 class QMPConnectError(QMPError
):
21 class QMPCapabilitiesError(QMPError
):
24 class QMPTimeoutError(QMPError
):
27 class QEMUMonitorProtocol
:
28 def __init__(self
, address
, server
=False):
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
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
41 self
.__address
= address
42 self
.__sock
= self
.__get
_sock
()
44 self
.__sock
.bind(self
.__address
)
48 if isinstance(self
.__address
, tuple):
49 family
= socket
.AF_INET
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'):
58 # Greeting seems ok, negotiate capabilities
59 resp
= self
.cmd('qmp_capabilities')
62 raise QMPCapabilitiesError
64 def __json_read(self
, only_event
=False):
66 data
= self
.__sockfile
.readline()
69 resp
= json
.loads(data
)
71 self
.__events
.append(resp
)
78 def __get_events(self
, wait
=False):
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
87 @raise QMPConnectError: If wait is True but no events could be retrieved
88 or if some other error occurred.
91 # Check for new events regardless and pull them into the cache:
92 self
.__sock
.setblocking(0)
95 except socket
.error
as err
:
96 if err
[0] == errno
.EAGAIN
:
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
)
107 ret
= self
.__json
_read
(only_event
=True)
108 except socket
.timeout
:
109 raise QMPTimeoutError("Timeout waiting for event")
111 raise QMPConnectError("Error while reading from socket")
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()
128 return self
.__negotiate
_capabilities
()
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
152 self
.__sock
.sendall(json
.dumps(qmp_cmd
))
153 except socket
.error
as err
:
154 if err
[0] == errno
.EPIPE
:
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
}
169 qmp_cmd
['arguments'] = args
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'])
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
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
)
197 return self
.__events
.pop(0)
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
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
)
217 def clear_events(self
):
219 Clear current list of pending events.
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