diff --git a/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java b/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java index 2fd732bb267..a8a566ad755 100644 --- a/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java +++ b/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java @@ -186,6 +186,8 @@ public interface StorageManager extends StorageService { */ boolean storagePoolHasEnoughSpace(List volume, StoragePool pool, Long clusterId); + boolean storagePoolHasEnoughSpaceForResize(StoragePool pool, long currentSize, long newSiz); + boolean registerHostListener(String providerUuid, HypervisorHostListener listener); void connectHostToSharedPool(long hostId, long poolId) throws StorageUnavailableException, StorageConflictException; diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java index fc409815402..92eb2b05013 100644 --- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java @@ -1790,8 +1790,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C if (s_logger.isDebugEnabled()) { s_logger.debug("Destination pool id: " + pool.getId()); } - - StoragePoolVO poolVO = _storagePoolDao.findById(pool.getId()); + // allocated space includes templates + final StoragePoolVO poolVO = _storagePoolDao.findById(pool.getId()); long allocatedSizeWithTemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, null); long totalAskingSize = 0; @@ -1832,6 +1832,32 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } } + return checkPoolforSpace(pool, allocatedSizeWithTemplate, totalAskingSize); + } + + @Override + public boolean storagePoolHasEnoughSpaceForResize(StoragePool pool, long currentSize, long newSiz) { + if (!checkUsagedSpace(pool)) { + return false; + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Destination pool id: " + pool.getId()); + } + long totalAskingSize = newSiz - currentSize; + + if (totalAskingSize <= 0) { + return true; + } else { + final StoragePoolVO poolVO = _storagePoolDao.findById(pool.getId()); + final long allocatedSizeWithTemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, null); + return checkPoolforSpace(pool, allocatedSizeWithTemplate, totalAskingSize); + } + } + + private boolean checkPoolforSpace(StoragePool pool, long allocatedSizeWithTemplate, long totalAskingSize) { + // allocated space includes templates + StoragePoolVO poolVO = _storagePoolDao.findById(pool.getId()); + long totalOverProvCapacity; if (pool.getPoolType().supportsOverProvisioning()) { @@ -1852,16 +1878,16 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C double storageAllocatedThreshold = CapacityManager.StorageAllocatedCapacityDisableThreshold.valueIn(pool.getDataCenterId()); if (s_logger.isDebugEnabled()) { - s_logger.debug("Checking pool with ID " + pool.getId() + " for volume allocation " + volumes.toString() + ", maxSize: " + totalOverProvCapacity + ", totalAllocatedSize: " - + allocatedSizeWithTemplate + ", askingSize: " + totalAskingSize + ", allocated disable threshold: " + storageAllocatedThreshold); + s_logger.debug("Checking pool: " + pool.getId() + " for storage allocation , maxSize : " + totalOverProvCapacity + ", totalAllocatedSize : " + allocatedSizeWithTemplate + + ", askingSize : " + totalAskingSize + ", allocated disable threshold: " + storageAllocatedThreshold); } double usedPercentage = (allocatedSizeWithTemplate + totalAskingSize) / (double)(totalOverProvCapacity); if (usedPercentage > storageAllocatedThreshold) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Insufficient un-allocated capacity on the pool with ID " + pool.getId() + " for volume allocation: " + volumes.toString() + " since its allocated percentage " - + usedPercentage + " has crossed the allocated pool.storage.allocated.capacity.disablethreshold " + storageAllocatedThreshold + ", skipping this pool"); + s_logger.debug("Insufficient un-allocated capacity on: " + pool.getId() + " for storage allocation since its allocated percentage: " + usedPercentage + + " has crossed the allocated pool.storage.allocated.capacity.disablethreshold: " + storageAllocatedThreshold + ", skipping this pool"); } return false; @@ -1869,8 +1895,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C if (totalOverProvCapacity < (allocatedSizeWithTemplate + totalAskingSize)) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Insufficient un-allocated capacity on the pool with ID " + pool.getId() + " for volume allocation: " + volumes.toString() + "; not enough storage, maxSize: " - + totalOverProvCapacity + ", totalAllocatedSize: " + allocatedSizeWithTemplate + ", askingSize: " + totalAskingSize); + s_logger.debug("Insufficient un-allocated capacity on: " + pool.getId() + " for storage allocation, not enough storage, maxSize : " + totalOverProvCapacity + + ", totalAllocatedSize : " + allocatedSizeWithTemplate + ", askingSize : " + totalAskingSize); } return false; diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index 3160dd30828..b0c0b7c760f 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -20,6 +20,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -1136,6 +1137,11 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic UserVmVO userVm = _userVmDao.findById(volume.getInstanceId()); StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId()); boolean isManaged = storagePool.isManaged(); + + if (!storageMgr.storagePoolHasEnoughSpaceForResize(storagePool, currentSize, newSize)) { + throw new CloudRuntimeException("Storage pool " + storagePool.getName() + " does not have enough space to resize volume " + volume.getName()); + } + /* * get a list of hosts to send the commands to, try the system the * associated vm is running on first, then the last known place it ran. @@ -2060,6 +2066,10 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic throw new InvalidParameterValueException("Cannot migrate volume " + vol + "to the destination storage pool " + destPool.getName() + " as the storage pool is in maintenance mode."); } + if (!storageMgr.storagePoolHasEnoughSpace(Collections.singletonList(vol), destPool)) { + throw new CloudRuntimeException("Storage pool " + destPool.getName() + " does not have enough space to migrate volume " + vol.getName()); + } + if (liveMigrateVolume && destPool.getClusterId() != null && srcClusterId != null) { if (!srcClusterId.equals(destPool.getClusterId())) { throw new InvalidParameterValueException("Cannot migrate a volume of a virtual machine to a storage pool in a different cluster");