Adding support for SolidFire snapshots

This commit is contained in:
Mike Tutkowski 2014-08-25 16:15:04 -06:00
parent 659eafffe1
commit 1d2f3300ad
10 changed files with 405 additions and 60 deletions

View File

@ -32,7 +32,14 @@ public interface PrimaryDataStoreDriver extends DataStoreDriver {
public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore);
public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool);
// intended for managed storage (cloud.storage_pool.managed = true)
// if not managed, return volume.getSize()
public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool storagePool);
// intended for managed storage (cloud.storage_pool.managed = true)
// if managed storage, return the total number of bytes currently in use for the storage pool in question
// if not managed storage, return 0
public long getUsedBytes(StoragePool storagePool);
public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CreateCmdResult> callback);

View File

@ -54,6 +54,11 @@ public class FakePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
@Override
public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) {}
@Override
public long getUsedBytes(StoragePool storagePool) {
return 0;
}
@Override
public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) {
return volume.getSize();

View File

@ -316,10 +316,10 @@ public class SnapshotServiceImpl implements SnapshotService {
}
try {
CopyCmdAnswer answer = (CopyCmdAnswer)result.getAnswer();
destSnapshot.processEvent(Event.OperationSuccessed, result.getAnswer());
CopyCmdAnswer copyCmdAnswer = (CopyCmdAnswer)result.getAnswer();
destSnapshot.processEvent(Event.OperationSuccessed, copyCmdAnswer);
srcSnapshot.processEvent(Snapshot.Event.OperationSucceeded);
snapResult = new SnapshotResult(_snapshotFactory.getSnapshot(destSnapshot.getId(), destSnapshot.getDataStore()), answer);
snapResult = new SnapshotResult(_snapshotFactory.getSnapshot(destSnapshot.getId(), destSnapshot.getDataStore()), copyCmdAnswer);
future.complete(snapResult);
} catch (Exception e) {
s_logger.debug("Failed to update snapshot state", e);

View File

@ -157,6 +157,11 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) {
}
@Override
public long getUsedBytes(StoragePool storagePool) {
return 0;
}
@Override
public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) {
return volume.getSize();

View File

@ -67,6 +67,11 @@ public class NexentaPrimaryDataStoreDriver implements PrimaryDataStoreDriver {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public long getUsedBytes(StoragePool storagePool) {
return 0;
}
@Override
public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) {
return 0; //To change body of implemented methods use File | Settings | File Templates.

View File

@ -87,6 +87,11 @@ public class SamplePrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
@Override
public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) {}
@Override
public long getUsedBytes(StoragePool storagePool) {
return 0;
}
@Override
public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) {
return volume.getSize();

View File

@ -32,11 +32,15 @@ import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
import org.apache.cloudstack.storage.command.CreateObjectAnswer;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.storage.datastore.util.SolidFireUtil;
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.to.DataObjectType;
@ -46,7 +50,6 @@ import com.cloud.capacity.CapacityManager;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.ClusterDetailsVO;
import com.cloud.dc.ClusterDetailsDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
@ -55,8 +58,14 @@ import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.ResizeVolumePayload;
import com.cloud.storage.StoragePool;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeDetailVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.SnapshotDetailsDao;
import com.cloud.storage.dao.SnapshotDetailsVO;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.dao.VolumeDetailsDao;
import com.cloud.user.AccountDetailVO;
import com.cloud.user.AccountDetailsDao;
import com.cloud.user.AccountVO;
@ -64,16 +73,20 @@ import com.cloud.user.dao.AccountDao;
import com.cloud.utils.exception.CloudRuntimeException;
public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
private static final Logger s_logger = Logger.getLogger(SolidFirePrimaryDataStoreDriver.class);
@Inject private AccountDao _accountDao;
@Inject private AccountDetailsDao _accountDetailsDao;
@Inject private CapacityManager _capacityMgr;
@Inject private ClusterDao _clusterDao;
@Inject private ClusterDetailsDao _clusterDetailsDao;
@Inject private DataCenterDao _zoneDao;
@Inject private HostDao _hostDao;
@Inject private SnapshotDao _snapshotDao;
@Inject private SnapshotDetailsDao _snapshotDetailsDao;
@Inject private PrimaryDataStoreDao _storagePoolDao;
@Inject private StoragePoolDetailsDao _storagePoolDetailsDao;
@Inject private VolumeDao _volumeDao;
@Inject private VolumeDetailsDao _volumeDetailsDao;
@Override
public Map<String, String> getCapabilities() {
@ -228,14 +241,54 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
return SolidFireUtil.getSolidFireVolume(sfConnection, sfVolumeId);
}
@Override
public long getUsedBytes(StoragePool storagePool) {
long usedSpace = 0;
List<VolumeVO> lstVolumes = _volumeDao.findByPoolId(storagePool.getId(), null);
if (lstVolumes != null) {
for (VolumeVO volume : lstVolumes) {
VolumeDetailVO volumeDetail = _volumeDetailsDao.findDetail(volume.getId(), SolidFireUtil.VOLUME_SIZE);
if (volumeDetail != null && volumeDetail.getValue() != null) {
long volumeSize = Long.parseLong(volumeDetail.getValue());
usedSpace += volumeSize;
}
}
}
List<SnapshotVO> lstSnapshots = _snapshotDao.listAll();
if (lstSnapshots != null) {
for (SnapshotVO snapshot : lstSnapshots) {
SnapshotDetailsVO snapshotDetails = _snapshotDetailsDao.findDetail(snapshot.getId(), SolidFireUtil.SNAPSHOT_STORAGE_POOL_ID);
// if this snapshot belong to the storagePool that was passed in
if (snapshotDetails != null && snapshotDetails.getValue() != null && Long.parseLong(snapshotDetails.getValue()) == storagePool.getId()) {
snapshotDetails = _snapshotDetailsDao.findDetail(snapshot.getId(), SolidFireUtil.SNAPSHOT_SIZE);
if (snapshotDetails != null && snapshotDetails.getValue() != null) {
long snapshotSize = Long.parseLong(snapshotDetails.getValue());
usedSpace += snapshotSize;
}
}
}
}
return usedSpace;
}
@Override
public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) {
long volumeSize = volume.getSize();
Integer hypervisorSnapshotReserve = volume.getHypervisorSnapshotReserve();
if (hypervisorSnapshotReserve != null) {
if (hypervisorSnapshotReserve < 25) {
hypervisorSnapshotReserve = 25;
if (hypervisorSnapshotReserve < 50) {
hypervisorSnapshotReserve = 50;
}
volumeSize += volumeSize * (hypervisorSnapshotReserve / 100f);
@ -280,17 +333,17 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
}
}
private SolidFireUtil.SolidFireVolume deleteSolidFireVolume(SolidFireUtil.SolidFireConnection sfConnection, VolumeInfo volumeInfo)
private void deleteSolidFireVolume(SolidFireUtil.SolidFireConnection sfConnection, VolumeInfo volumeInfo)
{
Long storagePoolId = volumeInfo.getPoolId();
if (storagePoolId == null) {
return null; // this volume was never assigned to a storage pool, so no SAN volume should exist for it
return; // this volume was never assigned to a storage pool, so no SAN volume should exist for it
}
long sfVolumeId = Long.parseLong(volumeInfo.getFolder());
return SolidFireUtil.deleteSolidFireVolume(sfConnection, sfVolumeId);
SolidFireUtil.deleteSolidFireVolume(sfConnection, sfVolumeId);
}
@Override
@ -327,7 +380,7 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
iqn = sfVolume.getIqn();
VolumeVO volume = this._volumeDao.findById(volumeInfo.getId());
VolumeVO volume = _volumeDao.findById(volumeInfo.getId());
volume.set_iScsiName(iqn);
volume.setFolder(String.valueOf(sfVolume.getId()));
@ -336,12 +389,14 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
_volumeDao.update(volume.getId(), volume);
updateVolumeDetails(volume.getId(), sfVolume.getTotalSize());
StoragePoolVO storagePool = _storagePoolDao.findById(dataStore.getId());
long capacityBytes = storagePool.getCapacityBytes();
long usedBytes = storagePool.getUsedBytes();
usedBytes += sfVolume.getTotalSize();
// getUsedBytes(StoragePool) will include the bytes of the newly created volume because
// updateVolumeDetails(long, long) has already been called for this volume
long usedBytes = getUsedBytes(storagePool);
storagePool.setUsedBytes(usedBytes > capacityBytes ? capacityBytes : usedBytes);
@ -359,29 +414,52 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
callback.complete(result);
}
private void updateVolumeDetails(long volumeId, long sfVolumeSize) {
VolumeDetailVO volumeDetailVo = _volumeDetailsDao.findDetail(volumeId, SolidFireUtil.VOLUME_SIZE);
if (volumeDetailVo == null || volumeDetailVo.getValue() == null) {
volumeDetailVo = new VolumeDetailVO(volumeId, SolidFireUtil.VOLUME_SIZE, String.valueOf(sfVolumeSize), false);
_volumeDetailsDao.persist(volumeDetailVo);
}
}
@Override
public void deleteAsync(DataStore dataStore, DataObject dataObject, AsyncCompletionCallback<CommandResult> callback) {
String errMsg = null;
if (dataObject.getType() == DataObjectType.VOLUME) {
VolumeInfo volumeInfo = (VolumeInfo)dataObject;
try {
VolumeInfo volumeInfo = (VolumeInfo)dataObject;
long volumeId = volumeInfo.getId();
long storagePoolId = dataStore.getId();
SolidFireUtil.SolidFireConnection sfConnection = SolidFireUtil.getSolidFireConnection(storagePoolId, _storagePoolDetailsDao);
long storagePoolId = dataStore.getId();
SolidFireUtil.SolidFireVolume sfVolume = deleteSolidFireVolume(sfConnection, volumeInfo);
SolidFireUtil.SolidFireConnection sfConnection = SolidFireUtil.getSolidFireConnection(storagePoolId, _storagePoolDetailsDao);
_volumeDao.deleteVolumesByInstance(volumeInfo.getId());
deleteSolidFireVolume(sfConnection, volumeInfo);
StoragePoolVO storagePool = _storagePoolDao.findById(storagePoolId);
_volumeDetailsDao.removeDetails(volumeId);
long usedBytes = storagePool.getUsedBytes();
_volumeDao.deleteVolumesByInstance(volumeId);
usedBytes -= sfVolume != null ? sfVolume.getTotalSize() : 0;
StoragePoolVO storagePool = _storagePoolDao.findById(storagePoolId);
storagePool.setUsedBytes(usedBytes < 0 ? 0 : usedBytes);
// getUsedBytes(StoragePool) will not include the volume to delete because it has already been deleted by this point
long usedBytes = getUsedBytes(storagePool);
_storagePoolDao.update(storagePoolId, storagePool);
storagePool.setUsedBytes(usedBytes < 0 ? 0 : usedBytes);
_storagePoolDao.update(storagePoolId, storagePool);
}
catch (Exception ex) {
s_logger.debug(SolidFireUtil.LOG_PREFIX + "Failed to delete SolidFire volume", ex);
errMsg = ex.getMessage();
}
} else if (dataObject.getType() == DataObjectType.SNAPSHOT) {
// should return null when no error message
errMsg = deleteSnapshot((SnapshotInfo)dataObject, dataStore.getId());
} else {
errMsg = "Invalid DataObjectType (" + dataObject.getType() + ") passed to deleteAsync";
}
@ -394,15 +472,145 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
}
@Override
public void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
public void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
if (srcData.getType() == DataObjectType.SNAPSHOT && destData.getType() == DataObjectType.SNAPSHOT) {
// in this situation, we don't want to copy the snapshot anywhere
CopyCmdAnswer copyCmdAnswer = new CopyCmdAnswer(destData.getTO());
CopyCommandResult result = new CopyCommandResult(null, copyCmdAnswer);
result.setResult(null);
callback.complete(result);
return;
}
throw new UnsupportedOperationException();
}
@Override
public boolean canCopy(DataObject srcData, DataObject destData) {
if (srcData.getType() == DataObjectType.SNAPSHOT && destData.getType() == DataObjectType.SNAPSHOT) {
return true;
}
return false;
}
@Override
public void takeSnapshot(SnapshotInfo snapshotInfo, AsyncCompletionCallback<CreateCmdResult> callback) {
CreateCmdResult result = null;
try {
VolumeInfo volumeInfo = snapshotInfo.getBaseVolume();
VolumeVO volume = _volumeDao.findById(volumeInfo.getId());
long sfVolumeId = Long.parseLong(volume.getFolder());
long storagePoolId = volume.getPoolId();
SolidFireUtil.SolidFireConnection sfConnection = SolidFireUtil.getSolidFireConnection(storagePoolId, _storagePoolDetailsDao);
SolidFireUtil.SolidFireVolume sfVolume = SolidFireUtil.getSolidFireVolume(sfConnection, sfVolumeId);
StoragePoolVO storagePool = _storagePoolDao.findById(storagePoolId);
long capacityBytes = storagePool.getCapacityBytes();
// getUsedBytes(StoragePool) will not include the bytes of the proposed snapshot because
// updateSnapshotDetails(long, long, long, long) has not yet been called for this snapshot
long usedBytes = getUsedBytes(storagePool);
long sfVolumeSize = sfVolume.getTotalSize();
usedBytes += sfVolumeSize;
// For taking a snapshot, we need to check to make sure a sufficient amount of space remains in the primary storage.
// For the purpose of "charging" these bytes against storage_pool.capacityBytes, we take the full size of the SolidFire volume.
// Generally snapshots take up much less space than the size of the volume, but the easiest way to track this space usage
// is to take the full size of the volume (you can always increase the amount of bytes you give to the primary storage).
if (usedBytes > capacityBytes) {
throw new CloudRuntimeException("Insufficient amount of space remains in this primary storage to take a snapshot");
}
storagePool.setUsedBytes(usedBytes);
long sfSnapshotId = SolidFireUtil.createSolidFireSnapshot(sfConnection, sfVolumeId, snapshotInfo.getUuid());
// Now that we have successfully taken a snapshot, update the space usage in the storage_pool table (even
// though storage_pool.used_bytes is likely no longer in use).
_storagePoolDao.update(storagePoolId, storagePool);
updateSnapshotDetails(snapshotInfo.getId(), sfSnapshotId, storagePoolId, sfVolumeSize);
SnapshotObjectTO snapshotObjectTo = (SnapshotObjectTO)snapshotInfo.getTO();
snapshotObjectTo.setPath(String.valueOf(sfSnapshotId));
CreateObjectAnswer createObjectAnswer = new CreateObjectAnswer(snapshotObjectTo);
result = new CreateCmdResult(null, createObjectAnswer);
result.setResult(null);
}
catch (Exception ex) {
s_logger.debug(SolidFireUtil.LOG_PREFIX + "Failed to take CloudStack snapshot: " + snapshotInfo.getId(), ex);
result = new CreateCmdResult(null, new CreateObjectAnswer(ex.toString()));
result.setResult(ex.toString());
}
callback.complete(result);
}
private void updateSnapshotDetails(long csSnapshotId, long sfSnapshotId, long storagePoolId, long sfSnapshotSize) {
SnapshotDetailsVO accountDetail = new SnapshotDetailsVO(csSnapshotId,
SolidFireUtil.SNAPSHOT_ID,
String.valueOf(sfSnapshotId),
false);
_snapshotDetailsDao.persist(accountDetail);
accountDetail = new SnapshotDetailsVO(csSnapshotId,
SolidFireUtil.SNAPSHOT_STORAGE_POOL_ID,
String.valueOf(storagePoolId),
false);
_snapshotDetailsDao.persist(accountDetail);
accountDetail = new SnapshotDetailsVO(csSnapshotId,
SolidFireUtil.SNAPSHOT_SIZE,
String.valueOf(sfSnapshotSize),
false);
_snapshotDetailsDao.persist(accountDetail);
}
// return null for no error message
private String deleteSnapshot(SnapshotInfo snapshotInfo, long storagePoolId) {
String errMsg = null;
try {
SolidFireUtil.SolidFireConnection sfConnection = SolidFireUtil.getSolidFireConnection(storagePoolId, _storagePoolDetailsDao);
SolidFireUtil.deleteSolidFireSnapshot(sfConnection, getSolidFireSnapshotId(snapshotInfo.getId()));
_snapshotDetailsDao.removeDetails(snapshotInfo.getId());
}
catch (Exception ex) {
s_logger.debug(SolidFireUtil.LOG_PREFIX + "Failed to delete SolidFire snapshot: " + snapshotInfo.getId(), ex);
errMsg = ex.getMessage();
}
return errMsg;
}
private long getSolidFireSnapshotId(long csSnapshotId) {
SnapshotDetailsVO snapshotDetails = _snapshotDetailsDao.findDetail(csSnapshotId, SolidFireUtil.SNAPSHOT_ID);
return Long.parseLong(snapshotDetails.getValue());
}
@Override
public void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CommandResult> callback) {
throw new UnsupportedOperationException();
@ -434,6 +642,12 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
volume.setMaxIops(payload.newMaxIops);
_volumeDao.update(volume.getId(), volume);
// SolidFireUtil.VOLUME_SIZE was introduced in 4.5.
// To be backward compatible with releases prior to 4.5, call updateVolumeDetails here.
// That way if SolidFireUtil.VOLUME_SIZE wasn't put in the volume_details table when the
// volume was initially created, it can be placed in volume_details if the volume is resized.
updateVolumeDetails(volume.getId(), sfVolume.getTotalSize());
} else {
errMsg = "Invalid DataObjectType (" + dataObject.getType() + ") passed to resize";
}
@ -462,9 +676,4 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
}
}
}
@Override
public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CreateCmdResult> callback) {
throw new UnsupportedOperationException();
}
}

