Python: synchronize python-qemu-qmp

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+ber27ys35W+dsvQfe+BBqr8OQ4FAmR3sUwACgkQfe+BBqr8
 OQ75GA/+NkO60LR6G7M68Wk2eaLlArlpWKa66lVTUPzIV+ERTzccjzFmEFhYM42z
 lJkkVieysuW/cFpjQqILSokfjiMOEH0XqC2R545vx0shZlExG6j6ky74jpFXxLCY
 1tnZ/wOB97D1nO273T6taGfS6ZPBULaL+J2iCBuruEQiM9OKDQTjojLQYn+hRokL
 BZHF5fkMDts92GHBJdUo8ftYDyblDQ2SUQqdq0pgBgkt+kHlQ4wFB7O39HUwKwT7
 rnAYz7EGbumYGwDkuNSIbpJ2pPiX7SxSPmmrebVPlQ79town3XATLraVbllls5eO
 8BvvkDakO7GvTkzcRvqcFnsnytWJvbEr0jPs1m8lQ2dMTv+NdZmsoItqGDP3LzVZ
 RU/Dr/8biKAbMXpSRH0Waddvmpb18I9I4U2NrVWDZ/vp6DqOFMgx/wUAVz0y0+3O
 M9o9Bj93YZhqBXhpShc75xjvaqJ10IzqG0roR0JbbskdbPmtIEvFlparxGDyH3cX
 UaQPKk8WdRCVOjtodqM28C441zMSUdL5ZCHB1LnMEhbTeV/MkR8W5KAXcYIzy2ay
 gh0FBYoiI8QNBGMR5AEpxdc3XKSSYFXlPGMz74yhlO1hWP1KZM1rE8OWHVfAPcwl
 T4xkw+Hoio9T6SlOWH4qwANaiaX9BII5Dv+L+UqqYt4+neeN8yk=
 =FvG2
 -----END PGP SIGNATURE-----

Merge tag 'python-pull-request' of https://gitlab.com/jsnow/qemu into staging

Python: synchronize python-qemu-qmp

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEE+ber27ys35W+dsvQfe+BBqr8OQ4FAmR3sUwACgkQfe+BBqr8
# OQ75GA/+NkO60LR6G7M68Wk2eaLlArlpWKa66lVTUPzIV+ERTzccjzFmEFhYM42z
# lJkkVieysuW/cFpjQqILSokfjiMOEH0XqC2R545vx0shZlExG6j6ky74jpFXxLCY
# 1tnZ/wOB97D1nO273T6taGfS6ZPBULaL+J2iCBuruEQiM9OKDQTjojLQYn+hRokL
# BZHF5fkMDts92GHBJdUo8ftYDyblDQ2SUQqdq0pgBgkt+kHlQ4wFB7O39HUwKwT7
# rnAYz7EGbumYGwDkuNSIbpJ2pPiX7SxSPmmrebVPlQ79town3XATLraVbllls5eO
# 8BvvkDakO7GvTkzcRvqcFnsnytWJvbEr0jPs1m8lQ2dMTv+NdZmsoItqGDP3LzVZ
# RU/Dr/8biKAbMXpSRH0Waddvmpb18I9I4U2NrVWDZ/vp6DqOFMgx/wUAVz0y0+3O
# M9o9Bj93YZhqBXhpShc75xjvaqJ10IzqG0roR0JbbskdbPmtIEvFlparxGDyH3cX
# UaQPKk8WdRCVOjtodqM28C441zMSUdL5ZCHB1LnMEhbTeV/MkR8W5KAXcYIzy2ay
# gh0FBYoiI8QNBGMR5AEpxdc3XKSSYFXlPGMz74yhlO1hWP1KZM1rE8OWHVfAPcwl
# T4xkw+Hoio9T6SlOWH4qwANaiaX9BII5Dv+L+UqqYt4+neeN8yk=
# =FvG2
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 31 May 2023 01:42:52 PM PDT
# gpg:                using RSA key F9B7ABDBBCACDF95BE76CBD07DEF8106AAFC390E
# gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# 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:
  Revert "python/qmp/protocol: add open_with_socket()"
  python/qmp/legacy: remove open_with_socket() calls
  python/machine: use connect-based interface for existing sockets
  python/qmp/legacy: allow using sockets for connect()
  python/qmp: allow sockets to be passed to connect()

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2023-05-31 14:32:23 -07:00
commit 9824490ded
3 changed files with 41 additions and 47 deletions

