]> xenbits.xensource.com Git - people/dariof/libvirt.git/commitdiff
qemu: support to drop disk with 'optional' startupPolicy
authorGuannan Ren <gren@redhat.com>
Wed, 7 Aug 2013 07:11:15 +0000 (15:11 +0800)
committerGuannan Ren <gren@redhat.com>
Wed, 7 Aug 2013 07:11:15 +0000 (15:11 +0800)
Go through disks of guest, if one disk doesn't exist or its backing
chain is broken, with 'optional' startupPolicy, for CDROM and Floppy
we only discard its source path definition in xml, for disks we drop
it from disk list and free it.

include/libvirt/libvirt.h.in
src/qemu/qemu_domain.c

index 7bd3559211a433a949009a761fc26894efcf6aef..52ac95d722a31d38e5f13dbf59349db5a0e325db 100644 (file)
@@ -4727,6 +4727,7 @@ typedef void (*virConnectDomainEventBlockJobCallback)(virConnectPtr conn,
  */
 typedef enum {
     VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START = 0, /* oldSrcPath is set */
+    VIR_DOMAIN_EVENT_DISK_DROP_MISSING_ON_START = 1,
 
 #ifdef VIR_ENUM_SENTINELS
     VIR_DOMAIN_EVENT_DISK_CHANGE_LAST
index d0f09ae6ad4d29389e906814324061692f0917e6..393af6b68f0fd89b78a035a8506f1f0e972f2d3b 100644 (file)
@@ -2067,6 +2067,47 @@ cleanup:
     virObjectUnref(cfg);
 }
 
+static int
+qemuDomainCheckRemoveOptionalDisk(virQEMUDriverPtr driver,
+                                  virDomainObjPtr vm,
+                                  virDomainDiskDefPtr disk)
+{
+    char uuid[VIR_UUID_STRING_BUFLEN];
+    virDomainEventPtr event = NULL;
+    virDomainDiskDefPtr del_disk = NULL;
+
+    virUUIDFormat(vm->def->uuid, uuid);
+
+    VIR_DEBUG("Dropping disk '%s' on domain '%s' (UUID '%s') "
+              "due to inaccessible source '%s'",
+              disk->dst, vm->def->name, uuid, disk->src);
+
+    if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
+        disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
+
+        event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL,
+                                                   disk->info.alias,
+                                                   VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START);
+        VIR_FREE(disk->src);
+    } else {
+        event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL,
+                                                   disk->info.alias,
+                                                   VIR_DOMAIN_EVENT_DISK_DROP_MISSING_ON_START);
+
+        if (!(del_disk = virDomainDiskRemoveByName(vm->def, disk->src))) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("no source device %s"), disk->src);
+            return -1;
+        }
+        virDomainDiskDefFree(del_disk);
+    }
+
+    if (event)
+        qemuDomainEventQueue(driver, event);
+
+    return 0;
+}
+
 static int
 qemuDomainCheckDiskStartupPolicy(virQEMUDriverPtr driver,
                                  virDomainObjPtr vm,
@@ -2074,7 +2115,6 @@ qemuDomainCheckDiskStartupPolicy(virQEMUDriverPtr driver,
                                  bool cold_boot)
 {
     char uuid[VIR_UUID_STRING_BUFLEN];
-    virDomainEventPtr event = NULL;
     int startupPolicy = disk->startupPolicy;
 
     virUUIDFormat(vm->def->uuid, uuid);
@@ -2097,17 +2137,8 @@ qemuDomainCheckDiskStartupPolicy(virQEMUDriverPtr driver,
             break;
     }
 
-    virResetLastError();
-    VIR_DEBUG("Dropping disk '%s' on domain '%s' (UUID '%s') "
-              "due to inaccessible source '%s'",
-              disk->dst, vm->def->name, uuid, disk->src);
-
-    event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL, disk->info.alias,
-                                               VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START);
-    if (event)
-        qemuDomainEventQueue(driver, event);
-
-    VIR_FREE(disk->src);
+    if (qemuDomainCheckRemoveOptionalDisk(driver, vm, disk) < 0)
+        goto error;
 
     return 0;
 
@@ -2125,8 +2156,8 @@ qemuDomainCheckDiskPresence(virQEMUDriverPtr driver,
     virDomainDiskDefPtr disk;
 
     VIR_DEBUG("Checking for disk presence");
-    for (i = 0; i < vm->def->ndisks; i++) {
-        disk = vm->def->disks[i];
+    for (i = vm->def->ndisks; i > 0; i--) {
+        disk = vm->def->disks[i - 1];
 
         if (!disk->src)
             continue;
@@ -2135,10 +2166,11 @@ qemuDomainCheckDiskPresence(virQEMUDriverPtr driver,
             qemuDiskChainCheckBroken(disk) >= 0)
             continue;
 
-        if (disk->startupPolicy) {
-            if (qemuDomainCheckDiskStartupPolicy(driver, vm, disk,
-                                                 cold_boot) >= 0)
-                continue;
+        if (disk->startupPolicy &&
+            qemuDomainCheckDiskStartupPolicy(driver, vm, disk,
+                                             cold_boot) >= 0) {
+            virResetLastError();
+            continue;
         }
 
         goto error;