render / rpms / libvirt

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