View file

@ -337,18 +337,18 @@ def _pre_launch(self) -> None:
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
sock_or_addr = self._monitor_address or sock
assert sock_or_addr is not None
self._qmp_connection = QEMUMonitorProtocol(
address=monitor_address,
sock=sock,
server=True,
sock_or_addr,
server=bool(self._monitor_address),
nickname=self._name
)
@ -370,7 +370,10 @@ def _post_launch(self) -> None:
if self._sock_pair:
self._sock_pair[0].close()
if self._qmp_connection:
self._qmp.accept(self._qmp_timer)
if self._sock_pair:
self._qmp.connect()
else:
self._qmp.accept(self._qmp_timer)
def _close_qemu_log_file(self) -> None:
if self._qemu_log_file is not None:

View file

@ -68,34 +68,31 @@ class QEMUMonitorProtocol:
Provide an API to connect to QEMU via QEMU Monitor Protocol (QMP)
and then allow to handle commands and events.
:param address: QEMU address, can be either a unix socket path (string)
or a tuple in the form ( address, port ) for a TCP
connection or None
:param sock: a socket or None
:param address: QEMU address, can be a unix socket path (string), a tuple
in the form ( address, port ) for a TCP connection, or an
existing `socket.socket` object.
:param server: Act as the socket server. (See 'accept')
Not applicable when passing a socket directly.
:param nickname: Optional nickname used for logging.
"""
def __init__(self,
address: Optional[SocketAddrT] = None,
sock: Optional[socket.socket] = None,
address: Union[SocketAddrT, socket.socket],
server: bool = False,
nickname: Optional[str] = None):
assert address or sock
if server and isinstance(address, socket.socket):
raise ValueError(
"server argument should be False when passing a socket")
self._qmp = QMPClient(nickname)
self._aloop = asyncio.get_event_loop()
self._address = address
self._sock = sock
self._timeout: Optional[float] = None
if server:
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))
assert not isinstance(self._address, socket.socket)
self._sync(self._qmp.start_server(self._address))
_T = TypeVar('_T')
@ -150,7 +147,6 @@ def connect(self, negotiate: bool = True) -> Optional[QMPMessage]:
: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

View file

@ -297,19 +297,6 @@ async def start_server_and_accept(
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,
@ -357,12 +344,11 @@ async def accept(self) -> None:
protocol-level failure occurs while establishing a new
session, the wrapped error may also be an `QMPError`.
"""
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')
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')
@ -370,7 +356,7 @@ async def accept(self) -> None:
@upper_half
@require(Runstate.IDLE)
async def connect(self, address: SocketAddrT,
async def connect(self, address: Union[SocketAddrT, socket.socket],
ssl: Optional[SSLContext] = None) -> None:
"""
Connect to the server and begin processing message queues.
@ -615,7 +601,7 @@ async def _do_accept(self) -> None:
self.logger.debug("Connection accepted.")
@upper_half
async def _do_connect(self, address: SocketAddrT,
async def _do_connect(self, address: Union[SocketAddrT, socket.socket],
ssl: Optional[SSLContext] = None) -> None:
"""
Acting as the transport client, initiate a connection to a server.
@ -634,9 +620,17 @@ async def _do_connect(self, address: SocketAddrT,
# otherwise yield.
await asyncio.sleep(0)
self.logger.debug("Connecting to %s ...", address)
if isinstance(address, tuple):
if isinstance(address, socket.socket):
self.logger.debug("Connecting with existing socket: "
"fd=%d, family=%r, type=%r",
address.fileno(), address.family, address.type)
connect = asyncio.open_connection(
limit=self._limit,
ssl=ssl,
sock=address,
)
elif isinstance(address, tuple):
self.logger.debug("Connecting to %s ...", address)
connect = asyncio.open_connection(
address[0],
address[1],
@ -644,13 +638,14 @@ async def _do_connect(self, address: SocketAddrT,
limit=self._limit,
)
else:
self.logger.debug("Connecting to file://%s ...", address)
connect = asyncio.open_unix_connection(
path=address,
ssl=ssl,
limit=self._limit,
)
self._reader, self._writer = await connect
self._reader, self._writer = await connect
self.logger.debug("Connected.")
@upper_half