View File

@ -69,6 +69,8 @@ public class SolidFireUtil {
public static final String PROVIDER_NAME = "SolidFire";
public static final String SHARED_PROVIDER_NAME = "SolidFireShared";
public static final String LOG_PREFIX = "SolidFire: ";
public static final String MANAGEMENT_VIP = "mVip";
public static final String STORAGE_VIP = "sVip";
@ -90,6 +92,13 @@ public class SolidFireUtil {
public static final String ACCOUNT_ID = "accountId";
public static final String VOLUME_ID = "volumeId";
public static final String SNAPSHOT_ID = "snapshotId";
public static final String CLONE_ID = "cloneId";
public static final String VOLUME_SIZE = "sfVolumeSize";
public static final String SNAPSHOT_SIZE = "sfSnapshotSize";
public static final String SNAPSHOT_STORAGE_POOL_ID = "sfSnapshotStoragePoolId";
public static final String CHAP_INITIATOR_USERNAME = "chapInitiatorUsername";
public static final String CHAP_INITIATOR_SECRET = "chapInitiatorSecret";
@ -554,10 +563,8 @@ public class SolidFireUtil {
return deletedVolumes;
}
public static SolidFireVolume deleteSolidFireVolume(SolidFireConnection sfConnection, long lVolumeId)
public static void deleteSolidFireVolume(SolidFireConnection sfConnection, long lVolumeId)
{
SolidFireVolume sfVolume = getSolidFireVolume(sfConnection, lVolumeId);
final Gson gson = new GsonBuilder().create();
VolumeToDelete volumeToDelete = new VolumeToDelete(lVolumeId);
@ -565,8 +572,6 @@ public class SolidFireUtil {
String strVolumeToDeleteJson = gson.toJson(volumeToDelete);
executeJsonRpc(sfConnection, strVolumeToDeleteJson);
return sfVolume;
}
public static void purgeSolidFireVolume(SolidFireConnection sfConnection, long lVolumeId)
@ -657,6 +662,49 @@ public class SolidFireUtil {
}
}
public static long createSolidFireSnapshot(SolidFireConnection sfConnection, long lVolumeId, String snapshotName) {
final Gson gson = new GsonBuilder().create();
SnapshotToCreate snapshotToCreate = new SnapshotToCreate(lVolumeId, snapshotName);
String strSnapshotToCreateJson = gson.toJson(snapshotToCreate);
String strSnapshotCreateResultJson = executeJsonRpc(sfConnection, strSnapshotToCreateJson);
SnapshotCreateResult snapshotCreateResult = gson.fromJson(strSnapshotCreateResultJson, SnapshotCreateResult.class);
verifyResult(snapshotCreateResult.result, strSnapshotCreateResultJson, gson);
return snapshotCreateResult.result.snapshotID;
}
public static void deleteSolidFireSnapshot(SolidFireConnection sfConnection, long lSnapshotId)
{
final Gson gson = new GsonBuilder().create();
SnapshotToDelete snapshotToDelete = new SnapshotToDelete(lSnapshotId);
String strSnapshotToDeleteJson = gson.toJson(snapshotToDelete);
executeJsonRpc(sfConnection, strSnapshotToDeleteJson);
}
public static long createSolidFireClone(SolidFireConnection sfConnection, long lVolumeId, String cloneName) {
final Gson gson = new GsonBuilder().create();
CloneToCreate cloneToCreate = new CloneToCreate(lVolumeId, cloneName);
String strCloneToCreateJson = gson.toJson(cloneToCreate);
String strCloneCreateResultJson = executeJsonRpc(sfConnection, strCloneToCreateJson);
CloneCreateResult cloneCreateResult = gson.fromJson(strCloneCreateResultJson, CloneCreateResult.class);
verifyResult(cloneCreateResult.result, strCloneCreateResultJson, gson);
return cloneCreateResult.result.cloneID;
}
public static long createSolidFireAccount(SolidFireConnection sfConnection, String strAccountName)
{
final Gson gson = new GsonBuilder().create();
@ -1206,6 +1254,65 @@ public class SolidFireUtil {
}
}
@SuppressWarnings("unused")
private static final class SnapshotToCreate {
private final String method = "CreateSnapshot";
private final SnapshotToCreateParams params;
private SnapshotToCreate(final long lVolumeId, final String snapshotName) {
params = new SnapshotToCreateParams(lVolumeId, snapshotName);
}
private static final class SnapshotToCreateParams {
private long volumeID;
private String name;
private SnapshotToCreateParams(final long lVolumeId, final String snapshotName) {
volumeID = lVolumeId;
name = snapshotName;
}
}
}
@SuppressWarnings("unused")
private static final class SnapshotToDelete
{
private final String method = "DeleteSnapshot";
private final SnapshotToDeleteParams params;
private SnapshotToDelete(final long lSnapshotId) {
params = new SnapshotToDeleteParams(lSnapshotId);
}
private static final class SnapshotToDeleteParams {
private long snapshotID;
private SnapshotToDeleteParams(final long lSnapshotId) {
snapshotID = lSnapshotId;
}
}
}
@SuppressWarnings("unused")
private static final class CloneToCreate {
private final String method = "CloneVolume";
private final CloneToCreateParams params;
private CloneToCreate(final long lVolumeId, final String cloneName) {
params = new CloneToCreateParams(lVolumeId, cloneName);
}
private static final class CloneToCreateParams {
private long volumeID;
private String name;
private CloneToCreateParams(final long lVolumeId, final String cloneName) {
volumeID = lVolumeId;
name = cloneName;
}
}
}
@SuppressWarnings("unused")
private static final class AccountToAdd
{
@ -1424,6 +1531,22 @@ public class SolidFireUtil {
}
}
private static final class SnapshotCreateResult {
private Result result;
private static final class Result {
private long snapshotID;
}
}
private static final class CloneCreateResult {
private Result result;
private static final class Result {
private long cloneID;
}
}
private static final class AccountAddResult {
private Result result;
@ -1528,7 +1651,7 @@ public class SolidFireUtil {
httpClient = getHttpClient(sfConnection.getManagementPort());
URI uri = new URI("https://" + sfConnection.getManagementVip() + ":" + sfConnection.getManagementPort() + "/json-rpc/5.0");
URI uri = new URI("https://" + sfConnection.getManagementVip() + ":" + sfConnection.getManagementPort() + "/json-rpc/6.0");
AuthScope authScope = new AuthScope(uri.getHost(), uri.getPort(), AuthScope.ANY_SCHEME);
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword());

View File

@ -516,30 +516,16 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager,
@Override
public long getUsedBytes(StoragePoolVO pool) {
long usedBytes = 0;
DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName());
DataStoreDriver storeDriver = storeProvider.getDataStoreDriver();
List<VolumeVO> volumes = _volumeDao.findByPoolId(pool.getId(), null);
if (storeDriver instanceof PrimaryDataStoreDriver) {
PrimaryDataStoreDriver primaryStoreDriver = (PrimaryDataStoreDriver)storeDriver;
if (volumes != null && volumes.size() > 0) {
DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName());
DataStoreDriver storeDriver = storeProvider.getDataStoreDriver();
PrimaryDataStoreDriver primaryStoreDriver = null;
if (storeDriver instanceof PrimaryDataStoreDriver) {
primaryStoreDriver = (PrimaryDataStoreDriver)storeDriver;
}
for (VolumeVO volume : volumes) {
if (primaryStoreDriver != null) {
usedBytes += primaryStoreDriver.getVolumeSizeIncludingHypervisorSnapshotReserve(volume, pool);
}
else {
usedBytes += volume.getSize();
}
}
return primaryStoreDriver.getUsedBytes(pool);
}
return usedBytes;
throw new CloudRuntimeException("Storage driver in CapacityManagerImpl.getUsedBytes(StoragePoolVO) is not a PrimaryDataStoreDriver.");
}
@Override
@ -548,7 +534,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager,
List<VolumeVO> volumes = _volumeDao.findByPoolId(pool.getId(), null);
if (volumes != null && volumes.size() > 0) {
if (volumes != null) {
for (VolumeVO volume : volumes) {
usedIops += volume.getMinIops() != null ? volume.getMinIops() : 0;
}

View File

@ -1578,7 +1578,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
}
}
if (volume.getState() != Volume.State.Ready) {
totalAskingSize = totalAskingSize + getVolumeSizeIncludingHvSsReserve(volume, pool);
totalAskingSize = totalAskingSize + getVolumeSizeIncludingHypervisorSnapshotReserve(volume, pool);
}
}
@ -1623,7 +1623,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
return true;
}
private long getVolumeSizeIncludingHvSsReserve(Volume volume, StoragePool pool) {
private long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) {
DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName());
DataStoreDriver storeDriver = storeProvider.getDataStoreDriver();