Skip to content

Commit a569d4f

Browse files
author
Mike Tutkowski
committed
Updates to capacity management
1 parent 3221a55 commit a569d4f

File tree

2 files changed

+67
-29
lines changed

2 files changed

+67
-29
lines changed

plugins/storage/volume/solidfire/src/main/java/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import com.cloud.storage.SnapshotVO;
4444
import com.cloud.storage.StoragePool;
4545
import com.cloud.storage.VMTemplateStoragePoolVO;
46+
import com.cloud.storage.Volume;
4647
import com.cloud.storage.VolumeDetailVO;
4748
import com.cloud.storage.VolumeVO;
4849
import com.cloud.storage.Storage.StoragePoolType;
@@ -474,7 +475,9 @@ public long getUsedIops(StoragePool storagePool) {
474475

475476
if (volumes != null) {
476477
for (VolumeVO volume : volumes) {
477-
usedIops += volume.getMinIops() != null ? volume.getMinIops() : 0;
478+
if (!Volume.State.Creating.equals(volume.getState())) {
479+
usedIops += volume.getMinIops() != null ? volume.getMinIops() : 0;
480+
}
478481
}
479482
}
480483

server/src/main/java/com/cloud/storage/StorageManagerImpl.java

Lines changed: 63 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1728,6 +1728,11 @@ public HypervisorType getHypervisorTypeFromFormat(ImageFormat format) {
17281728
}
17291729

17301730
private boolean checkUsagedSpace(StoragePool pool) {
1731+
// Managed storage does not currently deal with accounting for physically used space (only provisioned space). Just return true if "pool" is managed.
1732+
if (pool.isManaged()) {
1733+
return true;
1734+
}
1735+
17311736
StatsCollector sc = StatsCollector.getInstance();
17321737
double storageUsedThreshold = CapacityManager.StorageCapacityDisableThreshold.valueIn(pool.getDataCenterId());
17331738
if (sc != null) {
@@ -1803,9 +1808,10 @@ public boolean storagePoolHasEnoughSpace(List<Volume> volumes, StoragePool pool,
18031808
}
18041809

18051810
// allocated space includes templates
1806-
if(s_logger.isDebugEnabled()) {
1811+
if (s_logger.isDebugEnabled()) {
18071812
s_logger.debug("Destination pool id: " + pool.getId());
18081813
}
1814+
18091815
StoragePoolVO poolVO = _storagePoolDao.findById(pool.getId());
18101816
long allocatedSizeWithTemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, null);
18111817
long totalAskingSize = 0;
@@ -1833,70 +1839,99 @@ public boolean storagePoolHasEnoughSpace(List<Volume> volumes, StoragePool pool,
18331839
allocatedSizeWithTemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, tmpl);
18341840
}
18351841
}
1836-
// A ready state volume is already allocated in a pool. so the asking size is zero for it.
1837-
// In case the volume is moving across pools or is not ready yet, the asking size has to be computed
1842+
18381843
if (s_logger.isDebugEnabled()) {
1839-
s_logger.debug("pool id for the volume with id: " + volumeVO.getId() + " is " + volumeVO.getPoolId());
1844+
s_logger.debug("Pool ID for the volume with ID " + volumeVO.getId() + " is " + volumeVO.getPoolId());
18401845
}
1841-
if ((volumeVO.getState() != Volume.State.Ready) || (volumeVO.getPoolId() != pool.getId())) {
1842-
if (ScopeType.ZONE.equals(poolVO.getScope()) && volumeVO.getTemplateId() != null) {
1843-
VMTemplateVO tmpl = _templateDao.findByIdIncludingRemoved(volumeVO.getTemplateId());
18441846

1845-
if (tmpl != null && !ImageFormat.ISO.equals(tmpl.getFormat())) {
1846-
// Storage plug-ins for zone-wide primary storage can be designed in such a way as to store a template on the
1847-
// primary storage once and make use of it in different clusters (via cloning).
1848-
// This next call leads to CloudStack asking how many more bytes it will need for the template (if the template is
1849-
// already stored on the primary storage, then the answer is 0).
1847+
// A ready-state volume is already allocated in a pool, so the asking size is zero for it.
1848+
// In case the volume is moving across pools or is not ready yet, the asking size has to be computed.
1849+
if ((volumeVO.getState() != Volume.State.Ready) || (volumeVO.getPoolId() != pool.getId())) {
1850+
totalAskingSize += getDataObjectSizeIncludingHypervisorSnapshotReserve(volumeVO, poolVO);
18501851

1851-
if (clusterId != null && _clusterDao.getSupportsResigning(clusterId)) {
1852-
totalAskingSize += getBytesRequiredForTemplate(tmpl, pool);
1853-
}
1854-
}
1855-
}
1852+
totalAskingSize += getAskingSizeForTemplateBasedOnClusterAndStoragePool(volumeVO.getTemplateId(), clusterId, poolVO);
18561853
}
18571854
}
18581855

18591856
long totalOverProvCapacity;
1857+
18601858
if (pool.getPoolType().supportsOverProvisioning()) {
18611859
BigDecimal overProvFactor = getStorageOverProvisioningFactor(pool.getId());
1860+
18621861
totalOverProvCapacity = overProvFactor.multiply(new BigDecimal(pool.getCapacityBytes())).longValue();
1863-
s_logger.debug("Found storage pool " + poolVO.getName() + " of type " + pool.getPoolType().toString() + " with overprovisioning factor "
1864-
+ overProvFactor.toString());
1865-
s_logger.debug("Total over provisioned capacity calculated is " + overProvFactor + " * " + pool.getCapacityBytes());
1862+
1863+
s_logger.debug("Found storage pool " + poolVO.getName() + " of type " + pool.getPoolType().toString() + " with over-provisioning factor " +
1864+
overProvFactor.toString());
1865+
s_logger.debug("Total over-provisioned capacity calculated is " + overProvFactor + " * " + pool.getCapacityBytes());
18661866
} else {
18671867
totalOverProvCapacity = pool.getCapacityBytes();
1868+
18681869
s_logger.debug("Found storage pool " + poolVO.getName() + " of type " + pool.getPoolType().toString());
18691870
}
18701871

1871-
s_logger.debug("Total capacity of the pool " + poolVO.getName() + " id: " + pool.getId() + " is " + totalOverProvCapacity);
1872+
s_logger.debug("Total capacity of the pool " + poolVO.getName() + " with ID " + pool.getId() + " is " + totalOverProvCapacity);
1873+
18721874
double storageAllocatedThreshold = CapacityManager.StorageAllocatedCapacityDisableThreshold.valueIn(pool.getDataCenterId());
1875+
18731876
if (s_logger.isDebugEnabled()) {
1874-
s_logger.debug("Checking pool: " + pool.getId() + " for volume allocation " + volumes.toString() + ", maxSize : " + totalOverProvCapacity +
1875-
", totalAllocatedSize : " + allocatedSizeWithTemplate + ", askingSize : " + totalAskingSize + ", allocated disable threshold: " +
1876-
storageAllocatedThreshold);
1877+
s_logger.debug("Checking pool with ID " + pool.getId() + " for volume allocation " + volumes.toString() + ", maxSize: " +
1878+
totalOverProvCapacity + ", totalAllocatedSize: " + allocatedSizeWithTemplate + ", askingSize: " + totalAskingSize +
1879+
", allocated disable threshold: " + storageAllocatedThreshold);
18771880
}
18781881

18791882
double usedPercentage = (allocatedSizeWithTemplate + totalAskingSize) / (double)(totalOverProvCapacity);
1883+
18801884
if (usedPercentage > storageAllocatedThreshold) {
18811885
if (s_logger.isDebugEnabled()) {
1882-
s_logger.debug("Insufficient un-allocated capacity on: " + pool.getId() + " for volume allocation: " + volumes.toString() +
1883-
" since its allocated percentage: " + usedPercentage + " has crossed the allocated pool.storage.allocated.capacity.disablethreshold: " +
1886+
s_logger.debug("Insufficient un-allocated capacity on the pool with ID " + pool.getId() + " for volume allocation: " + volumes.toString() +
1887+
" since its allocated percentage " + usedPercentage + " has crossed the allocated pool.storage.allocated.capacity.disablethreshold " +
18841888
storageAllocatedThreshold + ", skipping this pool");
18851889
}
1890+
18861891
return false;
18871892
}
18881893

18891894
if (totalOverProvCapacity < (allocatedSizeWithTemplate + totalAskingSize)) {
18901895
if (s_logger.isDebugEnabled()) {
1891-
s_logger.debug("Insufficient un-allocated capacity on: " + pool.getId() + " for volume allocation: " + volumes.toString() +
1892-
", not enough storage, maxSize : " + totalOverProvCapacity + ", totalAllocatedSize : " + allocatedSizeWithTemplate + ", askingSize : " +
1896+
s_logger.debug("Insufficient un-allocated capacity on the pool with ID " + pool.getId() + " for volume allocation: " + volumes.toString() +
1897+
"; not enough storage, maxSize: " + totalOverProvCapacity + ", totalAllocatedSize: " + allocatedSizeWithTemplate + ", askingSize: " +
18931898
totalAskingSize);
18941899
}
1900+
18951901
return false;
18961902
}
1903+
18971904
return true;
18981905
}
18991906

1907+
/**
1908+
* Storage plug-ins for managed storage can be designed in such a way as to store a template on the primary storage once and
1909+
* make use of it via storage-side cloning.
1910+
*
1911+
* This method determines how many more bytes it will need for the template (if the template is already stored on the primary storage,
1912+
* then the answer is 0).
1913+
*/
1914+
private long getAskingSizeForTemplateBasedOnClusterAndStoragePool(Long templateId, Long clusterId, StoragePoolVO storagePoolVO) {
1915+
if (templateId == null || clusterId == null || storagePoolVO == null || !storagePoolVO.isManaged()) {
1916+
return 0;
1917+
}
1918+
1919+
VMTemplateVO tmpl = _templateDao.findByIdIncludingRemoved(templateId);
1920+
1921+
if (tmpl == null || ImageFormat.ISO.equals(tmpl.getFormat())) {
1922+
return 0;
1923+
}
1924+
1925+
HypervisorType hypervisorType = tmpl.getHypervisorType();
1926+
1927+
// The getSupportsResigning method is applicable for XenServer as a UUID-resigning patch may or may not be installed on those hypervisor hosts.
1928+
if (_clusterDao.getSupportsResigning(clusterId) || HypervisorType.VMware.equals(hypervisorType) || HypervisorType.KVM.equals(hypervisorType)) {
1929+
return getBytesRequiredForTemplate(tmpl, storagePoolVO);
1930+
}
1931+
1932+
return 0;
1933+
}
1934+
19001935
private DiskOfferingVO getDiskOfferingVO(Volume volume) {
19011936
Long diskOfferingId = volume.getDiskOfferingId();
19021937

0 commit comments

Comments
 (0)