mirror of https://github.com/apache/cloudstack.git
CLOUDSTACK-4810: Enable hypervisor snapshots for CloudStack-managed storage (for XenServer and VMware)
This commit is contained in:
parent
cd11d3e9df
commit
bb8794203e
|
|
@ -186,7 +186,5 @@ public interface Volume extends ControlledEntity, Identity, InternalIdentity, Ba
|
|||
Storage.ImageFormat getFormat();
|
||||
Long getVmSnapshotChainSize();
|
||||
|
||||
void setHypervisorSnapshotReserve(Integer hypervisorSnapshotReserve);
|
||||
|
||||
Integer getHypervisorSnapshotReserve();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -587,6 +587,7 @@ public class VolumeVO implements Volume {
|
|||
this.hypervisorSnapshotReserve = hypervisorSnapshotReserve;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getHypervisorSnapshotReserve() {
|
||||
return hypervisorSnapshotReserve;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -43,6 +45,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<CreateCmdResult> callback) {
|
||||
CreateCmdResult result = new CreateCmdResult(null, null);
|
||||
|
|
|
|||
|
|
@ -141,7 +141,6 @@ public class VolumeObject implements VolumeInfo {
|
|||
return volumeVO.getMaxIops();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHypervisorSnapshotReserve(Integer hypervisorSnapshotReserve) {
|
||||
volumeVO.setHypervisorSnapshotReserve(hypervisorSnapshotReserve);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
@ -132,6 +133,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<CreateCmdResult> callback) {
|
||||
String errMsg = null;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 + ".");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue