c1c534
From 618632843aeb3a587c2bbfdb7442217ae13b45fe Mon Sep 17 00:00:00 2001
c1c534
Message-Id: <618632843aeb3a587c2bbfdb7442217ae13b45fe@dist-git>
6d3351
From: Jiri Denemark <jdenemar@redhat.com>
6d3351
Date: Tue, 5 Apr 2016 09:14:09 +0200
6d3351
Subject: [PATCH] RHEL: Support virtio disk hotplug in JSON mode
6d3351
6d3351
RHEL only, no upstream
6d3351
6d3351
For bug
6d3351
  https://bugzilla.redhat.com/show_bug.cgi?id=1026966
6d3351
  https://bugzilla.redhat.com/show_bug.cgi?id=573946
6d3351
6d3351
The existing drive_add command can hotplug SCSI and VirtIO
6d3351
disks, but this isn't ported to JSON mode. RHEL6 introduces
6d3351
a custom __com.redhat_drive_add that only supports VirtIO
6d3351
disks. Switch the VirtIO hotplug to this command, but leave
6d3351
the SCSI hotplug using old command so SCSI gets an explicit
6d3351
error about being unsupported.
6d3351
6d3351
* src/libvirt_private.syms: Export virJSONValueObjectRemoveKey
6d3351
* src/util/json.c, src/util/json.h: Add virJSONValueObjectRemoveKey
6d3351
  to allow a key to be deleted from an object
6d3351
* src/qemu/qemu_monitor_json.c: Try __com.redhat_drive_add first and use
6d3351
  drive_add only if the redhat command is not known to qemu.
6d3351
6d3351
Also includes the following fix:
6d3351
6d3351
https://bugzilla.redhat.com/show_bug.cgi?id=696596
6d3351
6d3351
Upstream added drive_del as a way to ensure that disks are fully
6d3351
removed before returning control to libvirt.  But RHEL backported
6d3351
it as __com.redhat_drive_del, prior to upstream adoption of a
6d3351
QMP counterpart.  Because we weren't trying the RHEL-specific
6d3351
spelling, we were falling back to the unsafe approach of just
6d3351
removing the device and hoping for the best, which was racy and
6d3351
could occasionally result in a rapid hot-plug cycle trying to
6d3351
plug in a new disk that collides with the old disk not yet gone.
6d3351
6d3351
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONDriveDel): Try
6d3351
rhel-specific drive_del monitor command first.
6d3351
6d3351
(cherry picked from commit d1c200dfead14a590a4ddebe20a20ffe441d2b24 in
6d3351
rhel-6.5 branch)
6d3351
6d3351
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
6d3351
6d3351
Conflicts:
6d3351
	src/libvirt_private.syms - the change is already upstream
6d3351
        src/util/virjson.[ch] - the change is already upstream
6d3351
	src/qemu/qemu_monitor_json.c - context; upstream doesn't try to
6d3351
	    call nonexistent drive_{add,del} QMP commands any more
6d3351
---
6d3351
 src/qemu/qemu_monitor.c      |  12 +++--
6d3351
 src/qemu/qemu_monitor_json.c | 106 +++++++++++++++++++++++++++++++++++++++++++
6d3351
 src/qemu/qemu_monitor_json.h |   6 +++
c1c534
 tests/qemuhotplugtest.c      |  93 ++++++++++++++++++++++++++++++++++++-
c1c534
 4 files changed, 211 insertions(+), 6 deletions(-)
6d3351
6d3351
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
c1c534
index 3cf23db874..12ad45d340 100644
6d3351
--- a/src/qemu/qemu_monitor.c
6d3351
+++ b/src/qemu/qemu_monitor.c
c1c534
@@ -3125,8 +3125,10 @@ qemuMonitorDriveDel(qemuMonitorPtr mon,
6d3351
 
6d3351
     QEMU_CHECK_MONITOR(mon);
6d3351
 
6d3351
-    /* there won't be a direct replacement for drive_del in QMP */
6d3351
-    return qemuMonitorTextDriveDel(mon, drivestr);
6d3351
+    if (mon->json)
6d3351
+        return qemuMonitorJSONDriveDel(mon, drivestr);
6d3351
+    else
6d3351
+        return qemuMonitorTextDriveDel(mon, drivestr);
6d3351
 }
6d3351
 
6d3351
 
c1c534
@@ -3247,8 +3249,10 @@ qemuMonitorAddDrive(qemuMonitorPtr mon,
6d3351
 
6d3351
     QEMU_CHECK_MONITOR(mon);
6d3351
 
6d3351
-    /* there won't ever be a direct QMP replacement for this function */
6d3351
-    return qemuMonitorTextAddDrive(mon, drivestr);
6d3351
+    if (mon->json)
6d3351
+        return qemuMonitorJSONAddDrive(mon, drivestr);
6d3351
+    else
6d3351
+        return qemuMonitorTextAddDrive(mon, drivestr);
6d3351
 }
6d3351
 
6d3351
 
6d3351
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
c1c534
index 8a75e0ef7e..e0f942788d 100644
6d3351
--- a/src/qemu/qemu_monitor_json.c
6d3351
+++ b/src/qemu/qemu_monitor_json.c
c1c534
@@ -3839,6 +3839,112 @@ int qemuMonitorJSONDelObject(qemuMonitorPtr mon,
6d3351
 }
6d3351
 
6d3351
 
6d3351
+int qemuMonitorJSONAddDrive(qemuMonitorPtr mon,
6d3351
+                            const char *drivestr)
6d3351
+{
6d3351
+    int ret = -1;
6d3351
+    virJSONValuePtr cmd;
6d3351
+    virJSONValuePtr reply = NULL;
6d3351
+    virJSONValuePtr args;
6d3351
+
6d3351
+    cmd = qemuMonitorJSONMakeCommand("__com.redhat_drive_add",
6d3351
+                                     NULL);
6d3351
+    if (!cmd)
6d3351
+        return -1;
6d3351
+
6d3351
+    args = qemuMonitorJSONKeywordStringToJSON(drivestr, "type");
6d3351
+    if (!args)
6d3351
+        goto cleanup;
6d3351
+
6d3351
+    /* __com.redhat_drive_add rejects the 'if' key */
6d3351
+    virJSONValueObjectRemoveKey(args, "if", NULL);
6d3351
+
6d3351
+    if (virJSONValueObjectAppend(cmd, "arguments", args) < 0) {
6d3351
+        virReportOOMError();
6d3351
+        goto cleanup;
6d3351
+    }
6d3351
+    args = NULL; /* cmd owns reference to args now */
6d3351
+
6d3351
+    if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0)
6d3351
+        goto cleanup;
6d3351
+
6d3351
+    if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
6d3351
+        virJSONValueFree(cmd);
6d3351
+        virJSONValueFree(reply);
6d3351
+        cmd = reply = NULL;
6d3351
+
6d3351
+        VIR_DEBUG("__com.redhat_drive_add command not found,"
6d3351
+                  " trying upstream way");
6d3351
+    } else {
6d3351
+        ret = qemuMonitorJSONCheckError(cmd, reply);
6d3351
+        goto cleanup;
6d3351
+    }
6d3351
+
6d3351
+    /* Upstream approach */
6d3351
+    /* there won't be a direct replacement for drive_add in QMP */
6d3351
+    ret = qemuMonitorTextAddDrive(mon, drivestr);
6d3351
+
6d3351
+ cleanup:
6d3351
+    virJSONValueFree(args);
6d3351
+    virJSONValueFree(cmd);
6d3351
+    virJSONValueFree(reply);
6d3351
+    return ret;
6d3351
+}
6d3351
+
6d3351
+
6d3351
+int qemuMonitorJSONDriveDel(qemuMonitorPtr mon,
6d3351
+                            const char *drivestr)
6d3351
+{
6d3351
+    int ret;
6d3351
+    virJSONValuePtr cmd;
6d3351
+    virJSONValuePtr reply = NULL;
6d3351
+
6d3351
+    VIR_DEBUG("drivestr=%s", drivestr);
6d3351
+    cmd = qemuMonitorJSONMakeCommand("__com.redhat_drive_del",
6d3351
+                                     "s:id", drivestr,
6d3351
+                                     NULL);
6d3351
+    if (!cmd)
6d3351
+        return -1;
6d3351
+
6d3351
+    if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0)
6d3351
+        goto cleanup;
6d3351
+
6d3351
+    if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
6d3351
+        virJSONValueFree(cmd);
6d3351
+        virJSONValueFree(reply);
6d3351
+        cmd = reply = NULL;
6d3351
+
6d3351
+        VIR_DEBUG("__com.redhat_drive_del command not found,"
6d3351
+                  " trying upstream way");
6d3351
+    } else if (qemuMonitorJSONHasError(reply, "DeviceNotFound")) {
6d3351
+        /* NB: device not found errors mean the drive was
6d3351
+         * auto-deleted and we ignore the error */
6d3351
+        ret = 0;
6d3351
+        goto cleanup;
6d3351
+    } else {
6d3351
+        ret = qemuMonitorJSONCheckError(cmd, reply);
6d3351
+        goto cleanup;
6d3351
+    }
6d3351
+
6d3351
+    /* Upstream approach */
6d3351
+    /* there won't be a direct replacement for drive_del in QMP */
6d3351
+    if ((ret = qemuMonitorTextDriveDel(mon, drivestr)) < 0) {
6d3351
+        virErrorPtr err = virGetLastError();
6d3351
+        if (err && err->code == VIR_ERR_OPERATION_UNSUPPORTED) {
6d3351
+            VIR_ERROR("%s",
6d3351
+                      _("deleting disk is not supported.  "
6d3351
+                        "This may leak data if disk is reassigned"));
6d3351
+            ret = 1;
6d3351
+            virResetLastError();
6d3351
+        }
6d3351
+    }
6d3351
+
6d3351
+ cleanup:
6d3351
+    virJSONValueFree(cmd);
6d3351
+    virJSONValueFree(reply);
6d3351
+    return ret;
6d3351
+}
6d3351
+
6d3351
 int qemuMonitorJSONSetDrivePassphrase(qemuMonitorPtr mon,
6d3351
                                       const char *alias,
6d3351
                                       const char *passphrase)
6d3351
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
c1c534
index 02a504ab85..f1e818aed2 100644
6d3351
--- a/src/qemu/qemu_monitor_json.h
6d3351
+++ b/src/qemu/qemu_monitor_json.h
c1c534
@@ -234,6 +234,12 @@ int qemuMonitorJSONAddObject(qemuMonitorPtr mon,
6d3351
 int qemuMonitorJSONDelObject(qemuMonitorPtr mon,
6d3351
                              const char *objalias);
6d3351
 
6d3351
+int qemuMonitorJSONAddDrive(qemuMonitorPtr mon,
6d3351
+                            const char *drivestr);
6d3351
+
6d3351
+int qemuMonitorJSONDriveDel(qemuMonitorPtr mon,
6d3351
+                            const char *drivestr);
6d3351
+
6d3351
 int qemuMonitorJSONSetDrivePassphrase(qemuMonitorPtr mon,
6d3351
                                       const char *alias,
6d3351
                                       const char *passphrase);
6d3351
diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c
c1c534
index bdde7e45f3..7691ad8f0f 100644
6d3351
--- a/tests/qemuhotplugtest.c
6d3351
+++ b/tests/qemuhotplugtest.c
c1c534
@@ -663,6 +663,14 @@ mymain(void)
6d3351
     "    }"                                                 \
6d3351
     "}\r\n"
6d3351
 
6d3351
+#define QMP_NOT_FOUND \
6d3351
+    "{" \
6d3351
+    "    \"error\": {" \
6d3351
+    "        \"class\": \"CommandNotFound\"," \
6d3351
+    "        \"desc\": \"The command has not been found\"" \
6d3351
+    "    }" \
6d3351
+    "}"
6d3351
+
6d3351
     DO_TEST_UPDATE("graphics-spice", "graphics-spice-nochange", false, false, NULL);
6d3351
     DO_TEST_UPDATE("graphics-spice-timeout", "graphics-spice-timeout-nochange", false, false,
6d3351
                    "set_password", QMP_OK, "expire_password", QMP_OK);
c1c534
@@ -683,67 +691,135 @@ mymain(void)
6d3351
                    "chardev-remove", QMP_OK);
