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(-)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 2e9e2de..5612491 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3094,7 +3094,7 @@ qemuMonitorSupportsNodeNames(qemuMonitorPtr mon)
}
-/* Determine the name that qemu is using for tracking the backing
+/* Determine the path name that qemu is using for tracking the backing
* element TARGET within the chain starting at TOP. */
char *
qemuMonitorDiskNameLookup(qemuMonitorPtr mon,
@@ -3108,6 +3108,19 @@ qemuMonitorDiskNameLookup(qemuMonitorPtr mon,
}
+/* Determine the node name that qemu is using for tracking the raw
+ * file of the qcow2 protocol at DEVICE. */
+char *
+qemuMonitorNodeNameLookup(qemuMonitorPtr mon,
+ const char *device)
+{
+ /* TODO - change signature to allow backing file lookups */
+ QEMU_CHECK_MONITOR_JSON_NULL(mon);
+
+ return qemuMonitorJSONNodeNameLookup(mon, device);
+}
+
+
/* Use the block-job-complete monitor command to pivot a block copy job. */
int
qemuMonitorDrivePivot(qemuMonitorPtr mon,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index e198c06..826835b 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -745,6 +745,9 @@ char *qemuMonitorDiskNameLookup(qemuMonitorPtr mon,
virStorageSourcePtr top,
virStorageSourcePtr target)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
+char *qemuMonitorNodeNameLookup(qemuMonitorPtr mon,
+ const char *device)
+ ATTRIBUTE_NONNULL(2);
int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
const char *cmd,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index e4701aa..32b2719 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -3835,6 +3835,8 @@ qemuMonitorJSONDiskNameLookupOne(virJSONValuePtr image,
}
+/* Look up the image name that qemu is using for a member in a backing
+ * chain. */
char *
qemuMonitorJSONDiskNameLookup(qemuMonitorPtr mon,
const char *device,
@@ -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);
+ 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);
+
+ cleanup:
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+
+ return ret;
+}
+
+
/* Used only for capability probing. Assumes that fd set 0 is already
* connected to /dev/null and that we have no existing nodes; we then
* try to add the fd as a block device, and see if the new device has
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index a8ae411..f18295b 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -281,6 +281,9 @@ char *qemuMonitorJSONDiskNameLookup(qemuMonitorPtr mon,
virStorageSourcePtr target)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
ATTRIBUTE_NONNULL(4);
+char *qemuMonitorJSONNodeNameLookup(qemuMonitorPtr mon,
+ const char *device)
+ ATTRIBUTE_NONNULL(2);
bool qemuMonitorJSONSupportsNodeNames(qemuMonitorPtr mon)
ATTRIBUTE_NONNULL(1);
--
2.4.3