[libvirt] [PATCH 6/6] vbox: Update XML dump of storage devices.

Dawid Zamirski dzamirski at datto.com
Mon Oct 9 20:49:54 UTC 2017


From: Dawid Zamirski <dzamirski at datto.com>

* added vboxDumpStorageControllers
* replaced vboxDumpIDEHDDs with vboxDumpDisks which has been refectored
  quite a bit to handle removable devices, the new SAS controller
  support etc.
* align the logic in vboxSnapshotGetReadWriteDisks and
  vboxSnapshotGetReadOnlyDisks to more closely resemble vboxDumpDisks.
* vboxGenerateMediumName was simplified to no longer "compute" the
  device name value as deviePort/deviceSlot and their upper bound
  values are no longer enough to do this accurately due to the added
  SAS bus support which does not "map" directly into libvirt XML
  semantics
* vboxGetMaxPortSlotValues is now removed as it's no longer used
---
 src/vbox/vbox_common.c | 691 ++++++++++++++++++++++++++++---------------------
 1 file changed, 393 insertions(+), 298 deletions(-)

diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c
index 7645b29a0..dd876645a 100644
--- a/src/vbox/vbox_common.c
+++ b/src/vbox/vbox_common.c
@@ -290,126 +290,44 @@ static int openSessionForMachine(vboxDriverPtr data, const unsigned char *dom_uu
     return 0;
 }
 
-/**
- * function to get the values for max port per
- * instance and max slots per port for the devices
- *
- * @returns     true on Success, false on failure.
- * @param       vbox            Input IVirtualBox pointer
- * @param       maxPortPerInst  Output array of max port per instance
- * @param       maxSlotPerPort  Output array of max slot per port
- *
- */
-
-static bool vboxGetMaxPortSlotValues(IVirtualBox *vbox,
-                                     PRUint32 *maxPortPerInst,
-                                     PRUint32 *maxSlotPerPort)
-{
-    ISystemProperties *sysProps = NULL;
-
-    if (!vbox)
-        return false;
-
-    gVBoxAPI.UIVirtualBox.GetSystemProperties(vbox, &sysProps);
-
-    if (!sysProps)
-        return false;
-
-    gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps,
-                                                             StorageBus_IDE,
-                                                             &maxPortPerInst[StorageBus_IDE]);
-    gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps,
-                                                             StorageBus_SATA,
-                                                             &maxPortPerInst[StorageBus_SATA]);
-    gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps,
-                                                             StorageBus_SCSI,
-                                                             &maxPortPerInst[StorageBus_SCSI]);
-    gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps,
-                                                             StorageBus_SAS,
-                                                             &maxPortPerInst[StorageBus_SAS]);
-    gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps,
-                                                             StorageBus_Floppy,
-                                                             &maxPortPerInst[StorageBus_Floppy]);
-
-    gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps,
-                                                                  StorageBus_IDE,
-                                                                  &maxSlotPerPort[StorageBus_IDE]);
-    gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps,
-                                                                  StorageBus_SATA,
-                                                                  &maxSlotPerPort[StorageBus_SATA]);
-    gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps,
-                                                                  StorageBus_SCSI,
-                                                                  &maxSlotPerPort[StorageBus_SCSI]);
-    gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps,
-                                                                  StorageBus_SAS,
-                                                                  &maxSlotPerPort[StorageBus_SAS]);
-    gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps,
-                                                                  StorageBus_Floppy,
-                                                                  &maxSlotPerPort[StorageBus_Floppy]);
-
-    VBOX_RELEASE(sysProps);
-
-    return true;
-}
-
 /**
  * function to generate the name for medium,
  * for e.g: hda, sda, etc
  *
  * @returns     null terminated string with device name or NULL
  *              for failures
- * @param       conn            Input Connection Pointer
  * @param       storageBus      Input storage bus type
- * @param       deviceInst      Input device instance number
  * @param       devicePort      Input port number
  * @param       deviceSlot      Input slot number
- * @param       aMaxPortPerInst Input array of max port per device instance
- * @param       aMaxSlotPerPort Input array of max slot per device port
- *
+ * @param       sdCount         Running total of disk devices with "sd" prefix
  */
-static char *vboxGenerateMediumName(PRUint32 storageBus,
-                                    PRInt32 deviceInst,
-                                    PRInt32 devicePort,
-                                    PRInt32 deviceSlot,
-                                    PRUint32 *aMaxPortPerInst,
-                                    PRUint32 *aMaxSlotPerPort)
+static char *
+vboxGenerateMediumName(PRUint32 storageBus, PRInt32 devicePort,
+                       PRInt32 deviceSlot, size_t sdCount)
 {
     const char *prefix = NULL;
     char *name = NULL;
     int total = 0;
-    PRUint32 maxPortPerInst = 0;
-    PRUint32 maxSlotPerPort = 0;
-
-    if (!aMaxPortPerInst ||
-        !aMaxSlotPerPort)
-        return NULL;
 
     if ((storageBus < StorageBus_IDE) ||
         (storageBus > StorageBus_SAS))
         return NULL;
 
-    maxPortPerInst = aMaxPortPerInst[storageBus];
-    maxSlotPerPort = aMaxSlotPerPort[storageBus];
-    total = (deviceInst * maxPortPerInst * maxSlotPerPort)
-            + (devicePort * maxSlotPerPort)
-            + deviceSlot;
-
     if (storageBus == StorageBus_IDE) {
         prefix = "hd";
+        total = devicePort * 2 + deviceSlot;
     } else if (storageBus == StorageBus_SATA ||
                storageBus == StorageBus_SCSI ||
                storageBus == StorageBus_SAS) {
         prefix = "sd";
+        total = sdCount;
     } else if (storageBus == StorageBus_Floppy) {
+        total = deviceSlot;
         prefix = "fd";
     }
 
     name = virIndexToDiskName(total, prefix);
 
-    VIR_DEBUG("name=%s, total=%d, storageBus=%u, deviceInst=%d, "
-          "devicePort=%d deviceSlot=%d, maxPortPerInst=%u maxSlotPerPort=%u",
-          NULLSTR(name), total, storageBus, deviceInst, devicePort,
-          deviceSlot, maxPortPerInst, maxSlotPerPort);
     return name;
 }
 
@@ -3086,162 +3004,300 @@ vboxHostDeviceGetXMLDesc(vboxDriverPtr data, virDomainDefPtr def, IMachine *mach
 }
 
 static void
-vboxDumpIDEHDDs(virDomainDefPtr def, vboxDriverPtr data, IMachine *machine)
+vboxDumpStorageControllers(virDomainDefPtr def,
+                           vboxDriverPtr data ATTRIBUTE_UNUSED,
+                           IMachine *machine)
 {
-    /* dump IDE hdds if present */
-    vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER;
-    bool error = false;
-    int diskCount = 0;
-    size_t i;
-    PRUint32 maxPortPerInst[StorageBus_SAS + 1] = {};
-    PRUint32 maxSlotPerPort[StorageBus_SAS + 1] = {};
+    vboxArray storageControllers = VBOX_ARRAY_INITIALIZER;
+    virDomainControllerDefPtr cont = NULL;
+    size_t i = 0;
 
-    def->ndisks = 0;
-    gVBoxAPI.UArray.vboxArrayGet(&mediumAttachments, machine,
-                                 gVBoxAPI.UArray.handleMachineGetMediumAttachments(machine));
+    gVBoxAPI.UArray.vboxArrayGet(&storageControllers, machine,
+                 gVBoxAPI.UArray.handleMachineGetStorageControllers(machine));
 
-    /* get the number of attachments */
-    for (i = 0; i < mediumAttachments.count; i++) {
-        IMediumAttachment *imediumattach = mediumAttachments.items[i];
-        if (imediumattach) {
-            IMedium *medium = NULL;
+    for (i = 0; i < storageControllers.count; i++) {
+        IStorageController *controller = storageControllers.items[i];
+        PRUint32 storageBus = StorageBus_Null;
+        PRUint32 controllerType = StorageControllerType_Null;
+
+        gVBoxAPI.UIStorageController.GetBus(controller, &storageBus);
+        gVBoxAPI.UIStorageController.GetControllerType(controller,
+                                                       &controllerType);
+
+        switch (storageBus) {
+        case StorageBus_IDE:
+        {
+            int model = -1;
+            switch (controllerType) {
+            case StorageControllerType_PIIX3:
+                model = VIR_DOMAIN_CONTROLLER_MODEL_IDE_PIIX3;
+                break;
+            case StorageControllerType_PIIX4:
+                model = VIR_DOMAIN_CONTROLLER_MODEL_IDE_PIIX4;
+                break;
+            case StorageControllerType_ICH6:
+                model = VIR_DOMAIN_CONTROLLER_MODEL_IDE_ICH6;
+                break;
+            }
 
-            gVBoxAPI.UIMediumAttachment.GetMedium(imediumattach, &medium);
-            if (medium) {
-                def->ndisks++;
-                VBOX_RELEASE(medium);
+            cont = virDomainDefAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_IDE,
+                                            -1, model);
+
+            break;
+        }
+        case StorageBus_SCSI:
+        {
+            int model = -1;
+            switch (controllerType) {
+            case StorageControllerType_BusLogic:
+                model = VIR_DOMAIN_CONTROLLER_MODEL_SCSI_BUSLOGIC;
+                break;
+            case StorageControllerType_LsiLogic:
+                model = VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC;
+                break;
             }
+
+            cont = virDomainDefAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_SCSI,
+                                             -1, model);
+
+            break;
+        }
+        case StorageBus_SAS:
+            cont = virDomainDefAddController(def,
+                                             VIR_DOMAIN_CONTROLLER_TYPE_SCSI, -1,
+                                             VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1068);
+            break;
+        case StorageBus_SATA:
+            cont = virDomainDefAddController(def,
+                                             VIR_DOMAIN_CONTROLLER_TYPE_SATA, -1, -1);
+            break;
+        case StorageBus_Floppy:
+            cont = virDomainDefAddController(def,
+                                      VIR_DOMAIN_CONTROLLER_TYPE_FDC, -1, -1);
+            break;
         }
     }
 
-    /* Allocate mem, if fails return error */
-    if (VIR_ALLOC_N(def->disks, def->ndisks) >= 0) {
-        for (i = 0; i < def->ndisks; i++) {
-            virDomainDiskDefPtr disk = virDomainDiskDefNew(NULL);
-            if (!disk) {
-                error = true;
-                break;
+    if (!cont) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Failed to add controller definition"));
+    }
+}
+
+static void
+vboxDumpDisks(virDomainDefPtr def, vboxDriverPtr data, IMachine *machine)
+{
+    vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER;
+    IMediumAttachment *mediumattach = NULL;
+    IMedium *medium = NULL;
+    nsresult rc;
+    size_t sdCount = 0, i, j;
+
+    def->ndisks = 0;
+    rc = gVBoxAPI.UArray.vboxArrayGet(&mediumAttachments, machine,
+                  gVBoxAPI.UArray.handleMachineGetMediumAttachments(machine));
+
+    if (NS_FAILED(rc)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Could not get machine's medium attachments"));
+        goto error;
+    }
+
+    /* get the number of attachments */
+    for (i = 0; i < mediumAttachments.count; i++) {
+        mediumattach = mediumAttachments.items[i];
+        if (mediumattach) {
+            rc = gVBoxAPI.UIMediumAttachment.GetMedium(mediumattach, &medium);
+            if (NS_FAILED(rc)) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("cannot get medium"));
+                goto error;
             }
-            def->disks[i] = disk;
+
+            def->ndisks++;
+            VBOX_RELEASE(medium);
         }
-    } else {
-        error = true;
     }
 
-    if (!error)
-        error = !vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst, maxSlotPerPort);
+    if (VIR_ALLOC_N(def->disks, def->ndisks) < 0)
+        goto error;
+
+    for (i = 0; i < def->ndisks; i++) {
+        virDomainDiskDefPtr disk = virDomainDiskDefNew(NULL);
+        if (!disk)
+            goto error;
+
+        def->disks[i] = disk;
+    }
 
     /* get the attachment details here */
-    for (i = 0; i < mediumAttachments.count && diskCount < def->ndisks && !error; i++) {
-        IMediumAttachment *imediumattach = mediumAttachments.items[i];
+    for (i = 0; i < mediumAttachments.count; i++) {
+        mediumattach = mediumAttachments.items[i];
         IStorageController *storageController = NULL;
         PRUnichar *storageControllerName = NULL;
         PRUint32 deviceType = DeviceType_Null;
         PRUint32 storageBus = StorageBus_Null;
         PRBool readOnly = PR_FALSE;
-        IMedium *medium = NULL;
         PRUnichar *mediumLocUtf16 = NULL;
         char *mediumLocUtf8 = NULL;
-        PRUint32 deviceInst = 0;
         PRInt32 devicePort = 0;
         PRInt32 deviceSlot = 0;
+        virDomainDiskDefPtr disk = def->disks[i];
 
-        if (!imediumattach)
-            continue;
+        if (!mediumattach)
+            goto skip;
 
-        gVBoxAPI.UIMediumAttachment.GetMedium(imediumattach, &medium);
-        if (!medium)
-            continue;
+        rc = gVBoxAPI.UIMediumAttachment.GetController(mediumattach,
+                                                       &storageControllerName);
+        if (NS_FAILED(rc)) {
+            VIR_WARN("Could not get storage controller name for medium "
+                     "attachment, rc=%08x", (unsigned) rc);
+            goto skip;
+        }
 
-        gVBoxAPI.UIMediumAttachment.GetController(imediumattach, &storageControllerName);
-        if (!storageControllerName) {
-            VBOX_RELEASE(medium);
-            continue;
+        rc = gVBoxAPI.UIMachine.GetStorageControllerByName(machine,
+                                                           storageControllerName,
+                                                           &storageController);
+        if (NS_FAILED(rc)) {
+            VIR_WARN("Could not get storage controller for medium attachment, "
+                     "rc=%08x", (unsigned) rc);
+            goto skip;
         }
 
-        gVBoxAPI.UIMachine.GetStorageControllerByName(machine,
-                                                      storageControllerName,
-                                                      &storageController);
-        VBOX_UTF16_FREE(storageControllerName);
-        if (!storageController) {
-            VBOX_RELEASE(medium);
-            continue;
+        rc = gVBoxAPI.UIStorageController.GetBus(storageController,
+                                                 &storageBus);
+        if (NS_FAILED(rc)) {
+            VIR_WARN("Could not get storage controller bus type, rc=%08x",
+                     (unsigned) rc);
+            goto skip;
         }
 
-        gVBoxAPI.UIMedium.GetLocation(medium, &mediumLocUtf16);
-        VBOX_UTF16_TO_UTF8(mediumLocUtf16, &mediumLocUtf8);
-        VBOX_UTF16_FREE(mediumLocUtf16);
-        ignore_value(virDomainDiskSetSource(def->disks[diskCount],
-                                            mediumLocUtf8));
-        VBOX_UTF8_FREE(mediumLocUtf8);
+        rc = gVBoxAPI.UIMediumAttachment.GetType(mediumattach, &deviceType);
+        if (NS_FAILED(rc)) {
+            VIR_WARN("Could not get device type for medium attachment, rc=%08x",
+                     (unsigned) rc);
+            goto skip;
+        }
 
-        if (!virDomainDiskGetSource(def->disks[diskCount])) {
-            VBOX_RELEASE(medium);
-            VBOX_RELEASE(storageController);
-            error = true;
-            break;
+        rc = gVBoxAPI.UIMediumAttachment.GetPort(mediumattach, &devicePort);
+        if (NS_FAILED(rc)) {
+            VIR_WARN("Could not get device port for medium attachment, rc=%08x",
+                     (unsigned) rc);
+            goto skip;
+        }
+
+        rc = gVBoxAPI.UIMediumAttachment.GetDevice(mediumattach, &deviceSlot);
+        if (NS_FAILED(rc)) {
+            VIR_WARN("Could not get device slot for medium attachment, rc=%08x",
+                     (unsigned) rc);
+            goto skip;
         }
 
-        gVBoxAPI.UIStorageController.GetBus(storageController, &storageBus);
+        rc = gVBoxAPI.UIMediumAttachment.GetMedium(mediumattach, &medium);
+        if (NS_FAILED(rc)) {
+            VIR_WARN("Could not get medium for medium attachment, rc=%08x",
+                     (unsigned) rc);
+            goto skip;
+        }
+
+        /* removable drives might not have mediums */
+        if (medium) {
+            rc = gVBoxAPI.UIMedium.GetLocation(medium, &mediumLocUtf16);
+            if (NS_FAILED(rc)) {
+                VIR_WARN("Clould not get storage location for medium, rc=%08x",
+                         (unsigned) rc);
+                goto skip;
+            }
+
+            rc = gVBoxAPI.UIMedium.GetReadOnly(medium, &readOnly);
+            if (NS_FAILED(rc)) {
+                VIR_WARN("Clould not get read-only status for medium, rc=%08x",
+                         (unsigned) rc);
+                goto skip;
+            }
+
+            VBOX_UTF16_TO_UTF8(mediumLocUtf16, &mediumLocUtf8);
+            if (virDomainDiskSetSource(disk, mediumLocUtf8) < 0) {
+                VIR_WARN("Could not set disk source for medium %s",
+                         mediumLocUtf8);
+                goto skip;
+            }
+        }
+
+        disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
+        disk->info.addr.drive.bus = 0;
+        disk->info.addr.drive.unit = devicePort;
+
+        disk->dst = vboxGenerateMediumName(storageBus, devicePort, deviceSlot,
+                                           sdCount);
         if (storageBus == StorageBus_IDE) {
-            def->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_IDE;
+            disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
+            disk->info.addr.drive.bus = devicePort; /* primary, secondary */
+            disk->info.addr.drive.unit = deviceSlot; /* master, slave */
+            disk->dst = virIndexToDiskName(devicePort * 2 + deviceSlot, "hd");
+            disk->info.addr.drive.controller =
+                virDomainControllerFindByType(def,
+                                              VIR_DOMAIN_CONTROLLER_TYPE_IDE);
         } else if (storageBus == StorageBus_SATA) {
-            def->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SATA;
+            disk->bus = VIR_DOMAIN_DISK_BUS_SATA;
+            disk->info.addr.drive.controller =
+                virDomainControllerFindByType(def,
+                                              VIR_DOMAIN_CONTROLLER_TYPE_SATA);
+            sdCount++;
         } else if (storageBus == StorageBus_SCSI ||
                    storageBus == StorageBus_SAS) {
-            def->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SCSI;
+            disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
+            sdCount++;
+            /* find scsi controller index with matching model for vbox bus type */
+            for (j = 0; j < def->ncontrollers; j++) {
+                virDomainControllerDefPtr ctrl = def->controllers[j];
+
+                if (ctrl->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI)
+                    continue;
+
+                if (storageBus == StorageBus_SAS &&
+                    ctrl->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1068) {
+                    disk->info.addr.drive.controller = ctrl->idx;
+                } else if (storageBus == StorageBus_SCSI &&
+                           ctrl->model != VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1068) {
+                    disk->info.addr.drive.controller = ctrl->idx;
+                }
+            }
         } else if (storageBus == StorageBus_Floppy) {
-            def->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_FDC;
+            disk->bus = VIR_DOMAIN_DISK_BUS_FDC;
+            disk->info.addr.drive.unit = deviceSlot;
         }
 
-        gVBoxAPI.UIMediumAttachment.GetType(imediumattach, &deviceType);
         if (deviceType == DeviceType_HardDisk)
-            def->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_DISK;
+            disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
         else if (deviceType == DeviceType_Floppy)
-            def->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
+            disk->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
         else if (deviceType == DeviceType_DVD)
-            def->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
-
-        gVBoxAPI.UIMediumAttachment.GetPort(imediumattach, &devicePort);
-        gVBoxAPI.UIMediumAttachment.GetDevice(imediumattach, &deviceSlot);
-        def->disks[diskCount]->dst = vboxGenerateMediumName(storageBus,
-                                                            deviceInst,
-                                                            devicePort,
-                                                            deviceSlot,
-                                                            maxPortPerInst,
-                                                            maxSlotPerPort);
-        if (!def->disks[diskCount]->dst) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Could not generate medium name for the disk "
-                             "at: controller instance:%u, port:%d, slot:%d"),
-                           deviceInst, devicePort, deviceSlot);
-            VBOX_RELEASE(medium);
-            VBOX_RELEASE(storageController);
-            error = true;
-            break;
-        }
+            disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
 
-        gVBoxAPI.UIMedium.GetReadOnly(medium, &readOnly);
         if (readOnly == PR_TRUE)
-            def->disks[diskCount]->src->readonly = true;
+            disk->src->readonly = true;
 
-        virDomainDiskSetType(def->disks[diskCount],
-                             VIR_STORAGE_TYPE_FILE);
+        virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
 
+ skip:
+        VBOX_UTF16_FREE(storageControllerName);
+        VBOX_UTF8_FREE(mediumLocUtf8);
+        VBOX_UTF16_FREE(mediumLocUtf16);
         VBOX_RELEASE(medium);
         VBOX_RELEASE(storageController);
-        diskCount++;
     }
 
     gVBoxAPI.UArray.vboxArrayRelease(&mediumAttachments);
 
-    /* cleanup on error */
-    if (error) {
-        for (i = 0; i < def->ndisks; i++)
-            VIR_FREE(def->disks[i]);
-        VIR_FREE(def->disks);
-        def->ndisks = 0;
-    }
+    return;
+
+ error:
+    for (i = 0; i < def->ndisks; i++)
+        VIR_FREE(def->disks[i]);
+    VIR_FREE(def->disks);
+    def->ndisks = 0;
+    gVBoxAPI.UArray.vboxArrayRelease(&mediumAttachments);
 }
 
 static int
@@ -3934,8 +3990,8 @@ static char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
     if (vboxDumpDisplay(def, data, machine) < 0)
         goto cleanup;
 
-    vboxDumpIDEHDDs(def, data, machine);
-
+    vboxDumpStorageControllers(def, data, machine);
+    vboxDumpDisks(def, data, machine);
     vboxDumpSharedFolders(def, data, machine);
     vboxDumpNetwork(def, data, machine, networkAdapterCount);
     vboxDumpAudio(def, data, machine);
@@ -5490,8 +5546,9 @@ vboxDomainSnapshotGet(vboxDriverPtr data,
     return snapshot;
 }
 
-static int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def,
-                                         virDomainSnapshotPtr snapshot)
+static int
+vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def,
+                              virDomainSnapshotPtr snapshot)
 {
     virDomainPtr dom = snapshot->domain;
     vboxDriverPtr data = dom->conn->privateData;
@@ -5500,9 +5557,7 @@ static int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def,
     ISnapshot *snap = NULL;
     IMachine *snapMachine = NULL;
     vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER;
-    PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {};
-    PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {};
-    int diskCount = 0;
+    size_t diskCount = 0, sdCount = 0;
     nsresult rc;
     vboxIID snapIid;
     char *snapshotUuidStr = NULL;
@@ -5571,9 +5626,6 @@ static int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def,
             goto cleanup;
     }
 
