diff --git a/api/src/com/cloud/storage/Volume.java b/api/src/com/cloud/storage/Volume.java index bb5ee08b512..84f0872f909 100755 --- a/api/src/com/cloud/storage/Volume.java +++ b/api/src/com/cloud/storage/Volume.java @@ -189,7 +189,5 @@ public interface Volume extends ControlledEntity, Identity, InternalIdentity, Ba Long getVmSnapshotChainSize(); - void setHypervisorSnapshotReserve(Integer hypervisorSnapshotReserve); - Integer getHypervisorSnapshotReserve(); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java index f3399cd733e..369ee9c01e9 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java @@ -21,9 +21,14 @@ package org.apache.cloudstack.engine.subsystem.api.storage; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.storage.command.CommandResult; +import com.cloud.storage.StoragePool; +import com.cloud.storage.Volume; + public interface PrimaryDataStoreDriver extends DataStoreDriver { public ChapInfo getChapInfo(VolumeInfo volumeInfo); + public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool); + public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback); public void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback); diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index 72aaf3d4a13..f094fb248a9 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -404,6 +404,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati @DB public VolumeInfo createVolume(VolumeInfo volume, VirtualMachine vm, VirtualMachineTemplate template, DataCenter dc, Pod pod, Long clusterId, ServiceOffering offering, DiskOffering diskOffering, List avoids, long size, HypervisorType hyperType) { + volume = updateHypervisorSnapshotReserveForVolume(diskOffering, volume, hyperType); + StoragePool pool = null; DiskProfile dskCh = null; @@ -423,8 +425,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati pool = findStoragePool(dskCh, dc, pod, clusterId, vm.getHostId(), vm, avoidPools); if (pool == null) { - s_logger.warn("Unable to find storage pool when create volume " + volume.getName()); - throw new CloudRuntimeException("Unable to find storage pool when create volume" + volume.getName()); + s_logger.warn("Unable to find suitable primary storage when creating volume " + volume.getName()); + throw new CloudRuntimeException("Unable to find suitable primary storage when creating volume " + volume.getName()); } if (s_logger.isDebugEnabled()) { @@ -436,7 +438,6 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati AsyncCallFuture future = null; boolean isNotCreatedFromTemplate = volume.getTemplateId() == null ? true : false; if (isNotCreatedFromTemplate) { - volume = updateHypervisorSnapshotReserveForVolume(diskOffering, volume, hyperType); future = volService.createVolumeAsync(volume, store); } else { TemplateInfo templ = tmplFactory.getTemplate(template.getId(), DataStoreRole.Image); diff --git a/engine/schema/src/com/cloud/storage/VolumeVO.java b/engine/schema/src/com/cloud/storage/VolumeVO.java index 944847f9298..901e07c70ef 100755 --- a/engine/schema/src/com/cloud/storage/VolumeVO.java +++ b/engine/schema/src/com/cloud/storage/VolumeVO.java @@ -587,7 +587,6 @@ public class VolumeVO implements Volume { this.state = state; } - @Override public void setHypervisorSnapshotReserve(Integer hypervisorSnapshotReserve) { this.hypervisorSnapshotReserve = hypervisorSnapshotReserve; } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/FakePrimaryDataStoreDriver.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/FakePrimaryDataStoreDriver.java index 54dbb65a6b1..dad64087e00 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/FakePrimaryDataStoreDriver.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/FakePrimaryDataStoreDriver.java @@ -36,6 +36,8 @@ import org.apache.cloudstack.storage.to.SnapshotObjectTO; import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.DataTO; +import com.cloud.storage.StoragePool; +import com.cloud.storage.Volume; public class FakePrimaryDataStoreDriver implements PrimaryDataStoreDriver { boolean snapshotResult = true; @@ -45,6 +47,11 @@ public class FakePrimaryDataStoreDriver implements PrimaryDataStoreDriver { return null; //To change body of implemented methods use File | Settings | File Templates. } + @Override + public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) { + return volume.getSize(); + } + @Override public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) { CreateCmdResult result = new CreateCmdResult(null, null); diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java index 76a94cd3b8d..fd0f2c1e19d 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java @@ -153,7 +153,6 @@ public class VolumeObject implements VolumeInfo { return volumeVO.getMaxIops(); } - @Override public void setHypervisorSnapshotReserve(Integer hypervisorSnapshotReserve) { volumeVO.setHypervisorSnapshotReserve(hypervisorSnapshotReserve); } diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java index bab960e03e4..c8e2582894e 100644 --- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java +++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java @@ -68,6 +68,7 @@ import com.cloud.storage.ResizeVolumePayload; import com.cloud.storage.Storage; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; +import com.cloud.storage.Volume; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.VMTemplateDao; @@ -148,6 +149,11 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri return null; } + @Override + public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) { + return volume.getSize(); + } + @Override public void createAsync(DataStore dataStore, DataObject data, AsyncCompletionCallback callback) { String errMsg = null; diff --git a/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java index 5e5a9340486..4cfc0975613 100644 --- a/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java +++ b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java @@ -42,6 +42,8 @@ import org.apache.cloudstack.storage.datastore.DataObjectManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.DataTO; +import com.cloud.storage.StoragePool; +import com.cloud.storage.Volume; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.utils.exception.CloudRuntimeException; @@ -78,6 +80,11 @@ public class SamplePrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver return null; } + @Override + public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) { + return volume.getSize(); + } + private class CreateVolumeContext extends AsyncRpcContext { private final DataObject volume; diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java index d85ed0da820..460cb0db499 100644 --- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java +++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java @@ -46,6 +46,8 @@ import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.DataTO; import com.cloud.dc.dao.DataCenterDao; import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.StoragePool; +import com.cloud.storage.Volume; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.dao.VolumeDetailsDao; @@ -284,8 +286,20 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver { iops = new Iops(volumeInfo.getMinIops(), volumeInfo.getMaxIops(), getDefaultBurstIops(storagePoolId, volumeInfo.getMaxIops())); } - long volumeSize = volumeInfo.getSize(); - Integer hypervisorSnapshotReserve = volumeInfo.getHypervisorSnapshotReserve(); + long volumeSize = getVolumeSizeIncludingHypervisorSnapshotReserve(volumeInfo, _storagePoolDao.findById(storagePoolId)); + + long sfVolumeId = SolidFireUtil.createSolidFireVolume(mVip, mPort, clusterAdminUsername, clusterAdminPassword, + getSolidFireVolumeName(volumeInfo.getName()), sfAccountId, volumeSize, true, + NumberFormat.getInstance().format(volumeInfo.getSize()), + iops.getMinIops(), iops.getMaxIops(), iops.getBurstIops()); + + return SolidFireUtil.getSolidFireVolume(mVip, mPort, clusterAdminUsername, clusterAdminPassword, sfVolumeId); + } + + @Override + public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) { + long volumeSize = volume.getSize(); + Integer hypervisorSnapshotReserve = volume.getHypervisorSnapshotReserve(); if (hypervisorSnapshotReserve != null) { if (hypervisorSnapshotReserve < 25) { @@ -295,11 +309,7 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver { volumeSize += volumeSize * (hypervisorSnapshotReserve / 100f); } - long sfVolumeId = - SolidFireUtil.createSolidFireVolume(mVip, mPort, clusterAdminUsername, clusterAdminPassword, getSolidFireVolumeName(volumeInfo.getName()), sfAccountId, - volumeSize, true, NumberFormat.getNumberInstance().format(volumeInfo.getSize().toString()), iops.getMinIops(), iops.getMaxIops(), iops.getBurstIops()); - - return SolidFireUtil.getSolidFireVolume(mVip, mPort, clusterAdminUsername, clusterAdminPassword, sfVolumeId); + return volumeSize; } private String getSolidFireVolumeName(String strCloudStackVolumeName) { @@ -356,11 +366,12 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver { } } - private void deleteSolidFireVolume(VolumeInfo volumeInfo, SolidFireConnection sfConnection) { + private SolidFireUtil.SolidFireVolume deleteSolidFireVolume(VolumeInfo volumeInfo, SolidFireConnection sfConnection) + { Long storagePoolId = volumeInfo.getPoolId(); if (storagePoolId == null) { - return; // this volume was never assigned to a storage pool, so no SAN volume should exist for it + return null; // this volume was never assigned to a storage pool, so no SAN volume should exist for it } String mVip = sfConnection.getManagementVip(); @@ -370,7 +381,7 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver { long sfVolumeId = Long.parseLong(volumeInfo.getFolder()); - SolidFireUtil.deleteSolidFireVolume(mVip, mPort, clusterAdminUsername, clusterAdminPassword, sfVolumeId); + return SolidFireUtil.deleteSolidFireVolume(mVip, mPort, clusterAdminUsername, clusterAdminPassword, sfVolumeId); } private String getSfAccountName(String csAccountUuid, long csAccountId) { @@ -429,7 +440,7 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver { long capacityBytes = storagePool.getCapacityBytes(); long usedBytes = storagePool.getUsedBytes(); - usedBytes += volumeInfo.getSize(); + usedBytes += sfVolume.getTotalSize(); storagePool.setUsedBytes(usedBytes > capacityBytes ? capacityBytes : usedBytes); @@ -493,31 +504,31 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver { if (dataObject.getType() == DataObjectType.VOLUME) { VolumeInfo volumeInfo = (VolumeInfo)dataObject; - AccountVO account = _accountDao.findById(volumeInfo.getAccountId()); - AccountDetailVO accountDetails = _accountDetailsDao.findDetail(account.getAccountId(), SolidFireUtil.ACCOUNT_ID); - long sfAccountId = Long.parseLong(accountDetails.getValue()); + // AccountVO account = _accountDao.findById(volumeInfo.getAccountId()); + // AccountDetailVO accountDetails = _accountDetailsDao.findDetail(account.getAccountId(), SolidFireUtil.ACCOUNT_ID); + // long sfAccountId = Long.parseLong(accountDetails.getValue()); long storagePoolId = dataStore.getId(); SolidFireConnection sfConnection = getSolidFireConnection(storagePoolId); - deleteSolidFireVolume(volumeInfo, sfConnection); + SolidFireUtil.SolidFireVolume sfVolume = deleteSolidFireVolume(volumeInfo, sfConnection); _volumeDao.deleteVolumesByInstance(volumeInfo.getId()); - // if (!sfAccountHasVolume(sfAccountId, sfConnection)) { - // // delete the account from the SolidFire SAN - // deleteSolidFireAccount(sfAccountId, sfConnection); + // if (!sfAccountHasVolume(sfAccountId, sfConnection)) { + // // delete the account from the SolidFire SAN + // deleteSolidFireAccount(sfAccountId, sfConnection); // - // // delete the info in the account_details table - // // that's related to the SolidFire account - // _accountDetailsDao.deleteDetails(account.getAccountId()); - // } + // // delete the info in the account_details table + // // that's related to the SolidFire account + // _accountDetailsDao.deleteDetails(account.getAccountId()); + // } StoragePoolVO storagePool = _storagePoolDao.findById(storagePoolId); long usedBytes = storagePool.getUsedBytes(); - usedBytes -= volumeInfo.getSize(); + usedBytes -= sfVolume != null ? sfVolume.getTotalSize() : 0; storagePool.setUsedBytes(usedBytes < 0 ? 0 : usedBytes); diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java index 5f26c97b97c..131e088a222 100644 --- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java +++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java @@ -95,7 +95,10 @@ public class SolidFireUtil { return volumeCreateResult.result.volumeID; } - public static void deleteSolidFireVolume(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lVolumeId) { + public static SolidFireVolume deleteSolidFireVolume(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lVolumeId) + { + SolidFireVolume sfVolume = getSolidFireVolume(strSfMvip, iSfPort, strSfAdmin, strSfPassword, lVolumeId); + final Gson gson = new GsonBuilder().create(); VolumeToDelete volumeToDelete = new VolumeToDelete(lVolumeId); @@ -103,6 +106,8 @@ public class SolidFireUtil { String strVolumeToDeleteJson = gson.toJson(volumeToDelete); executeJsonRpc(strVolumeToDeleteJson, strSfMvip, iSfPort, strSfAdmin, strSfPassword); + + return sfVolume; } public static void purgeSolidFireVolume(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lVolumeId) { @@ -132,8 +137,9 @@ public class SolidFireUtil { String strVolumeIqn = getVolumeIqn(volumeGetResult, lVolumeId); long lAccountId = getVolumeAccountId(volumeGetResult, lVolumeId); String strVolumeStatus = getVolumeStatus(volumeGetResult, lVolumeId); + long lTotalSize = getVolumeTotalSize(volumeGetResult, lVolumeId); - return new SolidFireVolume(lVolumeId, strVolumeName, strVolumeIqn, lAccountId, strVolumeStatus); + return new SolidFireVolume(lVolumeId, strVolumeName, strVolumeIqn, lAccountId, strVolumeStatus, lTotalSize); } public static List getSolidFireVolumesForAccountId(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lAccountId) { @@ -152,7 +158,7 @@ public class SolidFireUtil { List sfVolumes = new ArrayList(); for (VolumeGetResult.Result.Volume volume : volumeGetResult.result.volumes) { - sfVolumes.add(new SolidFireVolume(volume.volumeID, volume.name, volume.iqn, volume.accountID, volume.status)); + sfVolumes.add(new SolidFireVolume(volume.volumeID, volume.name, volume.iqn, volume.accountID, volume.status, volume.totalSize)); } return sfVolumes; @@ -166,13 +172,17 @@ public class SolidFireUtil { private final String _iqn; private final long _accountId; private final String _status; + private final long _totalSize; - public SolidFireVolume(long id, String name, String iqn, long accountId, String status) { + public SolidFireVolume(long id, String name, String iqn, + long accountId, String status, long totalSize) + { _id = id; _name = name; _iqn = "/" + iqn + "/0"; _accountId = accountId; _status = status; + _totalSize = totalSize; } public long getId() { @@ -195,6 +205,10 @@ public class SolidFireUtil { return ACTIVE.equalsIgnoreCase(_status); } + public long getTotalSize() { + return _totalSize; + } + @Override public int hashCode() { return _iqn.hashCode(); @@ -217,7 +231,9 @@ public class SolidFireUtil { SolidFireVolume sfv = (SolidFireVolume)obj; - if (_id == sfv._id && _name.equals(sfv._name) && _iqn.equals(sfv._iqn) && _accountId == sfv._accountId && isActive() == sfv.isActive()) { + if (_id == sfv._id && _name.equals(sfv._name) && + _iqn.equals(sfv._iqn) && _accountId == sfv._accountId && + isActive() == sfv.isActive() && getTotalSize() == sfv.getTotalSize()) { return true; } @@ -366,7 +382,7 @@ public class SolidFireUtil { List deletedVolumes = new ArrayList(); for (VolumeGetResult.Result.Volume volume : volumeGetResult.result.volumes) { - deletedVolumes.add(new SolidFireVolume(volume.volumeID, volume.name, volume.iqn, volume.accountID, volume.status)); + deletedVolumes.add(new SolidFireVolume(volume.volumeID, volume.name, volume.iqn, volume.accountID, volume.status, volume.totalSize)); } return deletedVolumes; @@ -655,6 +671,7 @@ public class SolidFireUtil { private String iqn; private long accountID; private String status; + private long totalSize; } } } @@ -811,7 +828,7 @@ public class SolidFireUtil { return volumeGetResult.result.volumes[0].name; } - throw new CloudRuntimeException("Could not determine the name of the volume, " + "but the volume was created with an ID of " + lVolumeId + "."); + throw new CloudRuntimeException("Could not determine the name of the volume for volume ID of " + lVolumeId + "."); } private static String getVolumeIqn(VolumeGetResult volumeGetResult, long lVolumeId) { @@ -819,7 +836,7 @@ public class SolidFireUtil { return volumeGetResult.result.volumes[0].iqn; } - throw new CloudRuntimeException("Could not determine the IQN of the volume, " + "but the volume was created with an ID of " + lVolumeId + "."); + throw new CloudRuntimeException("Could not determine the IQN of the volume for volume ID of " + lVolumeId + "."); } private static long getVolumeAccountId(VolumeGetResult volumeGetResult, long lVolumeId) { @@ -827,7 +844,7 @@ public class SolidFireUtil { return volumeGetResult.result.volumes[0].accountID; } - throw new CloudRuntimeException("Could not determine the volume's account ID, " + "but the volume was created with an ID of " + lVolumeId + "."); + throw new CloudRuntimeException("Could not determine the account ID of the volume for volume ID of " + lVolumeId + "."); } private static String getVolumeStatus(VolumeGetResult volumeGetResult, long lVolumeId) { @@ -835,6 +852,17 @@ public class SolidFireUtil { return volumeGetResult.result.volumes[0].status; } - throw new CloudRuntimeException("Could not determine the status of the volume, " + "but the volume was created with an ID of " + lVolumeId + "."); + throw new CloudRuntimeException("Could not determine the status of the volume for volume ID of " + lVolumeId + "."); + } + + private static long getVolumeTotalSize(VolumeGetResult volumeGetResult, long lVolumeId) + { + if (volumeGetResult.result.volumes != null && volumeGetResult.result.volumes.length == 1 && + volumeGetResult.result.volumes[0].volumeID == lVolumeId) + { + return volumeGetResult.result.volumes[0].totalSize; + } + + throw new CloudRuntimeException("Could not determine the total size of the volume for volume ID of " + lVolumeId + "."); } } diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java index 7daf2779ed7..024c7f2d04b 100755 --- a/server/src/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java @@ -500,10 +500,19 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, @Override public long getAllocatedPoolCapacity(StoragePoolVO pool, VMTemplateVO templateForVmCreation) { + long totalAllocatedSize = 0; - // Get size for all the non-destroyed volumes - Pair sizes = _volumeDao.getNonDestroyedCountAndTotalByPool(pool.getId()); - long totalAllocatedSize = sizes.second() + sizes.first() * _extraBytesPerVolume; + // if the storage pool is managed, the used bytes can be larger than the sum of the sizes of all of the non-destroyed volumes + // in this case, just get the used bytes from the storage pool object + if (pool.isManaged()) { + totalAllocatedSize = pool.getUsedBytes(); + } + else { + // Get size for all the non-destroyed volumes + Pair sizes = _volumeDao.getNonDestroyedCountAndTotalByPool(pool.getId()); + + totalAllocatedSize = sizes.second() + sizes.first() * _extraBytesPerVolume; + } // Get size for VM Snapshots totalAllocatedSize = totalAllocatedSize + _volumeDao.getVMSnapshotSizeByPool(pool.getId()); diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 9afd47a869c..c274e2c5343 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -54,6 +54,7 @@ import org.apache.cloudstack.api.command.admin.storage.UpdateStoragePoolCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; @@ -62,6 +63,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; import org.apache.cloudstack.engine.subsystem.api.storage.ImageStoreProvider; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; @@ -1542,7 +1544,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } } if (volume.getState() != Volume.State.Ready) { - totalAskingSize = totalAskingSize + volume.getSize(); + totalAskingSize = totalAskingSize + getVolumeSizeIncludingHvSsReserve(volume, pool); } } @@ -1581,6 +1583,19 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C return true; } + private long getVolumeSizeIncludingHvSsReserve(Volume volume, StoragePool pool) { + DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName()); + DataStoreDriver storeDriver = storeProvider.getDataStoreDriver(); + + if (storeDriver instanceof PrimaryDataStoreDriver) { + PrimaryDataStoreDriver primaryStoreDriver = (PrimaryDataStoreDriver)storeDriver; + + return primaryStoreDriver.getVolumeSizeIncludingHypervisorSnapshotReserve(volume, pool); + } + + return volume.getSize(); + } + @Override public void createCapacityEntry(long poolId) { StoragePoolVO storage = _storagePoolDao.findById(poolId);