On Mon, Jun 22, 2015 at 17:06:42 -0600, Eric Blake wrote:
Implement the QMP side of asking qemu what node name it assigned
to an arbitrary top-level device node. Assumes that the caller
will have already validated that the device is qcow2 backed by
a block device, and that qemu auto-assigns node names.
* src/qemu/qemu_monitor.h (qemuMonitorNodeNameLookup): New function.
* src/qemu/qemu_monitor.c (qemuMonitorNodeNameLookup): Likewise.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONNodeNameLookup):
Likewise.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONNodeNameLookup):
Likewise.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
src/qemu/qemu_monitor.c | 15 ++++++++-
src/qemu/qemu_monitor.h | 3 ++
src/qemu/qemu_monitor_json.c | 77 ++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 3 ++
4 files changed, 97 insertions(+), 1 deletion(-)
...
@@ -3900,6 +3902,81 @@ qemuMonitorJSONDiskNameLookup(qemuMonitorPtr
mon,
}
+/* Look up the node name of the file underneath a qcow2 image. */
+char *
+qemuMonitorJSONNodeNameLookup(qemuMonitorPtr mon,
+ const char *device)
+{
+ char *ret = NULL;
+ virJSONValuePtr cmd = NULL;
+ virJSONValuePtr reply = NULL;
+ virJSONValuePtr devices;
+ size_t i;
+
+ cmd = qemuMonitorJSONMakeCommand("query-blockstats", NULL);
Since this is yet another function that would call query-blockstats ...
+ if (!cmd)
+ return NULL;
+ if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+ goto cleanup;
+
+ if (!(devices = virJSONValueObjectGetArray(reply, "return"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("blockstats reply was missing device list"));
+ goto cleanup;
+ }
+
+ for (i = 0; i < virJSONValueArraySize(devices); i++) {
+ virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
+ virJSONValuePtr parent;
+ const char *thisdev;
+ const char *node;
+
+ if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("blockstats entry was not in expected format"));
+ goto cleanup;
+ }
+
+ if (!(thisdev = virJSONValueObjectGetString(dev, "device"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("blockstats entry was not in expected format"));
+ goto cleanup;
+ }
+
+ if (STRPREFIX(thisdev, QEMU_DRIVE_HOST_PREFIX))
+ thisdev += strlen(QEMU_DRIVE_HOST_PREFIX);
+ if (STRNEQ(thisdev, device))
+ continue;
+
+ if (!(parent = virJSONValueObjectGetObject(dev, "parent"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("blockstats device %s missing parent node"),
+ device);
+ goto cleanup;
+ }
+
+ if (!(node = virJSONValueObjectGetString(parent, "node-name"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("node name missing for device %s"), device);
+ goto cleanup;
+ }
+ ignore_value(VIR_STRDUP(ret, node));
+ goto cleanup;
+ }
+
+ /* If we get here, we didn't find the device. */
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unable to find node name for device %s"),
+ device);
... and works only on one device and thus needs to be re-called for
every single disk I'd rather see us fold this code into
qemuMonitorJSONGetOneBlockStatsInfo so that all the info can be returned
via qemuMonitorJSONGetAllBlockStatsInfo.
I'll post a series that kills qemuMonitorJSONGetBlockExtent since it's
basically the same instance.
Peter