[PATCH 1/2] test_driver: provide basic disk hotplug support

John Levon posted 2 patches 2 weeks, 5 days ago
[PATCH 1/2] test_driver: provide basic disk hotplug support
Posted by John Levon 2 weeks, 5 days ago
Add some basic plumbing, based on the qemu driver.

Signed-off-by: John Levon <john.levon@nutanix.com>
---
 src/test/test_driver.c | 162 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 161 insertions(+), 1 deletion(-)

diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 03afe8af8d..b7e36e8451 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -10223,6 +10223,158 @@ testDomainAttachHostDevice(testDriver *driver,
 }
 
 
+/**
+ * @def: Domain definition
+ * @info: Domain device info
+ *
+ * Using the device info, find the controller related to the
+ * device by index and use that controller to return the model.
+ *
+ * Returns the model if found, -1 if not with an error message set
+ */
+static int
+testDomainFindSCSIControllerModel(const virDomainDef *def,
+                                  virDomainDeviceInfo *info)
+{
+    virDomainControllerDef *cont;
+
+    if (!(cont = virDomainDeviceFindSCSIController(def, &info->addr.drive))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("unable to find a SCSI controller for idx=%1$d"),
+                       info->addr.drive.controller);
+        return -1;
+    }
+
+    return cont->model;
+}
+
+
+static int
+testAssignDeviceDiskAlias(virDomainDef *def,
+                          virDomainDiskDef *disk)
+{
+    const char *prefix = virDomainDiskBusTypeToString(disk->bus);
+    int controllerModel = -1;
+
+    if (!disk->info.alias) {
+        if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
+            if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
+                controllerModel = testDomainFindSCSIControllerModel(def,
+                                                                    &disk->info);
+                if (controllerModel < 0)
+                    return -1;
+            }
+
+            if (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI ||
+                controllerModel == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC) {
+                disk->info.alias = g_strdup_printf("%s%d-%d-%d", prefix,
+                                                   disk->info.addr.drive.controller,
+                                                   disk->info.addr.drive.bus,
+                                                   disk->info.addr.drive.unit);
+            } else {
+                disk->info.alias = g_strdup_printf("%s%d-%d-%d-%d", prefix,
+                                                   disk->info.addr.drive.controller,
+                                                   disk->info.addr.drive.bus,
+                                                   disk->info.addr.drive.target,
+                                                   disk->info.addr.drive.unit);
+            }
+        } else {
+            int idx = virDiskNameToIndex(disk->dst);
+            disk->info.alias = g_strdup_printf("%s-disk%d", prefix, idx);
+        }
+    }
+
+    return 0;
+}
+
+
+static int
+testDomainAttachDeviceDiskLiveInternal(testDriver *driver G_GNUC_UNUSED,
+                                       virDomainObj *vm,
+                                       virDomainDeviceDef *dev)
+{
+    size_t i;
+    virDomainDiskDef *disk = dev->data.disk;
+    int ret = -1;
+
+    if (disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                       _("floppy device hotplug isn't supported"));
+        return -1;
+    }
+
+    if (virDomainDiskTranslateSourcePool(disk) < 0)
+        goto cleanup;
+
+    for (i = 0; i < vm->def->ndisks; i++) {
+        if (virDomainDiskDefCheckDuplicateInfo(vm->def->disks[i], disk) < 0)
+            goto cleanup;
+    }
+
+    switch (disk->bus) {
+    case VIR_DOMAIN_DISK_BUS_USB:
+        if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("disk device='lun' is not supported for usb bus"));
+            goto cleanup;
+        }
+
+        break;
+
+    case VIR_DOMAIN_DISK_BUS_VIRTIO:
+        if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
+            virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                           _("cdrom device with virtio bus isn't supported"));
+            goto cleanup;
+        }
+        break;
+
+    case VIR_DOMAIN_DISK_BUS_SCSI:
+    case VIR_DOMAIN_DISK_BUS_IDE:
+    case VIR_DOMAIN_DISK_BUS_FDC:
+    case VIR_DOMAIN_DISK_BUS_XEN:
+    case VIR_DOMAIN_DISK_BUS_UML:
+    case VIR_DOMAIN_DISK_BUS_SATA:
+    case VIR_DOMAIN_DISK_BUS_SD:
+    case VIR_DOMAIN_DISK_BUS_NONE:
+    case VIR_DOMAIN_DISK_BUS_LAST:
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+                       _("disk bus '%1$s' cannot be hotplugged."),
+                       virDomainDiskBusTypeToString(disk->bus));
+        goto cleanup;
+    }
+
+    if (testAssignDeviceDiskAlias(vm->def, disk) < 0)
+        goto cleanup;
+
+    virDomainDiskInsert(vm->def, disk);
+
+    ret = 0;
+
+ cleanup:
+    return ret;
+}
+
+
+/**
+ * testDomainAttachDeviceDiskLive:
+ * @driver: test driver struct
+ * @vm: domain object
+ * @dev: device to attach (expected type is DISK)
+ *
+ * Attach a new disk or in case of cdroms/floppies change the media in the drive.
+ * This function handles all the necessary steps to attach a new storage source
+ * to the VM.
+ */
+static int
+testDomainAttachDeviceDiskLive(testDriver *driver,
+                               virDomainObj *vm,
+                               virDomainDeviceDef *dev)
+{
+    return testDomainAttachDeviceDiskLiveInternal(driver, vm, dev);
+}
+
+
 static int
 testDomainAttachDeviceLive(virDomainObj *vm,
                            virDomainDeviceDef *dev,
@@ -10251,8 +10403,16 @@ testDomainAttachDeviceLive(virDomainObj *vm,
         }
         break;
 
-    case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_DISK:
+        testDomainObjCheckDiskTaint(vm, dev->data.disk);
+        ret = testDomainAttachDeviceDiskLive(driver, vm, dev);
+        if (!ret) {
+            alias = dev->data.disk->info.alias;
+            dev->data.disk = NULL;
+        }
+        break;
+
+    case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_LEASE:
     case VIR_DOMAIN_DEVICE_FS:
     case VIR_DOMAIN_DEVICE_INPUT:
-- 
2.34.1
Re: [PATCH 1/2] test_driver: provide basic disk hotplug support
Posted by Michal Prívozník 1 week, 2 days ago
On 11/1/24 23:31, John Levon wrote:
> Add some basic plumbing, based on the qemu driver.
> 
> Signed-off-by: John Levon <john.levon@nutanix.com>
> ---
>  src/test/test_driver.c | 162 ++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 161 insertions(+), 1 deletion(-)
> 
> diff --git a/src/test/test_driver.c b/src/test/test_driver.c
> index 03afe8af8d..b7e36e8451 100644
> --- a/src/test/test_driver.c
> +++ b/src/test/test_driver.c

> +
> +/**
> + * testDomainAttachDeviceDiskLive:
> + * @driver: test driver struct
> + * @vm: domain object
> + * @dev: device to attach (expected type is DISK)
> + *
> + * Attach a new disk or in case of cdroms/floppies change the media in the drive.
> + * This function handles all the necessary steps to attach a new storage source
> + * to the VM.
> + */
> +static int
> +testDomainAttachDeviceDiskLive(testDriver *driver,
> +                               virDomainObj *vm,
> +                               virDomainDeviceDef *dev)
> +{
> +    return testDomainAttachDeviceDiskLiveInternal(driver, vm, dev);

You've removed too much. As comment above says, and per
virDomainAttachDevice() documentation, there is one (arguably weird) use
of this function: to change media in CDROM/FLOPPY devices.

> +}
> +
> +

Michal