mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +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
|
static int
|
||||||
testDomainAttachDeviceLive(virDomainObj *vm,
|
testDomainAttachDeviceLive(virDomainObj *vm,
|
||||||
virDomainDeviceDef *dev,
|
virDomainDeviceDef *dev,
|
||||||
@ -10251,8 +10417,16 @@ testDomainAttachDeviceLive(virDomainObj *vm,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_DEVICE_NONE:
|
|
||||||
case VIR_DOMAIN_DEVICE_DISK:
|
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_LEASE:
|
||||||
case VIR_DOMAIN_DEVICE_FS:
|
case VIR_DOMAIN_DEVICE_FS:
|
||||||
case VIR_DOMAIN_DEVICE_INPUT:
|
case VIR_DOMAIN_DEVICE_INPUT:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user