[Libguestfs] Some notes on using QMP to hot plug disks

Richard W.M. Jones rjones at redhat.com
Fri Mar 25 14:57:23 UTC 2011


I was hoping that we could use QMP (now semi-stable since qemu 0.14)
to hot plug disks.

Unfortunately this is not yet possible.  There is no drive_add QMP
command which would be necessary for adding drives.  We (Red Hat)
hacked in a drive_add command into RHEL 6 (only for use by libvirt).
This doesn't help us with upstream or Fedora.  We could still use the
human monitor, but obviously this isn't designed for machine
consumption.

Anyway, below are my notes about QMP ...

----------------------------------------------------------------------

Documentation for QMP is somewhat sporadic.  The best sources I found
are:

  http://git.qemu.org/qemu.git/tree/qmp-commands.hx
  http://git.qemu.org/qemu.git/tree/QMP/qmp-spec.txt

I added '-qmp unix:$tmpdir/qemu.sock,server' to the QEMU command line
that we generate.

At start up, QEMU blocks until someone connects to the qmp socket.

You can connect manually by starting guestfish + launch, then in
another terminal doing:

  rlwrap socat STDIO UNIX:/tmp/libguestfsXXXXXX/qmp.sock

I'm using the convention of "->" to mean client to server and "<-" to
mean server to client.  QMP does not actually print these characters.

At start up (just after you connect) QMP sends:

<- {"QMP": {"version": {"qemu": {"micro": 0, "minor": 14, "major": 0}, "package": " (qemu-kvm-0.14.0)"}, "capabilities": []}}

The first command you *have* to send is qmp_capabilities (all other
commands are ignored until you do this).  It's unclear how
capabilities negotiation is supposed to work, since there are
currently no capabilities.

-> { "execute": "qmp_capabilities" }
<- {"return": {}}

At shut down QMP sends an asynch event:

<- {"timestamp": {"seconds": 1301057475, "microseconds": 2615}, "event": "SHUTDOWN"}

It appears asynch events can arrive at any time.

Other commands can be run (after capabilities "negotiation" see above):

-> { "execute": "query-kvm", "id": "example" }
<- {"return": {"enabled": true, "present": true}, "id": "example"}

-> { "execute": "query-commands" }
<- {"return": [{"name": "quit"}, {"name": "eject"}, {"name": "change"},
   {"name": "screendump"}, {"name": "stop"}, {"name": "cont"}, {"name":
   "system_reset"}, {"name": "system_powerdown"}, {"name": "device_add"},
   {"name": "device_del"}, {"name": "cpu"}, {"name": "memsave"}, {"name":
   "pmemsave"}, {"name": "migrate"}, {"name": "migrate_cancel"}, {"name":
   "migrate_set_speed"}, {"name": "client_migrate_info"}, {"name":
   "migrate_set_downtime"}, {"name": "netdev_add"}, {"name":
   "netdev_del"}, {"name": "block_resize"}, {"name": "balloon"}, {"name":
   "set_link"}, {"name": "getfd"}, {"name": "closefd"}, {"name":
   "block_passwd"}, {"name": "set_password"}, {"name":
   "expire_password"}, {"name": "qmp_capabilities"}, {"name":
   "human-monitor-command"}, {"name": "query-version"}, {"name":
   "query-commands"}, {"name": "query-chardev"}, {"name": "query-block"},
   {"name": "query-blockstats"}, {"name": "query-cpus"}, {"name":
   "query-pci"}, {"name": "query-kvm"}, {"name": "query-status"},
   {"name": "query-mice"}, {"name": "query-vnc"}, {"name":
   "query-spice"}, {"name": "query-name"}, {"name": "query-uuid"},
   {"name": "query-migrate"}, {"name": "query-balloon"}]}

-> { "execute": "query-pci" }
<- {"return": [{"bus": 0, "devices": [{"bus": 0, "qdev_id": "", "slot":
   0, "class_info": {"class": 1536, "desc": "Host bridge"}, "id":
   {"device": 32902, "vendor": 4663}, "function": 0, "regions": []},
   {"bus": 0, "qdev_id": "", "slot": 1, "class_info": {"class": 1537,
   "desc": "ISA bridge"}, "id": {"device": 32902, "vendor": 28672},
   "function": 0, "regions": []}, {"bus": 0, "qdev_id": "", "slot": 1,
   "class_info": {"class": 257, "desc": "IDE controller"}, "id":
   {"device": 32902, "vendor": 28688}, "function": 1, "regions": [{"bar":
   4, "size": 16, "address": 49152, "type": "io"}]}, {"bus": 0,
   "qdev_id": "", "irq": 9, "slot": 1, "class_info": {"class": 1664,
   "desc": "Bridge"}, "id": {"device": 32902, "vendor": 28947},
   "function": 3, "regions": []}, {"bus": 0, "qdev_id": "", "irq": 10,
   "slot": 2, "class_info": {"class": 1920}, "id": {"device": 6900,
   "vendor": 4099}, "function": 0, "regions": [{"bar": 0, "size": 32,
   "address": 49184, "type": "io"}, {"prefetch": false, "mem_type_64":
   false, "bar": 1, "size": 4096, "address": 4026531840, "type":
   "memory"}]}, {"bus": 0, "qdev_id": "", "irq": 11, "slot": 3,
   "class_info": {"class": 256, "desc": "SCSI controller"}, "id":
   {"device": 6900, "vendor": 4097}, "function": 0, "regions": [{"bar":
   0, "size": 64, "address": 49216, "type": "io"}, {"prefetch": false,
   "mem_type_64": false, "bar": 1, "size": 4096, "address": 4026535936,
   "type": "memory"}]}, {"bus": 0, "qdev_id": "", "irq": 11, "slot": 4,
   "class_info": {"class": 256, "desc": "SCSI controller"}, "id":
   {"device": 6900, "vendor": 4097}, "function": 0, "regions": [{"bar":
   0, "size": 64, "address": 49280, "type": "io"}, {"prefetch": false,
   "mem_type_64": false, "bar": 1, "size": 4096, "address": 4026540032,
   "type": "memory"}]}]}]}

Adding and removing disks:

-> { "execute": "query-block" }
<- {"return": [{"device": "virtio0", "locked": false, "removable":
   false, "inserted": {"ro": false, "drv": "raw", "encrypted": false,
   "file": "/dev/null"}, "type": "hd"}, {"device": "virtio1", "locked":
   false, "removable": false, "inserted": {"ro": false, "drv": "qcow2",
   "backing_file": "/var/tmp/.guestfs-500/root.14807", "encrypted":
   false, "file": "/tmp/vl.Jv5iLK"}, "type": "hd"}]}

[Failed here because adding block devices is not possible with
upstream QMP]

[Assuming we will be able to add devices in future ...] How do we add
devices before the febootstrap device?  Or do we add them after the
febootstrap device and somehow "jump over" that device in
list-devices?

----------------------------------------------------------------------

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming blog: http://rwmj.wordpress.com
Fedora now supports 80 OCaml packages (the OPEN alternative to F#)
http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora




More information about the Libguestfs mailing list