-    if (!vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst, maxSlotPerPort))
-        goto cleanup;
-
     /* get the attachment details here */
     for (i = 0; i < mediumAttachments.count && diskCount < def->ndisks; i++) {
         IStorageController *storageController = NULL;
@@ -5583,7 +5635,6 @@ static int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def,
         IMedium *disk = NULL;
         PRUnichar *childLocUtf16 = NULL;
         char *childLocUtf8 = NULL;
-        PRUint32 deviceInst = 0;
         PRInt32 devicePort = 0;
         PRInt32 deviceSlot = 0;
         vboxArray children = VBOX_ARRAY_INITIALIZER;
@@ -5592,31 +5643,76 @@ static int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def,
         void *handle;
         size_t j = 0;
         size_t k = 0;
+
         if (!imediumattach)
             continue;
-        rc = gVBoxAPI.UIMediumAttachment.GetMedium(imediumattach, &disk);
+
+        rc = gVBoxAPI.UIMediumAttachment.GetController(imediumattach,
+                                                       &storageControllerName);
         if (NS_FAILED(rc)) {
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("cannot get medium"));
+                           _("cannot get controller"));
             goto cleanup;
         }
-        if (!disk)
+
+        if (!storageControllerName)
             continue;
-        rc = gVBoxAPI.UIMediumAttachment.GetController(imediumattach, &storageControllerName);
+
+        rc = gVBoxAPI.UIMachine.GetStorageControllerByName(machine,
+                                                           storageControllerName,
+                                                           &storageController);
+        VBOX_UTF16_FREE(storageControllerName);
+        if (!storageController)
+            continue;
+
+        rc = gVBoxAPI.UIStorageController.GetBus(storageController, &storageBus);
         if (NS_FAILED(rc)) {
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("cannot get controller"));
+                           _("cannot get storage controller bus"));
+            VBOX_RELEASE(storageController);
             goto cleanup;
         }
