mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
test_driver: provide basic disk hotplug support
Add some basic plumbing, based on the qemu driver. Signed-off-by: John Levon <john.levon@nutanix.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
c7611a6b13
commit
c530a96151
@ -10223,6 +10223,172 @@ 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)
|
||||
{
|
||||
virDomainDiskDef *disk = dev->data.disk;
|
||||
virDomainDiskDef *orig_disk = NULL;
|
||||
|
||||
/* this API overloads media change semantics on disk hotplug
|
||||
* for devices supporting media changes */
|
||||
if ((disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
|
||||
disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) &&
|
||||
(orig_disk = virDomainDiskByTarget(vm->def, disk->dst))) {
|
||||
virObjectUnref(orig_disk->src);
|
||||
orig_disk->src = g_steal_pointer(&disk->src);
|
||||
virDomainDiskDefFree(disk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return testDomainAttachDeviceDiskLiveInternal(driver, vm, dev);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
testDomainAttachDeviceLive(virDomainObj *vm,
|
||||
virDomainDeviceDef *dev,
|
||||
@ -10251,8 +10417,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:
|
||||
|
Loading…
Reference in New Issue
Block a user