diff options
Diffstat (limited to 'python/qemu/machine/machine.py')
| -rw-r--r-- | python/qemu/machine/machine.py | 78 |
1 files changed, 49 insertions, 29 deletions
diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py index 35d5a672db..31cb9d617d 100644 --- a/python/qemu/machine/machine.py +++ b/python/qemu/machine/machine.py @@ -127,7 +127,6 @@ class QEMUMachine: name: Optional[str] = None, base_temp_dir: str = "/var/tmp", monitor_address: Optional[SocketAddrT] = None, - sock_dir: Optional[str] = None, drain_console: bool = False, console_log: Optional[str] = None, log_dir: Optional[str] = None, @@ -141,7 +140,6 @@ class QEMUMachine: @param name: prefix for socket and log file names (default: qemu-PID) @param base_temp_dir: default location where temp files are created @param monitor_address: address for QMP monitor - @param sock_dir: where to create socket (defaults to base_temp_dir) @param drain_console: (optional) True to drain console socket to buffer @param console_log: (optional) path to console log file @param log_dir: where to create and keep log files @@ -159,9 +157,10 @@ class QEMUMachine: self._name = name or f"{id(self):x}" self._sock_pair: Optional[Tuple[socket.socket, socket.socket]] = None + self._cons_sock_pair: Optional[ + Tuple[socket.socket, socket.socket]] = None self._temp_dir: Optional[str] = None self._base_temp_dir = base_temp_dir - self._sock_dir = sock_dir self._log_dir = log_dir self._monitor_address = monitor_address @@ -187,9 +186,6 @@ class QEMUMachine: self._console_index = 0 self._console_set = False self._console_device_type: Optional[str] = None - self._console_address = os.path.join( - self.sock_dir, f"{self._name}.con" - ) self._console_socket: Optional[socket.socket] = None self._console_file: Optional[socket.SocketIO] = None self._remove_files: List[str] = [] @@ -301,9 +297,7 @@ class QEMUMachine: if self._qmp_set: if self._sock_pair: - fd = self._sock_pair[0].fileno() - os.set_inheritable(fd, True) - moncdev = f"socket,id=mon,fd={fd}" + moncdev = f"socket,id=mon,fd={self._sock_pair[0].fileno()}" elif isinstance(self._monitor_address, tuple): moncdev = "socket,id=mon,host={},port={}".format( *self._monitor_address @@ -318,8 +312,9 @@ class QEMUMachine: for _ in range(self._console_index): args.extend(['-serial', 'null']) if self._console_set: - chardev = ('socket,id=console,path=%s,server=on,wait=off' % - self._console_address) + assert self._cons_sock_pair is not None + fd = self._cons_sock_pair[0].fileno() + chardev = f"socket,id=console,fd={fd}" args.extend(['-chardev', chardev]) if self._console_device_type is None: args.extend(['-serial', 'chardev:console']) @@ -334,12 +329,10 @@ class QEMUMachine: return self._args def _pre_launch(self) -> None: - if self._console_set: - self._remove_files.append(self._console_address) - if self._qmp_set: if self._monitor_address is None: self._sock_pair = socket.socketpair() + os.set_inheritable(self._sock_pair[0].fileno(), True) sock = self._sock_pair[1] if isinstance(self._monitor_address, str): self._remove_files.append(self._monitor_address) @@ -353,6 +346,10 @@ class QEMUMachine: nickname=self._name ) + if self._console_set: + self._cons_sock_pair = socket.socketpair() + os.set_inheritable(self._cons_sock_pair[0].fileno(), True) + # NOTE: Make sure any opened resources are *definitely* freed in # _post_shutdown()! # pylint: disable=consider-using-with @@ -370,6 +367,9 @@ class QEMUMachine: def _post_launch(self) -> None: if self._sock_pair: self._sock_pair[0].close() + if self._cons_sock_pair: + self._cons_sock_pair[0].close() + if self._qmp_connection: if self._sock_pair: self._qmp.connect() @@ -397,6 +397,11 @@ class QEMUMachine: finally: assert self._qmp_connection is None + if self._sock_pair: + self._sock_pair[0].close() + self._sock_pair[1].close() + self._sock_pair = None + self._close_qemu_log_file() self._load_io_log() @@ -520,6 +525,11 @@ class QEMUMachine: self._console_socket.close() self._console_socket = None + if self._cons_sock_pair: + self._cons_sock_pair[0].close() + self._cons_sock_pair[1].close() + self._cons_sock_pair = None + def _hard_shutdown(self) -> None: """ Perform early cleanup, kill the VM, and wait for it to terminate. @@ -692,21 +702,31 @@ class QEMUMachine: conv_keys = True qmp_args = self._qmp_args(conv_keys, args) - ret = self._qmp.cmd(cmd, args=qmp_args) + ret = self._qmp.cmd_raw(cmd, args=qmp_args) if cmd == 'quit' and 'error' not in ret and 'return' in ret: self._quit_issued = True return ret - def command(self, cmd: str, - conv_keys: bool = True, - **args: Any) -> QMPReturnValue: + def cmd(self, cmd: str, + args_dict: Optional[Dict[str, object]] = None, + conv_keys: Optional[bool] = None, + **args: Any) -> QMPReturnValue: """ Invoke a QMP command. On success return the response dict. On failure raise an exception. """ + if args_dict is not None: + assert not args + assert conv_keys is None + args = args_dict + conv_keys = False + + if conv_keys is None: + conv_keys = True + qmp_args = self._qmp_args(conv_keys, args) - ret = self._qmp.command(cmd, **qmp_args) + ret = self._qmp.cmd(cmd, **qmp_args) if cmd == 'quit': self._quit_issued = True return ret @@ -881,10 +901,19 @@ class QEMUMachine: """ if self._console_socket is None: LOG.debug("Opening console socket") + if not self._console_set: + raise QEMUMachineError( + "Attempt to access console socket with no connection") + assert self._cons_sock_pair is not None + # os.dup() is used here for sock_fd because otherwise we'd + # have two rich python socket objects that would each try to + # close the same underlying fd when either one gets garbage + # collected. self._console_socket = console_socket.ConsoleSocket( - self._console_address, + sock_fd=os.dup(self._cons_sock_pair[1].fileno()), file=self._console_log_path, drain=self._drain_console) + self._cons_sock_pair[1].close() return self._console_socket @property @@ -910,15 +939,6 @@ class QEMUMachine: return self._temp_dir @property - def sock_dir(self) -> str: - """ - Returns the directory used for sockfiles by this machine. - """ - if self._sock_dir: - return self._sock_dir - return self.temp_dir - - @property def log_dir(self) -> str: """ Returns a directory to be used for writing logs |