xics/spapr: Rename xics_kvm_init()
[qemu/ar7.git] / python / qemu / __init__.py
blobdbaf8a5311dd8896495d2045ba603c161f9cbccf
1 # QEMU library
3 # Copyright (C) 2015-2016 Red Hat Inc.
4 # Copyright (C) 2012 IBM Corp.
6 # Authors:
7 # Fam Zheng <famz@redhat.com>
9 # This work is licensed under the terms of the GNU GPL, version 2. See
10 # the COPYING file in the top-level directory.
12 # Based on qmp.py.
15 import errno
16 import logging
17 import os
18 import subprocess
19 import re
20 import shutil
21 import socket
22 import tempfile
24 from . import qmp
27 LOG = logging.getLogger(__name__)
29 # Mapping host architecture to any additional architectures it can
30 # support which often includes its 32 bit cousin.
31 ADDITIONAL_ARCHES = {
32 "x86_64" : "i386",
33 "aarch64" : "armhf"
36 def kvm_available(target_arch=None):
37 host_arch = os.uname()[4]
38 if target_arch and target_arch != host_arch:
39 if target_arch != ADDITIONAL_ARCHES.get(host_arch):
40 return False
41 return os.access("/dev/kvm", os.R_OK | os.W_OK)
44 class QEMUMachineError(Exception):
45 """
46 Exception called when an error in QEMUMachine happens.
47 """
50 class QEMUMachineAddDeviceError(QEMUMachineError):
51 """
52 Exception raised when a request to add a device can not be fulfilled
54 The failures are caused by limitations, lack of information or conflicting
55 requests on the QEMUMachine methods. This exception does not represent
56 failures reported by the QEMU binary itself.
57 """
59 class MonitorResponseError(qmp.QMPError):
60 """
61 Represents erroneous QMP monitor reply
62 """
63 def __init__(self, reply):
64 try:
65 desc = reply["error"]["desc"]
66 except KeyError:
67 desc = reply
68 super(MonitorResponseError, self).__init__(desc)
69 self.reply = reply
72 class QEMUMachine(object):
73 """
74 A QEMU VM
76 Use this object as a context manager to ensure the QEMU process terminates::
78 with VM(binary) as vm:
79 ...
80 # vm is guaranteed to be shut down here
81 """
83 def __init__(self, binary, args=None, wrapper=None, name=None,
84 test_dir="/var/tmp", monitor_address=None,
85 socket_scm_helper=None):
86 '''
87 Initialize a QEMUMachine
89 @param binary: path to the qemu binary
90 @param args: list of extra arguments
91 @param wrapper: list of arguments used as prefix to qemu binary
92 @param name: prefix for socket and log file names (default: qemu-PID)
93 @param test_dir: where to create socket and log file
94 @param monitor_address: address for QMP monitor
95 @param socket_scm_helper: helper program, required for send_fd_scm()
96 @note: Qemu process is not started until launch() is used.
97 '''
98 if args is None:
99 args = []
100 if wrapper is None:
101 wrapper = []
102 if name is None:
103 name = "qemu-%d" % os.getpid()
104 self._name = name
105 self._monitor_address = monitor_address
106 self._vm_monitor = None
107 self._qemu_log_path = None
108 self._qemu_log_file = None
109 self._popen = None
110 self._binary = binary
111 self._args = list(args) # Force copy args in case we modify them
112 self._wrapper = wrapper
113 self._events = []
114 self._iolog = None
115 self._socket_scm_helper = socket_scm_helper
116 self._qmp = None
117 self._qemu_full_args = None
118 self._test_dir = test_dir
119 self._temp_dir = None
120 self._launched = False
121 self._machine = None
122 self._console_set = False
123 self._console_device_type = None
124 self._console_address = None
125 self._console_socket = None
127 # just in case logging wasn't configured by the main script:
128 logging.basicConfig()
130 def __enter__(self):
131 return self
133 def __exit__(self, exc_type, exc_val, exc_tb):
134 self.shutdown()
135 return False
137 # This can be used to add an unused monitor instance.
138 def add_monitor_null(self):
139 self._args.append('-monitor')
140 self._args.append('null')
142 def add_fd(self, fd, fdset, opaque, opts=''):
144 Pass a file descriptor to the VM
146 options = ['fd=%d' % fd,
147 'set=%d' % fdset,
148 'opaque=%s' % opaque]
149 if opts:
150 options.append(opts)
152 # This did not exist before 3.4, but since then it is
153 # mandatory for our purpose
154 if hasattr(os, 'set_inheritable'):
155 os.set_inheritable(fd, True)
157 self._args.append('-add-fd')
158 self._args.append(','.join(options))
159 return self
161 # Exactly one of fd and file_path must be given.
162 # (If it is file_path, the helper will open that file and pass its
163 # own fd)
164 def send_fd_scm(self, fd=None, file_path=None):
165 # In iotest.py, the qmp should always use unix socket.
166 assert self._qmp.is_scm_available()
167 if self._socket_scm_helper is None:
168 raise QEMUMachineError("No path to socket_scm_helper set")
169 if not os.path.exists(self._socket_scm_helper):
170 raise QEMUMachineError("%s does not exist" %
171 self._socket_scm_helper)
173 # This did not exist before 3.4, but since then it is
174 # mandatory for our purpose
175 if hasattr(os, 'set_inheritable'):
176 os.set_inheritable(self._qmp.get_sock_fd(), True)
177 if fd is not None:
178 os.set_inheritable(fd, True)
180 fd_param = ["%s" % self._socket_scm_helper,
181 "%d" % self._qmp.get_sock_fd()]
183 if file_path is not None:
184 assert fd is None
185 fd_param.append(file_path)
186 else:
187 assert fd is not None
188 fd_param.append(str(fd))
190 devnull = open(os.path.devnull, 'rb')
191 proc = subprocess.Popen(fd_param, stdin=devnull, stdout=subprocess.PIPE,
192 stderr=subprocess.STDOUT, close_fds=False)
193 output = proc.communicate()[0]
194 if output:
195 LOG.debug(output)
197 return proc.returncode
199 @staticmethod
200 def _remove_if_exists(path):
202 Remove file object at path if it exists
204 try:
205 os.remove(path)
206 except OSError as exception:
207 if exception.errno == errno.ENOENT:
208 return
209 raise
211 def is_running(self):
212 return self._popen is not None and self._popen.poll() is None
214 def exitcode(self):
215 if self._popen is None:
216 return None
217 return self._popen.poll()
219 def get_pid(self):
220 if not self.is_running():
221 return None
222 return self._popen.pid
224 def _load_io_log(self):
225 if self._qemu_log_path is not None:
226 with open(self._qemu_log_path, "r") as iolog:
227 self._iolog = iolog.read()
229 def _base_args(self):
230 if isinstance(self._monitor_address, tuple):
231 moncdev = "socket,id=mon,host=%s,port=%s" % (
232 self._monitor_address[0],
233 self._monitor_address[1])
234 else:
235 moncdev = 'socket,id=mon,path=%s' % self._vm_monitor
236 args = ['-chardev', moncdev,
237 '-mon', 'chardev=mon,mode=control',
238 '-display', 'none', '-vga', 'none']
239 if self._machine is not None:
240 args.extend(['-machine', self._machine])
241 if self._console_set:
242 self._console_address = os.path.join(self._temp_dir,
243 self._name + "-console.sock")
244 chardev = ('socket,id=console,path=%s,server,nowait' %
245 self._console_address)
246 args.extend(['-chardev', chardev])
247 if self._console_device_type is None:
248 args.extend(['-serial', 'chardev:console'])
249 else:
250 device = '%s,chardev=console' % self._console_device_type
251 args.extend(['-device', device])
252 return args
254 def _pre_launch(self):
255 self._temp_dir = tempfile.mkdtemp(dir=self._test_dir)
256 if self._monitor_address is not None:
257 self._vm_monitor = self._monitor_address
258 else:
259 self._vm_monitor = os.path.join(self._temp_dir,
260 self._name + "-monitor.sock")
261 self._qemu_log_path = os.path.join(self._temp_dir, self._name + ".log")
262 self._qemu_log_file = open(self._qemu_log_path, 'wb')
264 self._qmp = qmp.QEMUMonitorProtocol(self._vm_monitor,
265 server=True)
267 def _post_launch(self):
268 self._qmp.accept()
270 def _post_shutdown(self):
271 if self._qemu_log_file is not None:
272 self._qemu_log_file.close()
273 self._qemu_log_file = None
275 self._qemu_log_path = None
277 if self._console_socket is not None:
278 self._console_socket.close()
279 self._console_socket = None
281 if self._temp_dir is not None:
282 shutil.rmtree(self._temp_dir)
283 self._temp_dir = None
285 def launch(self):
287 Launch the VM and make sure we cleanup and expose the
288 command line/output in case of exception
291 if self._launched:
292 raise QEMUMachineError('VM already launched')
294 self._iolog = None
295 self._qemu_full_args = None
296 try:
297 self._launch()
298 self._launched = True
299 except:
300 self.shutdown()
302 LOG.debug('Error launching VM')
303 if self._qemu_full_args:
304 LOG.debug('Command: %r', ' '.join(self._qemu_full_args))
305 if self._iolog:
306 LOG.debug('Output: %r', self._iolog)
307 raise
309 def _launch(self):
311 Launch the VM and establish a QMP connection
313 devnull = open(os.path.devnull, 'rb')
314 self._pre_launch()
315 self._qemu_full_args = (self._wrapper + [self._binary] +
316 self._base_args() + self._args)
317 LOG.debug('VM launch command: %r', ' '.join(self._qemu_full_args))
318 self._popen = subprocess.Popen(self._qemu_full_args,
319 stdin=devnull,
320 stdout=self._qemu_log_file,
321 stderr=subprocess.STDOUT,
322 shell=False,
323 close_fds=False)
324 self._post_launch()
326 def wait(self):
328 Wait for the VM to power off
330 self._popen.wait()
331 self._qmp.close()
332 self._load_io_log()
333 self._post_shutdown()
335 def shutdown(self):
337 Terminate the VM and clean up
339 if self.is_running():
340 try:
341 self._qmp.cmd('quit')
342 self._qmp.close()
343 except:
344 self._popen.kill()
345 self._popen.wait()
347 self._load_io_log()
348 self._post_shutdown()
350 exitcode = self.exitcode()
351 if exitcode is not None and exitcode < 0:
352 msg = 'qemu received signal %i: %s'
353 if self._qemu_full_args:
354 command = ' '.join(self._qemu_full_args)
355 else:
356 command = ''
357 LOG.warn(msg, -exitcode, command)
359 self._launched = False
361 def qmp(self, cmd, conv_keys=True, **args):
363 Invoke a QMP command and return the response dict
365 qmp_args = dict()
366 for key, value in args.items():
367 if conv_keys:
368 qmp_args[key.replace('_', '-')] = value
369 else:
370 qmp_args[key] = value
372 return self._qmp.cmd(cmd, args=qmp_args)
374 def command(self, cmd, conv_keys=True, **args):
376 Invoke a QMP command.
377 On success return the response dict.
378 On failure raise an exception.
380 reply = self.qmp(cmd, conv_keys, **args)
381 if reply is None:
382 raise qmp.QMPError("Monitor is closed")
383 if "error" in reply:
384 raise MonitorResponseError(reply)
385 return reply["return"]
387 def get_qmp_event(self, wait=False):
389 Poll for one queued QMP events and return it
391 if len(self._events) > 0:
392 return self._events.pop(0)
393 return self._qmp.pull_event(wait=wait)
395 def get_qmp_events(self, wait=False):
397 Poll for queued QMP events and return a list of dicts
399 events = self._qmp.get_events(wait=wait)
400 events.extend(self._events)
401 del self._events[:]
402 self._qmp.clear_events()
403 return events
405 @staticmethod
406 def event_match(event, match=None):
408 Check if an event matches optional match criteria.
410 The match criteria takes the form of a matching subdict. The event is
411 checked to be a superset of the subdict, recursively, with matching
412 values whenever the subdict values are not None.
414 This has a limitation that you cannot explicitly check for None values.
416 Examples, with the subdict queries on the left:
417 - None matches any object.
418 - {"foo": None} matches {"foo": {"bar": 1}}
419 - {"foo": None} matches {"foo": 5}
420 - {"foo": {"abc": None}} does not match {"foo": {"bar": 1}}
421 - {"foo": {"rab": 2}} matches {"foo": {"bar": 1, "rab": 2}}
423 if match is None:
424 return True
426 try:
427 for key in match:
428 if key in event:
429 if not QEMUMachine.event_match(event[key], match[key]):
430 return False
431 else:
432 return False
433 return True
434 except TypeError:
435 # either match or event wasn't iterable (not a dict)
436 return match == event
438 def event_wait(self, name, timeout=60.0, match=None):
440 event_wait waits for and returns a named event from QMP with a timeout.
442 name: The event to wait for.
443 timeout: QEMUMonitorProtocol.pull_event timeout parameter.
444 match: Optional match criteria. See event_match for details.
446 return self.events_wait([(name, match)], timeout)
448 def events_wait(self, events, timeout=60.0):
450 events_wait waits for and returns a named event from QMP with a timeout.
452 events: a sequence of (name, match_criteria) tuples.
453 The match criteria are optional and may be None.
454 See event_match for details.
455 timeout: QEMUMonitorProtocol.pull_event timeout parameter.
457 def _match(event):
458 for name, match in events:
459 if (event['event'] == name and
460 self.event_match(event, match)):
461 return True
462 return False
464 # Search cached events
465 for event in self._events:
466 if _match(event):
467 self._events.remove(event)
468 return event
470 # Poll for new events
471 while True:
472 event = self._qmp.pull_event(wait=timeout)
473 if _match(event):
474 return event
475 self._events.append(event)
477 return None
479 def get_log(self):
481 After self.shutdown or failed qemu execution, this returns the output
482 of the qemu process.
484 return self._iolog
486 def add_args(self, *args):
488 Adds to the list of extra arguments to be given to the QEMU binary
490 self._args.extend(args)
492 def set_machine(self, machine_type):
494 Sets the machine type
496 If set, the machine type will be added to the base arguments
497 of the resulting QEMU command line.
499 self._machine = machine_type
501 def set_console(self, device_type=None):
503 Sets the device type for a console device
505 If set, the console device and a backing character device will
506 be added to the base arguments of the resulting QEMU command
507 line.
509 This is a convenience method that will either use the provided
510 device type, or default to a "-serial chardev:console" command
511 line argument.
513 The actual setting of command line arguments will be be done at
514 machine launch time, as it depends on the temporary directory
515 to be created.
517 @param device_type: the device type, such as "isa-serial". If
518 None is given (the default value) a "-serial
519 chardev:console" command line argument will
520 be used instead, resorting to the machine's
521 default device type.
523 self._console_set = True
524 self._console_device_type = device_type
526 @property
527 def console_socket(self):
529 Returns a socket connected to the console
531 if self._console_socket is None:
532 self._console_socket = socket.socket(socket.AF_UNIX,
533 socket.SOCK_STREAM)
534 self._console_socket.connect(self._console_address)
535 return self._console_socket