6d3351
 
6d3351
     DO_TEST_ATTACH("base-live", "disk-virtio", false, true,
6d3351
+                   "__com.redhat_drive_add", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP("OK\\r\\n"),
6d3351
                    "device_add", QMP_OK);
6d3351
     DO_TEST_DETACH("base-live", "disk-virtio", false, false,
6d3351
                    "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP(""));
6d3351
 
6d3351
+    DO_TEST_ATTACH("base-live", "disk-virtio", false, true,
6d3351
+                   "__com.redhat_drive_add", QMP_OK,
6d3351
+                   "device_add", QMP_OK);
6d3351
+    DO_TEST_DETACH("base-live", "disk-virtio", false, false,
6d3351
+                   "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_OK);
6d3351
+
6d3351
     DO_TEST_ATTACH_EVENT("base-live", "disk-virtio", false, true,
6d3351
+                         "__com.redhat_drive_add", QMP_NOT_FOUND,
6d3351
                          "human-monitor-command", HMP("OK\\r\\n"),
6d3351
                          "device_add", QMP_OK);
6d3351
     DO_TEST_DETACH("base-live", "disk-virtio", true, true,
6d3351
                    "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP(""));
6d3351
     DO_TEST_DETACH("base-live", "disk-virtio", false, false,
6d3351
                    "device_del", QMP_DEVICE_DELETED("virtio-disk4") QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP(""));
6d3351
 
6d3351
+    DO_TEST_ATTACH_EVENT("base-live", "disk-virtio", false, true,
6d3351
+                         "__com.redhat_drive_add", QMP_OK,
6d3351
+                         "device_add", QMP_OK);
6d3351
+    DO_TEST_DETACH("base-live", "disk-virtio", true, true,
6d3351
+                   "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_OK);
6d3351
+    DO_TEST_DETACH("base-live", "disk-virtio", false, false,
6d3351
+                   "device_del", QMP_DEVICE_DELETED("virtio-disk4") QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_OK);
6d3351
+
6d3351
     DO_TEST_ATTACH("base-live", "disk-usb", false, true,
6d3351
+                   "__com.redhat_drive_add", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP("OK\\r\\n"),
6d3351
                    "device_add", QMP_OK);
6d3351
     DO_TEST_DETACH("base-live", "disk-usb", false, false,
6d3351
                    "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP(""));
6d3351
 
6d3351
+    DO_TEST_ATTACH("base-live", "disk-usb", false, true,
6d3351
+                   "__com.redhat_drive_add", QMP_OK,
6d3351
+                   "device_add", QMP_OK);
6d3351
+    DO_TEST_DETACH("base-live", "disk-usb", false, false,
6d3351
+                   "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_OK);
6d3351
+
6d3351
     DO_TEST_ATTACH_EVENT("base-live", "disk-usb", false, true,
6d3351
+                         "__com.redhat_drive_add", QMP_NOT_FOUND,
6d3351
                          "human-monitor-command", HMP("OK\\r\\n"),
6d3351
                          "device_add", QMP_OK);
6d3351
     DO_TEST_DETACH("base-live", "disk-usb", true, true,
6d3351
                    "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP(""));
6d3351
     DO_TEST_DETACH("base-live", "disk-usb", false, false,
6d3351
                    "device_del", QMP_DEVICE_DELETED("usb-disk16") QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP(""));
6d3351
 
6d3351
+    DO_TEST_ATTACH_EVENT("base-live", "disk-usb", false, true,
6d3351
+                         "__com.redhat_drive_add", QMP_OK,
6d3351
+                         "device_add", QMP_OK);
6d3351
+    DO_TEST_DETACH("base-live", "disk-usb", true, true,
6d3351
+                   "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_OK);
6d3351
+    DO_TEST_DETACH("base-live", "disk-usb", false, false,
6d3351
+                   "device_del", QMP_DEVICE_DELETED("usb-disk16") QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_OK);
6d3351
+
6d3351
     DO_TEST_ATTACH("base-live", "disk-scsi", false, true,
6d3351
+                   "__com.redhat_drive_add", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP("OK\\r\\n"),
6d3351
                    "device_add", QMP_OK);
6d3351
     DO_TEST_DETACH("base-live", "disk-scsi", false, false,
6d3351
                    "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP(""));
6d3351
 
6d3351
+    DO_TEST_ATTACH("base-live", "disk-scsi", false, true,
6d3351
+                   "__com.redhat_drive_add", QMP_OK,
6d3351
+                   "device_add", QMP_OK);
6d3351
+    DO_TEST_DETACH("base-live", "disk-scsi", false, false,
6d3351
+                   "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_OK);
6d3351
+
6d3351
     DO_TEST_ATTACH_EVENT("base-live", "disk-scsi", false, true,
6d3351
+                         "__com.redhat_drive_add", QMP_NOT_FOUND,
6d3351
                          "human-monitor-command", HMP("OK\\r\\n"),
6d3351
                          "device_add", QMP_OK);
6d3351
     DO_TEST_DETACH("base-live", "disk-scsi", true, true,
6d3351
                    "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP(""));
6d3351
     DO_TEST_DETACH("base-live", "disk-scsi", false, false,
6d3351
                    "device_del", QMP_DEVICE_DELETED("scsi0-0-0-5") QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP(""));
6d3351
 
6d3351
+    DO_TEST_ATTACH_EVENT("base-live", "disk-scsi", false, true,
6d3351
+                         "__com.redhat_drive_add", QMP_OK,
6d3351
+                         "device_add", QMP_OK);
6d3351
+    DO_TEST_DETACH("base-live", "disk-scsi", true, true,
6d3351
+                   "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_OK);
6d3351
+    DO_TEST_DETACH("base-live", "disk-scsi", false, false,
6d3351
+                   "device_del", QMP_DEVICE_DELETED("scsi0-0-0-5") QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_OK);
6d3351
+
6d3351
     DO_TEST_ATTACH("base-without-scsi-controller-live", "disk-scsi-2", false, true,
6d3351
                    /* Four controllers added */
6d3351
                    "device_add", QMP_OK,
6d3351
                    "device_add", QMP_OK,
6d3351
                    "device_add", QMP_OK,
6d3351
                    "device_add", QMP_OK,
6d3351
-                   "human-monitor-command", HMP("OK\\r\\n"),
6d3351
                    /* Disk added */
6d3351
+                   "__com.redhat_drive_add", QMP_NOT_FOUND,
6d3351
+                   "human-monitor-command", HMP("OK\\r\\n"),
6d3351
                    "device_add", QMP_OK);
6d3351
     DO_TEST_DETACH("base-with-scsi-controller-live", "disk-scsi-2", false, false,
6d3351
                    "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP(""));
6d3351
 
6d3351
     DO_TEST_ATTACH_EVENT("base-without-scsi-controller-live", "disk-scsi-2", false, true,
c1c534
@@ -752,14 +828,17 @@ mymain(void)
6d3351
                          "device_add", QMP_OK,
6d3351
                          "device_add", QMP_OK,
6d3351
                          "device_add", QMP_OK,
6d3351
-                         "human-monitor-command", HMP("OK\\r\\n"),
6d3351
                          /* Disk added */
6d3351
+                         "__com.redhat_drive_add", QMP_NOT_FOUND,
6d3351
+                         "human-monitor-command", HMP("OK\\r\\n"),
6d3351
                          "device_add", QMP_OK);
6d3351
     DO_TEST_DETACH("base-with-scsi-controller-live", "disk-scsi-2", true, true,
6d3351
                    "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP(""));
6d3351
     DO_TEST_DETACH("base-with-scsi-controller-live", "disk-scsi-2", false, false,
6d3351
                    "device_del", QMP_DEVICE_DELETED("scsi3-0-5-7") QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP(""));
6d3351
 
6d3351
     DO_TEST_ATTACH("base-live", "qemu-agent", false, true,
c1c534
@@ -770,38 +849,47 @@ mymain(void)
6d3351
                    "chardev-remove", QMP_OK);
6d3351
 
6d3351
     DO_TEST_ATTACH("base-ccw-live", "ccw-virtio", false, true,
6d3351
+                   "__com.redhat_drive_add", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP("OK\\r\\n"),
6d3351
                    "device_add", QMP_OK);
6d3351
     DO_TEST_DETACH("base-ccw-live", "ccw-virtio", false, false,
6d3351
                    "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP(""));
6d3351
 
6d3351
     DO_TEST_ATTACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2", false, true,
6d3351
+                   "__com.redhat_drive_add", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP("OK\\r\\n"),
6d3351
                    "device_add", QMP_OK);
6d3351
 
6d3351
     DO_TEST_DETACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2", false, false,
6d3351
                    "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP(""));
6d3351
 
6d3351
     DO_TEST_ATTACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2-explicit", false, true,
6d3351
+                   "__com.redhat_drive_add", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP("OK\\r\\n"),
6d3351
                    "device_add", QMP_OK);
6d3351
 
6d3351
     DO_TEST_DETACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2-explicit", false, false,
6d3351
                    "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP(""));
6d3351
 
6d3351
     /* Attach a second device, then detach the first one. Then attach the first one again. */
6d3351
     DO_TEST_ATTACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2-explicit", false, true,
6d3351
+                   "__com.redhat_drive_add", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP("OK\\r\\n"),
6d3351
                    "device_add", QMP_OK);
6d3351
 
6d3351
     DO_TEST_DETACH("base-ccw-live-with-2-ccw-virtio", "ccw-virtio-1-explicit", false, true,
6d3351
                    "device_del", QMP_OK,
6d3351
+                   "__com.redhat_drive_del", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP(""));
6d3351
 
6d3351
     DO_TEST_ATTACH("base-ccw-live-with-2-ccw-virtio", "ccw-virtio-1-reverse", false, false,
6d3351
+                   "__com.redhat_drive_add", QMP_NOT_FOUND,
6d3351
                    "human-monitor-command", HMP("OK\\r\\n"),
6d3351
                    "device_add", QMP_OK);
6d3351
 
c1c534
@@ -819,6 +907,7 @@ mymain(void)
c1c534
                    "object-del", QMP_OK);
c1c534
     DO_TEST_ATTACH("base-live+disk-scsi-wwn",
c1c534
                    "disk-scsi-duplicate-wwn", false, false,
c1c534
+                   "__com.redhat_drive_add", QMP_NOT_FOUND,
c1c534
                    "human-monitor-command", HMP("OK\\r\\n"),
c1c534
                    "device_add", QMP_OK);
c1c534
 
6d3351
-- 
c1c534
2.14.3
6d3351