|
|
c401cc |
From 673fabafb0dc8eca749e9b0eae13645afe752e42 Mon Sep 17 00:00:00 2001
|
|
|
c401cc |
Message-Id: <673fabafb0dc8eca749e9b0eae13645afe752e42.1386932213.git.jdenemar@redhat.com>
|
|
|
c401cc |
From: "Daniel P. Berrange" <berrange@redhat.com>
|
|
|
c401cc |
Date: Fri, 17 Dec 2010 14:55:38 +0100
|
|
|
c401cc |
Subject: [PATCH] Support virtio disk hotplug in JSON mode
|
|
|
c401cc |
|
|
|
c401cc |
RHEL only, no upstream
|
|
|
c401cc |
|
|
|
c401cc |
For bug
|
|
|
c401cc |
https://bugzilla.redhat.com/show_bug.cgi?id=1026966
|
|
|
c401cc |
https://bugzilla.redhat.com/show_bug.cgi?id=573946
|
|
|
c401cc |
|
|
|
c401cc |
The existing drive_add command can hotplug SCSI and VirtIO
|
|
|
c401cc |
disks, but this isn't ported to JSON mode. RHEL6 introduces
|
|
|
c401cc |
a custom __com.redhat_drive_add that only supports VirtIO
|
|
|
c401cc |
disks. Switch the VirtIO hotplug to this command, but leave
|
|
|
c401cc |
the SCSI hotplug using old command so SCSI gets an explicit
|
|
|
c401cc |
error about being unsupported.
|
|
|
c401cc |
|
|
|
c401cc |
* src/libvirt_private.syms: Export virJSONValueObjectRemoveKey
|
|
|
c401cc |
* src/util/json.c, src/util/json.h: Add virJSONValueObjectRemoveKey
|
|
|
c401cc |
to allow a key to be deleted from an object
|
|
|
c401cc |
* src/qemu/qemu_monitor_json.c: Try __com.redhat_drive_add first and use
|
|
|
c401cc |
drive_add only if the redhat command is not known to qemu.
|
|
|
c401cc |
|
|
|
c401cc |
Also includes the following fix:
|
|
|
c401cc |
|
|
|
c401cc |
https://bugzilla.redhat.com/show_bug.cgi?id=696596
|
|
|
c401cc |
|
|
|
c401cc |
Upstream added drive_del as a way to ensure that disks are fully
|
|
|
c401cc |
removed before returning control to libvirt. But RHEL backported
|
|
|
c401cc |
it as __com.redhat_drive_del, prior to upstream adoption of a
|
|
|
c401cc |
QMP counterpart. Because we weren't trying the RHEL-specific
|
|
|
c401cc |
spelling, we were falling back to the unsafe approach of just
|
|
|
c401cc |
removing the device and hoping for the best, which was racy and
|
|
|
c401cc |
could occasionally result in a rapid hot-plug cycle trying to
|
|
|
c401cc |
plug in a new disk that collides with the old disk not yet gone.
|
|
|
c401cc |
|
|
|
c401cc |
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONDriveDel): Try
|
|
|
c401cc |
rhel-specific drive_del monitor command first.
|
|
|
c401cc |
|
|
|
c401cc |
(cherry picked from commit d1c200dfead14a590a4ddebe20a20ffe441d2b24 in
|
|
|
c401cc |
rhel-6.5 branch)
|
|
|
c401cc |
|
|
|
c401cc |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
c401cc |
|
|
|
c401cc |
Conflicts:
|
|
|
c401cc |
src/libvirt_private.syms - the change is already upstream
|
|
|
c401cc |
src/util/virjson.[ch] - the change is already upstream
|
|
|
c401cc |
src/qemu/qemu_monitor_json.c - context; upstream doesn't try to
|
|
|
c401cc |
call nonexistent drive_{add,del} QMP commands any more
|
|
|
c401cc |
---
|
|
|
c401cc |
src/qemu/qemu_monitor_json.c | 79 +++++++++++++++++++++++++++++++++++++++++++-
|
|
|
c401cc |
1 file changed, 78 insertions(+), 1 deletion(-)
|
|
|
c401cc |
|
|
|
c401cc |
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
|
|
|
c401cc |
index 18497e3..7b7992f 100644
|
|
|
c401cc |
--- a/src/qemu/qemu_monitor_json.c
|
|
|
c401cc |
+++ b/src/qemu/qemu_monitor_json.c
|
|
|
c401cc |
@@ -3113,9 +3113,53 @@ cleanup:
|
|
|
c401cc |
int qemuMonitorJSONAddDrive(qemuMonitorPtr mon,
|
|
|
c401cc |
const char *drivestr)
|
|
|
c401cc |
{
|
|
|
c401cc |
+ int ret = -1;
|
|
|
c401cc |
+ virJSONValuePtr cmd;
|
|
|
c401cc |
+ virJSONValuePtr reply = NULL;
|
|
|
c401cc |
+ virJSONValuePtr args;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ cmd = qemuMonitorJSONMakeCommand("__com.redhat_drive_add",
|
|
|
c401cc |
+ NULL);
|
|
|
c401cc |
+ if (!cmd)
|
|
|
c401cc |
+ return -1;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ args = qemuMonitorJSONKeywordStringToJSON(drivestr, "type");
|
|
|
c401cc |
+ if (!args)
|
|
|
c401cc |
+ goto cleanup;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ /* __com.redhat_drive_add rejects the 'if' key */
|
|
|
c401cc |
+ virJSONValueObjectRemoveKey(args, "if", NULL);
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (virJSONValueObjectAppend(cmd, "arguments", args) < 0) {
|
|
|
c401cc |
+ virReportOOMError();
|
|
|
c401cc |
+ goto cleanup;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+ args = NULL; /* cmd owns reference to args now */
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply) < 0))
|
|
|
c401cc |
+ goto cleanup;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
|
|
|
c401cc |
+ virJSONValueFree(cmd);
|
|
|
c401cc |
+ virJSONValueFree(reply);
|
|
|
c401cc |
+
|
|
|
c401cc |
+ VIR_DEBUG("__com.redhat_drive_add command not found,"
|
|
|
c401cc |
+ " trying upstream way");
|
|
|
c401cc |
+ } else {
|
|
|
c401cc |
+ ret = qemuMonitorJSONCheckError(cmd, reply);
|
|
|
c401cc |
+ goto cleanup;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+
|
|
|
c401cc |
+ /* Upstream approach */
|
|
|
c401cc |
/* XXX Update to use QMP, if QMP ever adds support for drive_add */
|
|
|
c401cc |
VIR_DEBUG("drive_add command not found, trying HMP");
|
|
|
c401cc |
- return qemuMonitorTextAddDrive(mon, drivestr);
|
|
|
c401cc |
+ ret = qemuMonitorTextAddDrive(mon, drivestr);
|
|
|
c401cc |
+
|
|
|
c401cc |
+cleanup:
|
|
|
c401cc |
+ virJSONValueFree(args);
|
|
|
c401cc |
+ virJSONValueFree(cmd);
|
|
|
c401cc |
+ virJSONValueFree(reply);
|
|
|
c401cc |
+ return ret;
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
|
|
|
c401cc |
@@ -3123,7 +3167,36 @@ int qemuMonitorJSONDriveDel(qemuMonitorPtr mon,
|
|
|
c401cc |
const char *drivestr)
|
|
|
c401cc |
{
|
|
|
c401cc |
int ret;
|
|
|
c401cc |
+ virJSONValuePtr cmd;
|
|
|
c401cc |
+ virJSONValuePtr reply = NULL;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ VIR_DEBUG("drivestr=%s", drivestr);
|
|
|
c401cc |
+ cmd = qemuMonitorJSONMakeCommand("__com.redhat_drive_del",
|
|
|
c401cc |
+ "s:id", drivestr,
|
|
|
c401cc |
+ NULL);
|
|
|
c401cc |
+ if (!cmd)
|
|
|
c401cc |
+ return -1;
|
|
|
c401cc |
|
|
|
c401cc |
+ if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0)
|
|
|
c401cc |
+ goto cleanup;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
|
|
|
c401cc |
+ virJSONValueFree(cmd);
|
|
|
c401cc |
+ virJSONValueFree(reply);
|
|
|
c401cc |
+
|
|
|
c401cc |
+ VIR_DEBUG("__com.redhat_drive_del command not found,"
|
|
|
c401cc |
+ " trying upstream way");
|
|
|
c401cc |
+ } else if (qemuMonitorJSONHasError(reply, "DeviceNotFound")) {
|
|
|
c401cc |
+ /* NB: device not found errors mean the drive was
|
|
|
c401cc |
+ * auto-deleted and we ignore the error */
|
|
|
c401cc |
+ ret = 0;
|
|
|
c401cc |
+ goto cleanup;
|
|
|
c401cc |
+ } else {
|
|
|
c401cc |
+ ret = qemuMonitorJSONCheckError(cmd, reply);
|
|
|
c401cc |
+ goto cleanup;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+
|
|
|
c401cc |
+ /* Upstream approach */
|
|
|
c401cc |
/* XXX Update to use QMP, if QMP ever adds support for drive_del */
|
|
|
c401cc |
VIR_DEBUG("drive_del command not found, trying HMP");
|
|
|
c401cc |
if ((ret = qemuMonitorTextDriveDel(mon, drivestr)) < 0) {
|
|
|
c401cc |
@@ -3136,6 +3209,10 @@ int qemuMonitorJSONDriveDel(qemuMonitorPtr mon,
|
|
|
c401cc |
virResetLastError();
|
|
|
c401cc |
}
|
|
|
c401cc |
}
|
|
|
c401cc |
+
|
|
|
c401cc |
+cleanup:
|
|
|
c401cc |
+ virJSONValueFree(cmd);
|
|
|
c401cc |
+ virJSONValueFree(reply);
|
|
|
c401cc |
return ret;
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
--
|
|
|
c401cc |
1.8.5.1
|
|
|
c401cc |
|