-        if (!storageControllerName) {
-            VBOX_RELEASE(disk);
-            continue;
+        rc = gVBoxAPI.UIMediumAttachment.GetType(imediumattach, &deviceType);
+        if (NS_FAILED(rc)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("cannot get medium attachment type"));
+            VBOX_RELEASE(storageController);
+            goto cleanup;
+        }
+        rc = gVBoxAPI.UIMediumAttachment.GetPort(imediumattach, &devicePort);
+        if (NS_FAILED(rc)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("cannot get medium attachment type"));
+            VBOX_RELEASE(storageController);
+            goto cleanup;
         }
+        rc = gVBoxAPI.UIMediumAttachment.GetDevice(imediumattach, &deviceSlot);
+        if (NS_FAILED(rc)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("cannot get medium attachment device"));
+            VBOX_RELEASE(storageController);
+            goto cleanup;
+        }
+
+        rc = gVBoxAPI.UIMediumAttachment.GetMedium(imediumattach, &disk);
+        if (NS_FAILED(rc)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("cannot get medium"));
+            VBOX_RELEASE(storageController);
+            goto cleanup;
+        }
+
+        /* skip removable disk */
+        if (!disk)
+            goto skip;
+
         handle = gVBoxAPI.UArray.handleMediumGetChildren(disk);
         rc = gVBoxAPI.UArray.vboxArrayGet(&children, disk, handle);
         if (NS_FAILED(rc)) {
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("cannot get children disk"));
+            VBOX_RELEASE(storageController);
+            VBOX_RELEASE(disk);
             goto cleanup;
         }
         handle = gVBoxAPI.UArray.handleMediumGetSnapshotIds(disk);
