4 The machine module primarily provides the QEMUMachine class,
5 which provides facilities for managing the lifetime of a QEMU VM.
8 # Copyright (C) 2015-2016 Red Hat Inc.
9 # Copyright (C) 2012 IBM Corp.
12 # Fam Zheng <famz@redhat.com>
14 # This work is licensed under the terms of the GNU GPL, version 2. See
15 # the COPYING file in the top-level directory.
27 from typing
import Optional
, Type
28 from types
import TracebackType
29 from . import console_socket
33 LOG
= logging
.getLogger(__name__
)
36 class QEMUMachineError(Exception):
38 Exception called when an error in QEMUMachine happens.
42 class QEMUMachineAddDeviceError(QEMUMachineError
):
44 Exception raised when a request to add a device can not be fulfilled
46 The failures are caused by limitations, lack of information or conflicting
47 requests on the QEMUMachine methods. This exception does not represent
48 failures reported by the QEMU binary itself.
52 class AbnormalShutdown(QEMUMachineError
):
54 Exception raised when a graceful shutdown was requested, but not performed.
62 Use this object as a context manager to ensure
63 the QEMU process terminates::
65 with VM(binary) as vm:
67 # vm is guaranteed to be shut down here
70 def __init__(self
, binary
, args
=None, wrapper
=None, name
=None,
71 test_dir
="/var/tmp", monitor_address
=None,
72 socket_scm_helper
=None, sock_dir
=None,
73 drain_console
=False, console_log
=None):
75 Initialize a QEMUMachine
77 @param binary: path to the qemu binary
78 @param args: list of extra arguments
79 @param wrapper: list of arguments used as prefix to qemu binary
80 @param name: prefix for socket and log file names (default: qemu-PID)
81 @param test_dir: where to create socket and log file
82 @param monitor_address: address for QMP monitor
83 @param socket_scm_helper: helper program, required for send_fd_scm()
84 @param sock_dir: where to create socket (overrides test_dir for sock)
85 @param console_log: (optional) path to console log file
86 @param drain_console: (optional) True to drain console socket to buffer
87 @note: Qemu process is not started until launch() is used.
94 name
= "qemu-%d" % os
.getpid()
98 self
._monitor
_address
= monitor_address
99 self
._vm
_monitor
= None
100 self
._qemu
_log
_path
= None
101 self
._qemu
_log
_file
= None
103 self
._binary
= binary
104 self
._args
= list(args
) # Force copy args in case we modify them
105 self
._wrapper
= wrapper
108 self
._socket
_scm
_helper
= socket_scm_helper
109 self
._qmp
_set
= True # Enable QMP monitor by default.
111 self
._qemu
_full
_args
= None
112 self
._test
_dir
= test_dir
113 self
._temp
_dir
= None
114 self
._sock
_dir
= sock_dir
115 self
._launched
= False
117 self
._console
_index
= 0
118 self
._console
_set
= False
119 self
._console
_device
_type
= None
120 self
._console
_address
= None
121 self
._console
_socket
= None
122 self
._remove
_files
= []
123 self
._user
_killed
= False
124 self
._console
_log
_path
= console_log
125 if self
._console
_log
_path
:
126 # In order to log the console, buffering needs to be enabled.
127 self
._drain
_console
= True
129 self
._drain
_console
= drain_console
135 exc_type
: Optional
[Type
[BaseException
]],
136 exc_val
: Optional
[BaseException
],
137 exc_tb
: Optional
[TracebackType
]) -> None:
140 def add_monitor_null(self
):
142 This can be used to add an unused monitor instance.
144 self
._args
.append('-monitor')
145 self
._args
.append('null')
147 def add_fd(self
, fd
, fdset
, opaque
, opts
=''):
149 Pass a file descriptor to the VM
151 options
= ['fd=%d' % fd
,
153 'opaque=%s' % opaque
]
157 # This did not exist before 3.4, but since then it is
158 # mandatory for our purpose
159 if hasattr(os
, 'set_inheritable'):
160 os
.set_inheritable(fd
, True)
162 self
._args
.append('-add-fd')
163 self
._args
.append(','.join(options
))
166 def send_fd_scm(self
, fd
=None, file_path
=None):
168 Send an fd or file_path to socket_scm_helper.
170 Exactly one of fd and file_path must be given.
171 If it is file_path, the helper will open that file and pass its own fd.
173 # In iotest.py, the qmp should always use unix socket.
174 assert self
._qmp
.is_scm_available()
175 if self
._socket
_scm
_helper
is None:
176 raise QEMUMachineError("No path to socket_scm_helper set")
177 if not os
.path
.exists(self
._socket
_scm
_helper
):
178 raise QEMUMachineError("%s does not exist" %
179 self
._socket
_scm
_helper
)
181 # This did not exist before 3.4, but since then it is
182 # mandatory for our purpose
183 if hasattr(os
, 'set_inheritable'):
184 os
.set_inheritable(self
._qmp
.get_sock_fd(), True)
186 os
.set_inheritable(fd
, True)
188 fd_param
= ["%s" % self
._socket
_scm
_helper
,
189 "%d" % self
._qmp
.get_sock_fd()]
191 if file_path
is not None:
193 fd_param
.append(file_path
)
195 assert fd
is not None
196 fd_param
.append(str(fd
))
198 devnull
= open(os
.path
.devnull
, 'rb')
199 proc
= subprocess
.Popen(
200 fd_param
, stdin
=devnull
, stdout
=subprocess
.PIPE
,
201 stderr
=subprocess
.STDOUT
, close_fds
=False
203 output
= proc
.communicate()[0]
207 return proc
.returncode
210 def _remove_if_exists(path
):
212 Remove file object at path if it exists
216 except OSError as exception
:
217 if exception
.errno
== errno
.ENOENT
:
221 def is_running(self
):
222 """Returns true if the VM is running."""
223 return self
._popen
is not None and self
._popen
.poll() is None
226 """Returns the exit code if possible, or None."""
227 if self
._popen
is None:
229 return self
._popen
.poll()
232 """Returns the PID of the running process, or None."""
233 if not self
.is_running():
235 return self
._popen
.pid
237 def _load_io_log(self
):
238 if self
._qemu
_log
_path
is not None:
239 with
open(self
._qemu
_log
_path
, "r") as iolog
:
240 self
._iolog
= iolog
.read()
242 def _base_args(self
):
243 args
= ['-display', 'none', '-vga', 'none']
245 if isinstance(self
._monitor
_address
, tuple):
246 moncdev
= "socket,id=mon,host=%s,port=%s" % (
247 self
._monitor
_address
[0],
248 self
._monitor
_address
[1])
250 moncdev
= 'socket,id=mon,path=%s' % self
._vm
_monitor
251 args
.extend(['-chardev', moncdev
, '-mon',
252 'chardev=mon,mode=control'])
253 if self
._machine
is not None:
254 args
.extend(['-machine', self
._machine
])
255 for _
in range(self
._console
_index
):
256 args
.extend(['-serial', 'null'])
257 if self
._console
_set
:
258 self
._console
_address
= os
.path
.join(self
._sock
_dir
,
259 self
._name
+ "-console.sock")
260 self
._remove
_files
.append(self
._console
_address
)
261 chardev
= ('socket,id=console,path=%s,server,nowait' %
262 self
._console
_address
)
263 args
.extend(['-chardev', chardev
])
264 if self
._console
_device
_type
is None:
265 args
.extend(['-serial', 'chardev:console'])
267 device
= '%s,chardev=console' % self
._console
_device
_type
268 args
.extend(['-device', device
])
271 def _pre_launch(self
):
272 self
._temp
_dir
= tempfile
.mkdtemp(dir=self
._test
_dir
)
273 self
._qemu
_log
_path
= os
.path
.join(self
._temp
_dir
, self
._name
+ ".log")
274 self
._qemu
_log
_file
= open(self
._qemu
_log
_path
, 'wb')
277 if self
._monitor
_address
is not None:
278 self
._vm
_monitor
= self
._monitor
_address
280 self
._vm
_monitor
= os
.path
.join(self
._sock
_dir
,
281 self
._name
+ "-monitor.sock")
282 self
._remove
_files
.append(self
._vm
_monitor
)
283 self
._qmp
= qmp
.QEMUMonitorProtocol(self
._vm
_monitor
, server
=True,
286 def _post_launch(self
):
290 def _post_shutdown(self
):
292 Called to cleanup the VM instance after the process has exited.
293 May also be called after a failed launch.
295 # Comprehensive reset for the failed launch case:
296 self
._early
_cleanup
()
304 if self
._qemu
_log
_file
is not None:
305 self
._qemu
_log
_file
.close()
306 self
._qemu
_log
_file
= None
308 self
._qemu
_log
_path
= None
310 if self
._temp
_dir
is not None:
311 shutil
.rmtree(self
._temp
_dir
)
312 self
._temp
_dir
= None
314 while len(self
._remove
_files
) > 0:
315 self
._remove
_if
_exists
(self
._remove
_files
.pop())
317 exitcode
= self
.exitcode()
318 if (exitcode
is not None and exitcode
< 0
319 and not (self
._user
_killed
and exitcode
== -signal
.SIGKILL
)):
320 msg
= 'qemu received signal %i; command: "%s"'
321 if self
._qemu
_full
_args
:
322 command
= ' '.join(self
._qemu
_full
_args
)
325 LOG
.warning(msg
, -int(exitcode
), command
)
327 self
._user
_killed
= False
328 self
._launched
= False
332 Launch the VM and make sure we cleanup and expose the
333 command line/output in case of exception
337 raise QEMUMachineError('VM already launched')
340 self
._qemu
_full
_args
= None
343 self
._launched
= True
345 self
._post
_shutdown
()
347 LOG
.debug('Error launching VM')
348 if self
._qemu
_full
_args
:
349 LOG
.debug('Command: %r', ' '.join(self
._qemu
_full
_args
))
351 LOG
.debug('Output: %r', self
._iolog
)
356 Launch the VM and establish a QMP connection
358 devnull
= open(os
.path
.devnull
, 'rb')
360 self
._qemu
_full
_args
= (self
._wrapper
+ [self
._binary
] +
361 self
._base
_args
() + self
._args
)
362 LOG
.debug('VM launch command: %r', ' '.join(self
._qemu
_full
_args
))
363 self
._popen
= subprocess
.Popen(self
._qemu
_full
_args
,
365 stdout
=self
._qemu
_log
_file
,
366 stderr
=subprocess
.STDOUT
,
371 def _early_cleanup(self
) -> None:
373 Perform any cleanup that needs to happen before the VM exits.
375 May be invoked by both soft and hard shutdown in failover scenarios.
376 Called additionally by _post_shutdown for comprehensive cleanup.
378 # If we keep the console socket open, we may deadlock waiting
379 # for QEMU to exit, while QEMU is waiting for the socket to
381 if self
._console
_socket
is not None:
382 self
._console
_socket
.close()
383 self
._console
_socket
= None
385 def _hard_shutdown(self
) -> None:
387 Perform early cleanup, kill the VM, and wait for it to terminate.
389 :raise subprocess.Timeout: When timeout is exceeds 60 seconds
390 waiting for the QEMU process to terminate.
392 self
._early
_cleanup
()
394 self
._popen
.wait(timeout
=60)
396 def _soft_shutdown(self
, timeout
: Optional
[int],
397 has_quit
: bool = False) -> None:
399 Perform early cleanup, attempt to gracefully shut down the VM, and wait
402 :param timeout: Timeout in seconds for graceful shutdown.
403 A value of None is an infinite wait.
404 :param has_quit: When True, don't attempt to issue 'quit' QMP command
406 :raise ConnectionReset: On QMP communication errors
407 :raise subprocess.TimeoutExpired: When timeout is exceeded waiting for
408 the QEMU process to terminate.
410 self
._early
_cleanup
()
412 if self
._qmp
is not None:
414 # Might raise ConnectionReset
415 self
._qmp
.cmd('quit')
417 # May raise subprocess.TimeoutExpired
418 self
._popen
.wait(timeout
=timeout
)
420 def _do_shutdown(self
, timeout
: Optional
[int],
421 has_quit
: bool = False) -> None:
423 Attempt to shutdown the VM gracefully; fallback to a hard shutdown.
425 :param timeout: Timeout in seconds for graceful shutdown.
426 A value of None is an infinite wait.
427 :param has_quit: When True, don't attempt to issue 'quit' QMP command
429 :raise AbnormalShutdown: When the VM could not be shut down gracefully.
430 The inner exception will likely be ConnectionReset or
431 subprocess.TimeoutExpired. In rare cases, non-graceful termination
432 may result in its own exceptions, likely subprocess.TimeoutExpired.
435 self
._soft
_shutdown
(timeout
, has_quit
)
436 except Exception as exc
:
437 self
._hard
_shutdown
()
438 raise AbnormalShutdown("Could not perform graceful shutdown") \
441 def shutdown(self
, has_quit
: bool = False,
443 timeout
: Optional
[int] = 30) -> None:
445 Terminate the VM (gracefully if possible) and perform cleanup.
446 Cleanup will always be performed.
448 If the VM has not yet been launched, or shutdown(), wait(), or kill()
449 have already been called, this method does nothing.
451 :param has_quit: When true, do not attempt to issue 'quit' QMP command.
452 :param hard: When true, do not attempt graceful shutdown, and
453 suppress the SIGKILL warning log message.
454 :param timeout: Optional timeout in seconds for graceful shutdown.
455 Default 30 seconds, A `None` value is an infinite wait.
457 if not self
._launched
:
462 self
._user
_killed
= True
463 self
._hard
_shutdown
()
465 self
._do
_shutdown
(timeout
, has_quit
)
467 self
._post
_shutdown
()
471 Terminate the VM forcefully, wait for it to exit, and perform cleanup.
473 self
.shutdown(hard
=True)
475 def wait(self
, timeout
: Optional
[int] = 30) -> None:
477 Wait for the VM to power off and perform post-shutdown cleanup.
479 :param timeout: Optional timeout in seconds. Default 30 seconds.
480 A value of `None` is an infinite wait.
482 self
.shutdown(has_quit
=True, timeout
=timeout
)
484 def set_qmp_monitor(self
, enabled
=True):
488 @param enabled: if False, qmp monitor options will be removed from
489 the base arguments of the resulting QEMU command
490 line. Default is True.
491 @note: call this function before launch().
496 self
._qmp
_set
= False
499 def qmp(self
, cmd
, conv_keys
=True, **args
):
501 Invoke a QMP command and return the response dict
504 for key
, value
in args
.items():
506 qmp_args
[key
.replace('_', '-')] = value
508 qmp_args
[key
] = value
510 return self
._qmp
.cmd(cmd
, args
=qmp_args
)
512 def command(self
, cmd
, conv_keys
=True, **args
):
514 Invoke a QMP command.
515 On success return the response dict.
516 On failure raise an exception.
518 reply
= self
.qmp(cmd
, conv_keys
, **args
)
520 raise qmp
.QMPError("Monitor is closed")
522 raise qmp
.QMPResponseError(reply
)
523 return reply
["return"]
525 def get_qmp_event(self
, wait
=False):
527 Poll for one queued QMP events and return it
530 return self
._events
.pop(0)
531 return self
._qmp
.pull_event(wait
=wait
)
533 def get_qmp_events(self
, wait
=False):
535 Poll for queued QMP events and return a list of dicts
537 events
= self
._qmp
.get_events(wait
=wait
)
538 events
.extend(self
._events
)
540 self
._qmp
.clear_events()
544 def event_match(event
, match
=None):
546 Check if an event matches optional match criteria.
548 The match criteria takes the form of a matching subdict. The event is
549 checked to be a superset of the subdict, recursively, with matching
550 values whenever the subdict values are not None.
552 This has a limitation that you cannot explicitly check for None values.
554 Examples, with the subdict queries on the left:
555 - None matches any object.
556 - {"foo": None} matches {"foo": {"bar": 1}}
557 - {"foo": None} matches {"foo": 5}
558 - {"foo": {"abc": None}} does not match {"foo": {"bar": 1}}
559 - {"foo": {"rab": 2}} matches {"foo": {"bar": 1, "rab": 2}}
567 if not QEMUMachine
.event_match(event
[key
], match
[key
]):
573 # either match or event wasn't iterable (not a dict)
574 return match
== event
576 def event_wait(self
, name
, timeout
=60.0, match
=None):
578 event_wait waits for and returns a named event from QMP with a timeout.
580 name: The event to wait for.
581 timeout: QEMUMonitorProtocol.pull_event timeout parameter.
582 match: Optional match criteria. See event_match for details.
584 return self
.events_wait([(name
, match
)], timeout
)
586 def events_wait(self
, events
, timeout
=60.0):
588 events_wait waits for and returns a named event
589 from QMP with a timeout.
591 events: a sequence of (name, match_criteria) tuples.
592 The match criteria are optional and may be None.
593 See event_match for details.
594 timeout: QEMUMonitorProtocol.pull_event timeout parameter.
597 for name
, match
in events
:
598 if event
['event'] == name
and self
.event_match(event
, match
):
602 # Search cached events
603 for event
in self
._events
:
605 self
._events
.remove(event
)
608 # Poll for new events
610 event
= self
._qmp
.pull_event(wait
=timeout
)
613 self
._events
.append(event
)
619 After self.shutdown or failed qemu execution, this returns the output
624 def add_args(self
, *args
):
626 Adds to the list of extra arguments to be given to the QEMU binary
628 self
._args
.extend(args
)
630 def set_machine(self
, machine_type
):
632 Sets the machine type
634 If set, the machine type will be added to the base arguments
635 of the resulting QEMU command line.
637 self
._machine
= machine_type
639 def set_console(self
, device_type
=None, console_index
=0):
641 Sets the device type for a console device
643 If set, the console device and a backing character device will
644 be added to the base arguments of the resulting QEMU command
647 This is a convenience method that will either use the provided
648 device type, or default to a "-serial chardev:console" command
651 The actual setting of command line arguments will be be done at
652 machine launch time, as it depends on the temporary directory
655 @param device_type: the device type, such as "isa-serial". If
656 None is given (the default value) a "-serial
657 chardev:console" command line argument will
658 be used instead, resorting to the machine's
660 @param console_index: the index of the console device to use.
661 If not zero, the command line will create
662 'index - 1' consoles and connect them to
663 the 'null' backing character device.
665 self
._console
_set
= True
666 self
._console
_device
_type
= device_type
667 self
._console
_index
= console_index
670 def console_socket(self
):
672 Returns a socket connected to the console
674 if self
._console
_socket
is None:
675 self
._console
_socket
= console_socket
.ConsoleSocket(
676 self
._console
_address
,
677 file=self
._console
_log
_path
,
678 drain
=self
._drain
_console
)
679 return self
._console
_socket