hw/riscv: sifive_u: Sort the SoC memmap table entries
[qemu/ar7.git] / python / qemu / qmp.py
blobe64b6b5faa747d6146e30ac1d2079a052c60be30
1 """ QEMU Monitor Protocol Python class """
2 # Copyright (C) 2009, 2010 Red Hat Inc.
4 # Authors:
5 # Luiz Capitulino <lcapitulino@redhat.com>
7 # This work is licensed under the terms of the GNU GPL, version 2. See
8 # the COPYING file in the top-level directory.
10 import json
11 import errno
12 import socket
13 import logging
14 from typing import (
15 Optional,
16 TextIO,
17 Type,
19 from types import TracebackType
22 class QMPError(Exception):
23 """
24 QMP base exception
25 """
28 class QMPConnectError(QMPError):
29 """
30 QMP connection exception
31 """
34 class QMPCapabilitiesError(QMPError):
35 """
36 QMP negotiate capabilities exception
37 """
40 class QMPTimeoutError(QMPError):
41 """
42 QMP timeout exception
43 """
46 class QEMUMonitorProtocol:
47 """
48 Provide an API to connect to QEMU via QEMU Monitor Protocol (QMP) and then
49 allow to handle commands and events.
50 """
52 #: Logger object for debugging messages
53 logger = logging.getLogger('QMP')
55 def __init__(self, address, server=False, nickname=None):
56 """
57 Create a QEMUMonitorProtocol class.
59 @param address: QEMU address, can be either a unix socket path (string)
60 or a tuple in the form ( address, port ) for a TCP
61 connection
62 @param server: server mode listens on the socket (bool)
63 @raise OSError on socket connection errors
64 @note No connection is established, this is done by the connect() or
65 accept() methods
66 """
67 self.__events = []
68 self.__address = address
69 self.__sock = self.__get_sock()
70 self.__sockfile: Optional[TextIO] = None
71 self._nickname = nickname
72 if self._nickname:
73 self.logger = logging.getLogger('QMP').getChild(self._nickname)
74 if server:
75 self.__sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
76 self.__sock.bind(self.__address)
77 self.__sock.listen(1)
79 def __get_sock(self):
80 if isinstance(self.__address, tuple):
81 family = socket.AF_INET
82 else:
83 family = socket.AF_UNIX
84 return socket.socket(family, socket.SOCK_STREAM)
86 def __negotiate_capabilities(self):
87 greeting = self.__json_read()
88 if greeting is None or "QMP" not in greeting:
89 raise QMPConnectError
90 # Greeting seems ok, negotiate capabilities
91 resp = self.cmd('qmp_capabilities')
92 if resp and "return" in resp:
93 return greeting
94 raise QMPCapabilitiesError
96 def __json_read(self, only_event=False):
97 assert self.__sockfile is not None
98 while True:
99 data = self.__sockfile.readline()
100 if not data:
101 return None
102 resp = json.loads(data)
103 if 'event' in resp:
104 self.logger.debug("<<< %s", resp)
105 self.__events.append(resp)
106 if not only_event:
107 continue
108 return resp
110 def __get_events(self, wait=False):
112 Check for new events in the stream and cache them in __events.
114 @param wait (bool): block until an event is available.
115 @param wait (float): If wait is a float, treat it as a timeout value.
117 @raise QMPTimeoutError: If a timeout float is provided and the timeout
118 period elapses.
119 @raise QMPConnectError: If wait is True but no events could be
120 retrieved or if some other error occurred.
123 # Check for new events regardless and pull them into the cache:
124 self.__sock.setblocking(False)
125 try:
126 self.__json_read()
127 except OSError as err:
128 if err.errno == errno.EAGAIN:
129 # No data available
130 pass
131 self.__sock.setblocking(True)
133 # Wait for new events, if needed.
134 # if wait is 0.0, this means "no wait" and is also implicitly false.
135 if not self.__events and wait:
136 if isinstance(wait, float):
137 self.__sock.settimeout(wait)
138 try:
139 ret = self.__json_read(only_event=True)
140 except socket.timeout:
141 raise QMPTimeoutError("Timeout waiting for event")
142 except:
143 raise QMPConnectError("Error while reading from socket")
144 if ret is None:
145 raise QMPConnectError("Error while reading from socket")
146 self.__sock.settimeout(None)
148 def __enter__(self):
149 # Implement context manager enter function.
150 return self
152 def __exit__(self,
153 # pylint: disable=duplicate-code
154 # see https://github.com/PyCQA/pylint/issues/3619
155 exc_type: Optional[Type[BaseException]],
156 exc_val: Optional[BaseException],
157 exc_tb: Optional[TracebackType]) -> None:
158 # Implement context manager exit function.
159 self.close()
161 def connect(self, negotiate=True):
163 Connect to the QMP Monitor and perform capabilities negotiation.
165 @return QMP greeting dict, or None if negotiate is false
166 @raise OSError on socket connection errors
167 @raise QMPConnectError if the greeting is not received
168 @raise QMPCapabilitiesError if fails to negotiate capabilities
170 self.__sock.connect(self.__address)
171 self.__sockfile = self.__sock.makefile(mode='r')
172 if negotiate:
173 return self.__negotiate_capabilities()
174 return None
176 def accept(self, timeout=15.0):
178 Await connection from QMP Monitor and perform capabilities negotiation.
180 @param timeout: timeout in seconds (nonnegative float number, or
181 None). The value passed will set the behavior of the
182 underneath QMP socket as described in [1].
183 Default value is set to 15.0.
184 @return QMP greeting dict
185 @raise OSError on socket connection errors
186 @raise QMPConnectError if the greeting is not received
187 @raise QMPCapabilitiesError if fails to negotiate capabilities
190 https://docs.python.org/3/library/socket.html#socket.socket.settimeout
192 self.__sock.settimeout(timeout)
193 self.__sock, _ = self.__sock.accept()
194 self.__sockfile = self.__sock.makefile(mode='r')
195 return self.__negotiate_capabilities()
197 def cmd_obj(self, qmp_cmd):
199 Send a QMP command to the QMP Monitor.
201 @param qmp_cmd: QMP command to be sent as a Python dict
202 @return QMP response as a Python dict or None if the connection has
203 been closed
205 self.logger.debug(">>> %s", qmp_cmd)
206 try:
207 self.__sock.sendall(json.dumps(qmp_cmd).encode('utf-8'))
208 except OSError as err:
209 if err.errno == errno.EPIPE:
210 return None
211 raise err
212 resp = self.__json_read()
213 self.logger.debug("<<< %s", resp)
214 return resp
216 def cmd(self, name, args=None, cmd_id=None):
218 Build a QMP command and send it to the QMP Monitor.
220 @param name: command name (string)
221 @param args: command arguments (dict)
222 @param cmd_id: command id (dict, list, string or int)
224 qmp_cmd = {'execute': name}
225 if args:
226 qmp_cmd['arguments'] = args
227 if cmd_id:
228 qmp_cmd['id'] = cmd_id
229 return self.cmd_obj(qmp_cmd)
231 def command(self, cmd, **kwds):
233 Build and send a QMP command to the monitor, report errors if any
235 ret = self.cmd(cmd, kwds)
236 if "error" in ret:
237 raise Exception(ret['error']['desc'])
238 return ret['return']
240 def pull_event(self, wait=False):
242 Pulls a single event.
244 @param wait (bool): block until an event is available.
245 @param wait (float): If wait is a float, treat it as a timeout value.
247 @raise QMPTimeoutError: If a timeout float is provided and the timeout
248 period elapses.
249 @raise QMPConnectError: If wait is True but no events could be
250 retrieved or if some other error occurred.
252 @return The first available QMP event, or None.
254 self.__get_events(wait)
256 if self.__events:
257 return self.__events.pop(0)
258 return None
260 def get_events(self, wait=False):
262 Get a list of available QMP events.
264 @param wait (bool): block until an event is available.
265 @param wait (float): If wait is a float, treat it as a timeout value.
267 @raise QMPTimeoutError: If a timeout float is provided and the timeout
268 period elapses.
269 @raise QMPConnectError: If wait is True but no events could be
270 retrieved or if some other error occurred.
272 @return The list of available QMP events.
274 self.__get_events(wait)
275 return self.__events
277 def clear_events(self):
279 Clear current list of pending events.
281 self.__events = []
283 def close(self):
285 Close the socket and socket file.
287 if self.__sock:
288 self.__sock.close()
289 if self.__sockfile:
290 self.__sockfile.close()
292 def settimeout(self, timeout):
294 Set the socket timeout.
296 @param timeout (float): timeout in seconds, or None.
297 @note This is a wrap around socket.settimeout
299 self.__sock.settimeout(timeout)
301 def get_sock_fd(self):
303 Get the socket file descriptor.
305 @return The file descriptor number.
307 return self.__sock.fileno()
309 def is_scm_available(self):
311 Check if the socket allows for SCM_RIGHTS.
313 @return True if SCM_RIGHTS is available, otherwise False.
315 return self.__sock.family == socket.AF_UNIX