@@ -5625,8 +5721,11 @@ static int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def,
         if (NS_FAILED(rc)) {
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("cannot get snapshot ids"));
+            VBOX_RELEASE(storageController);
+            VBOX_RELEASE(disk);
             goto cleanup;
         }
+
         for (j = 0; j < children.count; ++j) {
             IMedium *child = children.items[j];
             for (k = 0; k < snapshotIids.count; ++k) {
@@ -5634,18 +5733,13 @@ static int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def,
                 char *diskSnapIdStr = NULL;
                 VBOX_UTF16_TO_UTF8(diskSnapId, &diskSnapIdStr);
                 if (STREQ(diskSnapIdStr, snapshotUuidStr)) {
-                    rc = gVBoxAPI.UIMachine.GetStorageControllerByName(machine,
-                                                                       storageControllerName,
-                                                                       &storageController);
-                    VBOX_UTF16_FREE(storageControllerName);
-                    if (!storageController) {
-                        VBOX_RELEASE(child);
-                        break;
-                    }
                     rc = gVBoxAPI.UIMedium.GetLocation(child, &childLocUtf16);
                     if (NS_FAILED(rc)) {
                         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                        _("cannot get disk location"));
+                        VBOX_RELEASE(child);
+                        VBOX_RELEASE(storageController);
+                        VBOX_RELEASE(disk);
                         goto cleanup;
                     }
                     VBOX_UTF16_TO_UTF8(childLocUtf16, &childLocUtf8);
@@ -5653,52 +5747,37 @@ static int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def,
                     if (VIR_STRDUP(def->disks[diskCount].src->path, childLocUtf8) < 0) {
                         VBOX_RELEASE(child);
                         VBOX_RELEASE(storageController);
+                        VBOX_RELEASE(disk);
                         goto cleanup;
                     }
                     VBOX_UTF8_FREE(childLocUtf8);
 
-                    rc = gVBoxAPI.UIStorageController.GetBus(storageController, &storageBus);
-                    if (NS_FAILED(rc)) {
-                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                       _("cannot get storage controller bus"));
-                        goto cleanup;
-                    }
-                    rc = gVBoxAPI.UIMediumAttachment.GetType(imediumattach, &deviceType);
-                    if (NS_FAILED(rc)) {
-                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                       _("cannot get medium attachment type"));
-                        goto cleanup;
-                    }
-                    rc = gVBoxAPI.UIMediumAttachment.GetPort(imediumattach, &devicePort);
-                    if (NS_FAILED(rc)) {
-                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                       _("cannot get medium attachment type"));
-                        goto cleanup;
-                    }
-                    rc = gVBoxAPI.UIMediumAttachment.GetDevice(imediumattach, &deviceSlot);
-                    if (NS_FAILED(rc)) {
-                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                       _("cannot get medium attachment device"));
-                        goto cleanup;
-                    }
                     def->disks[diskCount].src->type = VIR_STORAGE_TYPE_FILE;
                     def->disks[diskCount].name = vboxGenerateMediumName(storageBus,
-                                                                        deviceInst,
                                                                         devicePort,
                                                                         deviceSlot,
-                                                                        maxPortPerInst,
-                                                                        maxSlotPerPort);
+                                                                        sdCount);
                 }
                 VBOX_UTF8_FREE(diskSnapIdStr);
             }
         }
