mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-21 10:50:24 +03:00
qemu: hotplug: Add helper to initialize/teardown new disks for VMs
When we are changing media (or doing other hotplug operations) we need to setup cgroups, locking and seclabels on the new disk. This is a multi-step process where every piece can fail. To simplify dealing with this introduce qemuDomainPrepareDisk that similarly to qemuDomainPrepareDiskChainElement initializes/tears down a whole new disk to be used with the domain. Additionally the function supports passing a different source struct for media changes of cdroms that will be refactored later.
This commit is contained in:
parent
240eb2fb89
commit
ca91ba78bd
@ -6648,9 +6648,6 @@ qemuDomainChangeDiskMediaLive(virConnectPtr conn,
|
|||||||
if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0)
|
if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
if (qemuSetupDiskCgroup(vm, disk) < 0)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
switch (disk->device) {
|
switch (disk->device) {
|
||||||
case VIR_DOMAIN_DISK_DEVICE_CDROM:
|
case VIR_DOMAIN_DISK_DEVICE_CDROM:
|
||||||
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
|
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
|
||||||
@ -6701,11 +6698,6 @@ qemuDomainChangeDiskMediaLive(virConnectPtr conn,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != 0 &&
|
|
||||||
qemuTeardownDiskCgroup(vm, disk) < 0)
|
|
||||||
VIR_WARN("Failed to teardown cgroup for disk path %s",
|
|
||||||
NULLSTR(virDomainDiskGetSource(disk)));
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
virObjectUnref(caps);
|
virObjectUnref(caps);
|
||||||
virDomainDeviceDefFree(dev_copy);
|
virDomainDeviceDefFree(dev_copy);
|
||||||
|
@ -61,6 +61,83 @@ VIR_LOG_INIT("qemu.qemu_hotplug");
|
|||||||
unsigned long long qemuDomainRemoveDeviceWaitTime = 1000ull * 5;
|
unsigned long long qemuDomainRemoveDeviceWaitTime = 1000ull * 5;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuDomainPrepareDisk:
|
||||||
|
* @driver: qemu driver struct
|
||||||
|
* @vm: domain object
|
||||||
|
* @disk: disk to prepare
|
||||||
|
* @overridesrc: Source different than @disk->src when necessary
|
||||||
|
* @teardown: Teardown the disk instead of adding it to a vm
|
||||||
|
*
|
||||||
|
* Setup the locks, cgroups and security permissions on a disk of a VM.
|
||||||
|
* If @overridesrc is specified the source struct is used instead of the
|
||||||
|
* one present in @disk. If @teardown is true, then the labels and cgroups
|
||||||
|
* are removed instead.
|
||||||
|
*
|
||||||
|
* Returns 0 on success and -1 on error. Reports libvirt error.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
qemuDomainPrepareDisk(virQEMUDriverPtr driver,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
virDomainDiskDefPtr disk,
|
||||||
|
virStorageSourcePtr overridesrc,
|
||||||
|
bool teardown)
|
||||||
|
{
|
||||||
|
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||||
|
int ret = -1;
|
||||||
|
virStorageSourcePtr origsrc = NULL;
|
||||||
|
|
||||||
|
if (overridesrc) {
|
||||||
|
origsrc = disk->src;
|
||||||
|
disk->src = overridesrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* just tear down the disk access */
|
||||||
|
if (teardown) {
|
||||||
|
ret = 0;
|
||||||
|
goto rollback_cgroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virDomainLockDiskAttach(driver->lockManager, cfg->uri,
|
||||||
|
vm, disk) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virSecurityManagerSetDiskLabel(driver->securityManager,
|
||||||
|
vm->def, disk) < 0)
|
||||||
|
goto rollback_lock;
|
||||||
|
|
||||||
|
if (qemuSetupDiskCgroup(vm, disk) < 0)
|
||||||
|
goto rollback_label;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
rollback_cgroup:
|
||||||
|
if (qemuTeardownDiskCgroup(vm, disk) < 0)
|
||||||
|
VIR_WARN("Unable to tear down cgroup access on %s",
|
||||||
|
virDomainDiskGetSource(disk));
|
||||||
|
|
||||||
|
rollback_label:
|
||||||
|
if (virSecurityManagerRestoreDiskLabel(driver->securityManager,
|
||||||
|
vm->def, disk) < 0)
|
||||||
|
VIR_WARN("Unable to restore security label on %s",
|
||||||
|
virDomainDiskGetSource(disk));
|
||||||
|
|
||||||
|
rollback_lock:
|
||||||
|
if (virDomainLockDiskDetach(driver->lockManager, vm, disk) < 0)
|
||||||
|
VIR_WARN("Unable to release lock on %s",
|
||||||
|
virDomainDiskGetSource(disk));
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (origsrc)
|
||||||
|
disk->src = origsrc;
|
||||||
|
|
||||||
|
virObjectUnref(cfg);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
|
int qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
virDomainDiskDefPtr disk,
|
virDomainDiskDefPtr disk,
|
||||||
@ -88,18 +165,9 @@ int qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virDomainLockDiskAttach(driver->lockManager, cfg->uri,
|
if (qemuDomainPrepareDisk(driver, vm, disk, NULL, false) < 0)
|
||||||
vm, disk) < 0)
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (virSecurityManagerSetDiskLabel(driver->securityManager,
|
|
||||||
vm->def, disk) < 0) {
|
|
||||||
if (virDomainLockDiskDetach(driver->lockManager, vm, disk) < 0)
|
|
||||||
VIR_WARN("Unable to release lock on %s",
|
|
||||||
virDomainDiskGetSource(disk));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(driveAlias = qemuDeviceDriveHostAlias(origdisk, priv->qemuCaps)))
|
if (!(driveAlias = qemuDeviceDriveHostAlias(origdisk, priv->qemuCaps)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -160,14 +228,7 @@ int qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (virSecurityManagerRestoreDiskLabel(driver->securityManager,
|
ignore_value(qemuDomainPrepareDisk(driver, vm, origdisk, NULL, true));
|
||||||
vm->def, origdisk) < 0)
|
|
||||||
VIR_WARN("Unable to restore security label on ejected image %s",
|
|
||||||
virDomainDiskGetSource(origdisk));
|
|
||||||
|
|
||||||
if (virDomainLockDiskDetach(driver->lockManager, vm, origdisk) < 0)
|
|
||||||
VIR_WARN("Unable to release lock on disk %s",
|
|
||||||
virDomainDiskGetSource(origdisk));
|
|
||||||
|
|
||||||
if (virDomainDiskSetSource(origdisk, src) < 0)
|
if (virDomainDiskSetSource(origdisk, src) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
@ -183,12 +244,7 @@ int qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
|
|||||||
error:
|
error:
|
||||||
virDomainAuditDisk(vm, origdisk->src, disk->src, "update", false);
|
virDomainAuditDisk(vm, origdisk->src, disk->src, "update", false);
|
||||||
|
|
||||||
if (virSecurityManagerRestoreDiskLabel(driver->securityManager,
|
ignore_value(qemuDomainPrepareDisk(driver, vm, disk, NULL, true));
|
||||||
vm->def, disk) < 0)
|
|
||||||
VIR_WARN("Unable to restore security label on new media %s", src);
|
|
||||||
|
|
||||||
if (virDomainLockDiskDetach(driver->lockManager, vm, disk) < 0)
|
|
||||||
VIR_WARN("Unable to release lock on %s", src);
|
|
||||||
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -267,17 +323,9 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virDomainLockDiskAttach(driver->lockManager, cfg->uri,
|
if (qemuDomainPrepareDisk(driver, vm, disk, NULL, false) < 0)
|
||||||
vm, disk) < 0)
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (virSecurityManagerSetDiskLabel(driver->securityManager,
|
|
||||||
vm->def, disk) < 0) {
|
|
||||||
if (virDomainLockDiskDetach(driver->lockManager, vm, disk) < 0)
|
|
||||||
VIR_WARN("Unable to release lock on %s", src);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
||||||
if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
|
if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
|
||||||
if (virDomainCCWAddressAssign(&disk->info, priv->ccwaddrs,
|
if (virDomainCCWAddressAssign(&disk->info, priv->ccwaddrs,
|
||||||
@ -348,6 +396,8 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn,
|
|||||||
if (releaseaddr)
|
if (releaseaddr)
|
||||||
qemuDomainReleaseDeviceAddress(vm, &disk->info, src);
|
qemuDomainReleaseDeviceAddress(vm, &disk->info, src);
|
||||||
|
|
||||||
|
ignore_value(qemuDomainPrepareDisk(driver, vm, disk, NULL, true));
|
||||||
|
|
||||||
if (virSecurityManagerRestoreDiskLabel(driver->securityManager,
|
if (virSecurityManagerRestoreDiskLabel(driver->securityManager,
|
||||||
vm->def, disk) < 0)
|
vm->def, disk) < 0)
|
||||||
VIR_WARN("Unable to restore security label on %s", src);
|
VIR_WARN("Unable to restore security label on %s", src);
|
||||||
@ -496,7 +546,6 @@ qemuDomainAttachSCSIDisk(virConnectPtr conn,
|
|||||||
char *devstr = NULL;
|
char *devstr = NULL;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||||
const char *src = virDomainDiskGetSource(disk);
|
|
||||||
|
|
||||||
for (i = 0; i < vm->def->ndisks; i++) {
|
for (i = 0; i < vm->def->ndisks; i++) {
|
||||||
if (STREQ(vm->def->disks[i]->dst, disk->dst)) {
|
if (STREQ(vm->def->disks[i]->dst, disk->dst)) {
|
||||||
@ -506,17 +555,9 @@ qemuDomainAttachSCSIDisk(virConnectPtr conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virDomainLockDiskAttach(driver->lockManager, cfg->uri,
|
if (qemuDomainPrepareDisk(driver, vm, disk, NULL, false) < 0)
|
||||||
vm, disk) < 0)
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (virSecurityManagerSetDiskLabel(driver->securityManager,
|
|
||||||
vm->def, disk) < 0) {
|
|
||||||
if (virDomainLockDiskDetach(driver->lockManager, vm, disk) < 0)
|
|
||||||
VIR_WARN("Unable to release lock on %s", src);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We should have an address already, so make sure */
|
/* We should have an address already, so make sure */
|
||||||
if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
|
if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
@ -598,13 +639,7 @@ qemuDomainAttachSCSIDisk(virConnectPtr conn,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (virSecurityManagerRestoreDiskLabel(driver->securityManager,
|
ignore_value(qemuDomainPrepareDisk(driver, vm, disk, NULL, true));
|
||||||
vm->def, disk) < 0)
|
|
||||||
VIR_WARN("Unable to restore security label on %s", src);
|
|
||||||
|
|
||||||
if (virDomainLockDiskDetach(driver->lockManager, vm, disk) < 0)
|
|
||||||
VIR_WARN("Unable to release lock on %s", src);
|
|
||||||
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -737,9 +772,6 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
|
|||||||
if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0)
|
if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
if (qemuSetupDiskCgroup(vm, disk) < 0)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
switch (disk->device) {
|
switch (disk->device) {
|
||||||
case VIR_DOMAIN_DISK_DEVICE_CDROM:
|
case VIR_DOMAIN_DISK_DEVICE_CDROM:
|
||||||
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
|
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
|
||||||
@ -806,12 +838,6 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != 0 &&
|
|
||||||
qemuTeardownDiskCgroup(vm, disk) < 0) {
|
|
||||||
VIR_WARN("Failed to teardown cgroup for disk path %s",
|
|
||||||
NULLSTR(src));
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
ignore_value(qemuRemoveSharedDevice(driver, dev, vm->def->name));
|
ignore_value(qemuRemoveSharedDevice(driver, dev, vm->def->name));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user