QEMU Monitor Protocol Library
qemu.qmp is a Python library, built on asyncio, for interacting with QEMU emulators via the QEMU Monitor Protocol (QMP). It enables sending QMP messages to control and query QEMU instances, including the QEMU Guest Agent (QGA) and QEMU Storage Daemon (QSD). The library currently stands at version 0.0.6 and has a release cadence tied to the QEMU project's development, as it was originally split from the QEMU source tree.
Warnings
- breaking Older QMP commands, particularly those using `device` argument for `blockdev-open-tray`, `blockdev-close-tray`, `eject`, `blockdev-change-medium`, and `block_set_io_throttle`, are deprecated since QEMU 2.8. They should be replaced with the `id` argument. Using deprecated commands with newer QEMU versions may lead to unexpected behavior or errors.
- gotcha The PyPI package `qmp` (pypi.org/project/qmp) is an older, distinct project. This library is `qemu.qmp` (pypi.org/project/qemu.qmp). Ensure you are installing and importing from the correct package (`qemu.qmp`) to avoid using an unmaintained or incompatible library.
- gotcha The QMP command set is subject to a deprecation policy in QEMU. Commands may have ill-defined semantics, and applications should not rely on undocumented behavior, specific error classes, or data beyond the 'error' key. Always consult the QEMU QMP Reference Manual for stability considerations.
- gotcha Some QMP commands, particularly for querying specific guest details (e.g., `guest-get-cpustats`, `query-memory-devices`), may return 'CommandNotFound' or empty results if the QEMU Guest Agent (QGA) is not installed and running within the guest, or if the QEMU version does not support the command or capability.
Install
-
pip install qemu.qmp
Imports
- QMPClient
from qemu.qmp import QMPClient
- ProtocolError
from qemu.qmp import ProtocolError
- ExecuteError
from qemu.qmp import ExecuteError
- ExecInterruptedError
from qmp import QMPClient
from qemu.qmp import ExecInterruptedError
Quickstart
import asyncio
import os
from qemu.qmp import QMPClient
async def main():
# Replace '127.0.0.1' and '1234' with your QEMU QMP socket address and port.
# For a UNIX socket, use a path string like '/tmp/qemu-monitor.sock'.
# Ensure QEMU is started with a QMP monitor, e.g.,
# qemu-system-x86_64 -qmp tcp:127.0.0.1:1234,server,nowait -enable-kvm ...
# or
# qemu-system-x86_64 -qmp unix:/tmp/qemu-monitor.sock,server,nowait -enable-kvm ...
qmp_host = os.environ.get('QEMU_QMP_HOST', '127.0.0.1')
qmp_port = int(os.environ.get('QEMU_QMP_PORT', '1234'))
qmp_socket_path = os.environ.get('QEMU_QMP_UNIX_SOCKET', None)
qmp = QMPClient('my_vm_instance')
try:
if qmp_socket_path:
print(f"Connecting to QMP UNIX socket: {qmp_socket_path}")
await qmp.connect(qmp_socket_path)
else:
print(f"Connecting to QMP TCP socket: {qmp_host}:{qmp_port}")
await qmp.connect((qmp_host, qmp_port))
print("Connected to QEMU QMP.")
# Example: Execute 'query-status' command
status_response = await qmp.execute({'execute': 'query-status'})
print(f"QEMU Status: {status_response}")
# Example: Execute 'query-version' command
version_response = await qmp.execute({'execute': 'query-version'})
print(f"QEMU Version: {version_response}")
except Exception as e:
print(f"Error connecting or executing QMP command: {e}")
finally:
if qmp.is_connected():
await qmp.disconnect()
print("Disconnected from QEMU QMP.")
if __name__ == '__main__':
asyncio.run(main())