+
+        diskCount++;
+
+ skip:
         VBOX_RELEASE(storageController);
         VBOX_RELEASE(disk);
-        diskCount++;
+
+        if (storageBus == StorageBus_SATA || storageBus == StorageBus_SCSI ||
+            storageBus == StorageBus_SAS)
+            sdCount++;
+
     }
+
     gVBoxAPI.UArray.vboxArrayRelease(&mediumAttachments);
 
     ret = 0;
+
  cleanup:
     if (ret < 0) {
         for (i = 0; i < def->ndisks; i++)
@@ -5710,9 +5789,9 @@ static int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def,
     return ret;
 }
 
-static
-int vboxSnapshotGetReadOnlyDisks(virDomainSnapshotPtr snapshot,
-                                 virDomainSnapshotDefPtr def)
+static int
+vboxSnapshotGetReadOnlyDisks(virDomainSnapshotDefPtr def,
+                             virDomainSnapshotPtr snapshot)
 {
     virDomainPtr dom = snapshot->domain;
     vboxDriverPtr data = dom->conn->privateData;
@@ -5725,9 +5804,7 @@ int vboxSnapshotGetReadOnlyDisks(virDomainSnapshotPtr snapshot,
     nsresult rc;
     vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER;
     size_t i = 0;
-    PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {};
-    PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {};
-    int diskCount = 0;
+    size_t diskCount = 0, sdCount = 0;
     int ret = -1;
 
     if (!data->vboxObj)
@@ -5790,9 +5867,6 @@ int vboxSnapshotGetReadOnlyDisks(virDomainSnapshotPtr snapshot,
         goto cleanup;
     }
 
-    if (!vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst, maxSlotPerPort))
-        goto cleanup;
-
     /* get the attachment details here */
     for (i = 0; i < mediumAttachments.count && diskCount < def->dom->ndisks; i++) {
         PRUnichar *storageControllerName = NULL;
@@ -5805,16 +5879,17 @@ int vboxSnapshotGetReadOnlyDisks(virDomainSnapshotPtr snapshot,
         PRInt32 devicePort = 0;
         PRInt32 deviceSlot = 0;
         IMediumAttachment *imediumattach = mediumAttachments.items[i];
+
         if (!imediumattach)
             continue;
+
         rc = gVBoxAPI.UIMediumAttachment.GetMedium(imediumattach, &disk);
         if (NS_FAILED(rc)) {
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("cannot get medium"));
             goto cleanup;
         }
-        if (!disk)
-            continue;
+
         rc = gVBoxAPI.UIMediumAttachment.GetController(imediumattach, &storageControllerName);
         if (NS_FAILED(rc)) {
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -5834,41 +5909,85 @@ int vboxSnapshotGetReadOnlyDisks(virDomainSnapshotPtr snapshot,
         VBOX_UTF16_FREE(storageControllerName);
         if (!storageController)
             continue;
-        rc = gVBoxAPI.UIMedium.GetLocation(disk, &mediumLocUtf16);
+
+        rc = gVBoxAPI.UIStorageController.GetBus(storageController, &storageBus);
         if (NS_FAILED(rc)) {
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("cannot get disk location"));
+                           _("cannot get storage controller bus"));
             goto cleanup;
         }
-        VBOX_UTF16_TO_UTF8(mediumLocUtf16, &mediumLocUtf8);
-        VBOX_UTF16_FREE(mediumLocUtf16);
-        if (VIR_STRDUP(def->dom->disks[diskCount]->src->path, mediumLocUtf8) < 0)
+
+        rc = gVBoxAPI.UIMediumAttachment.GetPort(imediumattach, &devicePort);
+        if (NS_FAILED(rc)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("cannot get medium attachment port"));
             goto cleanup;
+        }
 
-        VBOX_UTF8_FREE(mediumLocUtf8);
+        rc = gVBoxAPI.UIMediumAttachment.GetDevice(imediumattach, &deviceSlot);
+        if (NS_FAILED(rc)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("cannot get device"));
+            goto cleanup;
+        }
 
