mirror of
https://github.com/qemu/qemu.git
synced 2024-12-01 15:53:35 +08:00
Python
Bits and pieces, kibbles'n'bits -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+ber27ys35W+dsvQfe+BBqr8OQ4FAmPQlMIACgkQfe+BBqr8 OQ5RIxAAqaG8Dx63CXa8WHMsGWc0CKTOcwTcRDw92GT3qhVkebZiNmNlZwckaU/c CkVunJnU5T6T2qkploysUXwdlQ+XsY4fQlACNciZeffmT2E4siNQ/4H1uPB4xca6 8Sgmg2VH7OF+EWwuBihY1pbe7g+sOJg9w9isRduBnLGrLbOrewGIJBNbiVzFlz5W 30RdvfLoUUak5qTlMT/6yl98r6fkkDmfPX653iYmpA/H/Ah+17ZJXB2XNigkqBdD Cp8OxtFceKQdZOqNiADJRzT3Gore4lBkPnULKwct/5U0B/tUiBdZ2YDJW8EObUMY zFE7giE5mCnyFSmfBmjKu8yS8zJm9NooYEjunTcodop/FDb96c3sh8376ZLamTii /p5WSwfo4a6DXPUTx0aiCkqpeCdPncRgwKc5TvqyKLKxQHbfjt6UZrcL6iYbe6O6 ltBcdvfdzL41TNjS678QqiGuYkADVa/nhig3ano4msx/Tf5e0O8eMoK9bDbVS9KF QuONtOcut1YhnAHJp4oYN2Nimtr0t8j07iOOfc4X3+WwdbMCfR+toDM4wWVJ3u/O 8Phy8hinfndMXdP9Q4eeFAiJ1zuD/XkpaKoDe0gHcEvp3zMEXmHiEOdv4hFeWTQB ivU3oM/j2uVcHU4CSxra3B54vfLc1gudJ2yLPvhwPKoIRbJ/kbc= =36NA -----END PGP SIGNATURE----- Merge tag 'python-pull-request' of https://gitlab.com/jsnow/qemu into staging Python Bits and pieces, kibbles'n'bits # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEE+ber27ys35W+dsvQfe+BBqr8OQ4FAmPQlMIACgkQfe+BBqr8 # OQ5RIxAAqaG8Dx63CXa8WHMsGWc0CKTOcwTcRDw92GT3qhVkebZiNmNlZwckaU/c # CkVunJnU5T6T2qkploysUXwdlQ+XsY4fQlACNciZeffmT2E4siNQ/4H1uPB4xca6 # 8Sgmg2VH7OF+EWwuBihY1pbe7g+sOJg9w9isRduBnLGrLbOrewGIJBNbiVzFlz5W # 30RdvfLoUUak5qTlMT/6yl98r6fkkDmfPX653iYmpA/H/Ah+17ZJXB2XNigkqBdD # Cp8OxtFceKQdZOqNiADJRzT3Gore4lBkPnULKwct/5U0B/tUiBdZ2YDJW8EObUMY # zFE7giE5mCnyFSmfBmjKu8yS8zJm9NooYEjunTcodop/FDb96c3sh8376ZLamTii # /p5WSwfo4a6DXPUTx0aiCkqpeCdPncRgwKc5TvqyKLKxQHbfjt6UZrcL6iYbe6O6 # ltBcdvfdzL41TNjS678QqiGuYkADVa/nhig3ano4msx/Tf5e0O8eMoK9bDbVS9KF # QuONtOcut1YhnAHJp4oYN2Nimtr0t8j07iOOfc4X3+WwdbMCfR+toDM4wWVJ3u/O # 8Phy8hinfndMXdP9Q4eeFAiJ1zuD/XkpaKoDe0gHcEvp3zMEXmHiEOdv4hFeWTQB # ivU3oM/j2uVcHU4CSxra3B54vfLc1gudJ2yLPvhwPKoIRbJ/kbc= # =36NA # -----END PGP SIGNATURE----- # gpg: Signature made Wed 25 Jan 2023 02:32:34 GMT # gpg: using RSA key F9B7ABDBBCACDF95BE76CBD07DEF8106AAFC390E # gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>" [full] # Primary key fingerprint: FAEB 9711 A12C F475 812F 18F2 88A9 064D 1835 61EB # Subkey fingerprint: F9B7 ABDB BCAC DF95 BE76 CBD0 7DEF 8106 AAFC 390E * tag 'python-pull-request' of https://gitlab.com/jsnow/qemu: python/qemu/machine: use socketpair() for QMP by default python/qmp/legacy: make QEMUMonitorProtocol accept a socket python/qmp/protocol: add open_with_socket() python/qmp: increase read buffer size python/machine: Fix AF_UNIX path too long on macOS python: QEMUMachine: enable qmp accept timeout by default Fix some typos Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
026817fb69
@ -68,7 +68,7 @@ class ConsoleSocket(socket.socket):
|
||||
"""Kick off a thread to drain the socket."""
|
||||
# Configure socket to not block and timeout.
|
||||
# This allows our drain thread to not block
|
||||
# on recieve and exit smoothly.
|
||||
# on receive and exit smoothly.
|
||||
socket.socket.setblocking(self, False)
|
||||
socket.socket.settimeout(self, 1)
|
||||
drain_thread = threading.Thread(target=self._drain_fn)
|
||||
|
@ -131,7 +131,7 @@ class QEMUMachine:
|
||||
drain_console: bool = False,
|
||||
console_log: Optional[str] = None,
|
||||
log_dir: Optional[str] = None,
|
||||
qmp_timer: Optional[float] = None):
|
||||
qmp_timer: Optional[float] = 30):
|
||||
'''
|
||||
Initialize a QEMUMachine
|
||||
|
||||
@ -157,18 +157,14 @@ class QEMUMachine:
|
||||
self._wrapper = wrapper
|
||||
self._qmp_timer = qmp_timer
|
||||
|
||||
self._name = name or f"qemu-{os.getpid()}-{id(self):02x}"
|
||||
self._name = name or f"{id(self):x}"
|
||||
self._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
|
||||
|
||||
if monitor_address is not None:
|
||||
self._monitor_address = monitor_address
|
||||
else:
|
||||
self._monitor_address = os.path.join(
|
||||
self.sock_dir, f"{self._name}-monitor.sock"
|
||||
)
|
||||
self._monitor_address = monitor_address
|
||||
|
||||
self._console_log_path = console_log
|
||||
if self._console_log_path:
|
||||
@ -192,7 +188,7 @@ class QEMUMachine:
|
||||
self._console_set = False
|
||||
self._console_device_type: Optional[str] = None
|
||||
self._console_address = os.path.join(
|
||||
self.sock_dir, f"{self._name}-console.sock"
|
||||
self.sock_dir, f"{self._name}.con"
|
||||
)
|
||||
self._console_socket: Optional[socket.socket] = None
|
||||
self._remove_files: List[str] = []
|
||||
@ -303,7 +299,11 @@ class QEMUMachine:
|
||||
args = ['-display', 'none', '-vga', 'none']
|
||||
|
||||
if self._qmp_set:
|
||||
if isinstance(self._monitor_address, tuple):
|
||||
if self._sock_pair:
|
||||
fd = self._sock_pair[0].fileno()
|
||||
os.set_inheritable(fd, True)
|
||||
moncdev = f"socket,id=mon,fd={fd}"
|
||||
elif isinstance(self._monitor_address, tuple):
|
||||
moncdev = "socket,id=mon,host={},port={}".format(
|
||||
*self._monitor_address
|
||||
)
|
||||
@ -337,10 +337,17 @@ class QEMUMachine:
|
||||
self._remove_files.append(self._console_address)
|
||||
|
||||
if self._qmp_set:
|
||||
monitor_address = None
|
||||
sock = None
|
||||
if self._monitor_address is None:
|
||||
self._sock_pair = socket.socketpair()
|
||||
sock = self._sock_pair[1]
|
||||
if isinstance(self._monitor_address, str):
|
||||
self._remove_files.append(self._monitor_address)
|
||||
monitor_address = self._monitor_address
|
||||
self._qmp_connection = QEMUMonitorProtocol(
|
||||
self._monitor_address,
|
||||
address=monitor_address,
|
||||
sock=sock,
|
||||
server=True,
|
||||
nickname=self._name
|
||||
)
|
||||
@ -360,6 +367,8 @@ class QEMUMachine:
|
||||
))
|
||||
|
||||
def _post_launch(self) -> None:
|
||||
if self._sock_pair:
|
||||
self._sock_pair[0].close()
|
||||
if self._qmp_connection:
|
||||
self._qmp.accept(self._qmp_timer)
|
||||
|
||||
|
@ -42,7 +42,7 @@ class QEMUQtestProtocol:
|
||||
:raise socket.error: on socket connection errors
|
||||
|
||||
.. note::
|
||||
No conection is estabalished by __init__(), this is done
|
||||
No connection is established by __init__(), this is done
|
||||
by the connect() or accept() methods.
|
||||
"""
|
||||
def __init__(self, address: SocketAddrT,
|
||||
|
@ -22,6 +22,7 @@ old interface.
|
||||
#
|
||||
|
||||
import asyncio
|
||||
import socket
|
||||
from types import TracebackType
|
||||
from typing import (
|
||||
Any,
|
||||
@ -69,22 +70,32 @@ class QEMUMonitorProtocol:
|
||||
|
||||
:param address: QEMU address, can be either a unix socket path (string)
|
||||
or a tuple in the form ( address, port ) for a TCP
|
||||
connection
|
||||
connection or None
|
||||
:param sock: a socket or None
|
||||
:param server: Act as the socket server. (See 'accept')
|
||||
:param nickname: Optional nickname used for logging.
|
||||
"""
|
||||
|
||||
def __init__(self, address: SocketAddrT,
|
||||
def __init__(self,
|
||||
address: Optional[SocketAddrT] = None,
|
||||
sock: Optional[socket.socket] = None,
|
||||
server: bool = False,
|
||||
nickname: Optional[str] = None):
|
||||
|
||||
assert address or sock
|
||||
self._qmp = QMPClient(nickname)
|
||||
self._aloop = asyncio.get_event_loop()
|
||||
self._address = address
|
||||
self._sock = sock
|
||||
self._timeout: Optional[float] = None
|
||||
|
||||
if server:
|
||||
self._sync(self._qmp.start_server(self._address))
|
||||
if sock:
|
||||
assert self._sock is not None
|
||||
self._sync(self._qmp.open_with_socket(self._sock))
|
||||
else:
|
||||
assert self._address is not None
|
||||
self._sync(self._qmp.start_server(self._address))
|
||||
|
||||
_T = TypeVar('_T')
|
||||
|
||||
@ -139,6 +150,7 @@ class QEMUMonitorProtocol:
|
||||
:return: QMP greeting dict, or None if negotiate is false
|
||||
:raise ConnectError: on connection errors
|
||||
"""
|
||||
assert self._address is not None
|
||||
self._qmp.await_greeting = negotiate
|
||||
self._qmp.negotiate = negotiate
|
||||
|
||||
|
@ -18,6 +18,7 @@ from asyncio import StreamReader, StreamWriter
|
||||
from enum import Enum
|
||||
from functools import wraps
|
||||
import logging
|
||||
import socket
|
||||
from ssl import SSLContext
|
||||
from typing import (
|
||||
Any,
|
||||
@ -296,6 +297,19 @@ class AsyncProtocol(Generic[T]):
|
||||
await self.accept()
|
||||
assert self.runstate == Runstate.RUNNING
|
||||
|
||||
@upper_half
|
||||
@require(Runstate.IDLE)
|
||||
async def open_with_socket(self, sock: socket.socket) -> None:
|
||||
"""
|
||||
Start connection with given socket.
|
||||
|
||||
:param sock: A socket.
|
||||
|
||||
:raise StateError: When the `Runstate` is not `IDLE`.
|
||||
"""
|
||||
self._reader, self._writer = await asyncio.open_connection(sock=sock)
|
||||
self._set_state(Runstate.CONNECTING)
|
||||
|
||||
@upper_half
|
||||
@require(Runstate.IDLE)
|
||||
async def start_server(self, address: SocketAddrT,
|
||||
@ -343,11 +357,12 @@ class AsyncProtocol(Generic[T]):
|
||||
protocol-level failure occurs while establishing a new
|
||||
session, the wrapped error may also be an `QMPError`.
|
||||
"""
|
||||
if self._accepted is None:
|
||||
raise QMPError("Cannot call accept() before start_server().")
|
||||
await self._session_guard(
|
||||
self._do_accept(),
|
||||
'Failed to establish connection')
|
||||
if not self._reader:
|
||||
if self._accepted is None:
|
||||
raise QMPError("Cannot call accept() before start_server().")
|
||||
await self._session_guard(
|
||||
self._do_accept(),
|
||||
'Failed to establish connection')
|
||||
await self._session_guard(
|
||||
self._establish_session(),
|
||||
'Failed to establish session')
|
||||
@ -812,7 +827,7 @@ class AsyncProtocol(Generic[T]):
|
||||
|
||||
@bottom_half
|
||||
async def _bh_close_stream(self, error_pathway: bool = False) -> None:
|
||||
# NB: Closing the writer also implcitly closes the reader.
|
||||
# NB: Closing the writer also implicitly closes the reader.
|
||||
if not self._writer:
|
||||
return
|
||||
|
||||
|
@ -197,8 +197,8 @@ class QMPClient(AsyncProtocol[Message], Events):
|
||||
#: Logger object used for debugging messages.
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Read buffer limit; large enough to accept query-qmp-schema
|
||||
_limit = (256 * 1024)
|
||||
# Read buffer limit; 10MB like libvirt default
|
||||
_limit = (10 * 1024 * 1024)
|
||||
|
||||
# Type alias for pending execute() result items
|
||||
_PendingT = Union[Message, ExecInterruptedError]
|
||||
|
@ -71,7 +71,7 @@ def format_json(msg: str) -> str:
|
||||
due to an decoding error then a simple string manipulation is done to
|
||||
achieve a single line JSON string.
|
||||
|
||||
Converting into single line is more asthetically pleasing when looking
|
||||
Converting into single line is more aesthetically pleasing when looking
|
||||
along with error messages.
|
||||
|
||||
Eg:
|
||||
@ -91,7 +91,7 @@ def format_json(msg: str) -> str:
|
||||
|
||||
[1, true, 3]: QMP message is not a JSON object.
|
||||
|
||||
The single line mode is more asthetically pleasing.
|
||||
The single line mode is more aesthetically pleasing.
|
||||
|
||||
:param msg:
|
||||
The message to formatted into single line.
|
||||
@ -498,7 +498,7 @@ class EditorWidget(urwid.Filler):
|
||||
class HistoryBox(urwid.ListBox):
|
||||
"""
|
||||
This widget is modelled using the ListBox widget, contains the list of
|
||||
all messages both QMP messages and log messsages to be shown in the TUI.
|
||||
all messages both QMP messages and log messages to be shown in the TUI.
|
||||
|
||||
The messages are urwid.Text widgets. On every append of a message, the
|
||||
focus is shifted to the last appended message.
|
||||
|
@ -306,7 +306,7 @@ class QemuSystemTest(QemuBaseTest):
|
||||
self.cancel('no support for user networking')
|
||||
|
||||
def _new_vm(self, name, *args):
|
||||
self._sd = tempfile.TemporaryDirectory(prefix="avo_qemu_sock_")
|
||||
self._sd = tempfile.TemporaryDirectory(prefix="qemu_")
|
||||
vm = QEMUMachine(self.qemu_bin, base_temp_dir=self.workdir,
|
||||
sock_dir=self._sd.name, log_dir=self.logdir)
|
||||
self.log.debug('QEMUMachine "%s" created', name)
|
||||
|
Loading…
Reference in New Issue
Block a user