[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v2 15/17] python/aqmp: Create sync QMP wrapper for iotests
From: |
John Snow |
Subject: |
[PATCH v2 15/17] python/aqmp: Create sync QMP wrapper for iotests |
Date: |
Wed, 22 Sep 2021 20:49:36 -0400 |
This is a wrapper around the async QMPClient that mimics the old,
synchronous QEMUMonitorProtocol class. It is designed to be
interchangeable with the old implementation.
It does not, however, attempt to mimic Exception compatibility.
Signed-off-by: John Snow <jsnow@redhat.com>
Acked-by: Hanna Reitz <hreitz@redhat.com>
---
python/qemu/aqmp/legacy.py | 135 +++++++++++++++++++++++++++++++++++++
1 file changed, 135 insertions(+)
create mode 100644 python/qemu/aqmp/legacy.py
diff --git a/python/qemu/aqmp/legacy.py b/python/qemu/aqmp/legacy.py
new file mode 100644
index 00000000000..a75dbc599c0
--- /dev/null
+++ b/python/qemu/aqmp/legacy.py
@@ -0,0 +1,135 @@
+"""
+Sync QMP Wrapper
+
+This class pretends to be qemu.qmp.QEMUMonitorProtocol.
+"""
+
+import asyncio
+from typing import (
+ Awaitable,
+ List,
+ Optional,
+ TypeVar,
+ Union,
+)
+
+import qemu.qmp
+from qemu.qmp import QMPMessage, QMPReturnValue, SocketAddrT
+
+from .qmp_client import QMPClient
+
+
+# pylint: disable=missing-docstring
+
+
+class QEMUMonitorProtocol(qemu.qmp.QEMUMonitorProtocol):
+ def __init__(self, address: SocketAddrT,
+ server: bool = False,
+ nickname: Optional[str] = None):
+
+ # pylint: disable=super-init-not-called
+ self._aqmp = QMPClient(nickname)
+ self._aloop = asyncio.get_event_loop()
+ self._address = address
+ self._timeout: Optional[float] = None
+
+ _T = TypeVar('_T')
+
+ def _sync(
+ self, future: Awaitable[_T], timeout: Optional[float] = None
+ ) -> _T:
+ return self._aloop.run_until_complete(
+ asyncio.wait_for(future, timeout=timeout)
+ )
+
+ def _get_greeting(self) -> Optional[QMPMessage]:
+ if self._aqmp.greeting is not None:
+ # pylint: disable=protected-access
+ return self._aqmp.greeting._asdict()
+ return None
+
+ # __enter__ and __exit__ need no changes
+ # parse_address needs no changes
+
+ def connect(self, negotiate: bool = True) -> Optional[QMPMessage]:
+ self._aqmp.await_greeting = negotiate
+ self._aqmp.negotiate = negotiate
+
+ self._sync(
+ self._aqmp.connect(self._address)
+ )
+ return self._get_greeting()
+
+ def accept(self, timeout: Optional[float] = 15.0) -> QMPMessage:
+ self._aqmp.await_greeting = True
+ self._aqmp.negotiate = True
+
+ self._sync(
+ self._aqmp.accept(self._address),
+ timeout
+ )
+
+ ret = self._get_greeting()
+ assert ret is not None
+ return ret
+
+ def cmd_obj(self, qmp_cmd: QMPMessage) -> QMPMessage:
+ return dict(
+ self._sync(
+ # pylint: disable=protected-access
+
+ # _raw() isn't a public API, because turning off
+ # automatic ID assignment is discouraged. For
+ # compatibility with iotests *only*, do it anyway.
+ self._aqmp._raw(qmp_cmd, assign_id=False),
+ self._timeout
+ )
+ )
+
+ # Default impl of cmd() delegates to cmd_obj
+
+ def command(self, cmd: str, **kwds: object) -> QMPReturnValue:
+ return self._sync(
+ self._aqmp.execute(cmd, kwds),
+ self._timeout
+ )
+
+ def pull_event(self,
+ wait: Union[bool, float] = False) -> Optional[QMPMessage]:
+ if wait is False:
+ # Return None if there's no event ready to go
+ if self._aqmp.events.empty():
+ return None
+
+ timeout = None
+ if isinstance(wait, float):
+ timeout = wait
+
+ return dict(
+ self._sync(
+ self._aqmp.events.get(),
+ timeout
+ )
+ )
+
+ def get_events(self, wait: Union[bool, float] = False) -> List[QMPMessage]:
+ events = [dict(x) for x in self._aqmp.events.clear()]
+ if events:
+ return events
+
+ event = self.pull_event(wait)
+ return [event] if event is not None else []
+
+ def clear_events(self) -> None:
+ self._aqmp.events.clear()
+
+ def close(self) -> None:
+ self._sync(
+ self._aqmp.disconnect()
+ )
+
+ def settimeout(self, timeout: Optional[float]) -> None:
+ self._timeout = timeout
+
+ def send_fd_scm(self, fd: int) -> None:
+ self._aqmp.send_fd_scm(fd)
--
2.31.1
- [PATCH v2 05/17] python/aqmp: Add dict conversion method to Greeting object, (continued)
- [PATCH v2 05/17] python/aqmp: Add dict conversion method to Greeting object, John Snow, 2021/09/22
- [PATCH v2 06/17] python/aqmp: Reduce severity of EOFError-caused loop terminations, John Snow, 2021/09/22
- [PATCH v2 07/17] python/aqmp: Disable logging messages by default, John Snow, 2021/09/22
- [PATCH v2 08/17] python/qmp: clear events on get_events() call, John Snow, 2021/09/22
- [PATCH v2 09/17] python/qmp: add send_fd_scm directly to QEMUMonitorProtocol, John Snow, 2021/09/22
- [PATCH v2 10/17] python, iotests: remove socket_scm_helper, John Snow, 2021/09/22
- [PATCH v2 11/17] python/machine: remove has_quit argument, John Snow, 2021/09/22
- [PATCH v2 12/17] python/machine: Handle QMP errors on close more meticulously, John Snow, 2021/09/22
- [PATCH v2 13/17] iotests: Accommodate async QMP Exception classes, John Snow, 2021/09/22
- [PATCH v2 16/17] python/aqmp: Remove scary message, John Snow, 2021/09/22
- [PATCH v2 15/17] python/aqmp: Create sync QMP wrapper for iotests,
John Snow <=
- [PATCH v2 14/17] iotests: Conditionally silence certain AQMP errors, John Snow, 2021/09/22
- [PATCH v2 17/17] python, iotests: replace qmp with aqmp, John Snow, 2021/09/22