QMP Protocol
QMP Protocol Implementation
This module provides the QMPClient
class, which can be used to connect
and send commands to a QMP server such as QEMU. The QMP class can be
used to either connect to a listening server, or used to listen and
accept an incoming connection from that server.
- exception qemu.qmp.qmp_client.GreetingError(error_message: str, exc: Exception)[source]
Bases:
_WrappedProtocolError
An exception occurred during the Greeting phase.
- Parameters:
error_message – Human-readable string describing the error.
exc – The root-cause exception.
- exception qemu.qmp.qmp_client.NegotiationError(error_message: str, exc: Exception)[source]
Bases:
_WrappedProtocolError
An exception occurred during the Negotiation phase.
- Parameters:
error_message – Human-readable string describing the error.
exc – The root-cause exception.
- exception qemu.qmp.qmp_client.ExecuteError(error_response: ErrorResponse, sent: Message, received: Message)[source]
Bases:
QMPError
Exception raised by
QMPClient.execute()
on RPC failure.This exception is raised when the server received, interpreted, and replied to a command successfully; but the command itself returned a failure status.
For example:
await qmp.execute('block-dirty-bitmap-add', {'node': 'foo', 'name': 'my_bitmap'}) # qemu.qmp.qmp_client.ExecuteError: # Cannot find device='foo' nor node-name='foo'
- Parameters:
error_response – The RPC error response object.
sent – The sent RPC message that caused the failure.
received – The raw RPC error reply received.
- error: ErrorResponse
The parsed error response
- exception qemu.qmp.qmp_client.ExecInterruptedError[source]
Bases:
QMPError
Exception raised by
execute()
(et al) when an RPC is interrupted.This error is raised when an
execute()
statement could not be completed. This can occur because the connection itself was terminated before a reply was received. The true cause of the interruption will be available viadisconnect()
.The QMP protocol does not make it possible to know if a command succeeded or failed after such an event; the client will need to query the server to determine the state of the server on a case-by-case basis.
For example, ECONNRESET might look like this:
try: await qmp.execute('query-block') # ExecInterruptedError: Disconnected except ExecInterruptedError: await qmp.disconnect() # ConnectionResetError: [Errno 104] Connection reset by peer
- exception qemu.qmp.qmp_client.ServerParseError(error_message: str, msg: Message, *args: object)[source]
Bases:
_MsgProtocolError
The Server sent a
Message
indicating parsing failure.i.e. A reply has arrived from the server, but it is missing the “ID” field, indicating a parsing error.
- Parameters:
error_message – Human-readable string describing the error.
msg – The QMP
Message
that caused the error.
- exception qemu.qmp.qmp_client.BadReplyError(error_message: str, msg: Message, sent: Message)[source]
Bases:
_MsgProtocolError
An execution reply was successfully routed, but not understood.
If a QMP message is received with an ‘id’ field to allow it to be routed, but is otherwise malformed, this exception will be raised.
A reply message is malformed if it is missing either the ‘return’ or ‘error’ keys, or if the ‘error’ value has missing keys or members of the wrong type.
- Parameters:
error_message – Human-readable string describing the error.
msg – The malformed reply that was received.
sent – The message that was sent that prompted the error.
- class qemu.qmp.qmp_client.QMPClient(name: str | None = None)[source]
Bases:
AsyncProtocol
[Message
],Events
Implements a QMP client connection.
QMPClient
can be used to either connect or listen to a QMP server, but always acts as the QMP client.- Parameters:
name – Optional nickname for the connection, used to differentiate instances when logging.
Basic script-style usage looks like this:
import asyncio from qemu.qmp import QMPClient async def main(): qmp = QMPClient('my_virtual_machine_name') await qmp.connect(('127.0.0.1', 1234)) ... res = await qmp.execute('query-block') ... await qmp.disconnect() asyncio.run(main())
A more advanced example that starts to take advantage of asyncio might look like this:
class Client: def __init__(self, name: str): self.qmp = QMPClient(name) async def watch_events(self): try: async for event in self.qmp.events: print(f"Event: {event['event']}") except asyncio.CancelledError: return async def run(self, address='/tmp/qemu.socket'): await self.qmp.connect(address) asyncio.create_task(self.watch_events()) await self.qmp.runstate_changed.wait() await self.disconnect()
See
qmp.events
for more detail on event handling patterns.- logger: logging.Logger = <Logger qemu.qmp.qmp_client (WARNING)>
Logger object used for debugging messages.
- await_greeting: bool
Whether or not to await a greeting after establishing a connection. Defaults to True; QGA servers expect this to be False.
- negotiate: bool
Whether or not to perform capabilities negotiation upon connection. Implies
await_greeting
. Defaults to True; QGA servers expect this to be False.
- property greeting: Greeting | None
The
Greeting
from the QMP server, if any.Defaults to
None
, and will be set after a greeting is received during the connection process. It is reset at the start of each connection attempt.
- async execute_msg(msg: Message) object [source]
Execute a QMP command on the server and return its value.
- Parameters:
msg – The QMP
Message
to execute.- Returns:
The command execution return value from the server. The type of object returned depends on the command that was issued, though most in QEMU return a
dict
.- Raises:
ValueError – If the QMP
Message
does not have either the ‘execute’ or ‘exec-oob’ fields set.ExecuteError – When the server returns an error response.
ExecInterruptedError – If the connection was disrupted before receiving a reply from the server.
- classmethod make_execute_msg(cmd: str, arguments: Mapping[str, object] | None = None, oob: bool = False) Message [source]
Create an executable message to be sent by
execute_msg
later.- Parameters:
cmd – QMP command name.
arguments – Arguments (if any). Must be JSON-serializable.
oob – If
True
, execute “out of band”.
- Returns:
A QMP
Message
that can be executed withexecute_msg()
.
- async execute(cmd: str, arguments: Mapping[str, object] | None = None, oob: bool = False) object [source]
Execute a QMP command on the server and return its value.
- Parameters:
cmd – QMP command name.
arguments – Arguments (if any). Must be JSON-serializable.
oob –
If
True
, execute “out of band”.
- Returns:
The command execution return value from the server. The type of object returned depends on the command that was issued, though most in QEMU return a
dict
.- Raises:
ExecuteError – When the server returns an error response.
ExecInterruptedError – If the connection was disrupted before receiving a reply from the server.
- send_fd_scm(fd: int) None [source]
Send a file descriptor to the remote via SCM_RIGHTS.
This method does not close the file descriptor.
- Parameters:
fd – The file descriptor to send to QEMU.
This is an advanced feature of QEMU where file descriptors can be passed from client to server. This is usually used as a security measure to isolate the QEMU process from being able to open its own files. See the QMP commands
getfd
andadd-fd
for more information.See
socket.socket.sendmsg
for more information on the Python implementation for sending file descriptors over a UNIX socket.
- events: EventListener
Default, all-events
EventListener
. Seeqmp.events
for more info.