43fe83
From 538c19af8b18ecaeda0dc30aa3140bc933283035 Mon Sep 17 00:00:00 2001
43fe83
Message-Id: <538c19af8b18ecaeda0dc30aa3140bc933283035.1377873637.git.jdenemar@redhat.com>
43fe83
From: Guannan Ren <gren@redhat.com>
43fe83
Date: Thu, 8 Aug 2013 16:07:30 +0800
43fe83
Subject: [PATCH] qemu: support to drop disk with 'optional' startupPolicy
43fe83
43fe83
Resovles: https://bugzilla.redhat.com/show_bug.cgi?id=910171
43fe83
(cherry picked from commit 8a160f11afe916284c569d4c23adb24f755e459e)
43fe83
43fe83
Go through disks of guest, if one disk doesn't exist or its backing
43fe83
chain is broken, with 'optional' startupPolicy, for CDROM and Floppy
43fe83
we only discard its source path definition in xml, for disks we drop
43fe83
it from disk list and free it.
43fe83
---
43fe83
 include/libvirt/libvirt.h.in |  1 +
43fe83
 src/qemu/qemu_domain.c       | 68 ++++++++++++++++++++++++++++++++------------
43fe83
 2 files changed, 51 insertions(+), 18 deletions(-)
43fe83
43fe83
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
43fe83
index 7bd3559..52ac95d 100644
43fe83
--- a/include/libvirt/libvirt.h.in
43fe83
+++ b/include/libvirt/libvirt.h.in
43fe83
@@ -4727,6 +4727,7 @@ typedef void (*virConnectDomainEventBlockJobCallback)(virConnectPtr conn,
43fe83
  */
43fe83
 typedef enum {
43fe83
     VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START = 0, /* oldSrcPath is set */
43fe83
+    VIR_DOMAIN_EVENT_DISK_DROP_MISSING_ON_START = 1,
43fe83
 
43fe83
 #ifdef VIR_ENUM_SENTINELS
43fe83
     VIR_DOMAIN_EVENT_DISK_CHANGE_LAST
43fe83
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
43fe83
index d0f09ae..393af6b 100644
43fe83
--- a/src/qemu/qemu_domain.c
43fe83
+++ b/src/qemu/qemu_domain.c
43fe83
@@ -2068,13 +2068,53 @@ cleanup:
43fe83
 }
43fe83
 
43fe83
 static int
43fe83
+qemuDomainCheckRemoveOptionalDisk(virQEMUDriverPtr driver,
43fe83
+                                  virDomainObjPtr vm,
43fe83
+                                  virDomainDiskDefPtr disk)
43fe83
+{
43fe83
+    char uuid[VIR_UUID_STRING_BUFLEN];
43fe83
+    virDomainEventPtr event = NULL;
43fe83
+    virDomainDiskDefPtr del_disk = NULL;
43fe83
+
43fe83
+    virUUIDFormat(vm->def->uuid, uuid);
43fe83
+
43fe83
+    VIR_DEBUG("Dropping disk '%s' on domain '%s' (UUID '%s') "
43fe83
+              "due to inaccessible source '%s'",
43fe83
+              disk->dst, vm->def->name, uuid, disk->src);
43fe83
+
43fe83
+    if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
43fe83
+        disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
43fe83
+
43fe83
+        event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL,
43fe83
+                                                   disk->info.alias,
43fe83
+                                                   VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START);
43fe83
+        VIR_FREE(disk->src);
43fe83
+    } else {
43fe83
+        event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL,
43fe83
+                                                   disk->info.alias,
43fe83
+                                                   VIR_DOMAIN_EVENT_DISK_DROP_MISSING_ON_START);
43fe83
+
43fe83
+        if (!(del_disk = virDomainDiskRemoveByName(vm->def, disk->src))) {
43fe83
+            virReportError(VIR_ERR_INVALID_ARG,
43fe83
+                           _("no source device %s"), disk->src);
43fe83
+            return -1;
43fe83
+        }
43fe83
+        virDomainDiskDefFree(del_disk);
43fe83
+    }
43fe83
+
43fe83
+    if (event)
43fe83
+        qemuDomainEventQueue(driver, event);
43fe83
+
43fe83
+    return 0;
43fe83
+}
43fe83
+
43fe83
+static int
43fe83
 qemuDomainCheckDiskStartupPolicy(virQEMUDriverPtr driver,
43fe83
                                  virDomainObjPtr vm,
43fe83
                                  virDomainDiskDefPtr disk,
43fe83
                                  bool cold_boot)
43fe83
 {
43fe83
     char uuid[VIR_UUID_STRING_BUFLEN];
43fe83
-    virDomainEventPtr event = NULL;
43fe83
     int startupPolicy = disk->startupPolicy;
43fe83
 
43fe83
     virUUIDFormat(vm->def->uuid, uuid);
43fe83
@@ -2097,17 +2137,8 @@ qemuDomainCheckDiskStartupPolicy(virQEMUDriverPtr driver,
43fe83
             break;
43fe83
     }
43fe83
 
43fe83
-    virResetLastError();
43fe83
-    VIR_DEBUG("Dropping disk '%s' on domain '%s' (UUID '%s') "
43fe83
-              "due to inaccessible source '%s'",
43fe83
-              disk->dst, vm->def->name, uuid, disk->src);
43fe83
-
43fe83
-    event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL, disk->info.alias,
43fe83
-                                               VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START);
43fe83
-    if (event)
43fe83
-        qemuDomainEventQueue(driver, event);
43fe83
-
43fe83
-    VIR_FREE(disk->src);
43fe83
+    if (qemuDomainCheckRemoveOptionalDisk(driver, vm, disk) < 0)
43fe83
+        goto error;
43fe83
 
43fe83
     return 0;
43fe83
 
43fe83
@@ -2125,8 +2156,8 @@ qemuDomainCheckDiskPresence(virQEMUDriverPtr driver,
43fe83
     virDomainDiskDefPtr disk;
43fe83
 
43fe83
     VIR_DEBUG("Checking for disk presence");
43fe83
-    for (i = 0; i < vm->def->ndisks; i++) {
43fe83
-        disk = vm->def->disks[i];
43fe83
+    for (i = vm->def->ndisks; i > 0; i--) {
43fe83
+        disk = vm->def->disks[i - 1];
43fe83
 
43fe83
         if (!disk->src)
43fe83
             continue;
43fe83
@@ -2135,10 +2166,11 @@ qemuDomainCheckDiskPresence(virQEMUDriverPtr driver,
43fe83
             qemuDiskChainCheckBroken(disk) >= 0)
43fe83
             continue;
43fe83
 
43fe83
-        if (disk->startupPolicy) {
43fe83
-            if (qemuDomainCheckDiskStartupPolicy(driver, vm, disk,
43fe83
-                                                 cold_boot) >= 0)
43fe83
-                continue;
43fe83
+        if (disk->startupPolicy &&
43fe83
+            qemuDomainCheckDiskStartupPolicy(driver, vm, disk,
43fe83
+                                             cold_boot) >= 0) {
43fe83
+            virResetLastError();
43fe83
+            continue;
43fe83
         }
43fe83
 
43fe83
         goto error;
43fe83
-- 
43fe83
1.8.3.2
43fe83