This is added in anticipation of wanting it for a synchronous wrapper for the iotest interface. Normally, execute() and execute_msg() both raise QMP errors in the form of Python exceptions.
Many iotests expect the entire reply as-is. To reduce churn there, add a private execution interface that will ease transition churn. However, I do not wish to encourage its use, so it will remain a private interface. Signed-off-by: John Snow <js...@redhat.com> --- python/qemu/aqmp/qmp_protocol.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/python/qemu/aqmp/qmp_protocol.py b/python/qemu/aqmp/qmp_protocol.py index 3c16cdc213..36baef9fb3 100644 --- a/python/qemu/aqmp/qmp_protocol.py +++ b/python/qemu/aqmp/qmp_protocol.py @@ -454,6 +454,31 @@ async def _execute(self, msg: Message, assign_id: bool = True) -> Message: exec_id = await self._issue(msg) return await self._reply(exec_id) + @upper_half + @require(Runstate.RUNNING) + async def _raw( + self, + msg: Union[Message, Mapping[str, object], bytes] + ) -> Message: + """ + Issue a fairly raw `Message` to the QMP server and await a reply. + + An AQMP execution ID will be assigned, so it isn't *truly* raw. + + :param msg: + A Message to send to the server. It may be a `Message`, any + Mapping (including Dict), or raw bytes. + + :return: Execution reply from the server. + :raise ExecInterruptedError: + When the reply could not be retrieved because the connection + was lost, or some other problem. + """ + # 1. convert generic Mapping or bytes to a QMP Message + # 2. copy Message objects so that we assign an ID only to the copy. + msg = Message(msg) + return await self._execute(msg) + @upper_half @require(Runstate.RUNNING) async def execute_msg(self, msg: Message) -> object: -- 2.31.1