-        rc = gVBoxAPI.UIStorageController.GetBus(storageController, &storageBus);
+
+        rc = gVBoxAPI.UIMediumAttachment.GetType(imediumattach, &deviceType);
         if (NS_FAILED(rc)) {
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("cannot get storage controller bus"));
+                           _("cannot get medium attachment type"));
             goto cleanup;
         }
+
+        if (disk) {
+            rc = gVBoxAPI.UIMedium.GetLocation(disk, &mediumLocUtf16);
+            if (NS_FAILED(rc)) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("cannot get disk location"));
+                goto cleanup;
+            }
+            VBOX_UTF16_TO_UTF8(mediumLocUtf16, &mediumLocUtf8);
+            VBOX_UTF16_FREE(mediumLocUtf16);
+            if (VIR_STRDUP(def->dom->disks[diskCount]->src->path, mediumLocUtf8) < 0)
+                goto cleanup;
+
+            VBOX_UTF8_FREE(mediumLocUtf8);
+
+            rc = gVBoxAPI.UIMedium.GetReadOnly(disk, &readOnly);
+            if (NS_FAILED(rc)) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("cannot get read only attribute"));
+                goto cleanup;
+            }
+        } else {
+            /* for removable drives, bump sdCount according to type so that
+             * device names are properly generated, and then skip it
+             */
+            if (storageBus == StorageBus_SATA ||
+                storageBus == StorageBus_SCSI ||
+                storageBus == StorageBus_SAS)
+                sdCount++;
+
+            continue;
+        }
+
+        def->dom->disks[diskCount]->dst = vboxGenerateMediumName(storageBus,
+                                                                 devicePort,
+                                                                 deviceSlot,
+                                                                 sdCount);
         if (storageBus == StorageBus_IDE) {
             def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_IDE;
         } else if (storageBus == StorageBus_SATA) {
             def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SATA;
-        } else if (storageBus == StorageBus_SCSI) {
+            sdCount++;
+        } else if (storageBus == StorageBus_SCSI ||
+                   storageBus == StorageBus_SAS) {
             def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SCSI;
+            sdCount++;
         } else if (storageBus == StorageBus_Floppy) {
             def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_FDC;
         }
 
-        rc = gVBoxAPI.UIMediumAttachment.GetType(imediumattach, &deviceType);
-        if (NS_FAILED(rc)) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("cannot get medium attachment type"));
-            goto cleanup;
-        }
         if (deviceType == DeviceType_HardDisk)
             def->dom->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_DISK;
         else if (deviceType == DeviceType_Floppy)
@@ -5876,33 +5995,9 @@ int vboxSnapshotGetReadOnlyDisks(virDomainSnapshotPtr snapshot,
         else if (deviceType == DeviceType_DVD)
             def->dom->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
 
-        rc = gVBoxAPI.UIMediumAttachment.GetPort(imediumattach, &devicePort);
-        if (NS_FAILED(rc)) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("cannot get medium attachment port"));
-            goto cleanup;
-        }
-        rc = gVBoxAPI.UIMediumAttachment.GetDevice(imediumattach, &deviceSlot);
-        if (NS_FAILED(rc)) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("cannot get device"));
-            goto cleanup;
-        }
-        rc = gVBoxAPI.UIMedium.GetReadOnly(disk, &readOnly);
-        if (NS_FAILED(rc)) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("cannot get read only attribute"));
-            goto cleanup;
-        }
         if (readOnly == PR_TRUE)
             def->dom->disks[diskCount]->src->readonly = true;
         def->dom->disks[diskCount]->src->type = VIR_STORAGE_TYPE_FILE;
-        def->dom->disks[diskCount]->dst = vboxGenerateMediumName(storageBus,
-                                                                 deviceInst,
-                                                                 devicePort,
-                                                                 deviceSlot,
-                                                                 maxPortPerInst,
-                                                                 maxSlotPerPort);
         if (!def->dom->disks[diskCount]->dst) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("Could not generate medium name for the disk "
@@ -5995,7 +6090,7 @@ static char *vboxDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
         if (vboxSnapshotGetReadWriteDisks(def, snapshot) < 0)
             VIR_DEBUG("Could not get read write disks for snapshot");
 
-        if (vboxSnapshotGetReadOnlyDisks(snapshot, def) < 0)
+        if (vboxSnapshotGetReadOnlyDisks(def, snapshot) < 0)
             VIR_DEBUG("Could not get Readonly disks for snapshot");
     }
 
-- 
2.14.2




More information about the libvir-list mailing list