Updated Branches: refs/heads/4.3 cd11d3e9d -> bb8794203
CLOUDSTACK-4810: Enable hypervisor snapshots for CloudStack-managed storage (for XenServer and VMware) Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/bb879420 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/bb879420 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/bb879420 Branch: refs/heads/4.3 Commit: bb8794203e6a961da0f9cf755bd0ada89c49a2d8 Parents: cd11d3e Author: Mike Tutkowski <[email protected]> Authored: Tue Nov 12 12:08:03 2013 -0700 Committer: Mike Tutkowski <[email protected]> Committed: Tue Nov 12 16:52:12 2013 -0700 ---------------------------------------------------------------------- api/src/com/cloud/storage/Volume.java | 2 - .../api/storage/PrimaryDataStoreDriver.java | 4 ++ .../orchestration/VolumeOrchestrator.java | 7 +-- .../schema/src/com/cloud/storage/VolumeVO.java | 1 + .../test/FakePrimaryDataStoreDriver.java | 7 +++ .../cloudstack/storage/volume/VolumeObject.java | 1 - .../CloudStackPrimaryDataStoreDriverImpl.java | 6 +++ .../SamplePrimaryDataStoreDriverImpl.java | 7 +++ .../driver/SolidfirePrimaryDataStoreDriver.java | 57 +++++++++++--------- .../storage/datastore/util/SolidFireUtil.java | 47 +++++++++++----- .../com/cloud/capacity/CapacityManagerImpl.java | 17 ++++-- .../com/cloud/storage/StorageManagerImpl.java | 17 +++++- 12 files changed, 124 insertions(+), 49 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bb879420/api/src/com/cloud/storage/Volume.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/storage/Volume.java b/api/src/com/cloud/storage/Volume.java index dd59f12..b1a253f 100755 --- a/api/src/com/cloud/storage/Volume.java +++ b/api/src/com/cloud/storage/Volume.java @@ -186,7 +186,5 @@ public interface Volume extends ControlledEntity, Identity, InternalIdentity, Ba Storage.ImageFormat getFormat(); Long getVmSnapshotChainSize(); - void setHypervisorSnapshotReserve(Integer hypervisorSnapshotReserve); - Integer getHypervisorSnapshotReserve(); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bb879420/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java ---------------------------------------------------------------------- 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 b124d83..6c353d9 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,8 +21,12 @@ 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<CreateCmdResult> callback); public void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CommandResult> callback); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bb879420/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java ---------------------------------------------------------------------- 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 f839d6c..71e8b7d 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -374,6 +374,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<StoragePool> avoids, long size, HypervisorType hyperType) { + volume = updateHypervisorSnapshotReserveForVolume(diskOffering, volume, hyperType); + StoragePool pool = null; if (diskOffering != null && diskOffering.isCustomized()) { @@ -393,8 +395,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()) { @@ -406,7 +408,6 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati AsyncCallFuture<VolumeApiResult> 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); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bb879420/engine/schema/src/com/cloud/storage/VolumeVO.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/storage/VolumeVO.java b/engine/schema/src/com/cloud/storage/VolumeVO.java index a130d89..e3516a3 100755 --- a/engine/schema/src/com/cloud/storage/VolumeVO.java +++ b/engine/schema/src/com/cloud/storage/VolumeVO.java @@ -587,6 +587,7 @@ public class VolumeVO implements Volume { this.hypervisorSnapshotReserve = hypervisorSnapshotReserve; } + @Override public Integer getHypervisorSnapshotReserve() { return hypervisorSnapshotReserve; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bb879420/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/FakePrimaryDataStoreDriver.java ---------------------------------------------------------------------- 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 de64b8f..72373e2 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 @@ -35,6 +35,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; @@ -44,6 +46,11 @@ public class FakePrimaryDataStoreDriver implements PrimaryDataStoreDriver { } @Override + public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) { + return volume.getSize(); + } + + @Override public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CreateCmdResult> callback) { CreateCmdResult result = new CreateCmdResult(null, null); if (snapshotResult) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bb879420/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java ---------------------------------------------------------------------- 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 f761a0c..859427c 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 @@ -141,7 +141,6 @@ public class VolumeObject implements VolumeInfo { return volumeVO.getMaxIops(); } - @Override public void setHypervisorSnapshotReserve(Integer hypervisorSnapshotReserve) { volumeVO.setHypervisorSnapshotReserve(hypervisorSnapshotReserve); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bb879420/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java ---------------------------------------------------------------------- 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 327d87c..9da29d6 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 @@ -23,6 +23,7 @@ import java.util.UUID; import javax.inject.Inject; import com.cloud.storage.*; + import org.apache.cloudstack.storage.to.SnapshotObjectTO; import org.apache.log4j.Logger; @@ -133,6 +134,11 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri } @Override + public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) { + return volume.getSize(); + } + + @Override public void createAsync(DataStore dataStore, DataObject data, AsyncCompletionCallback<CreateCmdResult> callback) { String errMsg = null; Answer answer = null; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bb879420/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java ---------------------------------------------------------------------- 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 8f4c7bb..302cb09 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 @@ -40,6 +40,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; @@ -71,6 +73,11 @@ public class SamplePrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver return null; } + @Override + public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) { + return volume.getSize(); + } + private class CreateVolumeContext<T> extends AsyncRpcContext<T> { private final DataObject volume; public CreateVolumeContext(AsyncCompletionCallback<T> callback, DataObject volume) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bb879420/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java ---------------------------------------------------------------------- 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 1c726cd..8a98b62 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 @@ -44,6 +44,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; @@ -288,8 +290,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) { @@ -299,12 +313,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) { @@ -367,12 +376,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(); @@ -382,7 +391,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) { @@ -443,7 +452,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); @@ -510,31 +519,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); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bb879420/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java ---------------------------------------------------------------------- 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 6659f98..1bf3788 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 @@ -97,8 +97,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); @@ -106,6 +108,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) @@ -137,8 +141,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<SolidFireVolume> getSolidFireVolumesForAccountId(String strSfMvip, int iSfPort, @@ -160,7 +165,7 @@ public class SolidFireUtil List<SolidFireVolume> sfVolumes = new ArrayList<SolidFireVolume>(); 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; @@ -175,15 +180,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) + long accountId, String status, long totalSize) { _id = id; _name = name; _iqn = "/" + iqn + "/0"; _accountId = accountId; _status = status; + _totalSize = totalSize; } public long getId() @@ -211,6 +218,10 @@ public class SolidFireUtil return ACTIVE.equalsIgnoreCase(_status); } + public long getTotalSize() { + return _totalSize; + } + @Override public int hashCode() { return _iqn.hashCode(); @@ -235,7 +246,7 @@ public class SolidFireUtil if (_id == sfv._id && _name.equals(sfv._name) && _iqn.equals(sfv._iqn) && _accountId == sfv._accountId && - isActive() == sfv.isActive()) { + isActive() == sfv.isActive() && getTotalSize() == sfv.getTotalSize()) { return true; } @@ -402,7 +413,7 @@ public class SolidFireUtil List<SolidFireVolume> deletedVolumes = new ArrayList<SolidFireVolume> (); 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; @@ -748,6 +759,7 @@ public class SolidFireUtil private String iqn; private long accountID; private String status; + private long totalSize; } } } @@ -927,8 +939,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) @@ -939,8 +950,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) @@ -951,8 +961,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) @@ -963,7 +972,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 + "."); } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bb879420/server/src/com/cloud/capacity/CapacityManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java index 70491bc..52cab12 100755 --- a/server/src/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java @@ -475,11 +475,20 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager, } @Override - public long getAllocatedPoolCapacity(StoragePoolVO pool, VMTemplateVO templateForVmCreation){ + public long getAllocatedPoolCapacity(StoragePoolVO pool, VMTemplateVO templateForVmCreation) { + long totalAllocatedSize = 0; - // Get size for all the non-destroyed volumes - Pair<Long, Long> 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<Long, Long> sizes = _volumeDao.getNonDestroyedCountAndTotalByPool(pool.getId()); + + totalAllocatedSize = sizes.second() + sizes.first() * _extraBytesPerVolume; + } // Get size for VM Snapshots totalAllocatedSize = totalAllocatedSize + _volumeDao.getVMSnapshotSizeByPool(pool.getId()); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bb879420/server/src/com/cloud/storage/StorageManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index e42d871..e81e30e 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -55,6 +55,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; @@ -63,6 +64,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; @@ -1582,7 +1584,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } } if (volume.getState() != Volume.State.Ready) { - totalAskingSize = totalAskingSize + volume.getSize(); + totalAskingSize = totalAskingSize + getVolumeSizeIncludingHvSsReserve(volume, pool); } } @@ -1623,6 +1625,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);
