This is an automated email from the ASF dual-hosted git repository.

rohit pushed a commit to branch 4.11
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/4.11 by this push:
     new 2ab3976  CLOUDSTACK-9473: storage pool capacity check when volume is 
resized or migrated (#2829)
2ab3976 is described below

commit 2ab3976c0df614f064c0fa23d81bcd5e026cf778
Author: Rohit Yadav <[email protected]>
AuthorDate: Fri Sep 7 22:01:16 2018 +0530

    CLOUDSTACK-9473: storage pool capacity check when volume is resized or 
migrated (#2829)
    
    * CLOUDSTACK-9473: storage pool capacity check when volume is resized or 
migrated
    
    Storage pool checker is not being called on resize and migrate volume.
    This may lead to allocated percentage of storage above 100%.
    
    Setup:
    1 VMware cluster with 2 Hosts.
    
    Executed Steps:
    
    Applied the following global settings:
    storage.overprovisioning.factor = 1
    pool.storage.allocated.capacity.disablethreshold = 1
    pool.storage.capacity.disablethreshold = 1
    Restarted management server
    Executed Resize and migrate pool and Observed that Storage pool checker is 
not performed on resizeVolume and migrateVolume.
    Result:
    Root cause analysis shows storage pool checker is not called when doing 
migration and resizing.
    
    Signed-off-by: Rohit Yadav <[email protected]>
---
 .../src/com/cloud/storage/StorageManager.java      |  2 +
 .../src/com/cloud/storage/StorageManagerImpl.java  | 50 +++++++++++++++++-----
 .../com/cloud/storage/VolumeApiServiceImpl.java    |  9 ++++
 3 files changed, 51 insertions(+), 10 deletions(-)

diff --git a/engine/components-api/src/com/cloud/storage/StorageManager.java 
b/engine/components-api/src/com/cloud/storage/StorageManager.java
index 530a7de..a532a4f 100644
--- a/engine/components-api/src/com/cloud/storage/StorageManager.java
+++ b/engine/components-api/src/com/cloud/storage/StorageManager.java
@@ -178,6 +178,8 @@ public interface StorageManager extends StorageService {
      */
     boolean storagePoolHasEnoughSpace(List<Volume> 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/com/cloud/storage/StorageManagerImpl.java 
b/server/src/com/cloud/storage/StorageManagerImpl.java
index 610789f..44c8189 100644
--- a/server/src/com/cloud/storage/StorageManagerImpl.java
+++ b/server/src/com/cloud/storage/StorageManagerImpl.java
@@ -1788,8 +1788,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;
 
@@ -1830,12 +1830,37 @@ 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()) {
             BigDecimal overProvFactor = 
getStorageOverProvisioningFactor(pool.getId());
             totalOverProvCapacity = overProvFactor.multiply(new 
BigDecimal(pool.getCapacityBytes())).longValue();
-
             s_logger.debug("Found storage pool " + poolVO.getName() + " of 
type " + pool.getPoolType().toString() + " with overprovisioning factor " + 
overProvFactor.toString());
             s_logger.debug("Total over provisioned capacity calculated is " + 
overProvFactor + " * " + pool.getCapacityBytes());
         } else {
@@ -1847,21 +1872,26 @@ public class StorageManagerImpl extends ManagerBase 
implements StorageManager, C
         s_logger.debug("Total capacity of the pool " + poolVO.getName() + " 
with ID " + pool.getId() + " is " + totalOverProvCapacity);
 
         double storageAllocatedThreshold = 
CapacityManager.StorageAllocatedCapacityDisableThreshold.valueIn(pool.getDataCenterId());
-
-        s_logger.debug("Checking pool: " + pool.getId() + " for volume 
allocation " + volumes.toString() + ", maxSize : " + totalOverProvCapacity + ", 
totalAllocatedSize : "
-                + allocatedSizeWithTemplate + ", askingSize : " + 
totalAskingSize + ", allocated disable threshold: " + 
storageAllocatedThreshold);
+        if (s_logger.isDebugEnabled()) {
+            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) {
-            s_logger.debug("Insufficient un-allocated capacity on: " + 
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");
+            if (s_logger.isDebugEnabled()) {
+                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;
         }
 
         if (totalOverProvCapacity < (allocatedSizeWithTemplate + 
totalAskingSize)) {
-            s_logger.debug("Insufficient un-allocated capacity on: " + 
pool.getId() + " for volume allocation: " + volumes.toString() + ", not enough 
storage, maxSize : " + totalOverProvCapacity
-                    + ", totalAllocatedSize : " + allocatedSizeWithTemplate + 
", askingSize : " + totalAskingSize);
+            if (s_logger.isDebugEnabled()) {
+                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/com/cloud/storage/VolumeApiServiceImpl.java 
b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
index 5e3bf54..372ab34 100644
--- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
@@ -19,6 +19,7 @@ package com.cloud.storage;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
@@ -1137,6 +1138,10 @@ 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.
@@ -2061,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 (_volumeMgr.volumeOnSharedStoragePool(vol)) {
             if (destPool.isLocal()) {
                 throw new InvalidParameterValueException("Migration of volume 
from shared to local storage pool is not supported");

Reply via email to