xref: /qemu/python/qemu/machine/machine.py (revision e4418354)
1"""
2QEMU machine module:
3
4The machine module primarily provides the QEMUMachine class,
5which provides facilities for managing the lifetime of a QEMU VM.
6"""
7
8# Copyright (C) 2015-2016 Red Hat Inc.
9# Copyright (C) 2012 IBM Corp.
10#
11# Authors:
12#  Fam Zheng <famz@redhat.com>
13#
14# This work is licensed under the terms of the GNU GPL, version 2.  See
15# the COPYING file in the top-level directory.
16#
17# Based on qmp.py.
18#
19
20import errno
21from itertools import chain
22import locale
23import logging
24import os
25import shutil
26import signal
27import socket
28import subprocess
29import tempfile
30from types import TracebackType
31from typing import (
32    Any,
33    BinaryIO,
34    Dict,
35    List,
36    Optional,
37    Sequence,
38    Tuple,
39    Type,
40    TypeVar,
41)
42
43from qemu.qmp import SocketAddrT
44from qemu.qmp.legacy import (
45    QEMUMonitorProtocol,
46    QMPMessage,
47    QMPReturnValue,
48)
49
50from . import console_socket
51
52
53LOG = logging.getLogger(__name__)
54
55
56class QEMUMachineError(Exception):
57    """
58    Exception called when an error in QEMUMachine happens.
59    """
60
61
62class QEMUMachineAddDeviceError(QEMUMachineError):
63    """
64    Exception raised when a request to add a device can not be fulfilled
65
66    The failures are caused by limitations, lack of information or conflicting
67    requests on the QEMUMachine methods.  This exception does not represent
68    failures reported by the QEMU binary itself.
69    """
70
71
72class VMLaunchFailure(QEMUMachineError):
73    """
74    Exception raised when a VM launch was attempted, but failed.
75    """
76    def __init__(self, exitcode: Optional[int],
77                 command: str, output: Optional[str]):
78        super().__init__(exitcode, command, output)
79        self.exitcode = exitcode
80        self.command = command
81        self.output = output
82
83    def __str__(self) -> str:
84        ret = ''
85        if self.__cause__ is not None:
86            name = type(self.__cause__).__name__
87            reason = str(self.__cause__)
88            if reason:
89                ret += f"{name}: {reason}"
90            else:
91                ret += f"{name}"
92        ret += '\n'
93
94        if self.exitcode is not None:
95            ret += f"\tExit code: {self.exitcode}\n"
96        ret += f"\tCommand: {self.command}\n"
97        ret += f"\tOutput: {self.output}\n"
98        return ret
99
100
101class AbnormalShutdown(QEMUMachineError):
102    """
103    Exception raised when a graceful shutdown was requested, but not performed.
104    """
105
106
107_T = TypeVar('_T', bound='QEMUMachine')
108
109
110class QEMUMachine:
111    """
112    A QEMU VM.
113
114    Use this object as a context manager to ensure
115    the QEMU process terminates::
116
117        with VM(binary) as vm:
118            ...
119        # vm is guaranteed to be shut down here
120    """
121    # pylint: disable=too-many-instance-attributes, too-many-public-methods
122
123    def __init__(self,
124                 binary: str,
125                 args: Sequence[str] = (),
126                 wrapper: Sequence[str] = (),
127                 name: Optional[str] = None,
128                 base_temp_dir: str = "/var/tmp",
129                 monitor_address: Optional[SocketAddrT] = None,
130                 sock_dir: Optional[str] = None,
131                 drain_console: bool = False,
132                 console_log: Optional[str] = None,
133                 log_dir: Optional[str] = None,
134                 qmp_timer: Optional[float] = None):
135        '''
136        Initialize a QEMUMachine
137
138        @param binary: path to the qemu binary
139        @param args: list of extra arguments
140        @param wrapper: list of arguments used as prefix to qemu binary
141        @param name: prefix for socket and log file names (default: qemu-PID)
142        @param base_temp_dir: default location where temp files are created
143        @param monitor_address: address for QMP monitor
144        @param sock_dir: where to create socket (defaults to base_temp_dir)
145        @param drain_console: (optional) True to drain console socket to buffer
146        @param console_log: (optional) path to console log file
147        @param log_dir: where to create and keep log files
148        @param qmp_timer: (optional) default QMP socket timeout
149        @note: Qemu process is not started until launch() is used.
150        '''
151        # pylint: disable=too-many-arguments
152
153        # Direct user configuration
154
155        self._binary = binary
156        self._args = list(args)
157        self._wrapper = wrapper
158        self._qmp_timer = qmp_timer
159
160        self._name = name or f"qemu-{os.getpid()}-{id(self):02x}"
161        self._temp_dir: Optional[str] = None
162        self._base_temp_dir = base_temp_dir
163        self._sock_dir = sock_dir
164        self._log_dir = log_dir
165
166        if monitor_address is not None:
167            self._monitor_address = monitor_address
168        else:
169            self._monitor_address = os.path.join(
170                self.sock_dir, f"{self._name}-monitor.sock"
171            )
172
173        self._console_log_path = console_log
174        if self._console_log_path:
175            # In order to log the console, buffering needs to be enabled.
176            self._drain_console = True
177        else:
178            self._drain_console = drain_console
179
180        # Runstate
181        self._qemu_log_path: Optional[str] = None
182        self._qemu_log_file: Optional[BinaryIO] = None
183        self._popen: Optional['subprocess.Popen[bytes]'] = None
184        self._events: List[QMPMessage] = []
185        self._iolog: Optional[str] = None
186        self._qmp_set = True   # Enable QMP monitor by default.
187        self._qmp_connection: Optional[QEMUMonitorProtocol] = None
188        self._qemu_full_args: Tuple[str, ...] = ()
189        self._launched = False
190        self._machine: Optional[str] = None
191        self._console_index = 0
192        self._console_set = False
193        self._console_device_type: Optional[str] = None
194        self._console_address = os.path.join(
195            self.sock_dir, f"{self._name}-console.sock"
196        )
197        self._console_socket: Optional[socket.socket] = None
198        self._remove_files: List[str] = []
199        self._user_killed = False
200        self._quit_issued = False
201
202    def __enter__(self: _T) -> _T:
203        return self
204
205    def __exit__(self,
206                 exc_type: Optional[Type[BaseException]],
207                 exc_val: Optional[BaseException],
208                 exc_tb: Optional[TracebackType]) -> None:
209        self.shutdown()
210
211    def add_monitor_null(self) -> None:
212        """
213        This can be used to add an unused monitor instance.
214        """
215        self._args.append('-monitor')
216        self._args.append('null')
217
218    def add_fd(self: _T, fd: int, fdset: int,
219               opaque: str, opts: str = '') -> _T:
220        """
221        Pass a file descriptor to the VM
222        """
223        options = ['fd=%d' % fd,
224                   'set=%d' % fdset,
225                   'opaque=%s' % opaque]
226        if opts:
227            options.append(opts)
228
229        # This did not exist before 3.4, but since then it is
230        # mandatory for our purpose
231        if hasattr(os, 'set_inheritable'):
232            os.set_inheritable(fd, True)
233
234        self._args.append('-add-fd')
235        self._args.append(','.join(options))
236        return self
237
238    def send_fd_scm(self, fd: Optional[int] = None,
239                    file_path: Optional[str] = None) -> int:
240        """
241        Send an fd or file_path to the remote via SCM_RIGHTS.
242
243        Exactly one of fd and file_path must be given.  If it is
244        file_path, the file will be opened read-only and the new file
245        descriptor will be sent to the remote.
246        """
247        if file_path is not None:
248            assert fd is None
249            with open(file_path, "rb") as passfile:
250                fd = passfile.fileno()
251                self._qmp.send_fd_scm(fd)
252        else:
253            assert fd is not None
254            self._qmp.send_fd_scm(fd)
255
256        return 0
257
258    @staticmethod
259    def _remove_if_exists(path: str) -> None:
260        """
261        Remove file object at path if it exists
262        """
263        try:
264            os.remove(path)
265        except OSError as exception:
266            if exception.errno == errno.ENOENT:
267                return
268            raise
269
270    def is_running(self) -> bool:
271        """Returns true if the VM is running."""
272        return self._popen is not None and self._popen.poll() is None
273
274    @property
275    def _subp(self) -> 'subprocess.Popen[bytes]':
276        if self._popen is None:
277            raise QEMUMachineError('Subprocess pipe not present')
278        return self._popen
279
280    def exitcode(self) -> Optional[int]:
281        """Returns the exit code if possible, or None."""
282        if self._popen is None:
283            return None
284        return self._popen.poll()
285
286    def get_pid(self) -> Optional[int]:
287        """Returns the PID of the running process, or None."""
288        if not self.is_running():
289            return None
290        return self._subp.pid
291
292    def _load_io_log(self) -> None:
293        # Assume that the output encoding of QEMU's terminal output is
294        # defined by our locale. If indeterminate, allow open() to fall
295        # back to the platform default.
296        _, encoding = locale.getlocale()
297        if self._qemu_log_path is not None:
298            with open(self._qemu_log_path, "r", encoding=encoding) as iolog:
299                self._iolog = iolog.read()
300
301    @property
302    def _base_args(self) -> List[str]:
303        args = ['-display', 'none', '-vga', 'none']
304
305        if self._qmp_set:
306            if isinstance(self._monitor_address, tuple):
307                moncdev = "socket,id=mon,host={},port={}".format(
308                    *self._monitor_address
309                )
310            else:
311                moncdev = f"socket,id=mon,path={self._monitor_address}"
312            args.extend(['-chardev', moncdev, '-mon',
313                         'chardev=mon,mode=control'])
314
315        if self._machine is not None:
316            args.extend(['-machine', self._machine])
317        for _ in range(self._console_index):
318            args.extend(['-serial', 'null'])
319        if self._console_set:
320            chardev = ('socket,id=console,path=%s,server=on,wait=off' %
321                       self._console_address)
322            args.extend(['-chardev', chardev])
323            if self._console_device_type is None:
324                args.extend(['-serial', 'chardev:console'])
325            else:
326                device = '%s,chardev=console' % self._console_device_type
327                args.extend(['-device', device])
328        return args
329
330    @property
331    def args(self) -> List[str]:
332        """Returns the list of arguments given to the QEMU binary."""
333        return self._args
334
335    def _pre_launch(self) -> None:
336        if self._console_set:
337            self._remove_files.append(self._console_address)
338
339        if self._qmp_set:
340            if isinstance(self._monitor_address, str):
341                self._remove_files.append(self._monitor_address)
342            self._qmp_connection = QEMUMonitorProtocol(
343                self._monitor_address,
344                server=True,
345                nickname=self._name
346            )
347
348        # NOTE: Make sure any opened resources are *definitely* freed in
349        # _post_shutdown()!
350        # pylint: disable=consider-using-with
351        self._qemu_log_path = os.path.join(self.log_dir, self._name + ".log")
352        self._qemu_log_file = open(self._qemu_log_path, 'wb')
353
354        self._iolog = None
355        self._qemu_full_args = tuple(chain(
356            self._wrapper,
357            [self._binary],
358            self._base_args,
359            self._args
360        ))
361
362    def _post_launch(self) -> None:
363        if self._qmp_connection:
364            self._qmp.accept(self._qmp_timer)
365
366    def _close_qemu_log_file(self) -> None:
367        if self._qemu_log_file is not None:
368            self._qemu_log_file.close()
369            self._qemu_log_file = None
370
371    def _post_shutdown(self) -> None:
372        """
373        Called to cleanup the VM instance after the process has exited.
374        May also be called after a failed launch.
375        """
376        LOG.debug("Cleaning up after VM process")
377        try:
378            self._close_qmp_connection()
379        except Exception as err:  # pylint: disable=broad-except
380            LOG.warning(
381                "Exception closing QMP connection: %s",
382                str(err) if str(err) else type(err).__name__
383            )
384        finally:
385            assert self._qmp_connection is None
386
387        self._close_qemu_log_file()
388
389        self._load_io_log()
390
391        self._qemu_log_path = None
392
393        if self._temp_dir is not None:
394            shutil.rmtree(self._temp_dir)
395            self._temp_dir = None
396
397        while len(self._remove_files) > 0:
398            self._remove_if_exists(self._remove_files.pop())
399
400        exitcode = self.exitcode()
401        if (exitcode is not None and exitcode < 0
402                and not (self._user_killed and exitcode == -signal.SIGKILL)):
403            msg = 'qemu received signal %i; command: "%s"'
404            if self._qemu_full_args:
405                command = ' '.join(self._qemu_full_args)
406            else:
407                command = ''
408            LOG.warning(msg, -int(exitcode), command)
409
410        self._quit_issued = False
411        self._user_killed = False
412        self._launched = False
413
414    def launch(self) -> None:
415        """
416        Launch the VM and make sure we cleanup and expose the
417        command line/output in case of exception
418        """
419
420        if self._launched:
421            raise QEMUMachineError('VM already launched')
422
423        try:
424            self._launch()
425        except BaseException as exc:
426            # We may have launched the process but it may
427            # have exited before we could connect via QMP.
428            # Assume the VM didn't launch or is exiting.
429            # If we don't wait for the process, exitcode() may still be
430            # 'None' by the time control is ceded back to the caller.
431            if self._launched:
432                self.wait()
433            else:
434                self._post_shutdown()
435
436            if isinstance(exc, Exception):
437                raise VMLaunchFailure(
438                    exitcode=self.exitcode(),
439                    command=' '.join(self._qemu_full_args),
440                    output=self._iolog
441                ) from exc
442
443            # Don't wrap 'BaseException'; doing so would downgrade
444            # that exception. However, we still want to clean up.
445            raise
446
447    def _launch(self) -> None:
448        """
449        Launch the VM and establish a QMP connection
450        """
451        self._pre_launch()
452        LOG.debug('VM launch command: %r', ' '.join(self._qemu_full_args))
453
454        # Cleaning up of this subprocess is guaranteed by _do_shutdown.
455        # pylint: disable=consider-using-with
456        self._popen = subprocess.Popen(self._qemu_full_args,
457                                       stdin=subprocess.DEVNULL,
458                                       stdout=self._qemu_log_file,
459                                       stderr=subprocess.STDOUT,
460                                       shell=False,
461                                       close_fds=False)
462        self._launched = True
463        self._post_launch()
464
465    def _close_qmp_connection(self) -> None:
466        """
467        Close the underlying QMP connection, if any.
468
469        Dutifully report errors that occurred while closing, but assume
470        that any error encountered indicates an abnormal termination
471        process and not a failure to close.
472        """
473        if self._qmp_connection is None:
474            return
475
476        try:
477            self._qmp.close()
478        except EOFError:
479            # EOF can occur as an Exception here when using the Async
480            # QMP backend. It indicates that the server closed the
481            # stream. If we successfully issued 'quit' at any point,
482            # then this was expected. If the remote went away without
483            # our permission, it's worth reporting that as an abnormal
484            # shutdown case.
485            if not (self._user_killed or self._quit_issued):
486                raise
487        finally:
488            self._qmp_connection = None
489
490    def _early_cleanup(self) -> None:
491        """
492        Perform any cleanup that needs to happen before the VM exits.
493
494        This method may be called twice upon shutdown, once each by soft
495        and hard shutdown in failover scenarios.
496        """
497        # If we keep the console socket open, we may deadlock waiting
498        # for QEMU to exit, while QEMU is waiting for the socket to
499        # become writable.
500        if self._console_socket is not None:
501            LOG.debug("Closing console socket")
502            self._console_socket.close()
503            self._console_socket = None
504
505    def _hard_shutdown(self) -> None:
506        """
507        Perform early cleanup, kill the VM, and wait for it to terminate.
508
509        :raise subprocess.Timeout: When timeout is exceeds 60 seconds
510            waiting for the QEMU process to terminate.
511        """
512        LOG.debug("Performing hard shutdown")
513        self._early_cleanup()
514        self._subp.kill()
515        self._subp.wait(timeout=60)
516
517    def _soft_shutdown(self, timeout: Optional[int]) -> None:
518        """
519        Perform early cleanup, attempt to gracefully shut down the VM, and wait
520        for it to terminate.
521
522        :param timeout: Timeout in seconds for graceful shutdown.
523                        A value of None is an infinite wait.
524
525        :raise ConnectionReset: On QMP communication errors
526        :raise subprocess.TimeoutExpired: When timeout is exceeded waiting for
527            the QEMU process to terminate.
528        """
529        LOG.debug("Attempting graceful termination")
530
531        self._early_cleanup()
532
533        if self._quit_issued:
534            LOG.debug(
535                "Anticipating QEMU termination due to prior 'quit' command, "
536                "or explicit call to wait()"
537            )
538        else:
539            LOG.debug("Politely asking QEMU to terminate")
540
541        if self._qmp_connection:
542            try:
543                if not self._quit_issued:
544                    # May raise ExecInterruptedError or StateError if the
545                    # connection dies or has *already* died.
546                    self.qmp('quit')
547            finally:
548                # Regardless, we want to quiesce the connection.
549                self._close_qmp_connection()
550        elif not self._quit_issued:
551            LOG.debug(
552                "Not anticipating QEMU quit and no QMP connection present, "
553                "issuing SIGTERM"
554            )
555            self._subp.terminate()
556
557        # May raise subprocess.TimeoutExpired
558        LOG.debug(
559            "Waiting (timeout=%s) for QEMU process (pid=%s) to terminate",
560            timeout, self._subp.pid
561        )
562        self._subp.wait(timeout=timeout)
563
564    def _do_shutdown(self, timeout: Optional[int]) -> None:
565        """
566        Attempt to shutdown the VM gracefully; fallback to a hard shutdown.
567
568        :param timeout: Timeout in seconds for graceful shutdown.
569                        A value of None is an infinite wait.
570
571        :raise AbnormalShutdown: When the VM could not be shut down gracefully.
572            The inner exception will likely be ConnectionReset or
573            subprocess.TimeoutExpired. In rare cases, non-graceful termination
574            may result in its own exceptions, likely subprocess.TimeoutExpired.
575        """
576        try:
577            self._soft_shutdown(timeout)
578        except Exception as exc:
579            if isinstance(exc, subprocess.TimeoutExpired):
580                LOG.debug("Timed out waiting for QEMU process to exit")
581            LOG.debug("Graceful shutdown failed", exc_info=True)
582            LOG.debug("Falling back to hard shutdown")
583            self._hard_shutdown()
584            raise AbnormalShutdown("Could not perform graceful shutdown") \
585                from exc
586
587    def shutdown(self,
588                 hard: bool = False,
589                 timeout: Optional[int] = 30) -> None:
590        """
591        Terminate the VM (gracefully if possible) and perform cleanup.
592        Cleanup will always be performed.
593
594        If the VM has not yet been launched, or shutdown(), wait(), or kill()
595        have already been called, this method does nothing.
596
597        :param hard: When true, do not attempt graceful shutdown, and
598                     suppress the SIGKILL warning log message.
599        :param timeout: Optional timeout in seconds for graceful shutdown.
600                        Default 30 seconds, A `None` value is an infinite wait.
601        """
602        if not self._launched:
603            return
604
605        LOG.debug("Shutting down VM appliance; timeout=%s", timeout)
606        if hard:
607            LOG.debug("Caller requests immediate termination of QEMU process.")
608
609        try:
610            if hard:
611                self._user_killed = True
612                self._hard_shutdown()
613            else:
614                self._do_shutdown(timeout)
615        finally:
616            self._post_shutdown()
617
618    def kill(self) -> None:
619        """
620        Terminate the VM forcefully, wait for it to exit, and perform cleanup.
621        """
622        self.shutdown(hard=True)
623
624    def wait(self, timeout: Optional[int] = 30) -> None:
625        """
626        Wait for the VM to power off and perform post-shutdown cleanup.
627
628        :param timeout: Optional timeout in seconds. Default 30 seconds.
629                        A value of `None` is an infinite wait.
630        """
631        self._quit_issued = True
632        self.shutdown(timeout=timeout)
633
634    def set_qmp_monitor(self, enabled: bool = True) -> None:
635        """
636        Set the QMP monitor.
637
638        @param enabled: if False, qmp monitor options will be removed from
639                        the base arguments of the resulting QEMU command
640                        line. Default is True.
641
642        .. note:: Call this function before launch().
643        """
644        self._qmp_set = enabled
645
646    @property
647    def _qmp(self) -> QEMUMonitorProtocol:
648        if self._qmp_connection is None:
649            raise QEMUMachineError("Attempt to access QMP with no connection")
650        return self._qmp_connection
651
652    @classmethod
653    def _qmp_args(cls, conv_keys: bool,
654                  args: Dict[str, Any]) -> Dict[str, object]:
655        if conv_keys:
656            return {k.replace('_', '-'): v for k, v in args.items()}
657
658        return args
659
660    def qmp(self, cmd: str,
661            args_dict: Optional[Dict[str, object]] = None,
662            conv_keys: Optional[bool] = None,
663            **args: Any) -> QMPMessage:
664        """
665        Invoke a QMP command and return the response dict
666        """
667        if args_dict is not None:
668            assert not args
669            assert conv_keys is None
670            args = args_dict
671            conv_keys = False
672
673        if conv_keys is None:
674            conv_keys = True
675
676        qmp_args = self._qmp_args(conv_keys, args)
677        ret = self._qmp.cmd(cmd, args=qmp_args)
678        if cmd == 'quit' and 'error' not in ret and 'return' in ret:
679            self._quit_issued = True
680        return ret
681
682    def command(self, cmd: str,
683                conv_keys: bool = True,
684                **args: Any) -> QMPReturnValue:
685        """
686        Invoke a QMP command.
687        On success return the response dict.
688        On failure raise an exception.
689        """
690        qmp_args = self._qmp_args(conv_keys, args)
691        ret = self._qmp.command(cmd, **qmp_args)
692        if cmd == 'quit':
693            self._quit_issued = True
694        return ret
695
696    def get_qmp_event(self, wait: bool = False) -> Optional[QMPMessage]:
697        """
698        Poll for one queued QMP events and return it
699        """
700        if self._events:
701            return self._events.pop(0)
702        return self._qmp.pull_event(wait=wait)
703
704    def get_qmp_events(self, wait: bool = False) -> List[QMPMessage]:
705        """
706        Poll for queued QMP events and return a list of dicts
707        """
708        events = self._qmp.get_events(wait=wait)
709        events.extend(self._events)
710        del self._events[:]
711        return events
712
713    @staticmethod
714    def event_match(event: Any, match: Optional[Any]) -> bool:
715        """
716        Check if an event matches optional match criteria.
717
718        The match criteria takes the form of a matching subdict. The event is
719        checked to be a superset of the subdict, recursively, with matching
720        values whenever the subdict values are not None.
721
722        This has a limitation that you cannot explicitly check for None values.
723
724        Examples, with the subdict queries on the left:
725         - None matches any object.
726         - {"foo": None} matches {"foo": {"bar": 1}}
727         - {"foo": None} matches {"foo": 5}
728         - {"foo": {"abc": None}} does not match {"foo": {"bar": 1}}
729         - {"foo": {"rab": 2}} matches {"foo": {"bar": 1, "rab": 2}}
730        """
731        if match is None:
732            return True
733
734        try:
735            for key in match:
736                if key in event:
737                    if not QEMUMachine.event_match(event[key], match[key]):
738                        return False
739                else:
740                    return False
741            return True
742        except TypeError:
743            # either match or event wasn't iterable (not a dict)
744            return bool(match == event)
745
746    def event_wait(self, name: str,
747                   timeout: float = 60.0,
748                   match: Optional[QMPMessage] = None) -> Optional[QMPMessage]:
749        """
750        event_wait waits for and returns a named event from QMP with a timeout.
751
752        name: The event to wait for.
753        timeout: QEMUMonitorProtocol.pull_event timeout parameter.
754        match: Optional match criteria. See event_match for details.
755        """
756        return self.events_wait([(name, match)], timeout)
757
758    def events_wait(self,
759                    events: Sequence[Tuple[str, Any]],
760                    timeout: float = 60.0) -> Optional[QMPMessage]:
761        """
762        events_wait waits for and returns a single named event from QMP.
763        In the case of multiple qualifying events, this function returns the
764        first one.
765
766        :param events: A sequence of (name, match_criteria) tuples.
767                       The match criteria are optional and may be None.
768                       See event_match for details.
769        :param timeout: Optional timeout, in seconds.
770                        See QEMUMonitorProtocol.pull_event.
771
772        :raise asyncio.TimeoutError:
773            If timeout was non-zero and no matching events were found.
774
775        :return: A QMP event matching the filter criteria.
776                 If timeout was 0 and no event matched, None.
777        """
778        def _match(event: QMPMessage) -> bool:
779            for name, match in events:
780                if event['event'] == name and self.event_match(event, match):
781                    return True
782            return False
783
784        event: Optional[QMPMessage]
785
786        # Search cached events
787        for event in self._events:
788            if _match(event):
789                self._events.remove(event)
790                return event
791
792        # Poll for new events
793        while True:
794            event = self._qmp.pull_event(wait=timeout)
795            if event is None:
796                # NB: None is only returned when timeout is false-ish.
797                # Timeouts raise asyncio.TimeoutError instead!
798                break
799            if _match(event):
800                return event
801            self._events.append(event)
802
803        return None
804
805    def get_log(self) -> Optional[str]:
806        """
807        After self.shutdown or failed qemu execution, this returns the output
808        of the qemu process.
809        """
810        return self._iolog
811
812    def add_args(self, *args: str) -> None:
813        """
814        Adds to the list of extra arguments to be given to the QEMU binary
815        """
816        self._args.extend(args)
817
818    def set_machine(self, machine_type: str) -> None:
819        """
820        Sets the machine type
821
822        If set, the machine type will be added to the base arguments
823        of the resulting QEMU command line.
824        """
825        self._machine = machine_type
826
827    def set_console(self,
828                    device_type: Optional[str] = None,
829                    console_index: int = 0) -> None:
830        """
831        Sets the device type for a console device
832
833        If set, the console device and a backing character device will
834        be added to the base arguments of the resulting QEMU command
835        line.
836
837        This is a convenience method that will either use the provided
838        device type, or default to a "-serial chardev:console" command
839        line argument.
840
841        The actual setting of command line arguments will be be done at
842        machine launch time, as it depends on the temporary directory
843        to be created.
844
845        @param device_type: the device type, such as "isa-serial".  If
846                            None is given (the default value) a "-serial
847                            chardev:console" command line argument will
848                            be used instead, resorting to the machine's
849                            default device type.
850        @param console_index: the index of the console device to use.
851                              If not zero, the command line will create
852                              'index - 1' consoles and connect them to
853                              the 'null' backing character device.
854        """
855        self._console_set = True
856        self._console_device_type = device_type
857        self._console_index = console_index
858
859    @property
860    def console_socket(self) -> socket.socket:
861        """
862        Returns a socket connected to the console
863        """
864        if self._console_socket is None:
865            self._console_socket = console_socket.ConsoleSocket(
866                self._console_address,
867                file=self._console_log_path,
868                drain=self._drain_console)
869        return self._console_socket
870
871    @property
872    def temp_dir(self) -> str:
873        """
874        Returns a temporary directory to be used for this machine
875        """
876        if self._temp_dir is None:
877            self._temp_dir = tempfile.mkdtemp(prefix="qemu-machine-",
878                                              dir=self._base_temp_dir)
879        return self._temp_dir
880
881    @property
882    def sock_dir(self) -> str:
883        """
884        Returns the directory used for sockfiles by this machine.
885        """
886        if self._sock_dir:
887            return self._sock_dir
888        return self.temp_dir
889
890    @property
891    def log_dir(self) -> str:
892        """
893        Returns a directory to be used for writing logs
894        """
895        if self._log_dir is None:
896            return self.temp_dir
897        return self._log_dir
898