QEMU QMP Mechanism

Zihao Chang2020-11-29QEMUQMPHMP

Introduction to QMP

The QEMU Machine Protocol (QMP) is a JSON-based protocol that allows users to query and configure QEMU instances.

In official QEMU documents, QMP has the following features:

  • Lightweight, text-based, easy to parse data format
  • Asynchronous messages support (events)
  • Capabilities negotiation
  • API/ABI stability guarantees

The QMP interface is used by many QEMU-based applications, such as the well-known virtualization middleware libvirt, to communicate with QEMU instances. The QMP interface can be used via telnet or qmp-shell script. For details, see the official QEMU document. This article uses libvirt to display QMP-related interfaces. The virsh tool provided by libvirt can be used to directly invoke QMP interfaces.

1 Prerequisite

  • A server supporting virtualization is installed with virtualization components such as QEMU and libvirt.
  • A virtual machine (VM) can be interacted with through virsh.

2.1 virsh list

This command can be used to check the VM status.

Linux:~ # virsh list
 Id   Name     State
------------------------
 1    ubuntu   running

2.2 qemu-monitor-command

This command is provided by virsh to invoke the QMP interface.

Linux:~ # virsh qemu-monitor-command --help
  NAME
    qemu-monitor-command - QEMU Monitor Command

  SYNOPSIS
    qemu-monitor-command <domain> [--hmp] [--pretty] [--return-value] {[--cmd] <string>}...

  DESCRIPTION
    QEMU Monitor Command

  OPTIONS
    [--domain] <string>  domain name, id or uuid
    --hmp            command is in human monitor protocol
    --pretty         pretty-print any qemu monitor protocol output
    --return-value   extract the value of the 'return' key from the returned string
    [--cmd] <string>  command

--pretty formats JSON output.

--hmp simplifies the complex QMP interface into an interface that can be manually executed.

--return-value extracts the value of the 'return' key from the returned string and ignores information such as status codes.

2.3 Examples

  1. virsh qemu-monitor-command ubuntu '{"execute":"query-commands"}'
Linux:~ # virsh qemu-monitor-command ubuntu '{"execute":"query-commands"}' 
{"return":[{"name":"netdev_add"},{"name":"device_add"},{"name":"query-QMP-schema"},
{"name":"query-memory-size-summary"},{"name":"closefd"},{"name":"getfd"},
{"name":"set_link"},{"name":"query-uuid"},{"name":"query-kvm"},{"name":"query-name"},
    ···
    More output...
    ···
{"name":"add_client"},{"name":"query-commands"},{"name":"query-version"},{"name":"QMP_capabilities"}],"id":"libvirt-21"}

QMP provides many interfaces, including query interfaces such as query-commands, query-qmp-schema, and query-kvm and interfaces for modifying settings such as add_client and set_link.

  1. virsh qemu-monitor-command ubuntu --pretty '{"execute":"query-memory-size-summary"}'
Linux:~ # virsh qemu-monitor-command ubuntu --pretty '{"execute":"query-memory-size-summary"}'
{
  "return": {
    "base-memory": 4294967296,
    "plugged-memory": 0
  },
  "id": "libvirt-30"
}

The --pretty option is added to format the output.

2.4 HMP Format

As mentioned above, the qemu-monitor-command subcommand supports the --hmp option, which simplifies the QMP commands and greatly reduces the complexity of using the QMP commands. In addition, some HMP commands encapsulate QMP commands, indicating that only QMP commands are used at the low-level. According to the official description of QEMU, the HMP is the simple interactive monitor on QEMU, designed primarily for debugging and simple human use. Higher level tools should connect to the QMP, which offers a stable interface with JSON to make it easy to parse reliably. For example, to query the VM memory, using HMP can simplify the command input and output.

Linux:~ # virsh qemu-monitor-command ubuntu --HMP info memory_size_summary
base memory: 4294967296
plugged memory: 0

3. Compiling a New QMP Command

The following shows how to add a hello-world interface to QEMU.

3.1 Compiling and Installing QEMU Source Code

This section describes only the basic steps. You need to install the dependencies based on the platform and host.

git clone https://git.qemu.org/git/qemu.git
cd qemu
git submodule init
git submodule update --recursive
./configure
make

3.2 Compiling the Source Code of the QMP Interface

3.2.3 Adding the QMP Interface

QEMU provides a QMP interface implementation framework. There are multiple .json files in the qapa path of the QEMU source code. These files define QMP interfaces of different categories. The following adds a hello-world interface declaration to the qapi/misc.json file.

##
# @hello-world:
# Print a client provided string to the standard output stream.
#
# @message: string to be printed
#
# Returns: Nothing on success.
#
# Notes: if @message is not provided, the "Hello, world" string will
#        be printed instead
# Since: <next qemu stable release, eg. 1.0>
##
{ 'command': 'hello-world', 'data': { '*message': 'str' } }
3.2.3 Implementing the QMP Function

Add the code for function implementation to monitor/qmp-cmds.c.

void qmp_hello_world(bool has_message, const char *message, Error **errp)
{
    if (has_message) {
        printf("%s\n", message);
    } else {
        printf("Hello, world\n");
    }
}
3.2.4 Implementing the HMP Command

Add the interface to hmp-commands.hx.

    {
        .name       = "hello-world",
        .args_type  = "message:s?",
        .params     = "hello-world [message]",
        .help       = "Print message to the standard output",
        .cmd        = hmp_hello_world,
    },

Add the function declaration to include/monitor/hmp.h.

void hmp_hello_world(Monitor *mon, const QDict *qdict);

Add the code for function implementation to monitor/hmp-cmds.c.

void hmp_hello_world(Monitor *mon, const QDict *qdict)
{
    const char *message = qdict_get_try_str(qdict, "message");
    Error *err = NULL;

    qmp_hello_world(!!message, message, &err);
    if (err) {
        monitor_printf(mon, "%s\n", error_get_pretty(err));
        error_free(err);
        return;
    }
}
3.2.5 Verifying the Implementation of the QMP Command

After compiling the preceding code, modify the tag in the VM XML file, use the customized QEMU to start the VM, and verify the new QMP command.

  1. Check whether the QMP command exists.
Linux:~ # virsh qemu-monitor-command ubuntu --pretty '{"execute":"query-commands"}' | grep hello
      "name": "hello-world"
  1. Invoke the QMP command.
Linux:~ # virsh qemu-monitor-command ubuntu --pretty '{ "execute": "hello-world", "arguments": { "message": "We love qemu" } }'
{
  "return": {

  },
  "id": "libvirt-17"
}
  1. Check whether the HMP command exists.
Linux:~ # virsh qemu-monitor-command ubuntu --hmp help | grep hello
hello-world hello-world [message] -- Print message to the standard output

[Disclaimer] This article only represents the author's opinions, and is irrelevant to this website. This website is neutral in terms of the statements and opinions in this article, and does not provide any express or implied warranty of accuracy, reliability, or completeness of the contents contained therein. This article is for readers' reference only, and all legal responsibilities arising therefrom are borne by the reader himself.