Skip to content

Commit 7eb3636

Browse files
Add lock mechanism considering template id, pool id, host id in PowerFlex Storage (#8233)
Observed a failure to start new virtual machine with PowerFlex storage. Traced it to concurrent VM starts using the same template and the same host to copy. Second mapping attempt failed. While creating the volume clone from the seeded template in primary storage, adding a lock with the string containing IDs of template, storage pool and destination host avoids the situation of concurrent mapping attempts with the same host.
1 parent 7ea068c commit 7eb3636

File tree

1 file changed

+28
-2
lines changed

1 file changed

+28
-2
lines changed

engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,8 +1478,8 @@ public AsyncCallFuture<VolumeApiResult> createManagedStorageVolumeFromTemplateAs
14781478
createManagedVolumeCloneTemplateAsync(volumeInfo, templateOnPrimary, destPrimaryDataStore, future);
14791479
} else {
14801480
// We have a template on PowerFlex primary storage. Create new volume and copy to it.
1481-
s_logger.debug("Copying the template to the volume on primary storage");
1482-
createManagedVolumeCopyManagedTemplateAsync(volumeInfo, destPrimaryDataStore, templateOnPrimary, destHost, future);
1481+
createManagedVolumeCopyManagedTemplateAsyncWithLock(volumeInfo, destPrimaryDataStore, templateOnPrimary,
1482+
destHost, future, destDataStoreId, srcTemplateInfo.getId());
14831483
}
14841484
} else {
14851485
s_logger.debug("Primary storage does not support cloning or no support for UUID resigning on the host side; copying the template normally");
@@ -1490,6 +1490,32 @@ public AsyncCallFuture<VolumeApiResult> createManagedStorageVolumeFromTemplateAs
14901490
return future;
14911491
}
14921492

1493+
private void createManagedVolumeCopyManagedTemplateAsyncWithLock(VolumeInfo volumeInfo, PrimaryDataStore destPrimaryDataStore, TemplateInfo templateOnPrimary,
1494+
Host destHost, AsyncCallFuture<VolumeApiResult> future, long destDataStoreId, long srcTemplateId) {
1495+
GlobalLock lock = null;
1496+
try {
1497+
String tmplIdManagedPoolIdDestinationHostLockString = "tmplId:" + srcTemplateId + "managedPoolId:" + destDataStoreId + "destinationHostId:" + destHost.getId();
1498+
lock = GlobalLock.getInternLock(tmplIdManagedPoolIdDestinationHostLockString);
1499+
if (lock == null) {
1500+
throw new CloudRuntimeException("Unable to create volume from template, couldn't get global lock on " + tmplIdManagedPoolIdDestinationHostLockString);
1501+
}
1502+
1503+
int storagePoolMaxWaitSeconds = NumbersUtil.parseInt(configDao.getValue(Config.StoragePoolMaxWaitSeconds.key()), 3600);
1504+
if (!lock.lock(storagePoolMaxWaitSeconds)) {
1505+
s_logger.debug("Unable to create volume from template, couldn't lock on " + tmplIdManagedPoolIdDestinationHostLockString);
1506+
throw new CloudRuntimeException("Unable to create volume from template, couldn't lock on " + tmplIdManagedPoolIdDestinationHostLockString);
1507+
}
1508+
1509+
s_logger.debug("Copying the template to the volume on primary storage");
1510+
createManagedVolumeCopyManagedTemplateAsync(volumeInfo, destPrimaryDataStore, templateOnPrimary, destHost, future);
1511+
} finally {
1512+
if (lock != null) {
1513+
lock.unlock();
1514+
lock.releaseRef();
1515+
}
1516+
}
1517+
}
1518+
14931519
private boolean computeSupportsVolumeClone(long zoneId, HypervisorType hypervisorType) {
14941520
if (HypervisorType.VMware.equals(hypervisorType) || HypervisorType.KVM.equals(hypervisorType)) {
14951521
return true;

0 commit comments

Comments
 (0)