mirror of https://github.com/apache/cloudstack.git
Merge forward branch '4.11' PR #2629
Fix primary storage count when deleting volumes (#2629)
This commit is contained in:
commit
15eddf3dd6
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
package com.cloud.storage;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
|
||||
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
|
||||
import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
|
||||
|
|
@ -26,13 +28,10 @@ import org.apache.cloudstack.api.command.user.volume.GetUploadParamsForVolumeCmd
|
|||
import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd;
|
||||
import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
|
||||
import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd;
|
||||
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.user.Account;
|
||||
import org.apache.cloudstack.api.response.GetUploadParamsResponse;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
public interface VolumeApiService {
|
||||
/**
|
||||
|
|
@ -72,17 +71,18 @@ public interface VolumeApiService {
|
|||
*
|
||||
* @return Volume object
|
||||
*/
|
||||
Volume uploadVolume(UploadVolumeCmd cmd) throws ResourceAllocationException;
|
||||
Volume uploadVolume(UploadVolumeCmd cmd) throws ResourceAllocationException;
|
||||
|
||||
GetUploadParamsResponse uploadVolume(GetUploadParamsForVolumeCmd cmd) throws ResourceAllocationException, MalformedURLException;
|
||||
|
||||
boolean deleteVolume(long volumeId, Account caller) throws ConcurrentOperationException;
|
||||
boolean deleteVolume(long volumeId, Account caller);
|
||||
|
||||
Volume attachVolumeToVM(AttachVolumeCmd command);
|
||||
|
||||
Volume detachVolumeFromVM(DetachVolumeCmd cmd);
|
||||
|
||||
Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup) throws ResourceAllocationException;
|
||||
Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup)
|
||||
throws ResourceAllocationException;
|
||||
|
||||
Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType) throws ResourceAllocationException;
|
||||
|
||||
|
|
@ -92,10 +92,8 @@ public interface VolumeApiService {
|
|||
* Extracts the volume to a particular location.
|
||||
*
|
||||
* @param cmd
|
||||
* the command specifying url (where the volume needs to be extracted to), zoneId (zone where the volume
|
||||
* exists),
|
||||
* the command specifying url (where the volume needs to be extracted to), zoneId (zone where the volume exists),
|
||||
* id (the id of the volume)
|
||||
*
|
||||
*/
|
||||
String extractVolume(ExtractVolumeCmd cmd);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import com.cloud.storage.Volume;
|
|||
import com.cloud.vm.VirtualMachine;
|
||||
|
||||
public interface VolumeInfo extends DataObject, Volume {
|
||||
|
||||
boolean isAttachedVM();
|
||||
|
||||
void addPayload(Object data);
|
||||
|
|
@ -36,6 +37,7 @@ public interface VolumeInfo extends DataObject, Volume {
|
|||
Long getLastPoolId();
|
||||
|
||||
String getAttachedVmName();
|
||||
|
||||
VirtualMachine getAttachedVM();
|
||||
|
||||
void processEventOnly(ObjectInDataStoreStateMachine.Event event);
|
||||
|
|
|
|||
|
|
@ -20,16 +20,15 @@ package org.apache.cloudstack.engine.subsystem.api.storage;
|
|||
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity;
|
||||
import org.apache.cloudstack.framework.async.AsyncCallFuture;
|
||||
import org.apache.cloudstack.storage.command.CommandResult;
|
||||
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
public interface VolumeService {
|
||||
class VolumeApiResult extends CommandResult {
|
||||
|
|
@ -54,38 +53,24 @@ public interface VolumeService {
|
|||
/**
|
||||
* Creates the volume based on the given criteria
|
||||
*
|
||||
* @param cmd
|
||||
*
|
||||
* @return the volume object
|
||||
*/
|
||||
AsyncCallFuture<VolumeApiResult> createVolumeAsync(VolumeInfo volume, DataStore store);
|
||||
|
||||
/**
|
||||
* Delete volume
|
||||
*
|
||||
* @param volumeId
|
||||
* @return
|
||||
* @throws ConcurrentOperationException
|
||||
*/
|
||||
AsyncCallFuture<VolumeApiResult> expungeVolumeAsync(VolumeInfo volume);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
boolean cloneVolume(long volumeId, long baseVolId);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
AsyncCallFuture<VolumeApiResult> createVolumeFromSnapshot(VolumeInfo volume, DataStore store, SnapshotInfo snapshot);
|
||||
|
||||
VolumeEntity getVolumeEntity(long volumeId);
|
||||
|
||||
AsyncCallFuture<VolumeApiResult> createManagedStorageVolumeFromTemplateAsync(VolumeInfo volumeInfo, long destDataStoreId,
|
||||
TemplateInfo srcTemplateInfo, long destHostId);
|
||||
AsyncCallFuture<VolumeApiResult> createManagedStorageVolumeFromTemplateAsync(VolumeInfo volumeInfo, long destDataStoreId, TemplateInfo srcTemplateInfo, long destHostId);
|
||||
|
||||
AsyncCallFuture<VolumeApiResult> createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId,
|
||||
TemplateInfo template);
|
||||
AsyncCallFuture<VolumeApiResult> createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId, TemplateInfo template);
|
||||
|
||||
AsyncCallFuture<VolumeApiResult> copyVolume(VolumeInfo srcVolume, DataStore destStore);
|
||||
|
||||
|
|
@ -93,11 +78,11 @@ public interface VolumeService {
|
|||
|
||||
AsyncCallFuture<CommandResult> migrateVolumes(Map<VolumeInfo, DataStore> volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost);
|
||||
|
||||
boolean destroyVolume(long volumeId) throws ConcurrentOperationException;
|
||||
void destroyVolume(long volumeId);
|
||||
|
||||
AsyncCallFuture<VolumeApiResult> registerVolume(VolumeInfo volume, DataStore store);
|
||||
|
||||
public Pair<EndPoint,DataObject> registerVolumeForPostUpload(VolumeInfo volume, DataStore store);
|
||||
public Pair<EndPoint, DataObject> registerVolumeForPostUpload(VolumeInfo volume, DataStore store);
|
||||
|
||||
AsyncCallFuture<VolumeApiResult> resize(VolumeInfo volume);
|
||||
|
||||
|
|
@ -108,5 +93,4 @@ public interface VolumeService {
|
|||
SnapshotInfo takeSnapshot(VolumeInfo volume);
|
||||
|
||||
VolumeInfo updateHypervisorSnapshotReserveForVolume(DiskOffering diskOffering, long volumeId, HypervisorType hyperType);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -85,7 +85,6 @@ import com.cloud.configuration.Resource.ResourceType;
|
|||
import com.cloud.dc.dao.ClusterDao;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.event.UsageEventUtils;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
|
|
@ -110,6 +109,7 @@ import com.cloud.storage.Volume.State;
|
|||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.dao.VMTemplatePoolDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.storage.dao.VolumeDetailsDao;
|
||||
import com.cloud.storage.snapshot.SnapshotManager;
|
||||
import com.cloud.storage.template.TemplateProp;
|
||||
import com.cloud.user.AccountManager;
|
||||
|
|
@ -119,8 +119,6 @@ import com.cloud.utils.Pair;
|
|||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.db.GlobalLock;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.storage.dao.VolumeDetailsDao;
|
||||
|
||||
|
||||
@Component
|
||||
public class VolumeServiceImpl implements VolumeService {
|
||||
|
|
@ -420,8 +418,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
if (!supportsStorageSystemSnapshots) {
|
||||
_snapshotStoreDao.remove(snapStoreVo.getId());
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
_snapshotStoreDao.remove(snapStoreVo.getId());
|
||||
}
|
||||
}
|
||||
|
|
@ -453,8 +450,8 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
private final TemplateInfo _templateInfo;
|
||||
private final AsyncCallFuture<VolumeApiResult> _future;
|
||||
|
||||
public ManagedCreateBaseImageContext(AsyncCompletionCallback<T> callback, VolumeInfo volumeInfo,
|
||||
PrimaryDataStore primaryDatastore, TemplateInfo templateInfo, AsyncCallFuture<VolumeApiResult> future) {
|
||||
public ManagedCreateBaseImageContext(AsyncCompletionCallback<T> callback, VolumeInfo volumeInfo, PrimaryDataStore primaryDatastore, TemplateInfo templateInfo,
|
||||
AsyncCallFuture<VolumeApiResult> future) {
|
||||
super(callback);
|
||||
|
||||
_volumeInfo = volumeInfo;
|
||||
|
|
@ -488,8 +485,8 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
final DataObject destObj;
|
||||
long templatePoolId;
|
||||
|
||||
public CreateBaseImageContext(AsyncCompletionCallback<T> callback, VolumeInfo volume, PrimaryDataStore datastore, TemplateInfo srcTemplate,
|
||||
AsyncCallFuture<VolumeApiResult> future, DataObject destObj, long templatePoolId) {
|
||||
public CreateBaseImageContext(AsyncCompletionCallback<T> callback, VolumeInfo volume, PrimaryDataStore datastore, TemplateInfo srcTemplate, AsyncCallFuture<VolumeApiResult> future,
|
||||
DataObject destObj, long templatePoolId) {
|
||||
super(callback);
|
||||
this.volume = volume;
|
||||
this.dataStore = datastore;
|
||||
|
|
@ -549,13 +546,11 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
throw new CloudRuntimeException("Failed to find template " + template.getUniqueName() + " in storage pool " + dataStore.getId());
|
||||
} else {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Found template " + template.getUniqueName() + " in storage pool " + dataStore.getId() + " with VMTemplateStoragePool id: " +
|
||||
templatePoolRef.getId());
|
||||
s_logger.debug("Found template " + template.getUniqueName() + " in storage pool " + dataStore.getId() + " with VMTemplateStoragePool id: " + templatePoolRef.getId());
|
||||
}
|
||||
}
|
||||
long templatePoolRefId = templatePoolRef.getId();
|
||||
CreateBaseImageContext<CreateCmdResult> context =
|
||||
new CreateBaseImageContext<CreateCmdResult>(null, volume, dataStore, template, future, templateOnPrimaryStoreObj, templatePoolRefId);
|
||||
CreateBaseImageContext<CreateCmdResult> context = new CreateBaseImageContext<CreateCmdResult>(null, volume, dataStore, template, future, templateOnPrimaryStoreObj, templatePoolRefId);
|
||||
AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
|
||||
caller.setCallback(caller.getTarget().copyBaseImageCallback(null, null)).setContext(context);
|
||||
|
||||
|
|
@ -571,8 +566,8 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
}
|
||||
templatePoolRef = _tmpltPoolDao.findByPoolTemplate(dataStore.getId(), template.getId());
|
||||
if (templatePoolRef != null && templatePoolRef.getState() == ObjectInDataStoreStateMachine.State.Ready) {
|
||||
s_logger.info("Unable to acquire lock on VMTemplateStoragePool " + templatePoolRefId + ", But Template " + template.getUniqueName() +
|
||||
" is already copied to primary storage, skip copying");
|
||||
s_logger.info(
|
||||
"Unable to acquire lock on VMTemplateStoragePool " + templatePoolRefId + ", But Template " + template.getUniqueName() + " is already copied to primary storage, skip copying");
|
||||
createVolumeFromBaseImageAsync(volume, templateOnPrimaryStoreObj, dataStore, future);
|
||||
return;
|
||||
}
|
||||
|
|
@ -606,8 +601,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
return;
|
||||
}
|
||||
|
||||
protected Void managedCopyBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback,
|
||||
ManagedCreateBaseImageContext<VolumeApiResult> context) {
|
||||
protected Void managedCopyBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, ManagedCreateBaseImageContext<VolumeApiResult> context) {
|
||||
CopyCommandResult result = callback.getResult();
|
||||
VolumeInfo volumeInfo = context.getVolumeInfo();
|
||||
VolumeApiResult res = new VolumeApiResult(volumeInfo);
|
||||
|
|
@ -626,8 +620,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
}
|
||||
|
||||
volDao.update(volume.getId(), volume);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
volumeInfo.processEvent(Event.DestroyRequested);
|
||||
|
||||
res.setResult(result.getResult());
|
||||
|
|
@ -652,8 +645,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
if (result.isSuccess()) {
|
||||
((TemplateObject)templateOnPrimaryStoreObj).setInstallPath(result.getPath());
|
||||
templateOnPrimaryStoreObj.processEvent(Event.OperationSuccessed, result.getAnswer());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
templateOnPrimaryStoreObj.processEvent(Event.OperationFailed);
|
||||
}
|
||||
|
||||
|
|
@ -673,8 +665,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
|
||||
if (result.isSuccess()) {
|
||||
templateOnPrimaryStoreObj.processEvent(Event.OperationSuccessed, result.getAnswer());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
templateOnPrimaryStoreObj.processEvent(Event.OperationFailed);
|
||||
}
|
||||
|
||||
|
|
@ -708,8 +699,8 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
private final DataObject templateOnStore;
|
||||
private final SnapshotInfo snapshot;
|
||||
|
||||
public CreateVolumeFromBaseImageContext(AsyncCompletionCallback<T> callback, DataObject vo, DataStore primaryStore, DataObject templateOnStore,
|
||||
AsyncCallFuture<VolumeApiResult> future, SnapshotInfo snapshot) {
|
||||
public CreateVolumeFromBaseImageContext(AsyncCompletionCallback<T> callback, DataObject vo, DataStore primaryStore, DataObject templateOnStore, AsyncCallFuture<VolumeApiResult> future,
|
||||
SnapshotInfo snapshot) {
|
||||
super(callback);
|
||||
this.vo = vo;
|
||||
this.future = future;
|
||||
|
|
@ -727,8 +718,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
DataObject volumeOnPrimaryStorage = pd.create(volume);
|
||||
volumeOnPrimaryStorage.processEvent(Event.CreateOnlyRequested);
|
||||
|
||||
CreateVolumeFromBaseImageContext<VolumeApiResult> context =
|
||||
new CreateVolumeFromBaseImageContext<VolumeApiResult>(null, volumeOnPrimaryStorage, pd, templateOnPrimaryStore, future, null);
|
||||
CreateVolumeFromBaseImageContext<VolumeApiResult> context = new CreateVolumeFromBaseImageContext<VolumeApiResult>(null, volumeOnPrimaryStorage, pd, templateOnPrimaryStore, future, null);
|
||||
AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
|
||||
caller.setCallback(caller.getTarget().createVolumeFromBaseImageCallBack(null, null));
|
||||
caller.setContext(context);
|
||||
|
|
@ -738,8 +728,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
}
|
||||
|
||||
@DB
|
||||
protected Void createVolumeFromBaseImageCallBack(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback,
|
||||
CreateVolumeFromBaseImageContext<VolumeApiResult> context) {
|
||||
protected Void createVolumeFromBaseImageCallBack(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CreateVolumeFromBaseImageContext<VolumeApiResult> context) {
|
||||
DataObject vo = context.vo;
|
||||
DataObject tmplOnPrimary = context.templateOnStore;
|
||||
CopyCommandResult result = callback.getResult();
|
||||
|
|
@ -771,7 +760,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
|
||||
_tmpltPoolDao.update(templatePoolRefId, templatePoolRef);
|
||||
}
|
||||
}finally {
|
||||
} finally {
|
||||
_tmpltPoolDao.releaseFromLockTable(templatePoolRefId);
|
||||
}
|
||||
}
|
||||
|
|
@ -836,10 +825,9 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
VolumeApiResult result = createTemplateFuture.get();
|
||||
|
||||
if (result.isFailed()) {
|
||||
String errMesg = result.getResult();
|
||||
String errMesg = result.getResult();
|
||||
|
||||
throw new CloudRuntimeException("Unable to create template " + templateOnPrimary.getId() +
|
||||
" on primary storage " + destPrimaryDataStore.getId() + ":" + errMesg);
|
||||
throw new CloudRuntimeException("Unable to create template " + templateOnPrimary.getId() + " on primary storage " + destPrimaryDataStore.getId() + ":" + errMesg);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
s_logger.debug("Failed to create template volume on storage", e);
|
||||
|
|
@ -847,8 +835,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
templateOnPrimary.processEvent(Event.OperationFailed);
|
||||
|
||||
throw new CloudRuntimeException(e.getMessage());
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
_tmpltPoolDao.releaseFromLockTable(templatePoolRefId);
|
||||
}
|
||||
|
||||
|
|
@ -866,9 +853,8 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
* @param destPrimaryDataStore The managed primary storage
|
||||
* @param destHost The host that we will use for the copy
|
||||
*/
|
||||
private void copyTemplateToManagedTemplateVolume(TemplateInfo srcTemplateInfo, TemplateInfo templateOnPrimary, VMTemplateStoragePoolVO templatePoolRef,
|
||||
PrimaryDataStore destPrimaryDataStore, Host destHost)
|
||||
{
|
||||
private void copyTemplateToManagedTemplateVolume(TemplateInfo srcTemplateInfo, TemplateInfo templateOnPrimary, VMTemplateStoragePoolVO templatePoolRef, PrimaryDataStore destPrimaryDataStore,
|
||||
Host destHost) {
|
||||
AsyncCallFuture<VolumeApiResult> copyTemplateFuture = new AsyncCallFuture<>();
|
||||
int storagePoolMaxWaitSeconds = NumbersUtil.parseInt(configDao.getValue(Config.StoragePoolMaxWaitSeconds.key()), 3600);
|
||||
long templatePoolRefId = templatePoolRef.getId();
|
||||
|
|
@ -889,11 +875,9 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
}
|
||||
|
||||
try {
|
||||
// copy the template from sec storage to the created volume
|
||||
CreateBaseImageContext<CreateCmdResult> copyContext = new CreateBaseImageContext<>(
|
||||
null, null, destPrimaryDataStore, srcTemplateInfo,
|
||||
copyTemplateFuture, templateOnPrimary, templatePoolRefId
|
||||
);
|
||||
// copy the template from sec storage to the created volume
|
||||
CreateBaseImageContext<CreateCmdResult> copyContext = new CreateBaseImageContext<>(null, null, destPrimaryDataStore, srcTemplateInfo, copyTemplateFuture, templateOnPrimary,
|
||||
templatePoolRefId);
|
||||
|
||||
AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> copyCaller = AsyncCallbackDispatcher.create(this);
|
||||
copyCaller.setCallback(copyCaller.getTarget().copyManagedTemplateCallback(null, null)).setContext(copyContext);
|
||||
|
|
@ -930,8 +914,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
motionSrv.copyAsync(srcTemplateInfo, templateOnPrimary, destHost, copyCaller);
|
||||
|
||||
result = copyTemplateFuture.get();
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
revokeAccess(templateOnPrimary, destHost, destPrimaryDataStore);
|
||||
|
||||
if (HypervisorType.VMware.equals(destHost.getHypervisorType())) {
|
||||
|
|
@ -946,21 +929,18 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
}
|
||||
|
||||
if (result.isFailed()) {
|
||||
throw new CloudRuntimeException("Failed to copy template " + templateOnPrimary.getId() +
|
||||
" to primary storage " + destPrimaryDataStore.getId() + ": " + result.getResult());
|
||||
throw new CloudRuntimeException("Failed to copy template " + templateOnPrimary.getId() + " to primary storage " + destPrimaryDataStore.getId() + ": " + result.getResult());
|
||||
// XXX: I find it is useful to destroy the volume on primary storage instead of another thread trying the copy again because I've seen
|
||||
// something weird happens to the volume (XenServer creates an SR, but the VDI copy can fail).
|
||||
// For now, I just retry the copy.
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
} catch (Throwable e) {
|
||||
s_logger.debug("Failed to create a template on primary storage", e);
|
||||
|
||||
templateOnPrimary.processEvent(Event.OperationFailed);
|
||||
|
||||
throw new CloudRuntimeException(e.getMessage());
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
_tmpltPoolDao.releaseFromLockTable(templatePoolRefId);
|
||||
}
|
||||
}
|
||||
|
|
@ -983,8 +963,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
String msg = "Unable to get an answer to the modify targets command";
|
||||
|
||||
s_logger.warn(msg);
|
||||
}
|
||||
else if (!answer.getResult()) {
|
||||
} else if (!answer.getResult()) {
|
||||
String msg = "Unable to modify target on the following host: " + hostId;
|
||||
|
||||
s_logger.warn(msg);
|
||||
|
|
@ -999,8 +978,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
* @param destPrimaryDataStore Primary storage of the volume
|
||||
* @param future For async
|
||||
*/
|
||||
private void createManagedVolumeCloneTemplateAsync(VolumeInfo volumeInfo, TemplateInfo templateOnPrimary, PrimaryDataStore destPrimaryDataStore,
|
||||
AsyncCallFuture<VolumeApiResult> future) {
|
||||
private void createManagedVolumeCloneTemplateAsync(VolumeInfo volumeInfo, TemplateInfo templateOnPrimary, PrimaryDataStore destPrimaryDataStore, AsyncCallFuture<VolumeApiResult> future) {
|
||||
VMTemplateStoragePoolVO templatePoolRef = _tmpltPoolDao.findByPoolTemplate(destPrimaryDataStore.getId(), templateOnPrimary.getId());
|
||||
|
||||
if (templatePoolRef == null) {
|
||||
|
|
@ -1015,8 +993,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
try {
|
||||
volumeInfo.processEvent(Event.CreateOnlyRequested);
|
||||
|
||||
CreateVolumeFromBaseImageContext<VolumeApiResult> context =
|
||||
new CreateVolumeFromBaseImageContext<>(null, volumeInfo, destPrimaryDataStore, templateOnPrimary, future, null);
|
||||
CreateVolumeFromBaseImageContext<VolumeApiResult> context = new CreateVolumeFromBaseImageContext<>(null, volumeInfo, destPrimaryDataStore, templateOnPrimary, future, null);
|
||||
|
||||
AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
|
||||
|
||||
|
|
@ -1033,8 +1010,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
}
|
||||
}
|
||||
|
||||
private void createManagedVolumeCopyTemplateAsync(VolumeInfo volumeInfo, PrimaryDataStore primaryDataStore, TemplateInfo srcTemplateInfo, Host destHost,
|
||||
AsyncCallFuture<VolumeApiResult> future) {
|
||||
private void createManagedVolumeCopyTemplateAsync(VolumeInfo volumeInfo, PrimaryDataStore primaryDataStore, TemplateInfo srcTemplateInfo, Host destHost, AsyncCallFuture<VolumeApiResult> future) {
|
||||
try {
|
||||
// Create a volume on managed storage.
|
||||
|
||||
|
|
@ -1050,8 +1026,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
// Refresh the volume info from the DB.
|
||||
volumeInfo = volFactory.getVolume(volumeInfo.getId(), primaryDataStore);
|
||||
|
||||
ManagedCreateBaseImageContext<CreateCmdResult> context = new ManagedCreateBaseImageContext<CreateCmdResult>(null, volumeInfo,
|
||||
primaryDataStore, srcTemplateInfo, future);
|
||||
ManagedCreateBaseImageContext<CreateCmdResult> context = new ManagedCreateBaseImageContext<CreateCmdResult>(null, volumeInfo, primaryDataStore, srcTemplateInfo, future);
|
||||
AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
|
||||
|
||||
caller.setCallback(caller.getTarget().managedCopyBaseImageCallback(null, null)).setContext(context);
|
||||
|
|
@ -1081,8 +1056,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
|
||||
try {
|
||||
motionSrv.copyAsync(srcTemplateInfo, destTemplateInfo, destHost, caller);
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
revokeAccess(volumeInfo, destHost, primaryDataStore);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
|
|
@ -1098,8 +1072,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
if (expungeVolumeResult.isFailed()) {
|
||||
errMsg += " : Failed to expunge a volume that was created";
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
} catch (Exception ex) {
|
||||
errMsg += " : " + ex.getMessage();
|
||||
}
|
||||
|
||||
|
|
@ -1112,8 +1085,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public AsyncCallFuture<VolumeApiResult> createManagedStorageVolumeFromTemplateAsync(VolumeInfo volumeInfo, long destDataStoreId,
|
||||
TemplateInfo srcTemplateInfo, long destHostId) {
|
||||
public AsyncCallFuture<VolumeApiResult> createManagedStorageVolumeFromTemplateAsync(VolumeInfo volumeInfo, long destDataStoreId, TemplateInfo srcTemplateInfo, long destHostId) {
|
||||
PrimaryDataStore destPrimaryDataStore = dataStoreMgr.getPrimaryDataStore(destDataStoreId);
|
||||
Host destHost = _hostDao.findById(destHostId);
|
||||
|
||||
|
|
@ -1121,9 +1093,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
throw new CloudRuntimeException("Destination host should not be null.");
|
||||
}
|
||||
|
||||
Boolean storageCanCloneVolume = new Boolean(
|
||||
destPrimaryDataStore.getDriver().getCapabilities().get(DataStoreCapabilities.CAN_CREATE_VOLUME_FROM_VOLUME.toString())
|
||||
);
|
||||
Boolean storageCanCloneVolume = new Boolean(destPrimaryDataStore.getDriver().getCapabilities().get(DataStoreCapabilities.CAN_CREATE_VOLUME_FROM_VOLUME.toString()));
|
||||
|
||||
boolean computeSupportsVolumeClone = computeSupportsVolumeClone(destHost.getDataCenterId(), destHost.getHypervisorType());
|
||||
|
||||
|
|
@ -1146,10 +1116,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
VMTemplateStoragePoolVO templatePoolRef = _tmpltPoolDao.findByPoolTemplate(destPrimaryDataStore.getId(), templateOnPrimary.getId());
|
||||
|
||||
if (templatePoolRef == null) {
|
||||
throw new CloudRuntimeException("Failed to find template " +
|
||||
srcTemplateInfo.getUniqueName() + " in storage pool " +
|
||||
destPrimaryDataStore.getId()
|
||||
);
|
||||
throw new CloudRuntimeException("Failed to find template " + srcTemplateInfo.getUniqueName() + " in storage pool " + destPrimaryDataStore.getId());
|
||||
}
|
||||
|
||||
if (templatePoolRef.getDownloadState() == Status.NOT_DOWNLOADED) {
|
||||
|
|
@ -1190,8 +1157,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
|
||||
Collections.shuffle(clusters, new Random(System.nanoTime()));
|
||||
|
||||
clusters:
|
||||
for (Cluster cluster : clusters) {
|
||||
clusters: for (Cluster cluster : clusters) {
|
||||
if (cluster.getAllocationState() == AllocationState.Enabled) {
|
||||
List<HostVO> hosts = _hostDao.findByClusterId(cluster.getId());
|
||||
|
||||
|
|
@ -1203,13 +1169,11 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
if (computeClusterMustSupportResign) {
|
||||
if (clusterDao.getSupportsResigning(cluster.getId())) {
|
||||
return host;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// no other host in the cluster in question should be able to satisfy our requirements here, so move on to the next cluster
|
||||
continue clusters;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return host;
|
||||
}
|
||||
}
|
||||
|
|
@ -1237,17 +1201,15 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public boolean destroyVolume(long volumeId) throws ConcurrentOperationException {
|
||||
@Override
|
||||
public void destroyVolume(long volumeId) {
|
||||
// mark volume entry in volumes table as destroy state
|
||||
VolumeInfo vol = volFactory.getVolume(volumeId);
|
||||
vol.stateTransit(Volume.Event.DestroyRequested);
|
||||
snapshotMgr.deletePoliciesForVolume(volumeId);
|
||||
|
||||
vol.stateTransit(Volume.Event.OperationSucceeded);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -1259,8 +1221,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
volumeOnStore.processEvent(Event.CreateOnlyRequested);
|
||||
_volumeDetailsDao.addDetail(volume.getId(), SNAPSHOT_ID, Long.toString(snapshot.getId()), false);
|
||||
|
||||
CreateVolumeFromBaseImageContext<VolumeApiResult> context =
|
||||
new CreateVolumeFromBaseImageContext<VolumeApiResult>(null, volume, store, volumeOnStore, future, snapshot);
|
||||
CreateVolumeFromBaseImageContext<VolumeApiResult> context = new CreateVolumeFromBaseImageContext<VolumeApiResult>(null, volume, store, volumeOnStore, future, snapshot);
|
||||
AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
|
||||
caller.setCallback(caller.getTarget().createVolumeFromSnapshotCallback(null, null)).setContext(context);
|
||||
motionSrv.copyAsync(snapshot, volumeOnStore, caller);
|
||||
|
|
@ -1274,8 +1235,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
return future;
|
||||
}
|
||||
|
||||
protected Void createVolumeFromSnapshotCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback,
|
||||
CreateVolumeFromBaseImageContext<VolumeApiResult> context) {
|
||||
protected Void createVolumeFromSnapshotCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CreateVolumeFromBaseImageContext<VolumeApiResult> context) {
|
||||
CopyCommandResult result = callback.getResult();
|
||||
VolumeInfo volume = (VolumeInfo)context.templateOnStore;
|
||||
SnapshotInfo snapshot = context.snapshot;
|
||||
|
|
@ -1332,8 +1292,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
final VolumeInfo destVolume;
|
||||
final AsyncCallFuture<VolumeApiResult> future;
|
||||
|
||||
public CopyVolumeContext(AsyncCompletionCallback<T> callback, AsyncCallFuture<VolumeApiResult> future, VolumeInfo srcVolume, VolumeInfo destVolume,
|
||||
DataStore destStore) {
|
||||
public CopyVolumeContext(AsyncCompletionCallback<T> callback, AsyncCallFuture<VolumeApiResult> future, VolumeInfo srcVolume, VolumeInfo destVolume, DataStore destStore) {
|
||||
super(callback);
|
||||
this.srcVolume = srcVolume;
|
||||
this.destVolume = destVolume;
|
||||
|
|
@ -1370,8 +1329,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
}
|
||||
}
|
||||
|
||||
protected Void
|
||||
copyVolumeFromImageToPrimaryCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CopyVolumeContext<VolumeApiResult> context) {
|
||||
protected Void copyVolumeFromImageToPrimaryCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CopyVolumeContext<VolumeApiResult> context) {
|
||||
VolumeInfo srcVolume = context.srcVolume;
|
||||
VolumeInfo destVolume = context.destVolume;
|
||||
CopyCommandResult result = callback.getResult();
|
||||
|
|
@ -1424,8 +1382,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
}
|
||||
}
|
||||
|
||||
protected Void
|
||||
copyVolumeFromPrimaryToImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CopyVolumeContext<VolumeApiResult> context) {
|
||||
protected Void copyVolumeFromPrimaryToImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CopyVolumeContext<VolumeApiResult> context) {
|
||||
VolumeInfo srcVolume = context.srcVolume;
|
||||
VolumeInfo destVolume = context.destVolume;
|
||||
CopyCommandResult result = callback.getResult();
|
||||
|
|
@ -1542,8 +1499,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
/**
|
||||
* @param callback
|
||||
*/
|
||||
public MigrateVolumeContext(AsyncCompletionCallback<T> callback, AsyncCallFuture<VolumeApiResult> future, VolumeInfo srcVolume, VolumeInfo destVolume,
|
||||
DataStore destStore) {
|
||||
public MigrateVolumeContext(AsyncCompletionCallback<T> callback, AsyncCallFuture<VolumeApiResult> future, VolumeInfo srcVolume, VolumeInfo destVolume, DataStore destStore) {
|
||||
super(callback);
|
||||
this.srcVolume = srcVolume;
|
||||
this.destVolume = destVolume;
|
||||
|
|
@ -1654,8 +1610,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
return future;
|
||||
}
|
||||
|
||||
protected Void
|
||||
migrateVmWithVolumesCallBack(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, MigrateVmWithVolumesContext<CommandResult> context) {
|
||||
protected Void migrateVmWithVolumesCallBack(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, MigrateVmWithVolumesContext<CommandResult> context) {
|
||||
Map<VolumeInfo, DataStore> volumeToPool = context.volumeToPool;
|
||||
CopyCommandResult result = callback.getResult();
|
||||
AsyncCallFuture<CommandResult> future = context.future;
|
||||
|
|
@ -1715,7 +1670,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Pair<EndPoint,DataObject> registerVolumeForPostUpload(VolumeInfo volume, DataStore store) {
|
||||
public Pair<EndPoint, DataObject> registerVolumeForPostUpload(VolumeInfo volume, DataStore store) {
|
||||
|
||||
EndPoint ep = _epSelector.select(store);
|
||||
if (ep == null) {
|
||||
|
|
@ -1724,7 +1679,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
throw new CloudRuntimeException(errorMessage);
|
||||
}
|
||||
DataObject volumeOnStore = store.create(volume);
|
||||
return new Pair<>(ep,volumeOnStore);
|
||||
return new Pair<>(ep, volumeOnStore);
|
||||
}
|
||||
|
||||
protected Void registerVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> callback, CreateVolumeContext<VolumeApiResult> context) {
|
||||
|
|
@ -1751,21 +1706,20 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
if (volStore != null) {
|
||||
physicalSize = volStore.getPhysicalSize();
|
||||
} else {
|
||||
s_logger.warn("No entry found in volume_store_ref for volume id: " + vo.getId() + " and image store id: " + ds.getId() +
|
||||
" at the end of uploading volume!");
|
||||
s_logger.warn("No entry found in volume_store_ref for volume id: " + vo.getId() + " and image store id: " + ds.getId() + " at the end of uploading volume!");
|
||||
}
|
||||
Scope dsScope = ds.getScope();
|
||||
if (dsScope.getScopeType() == ScopeType.ZONE) {
|
||||
if (dsScope.getScopeId() != null) {
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_UPLOAD, vo.getAccountId(), dsScope.getScopeId(), vo.getId(), vo.getName(), null,
|
||||
null, physicalSize, vo.getSize(), Volume.class.getName(), vo.getUuid());
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_UPLOAD, vo.getAccountId(), dsScope.getScopeId(), vo.getId(), vo.getName(), null, null, physicalSize, vo.getSize(),
|
||||
Volume.class.getName(), vo.getUuid());
|
||||
} else {
|
||||
s_logger.warn("Zone scope image store " + ds.getId() + " has a null scope id");
|
||||
}
|
||||
} else if (dsScope.getScopeType() == ScopeType.REGION) {
|
||||
// publish usage event for region-wide image store using a -1 zoneId for 4.2, need to revisit post-4.2
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_UPLOAD, vo.getAccountId(), -1, vo.getId(), vo.getName(), null, null, physicalSize,
|
||||
vo.getSize(), Volume.class.getName(), vo.getUuid());
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_UPLOAD, vo.getAccountId(), -1, vo.getId(), vo.getName(), null, null, physicalSize, vo.getSize(),
|
||||
Volume.class.getName(), vo.getUuid());
|
||||
|
||||
_resourceLimitMgr.incrementResourceCount(vo.getAccountId(), ResourceType.secondary_storage, vo.getSize());
|
||||
}
|
||||
|
|
@ -1829,8 +1783,8 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
if (ep != null) {
|
||||
VolumeVO volume = volDao.findById(volumeId);
|
||||
PrimaryDataStore primaryDataStore = this.dataStoreMgr.getPrimaryDataStore(volume.getPoolId());
|
||||
ResizeVolumeCommand resizeCmd = new ResizeVolumeCommand(volume.getPath(), new StorageFilerTO(primaryDataStore),
|
||||
volume.getSize(), newSize, true, instanceName, primaryDataStore.isManaged(), volume.get_iScsiName());
|
||||
ResizeVolumeCommand resizeCmd = new ResizeVolumeCommand(volume.getPath(), new StorageFilerTO(primaryDataStore), volume.getSize(), newSize, true, instanceName,
|
||||
primaryDataStore.isManaged(), volume.get_iScsiName());
|
||||
|
||||
answer = ep.sendMessage(resizeCmd);
|
||||
} else {
|
||||
|
|
@ -1903,8 +1857,8 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
for (VolumeDataStoreVO volumeStore : dbVolumes) {
|
||||
VolumeVO volume = volDao.findById(volumeStore.getVolumeId());
|
||||
if (volume == null) {
|
||||
s_logger.warn("Volume_store_ref table shows that volume " + volumeStore.getVolumeId() + " is on image store " + storeId +
|
||||
", but the volume is not found in volumes table, potentially some bugs in deleteVolume, so we just treat this volume to be deleted and mark it as destroyed");
|
||||
s_logger.warn("Volume_store_ref table shows that volume " + volumeStore.getVolumeId() + " is on image store " + storeId
|
||||
+ ", but the volume is not found in volumes table, potentially some bugs in deleteVolume, so we just treat this volume to be deleted and mark it as destroyed");
|
||||
volumeStore.setDestroyed(true);
|
||||
_volumeStoreDao.update(volumeStore.getId(), volumeStore);
|
||||
continue;
|
||||
|
|
@ -1929,7 +1883,8 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
VolumeObject volObj = (VolumeObject)volFactory.getVolume(volume.getId());
|
||||
volObj.processEvent(Event.OperationFailed);
|
||||
} else if (volumeStore.getDownloadUrl() == null) {
|
||||
msg = "Volume (" + volume.getUuid() + ") with install path " + volInfo.getInstallPath() + " is corrupted, please check in image store: " + volumeStore.getDataStoreId();
|
||||
msg = "Volume (" + volume.getUuid() + ") with install path " + volInfo.getInstallPath() + " is corrupted, please check in image store: "
|
||||
+ volumeStore.getDataStoreId();
|
||||
s_logger.warn(msg);
|
||||
} else {
|
||||
s_logger.info("Removing volume_store_ref entry for corrupted volume " + volume.getName());
|
||||
|
|
@ -1959,8 +1914,8 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
|
||||
if (volInfo.getSize() > 0) {
|
||||
try {
|
||||
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()),
|
||||
com.cloud.configuration.Resource.ResourceType.secondary_storage, volInfo.getSize() - volInfo.getPhysicalSize());
|
||||
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()), com.cloud.configuration.Resource.ResourceType.secondary_storage,
|
||||
volInfo.getSize() - volInfo.getPhysicalSize());
|
||||
} catch (ResourceAllocationException e) {
|
||||
s_logger.warn(e.getMessage());
|
||||
_alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, volume.getDataCenterId(), volume.getPodId(), e.getMessage(), e.getMessage());
|
||||
|
|
@ -2021,7 +1976,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
}
|
||||
|
||||
// Delete volumes which are not present on DB.
|
||||
for (Map.Entry<Long,TemplateProp> entry : volumeInfos.entrySet()) {
|
||||
for (Map.Entry<Long, TemplateProp> entry : volumeInfos.entrySet()) {
|
||||
Long uniqueName = entry.getKey();
|
||||
TemplateProp tInfo = entry.getValue();
|
||||
|
||||
|
|
@ -2091,7 +2046,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
s_logger.error("Take snapshot: " + volume.getId() + " failed", cre);
|
||||
throw cre;
|
||||
} catch (Exception e) {
|
||||
if(s_logger.isDebugEnabled()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("unknown exception while taking snapshot for volume " + volume.getId() + " was caught", e);
|
||||
}
|
||||
throw new CloudRuntimeException("Failed to take snapshot", e);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ import java.util.concurrent.ScheduledExecutorService;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd;
|
||||
import org.apache.cloudstack.api.command.admin.storage.CreateSecondaryStagingStoreCmd;
|
||||
|
|
@ -466,8 +465,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
|
||||
public boolean configure(String name, Map<String, Object> params) {
|
||||
Map<String, String> configs = _configDao.getConfiguration("management-server", params);
|
||||
|
||||
_storagePoolAcquisitionWaitSeconds = NumbersUtil.parseInt(configs.get("pool.acquisition.wait.seconds"), 1800);
|
||||
|
|
@ -524,7 +522,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
|||
|
||||
@Override
|
||||
public String getStoragePoolTags(long poolId) {
|
||||
return StringUtils.listToCsvTags(_storagePoolDao.searchForStoragePoolTags(poolId));
|
||||
return com.cloud.utils.StringUtils.listToCsvTags(_storagePoolDao.searchForStoragePoolTags(poolId));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -1176,10 +1174,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
|||
Host host = _hostDao.findById(ep.getId());
|
||||
if (host != null && host.getManagementServerId() != null) {
|
||||
if (_serverId == host.getManagementServerId().longValue()) {
|
||||
if (!volService.destroyVolume(volume.getId())) {
|
||||
s_logger.warn("Unable to destroy uploaded volume " + volume.getUuid());
|
||||
continue;
|
||||
}
|
||||
volService.destroyVolume(volume.getId());
|
||||
// decrement volume resource count
|
||||
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume, volume.isDisplayVolume());
|
||||
// expunge volume from secondary if volume is on image store
|
||||
|
|
@ -1844,8 +1839,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
|||
|
||||
totalOverProvCapacity = overProvFactor.multiply(new BigDecimal(pool.getCapacityBytes())).longValue();
|
||||
|
||||
s_logger.debug("Found storage pool " + poolVO.getName() + " of type " + pool.getPoolType().toString() + " with over-provisioning factor " +
|
||||
overProvFactor.toString());
|
||||
s_logger.debug("Found storage pool " + poolVO.getName() + " of type " + pool.getPoolType().toString() + " with over-provisioning factor " + overProvFactor.toString());
|
||||
s_logger.debug("Total over-provisioned capacity calculated is " + overProvFactor + " * " + pool.getCapacityBytes());
|
||||
} else {
|
||||
totalOverProvCapacity = pool.getCapacityBytes();
|
||||
|
|
@ -1858,18 +1852,16 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
|||
double storageAllocatedThreshold = CapacityManager.StorageAllocatedCapacityDisableThreshold.valueIn(pool.getDataCenterId());
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Checking pool with ID " + pool.getId() + " for volume allocation " + volumes.toString() + ", maxSize: " +
|
||||
totalOverProvCapacity + ", totalAllocatedSize: " + allocatedSizeWithTemplate + ", askingSize: " + totalAskingSize +
|
||||
", allocated disable threshold: " + storageAllocatedThreshold);
|
||||
s_logger.debug("Checking pool with ID " + pool.getId() + " for volume allocation " + volumes.toString() + ", maxSize: " + totalOverProvCapacity + ", totalAllocatedSize: "
|
||||
+ allocatedSizeWithTemplate + ", askingSize: " + totalAskingSize + ", allocated disable threshold: " + storageAllocatedThreshold);
|
||||
}
|
||||
|
||||
double usedPercentage = (allocatedSizeWithTemplate + totalAskingSize) / (double)(totalOverProvCapacity);
|
||||
|
||||
if (usedPercentage > storageAllocatedThreshold) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Insufficient un-allocated capacity on the pool with ID " + pool.getId() + " for volume allocation: " + volumes.toString() +
|
||||
" since its allocated percentage " + usedPercentage + " has crossed the allocated pool.storage.allocated.capacity.disablethreshold " +
|
||||
storageAllocatedThreshold + ", skipping this pool");
|
||||
s_logger.debug("Insufficient un-allocated capacity on the pool with ID " + pool.getId() + " for volume allocation: " + volumes.toString() + " since its allocated percentage "
|
||||
+ usedPercentage + " has crossed the allocated pool.storage.allocated.capacity.disablethreshold " + storageAllocatedThreshold + ", skipping this pool");
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -1877,9 +1869,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
|||
|
||||
if (totalOverProvCapacity < (allocatedSizeWithTemplate + totalAskingSize)) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Insufficient un-allocated capacity on the pool with ID " + pool.getId() + " for volume allocation: " + volumes.toString() +
|
||||
"; not enough storage, maxSize: " + totalOverProvCapacity + ", totalAllocatedSize: " + allocatedSizeWithTemplate + ", askingSize: " +
|
||||
totalAskingSize);
|
||||
s_logger.debug("Insufficient un-allocated capacity on the pool with ID " + pool.getId() + " for volume allocation: " + volumes.toString() + "; not enough storage, maxSize: "
|
||||
+ totalOverProvCapacity + ", totalAllocatedSize: " + allocatedSizeWithTemplate + ", askingSize: " + totalAskingSize);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1237,92 +1237,139 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_DELETE, eventDescription = "deleting volume")
|
||||
/**
|
||||
* Executes the removal of the volume. If the volume is only allocated we do not try to remove it from primary and secondary storage.
|
||||
* Otherwise, after the removal in the database, we will try to remove the volume from both primary and secondary storage.
|
||||
*/
|
||||
public boolean deleteVolume(long volumeId, Account caller) throws ConcurrentOperationException {
|
||||
|
||||
VolumeVO volume = _volsDao.findById(volumeId);
|
||||
if (volume == null) {
|
||||
throw new InvalidParameterValueException("Unable to find volume with ID: " + volumeId);
|
||||
}
|
||||
|
||||
if (!_snapshotMgr.canOperateOnVolume(volume)) {
|
||||
throw new InvalidParameterValueException("There are snapshot operations in progress on the volume, unable to delete it");
|
||||
}
|
||||
|
||||
_accountMgr.checkAccess(caller, null, true, volume);
|
||||
|
||||
if (volume.getInstanceId() != null) {
|
||||
throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM.");
|
||||
}
|
||||
|
||||
if (volume.getState() == Volume.State.UploadOp) {
|
||||
VolumeDataStoreVO volumeStore = _volumeStoreDao.findByVolume(volume.getId());
|
||||
if (volumeStore.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS) {
|
||||
throw new InvalidParameterValueException("Please specify a volume that is not uploading");
|
||||
}
|
||||
}
|
||||
|
||||
if (volume.getState() == Volume.State.NotUploaded || volume.getState() == Volume.State.UploadInProgress) {
|
||||
throw new InvalidParameterValueException("The volume is either getting uploaded or it may be initiated shortly, please wait for it to be completed");
|
||||
}
|
||||
|
||||
VolumeVO volume = retrieveAndValidateVolume(volumeId, caller);
|
||||
try {
|
||||
if (volume.getState() != Volume.State.Destroy && volume.getState() != Volume.State.Expunging && volume.getState() != Volume.State.Expunged) {
|
||||
Long instanceId = volume.getInstanceId();
|
||||
if (!volService.destroyVolume(volume.getId())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VMInstanceVO vmInstance = _vmInstanceDao.findById(instanceId);
|
||||
if (instanceId == null || (vmInstance.getType().equals(VirtualMachine.Type.User))) {
|
||||
// Decrement the resource count for volumes and primary storage belonging user VM's only
|
||||
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume, volume.isDisplayVolume());
|
||||
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.primary_storage, volume.isDisplayVolume(), new Long(volume.getSize()));
|
||||
}
|
||||
}
|
||||
destroyVolumeIfPossible(volume);
|
||||
// Mark volume as removed if volume has not been created on primary or secondary
|
||||
if (volume.getState() == Volume.State.Allocated) {
|
||||
_volsDao.remove(volumeId);
|
||||
stateTransitTo(volume, Volume.Event.DestroyRequested);
|
||||
return true;
|
||||
}
|
||||
// expunge volume from primary if volume is on primary
|
||||
VolumeInfo volOnPrimary = volFactory.getVolume(volume.getId(), DataStoreRole.Primary);
|
||||
if (volOnPrimary != null) {
|
||||
s_logger.info("Expunging volume " + volume.getId() + " from primary data store");
|
||||
AsyncCallFuture<VolumeApiResult> future = volService.expungeVolumeAsync(volOnPrimary);
|
||||
future.get();
|
||||
//decrement primary storage count
|
||||
_resourceLimitMgr.decrementResourceCount(volOnPrimary.getAccountId(), ResourceType.volume, volOnPrimary.isDisplayVolume());
|
||||
_resourceLimitMgr.decrementResourceCount(volOnPrimary.getAccountId(), ResourceType.primary_storage, volOnPrimary.isDisplayVolume(), new Long(volOnPrimary.getSize()));
|
||||
}
|
||||
// expunge volume from secondary if volume is on image store
|
||||
VolumeInfo volOnSecondary = volFactory.getVolume(volume.getId(), DataStoreRole.Image);
|
||||
if (volOnSecondary != null) {
|
||||
s_logger.info("Expunging volume " + volume.getId() + " from secondary data store");
|
||||
AsyncCallFuture<VolumeApiResult> future2 = volService.expungeVolumeAsync(volOnSecondary);
|
||||
future2.get();
|
||||
//decrement secondary storage count
|
||||
_resourceLimitMgr.decrementResourceCount(volOnSecondary.getAccountId(), ResourceType.secondary_storage, new Long(volOnSecondary.getSize()));
|
||||
}
|
||||
// delete all cache entries for this volume
|
||||
List<VolumeInfo> cacheVols = volFactory.listVolumeOnCache(volume.getId());
|
||||
for (VolumeInfo volOnCache : cacheVols) {
|
||||
s_logger.info("Delete volume from image cache store: " + volOnCache.getDataStore().getName());
|
||||
volOnCache.delete();
|
||||
}
|
||||
|
||||
expungeVolumesInPrimaryStorageIfNeeded(volume);
|
||||
expungeVolumesInSecondaryStorageIfNeeded(volume);
|
||||
cleanVolumesCache(volume);
|
||||
return true;
|
||||
} catch (InterruptedException | ExecutionException | NoTransitionException e) {
|
||||
s_logger.warn("Failed to expunge volume:", e);
|
||||
s_logger.warn("Failed to expunge volume: " + volume.getUuid(), e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean stateTransitTo(Volume vol, Volume.Event event) throws NoTransitionException {
|
||||
/**
|
||||
* Retrieves and validates the volume for the {@link #deleteVolume(long, Account)} method. The following validation are executed.
|
||||
* <ul>
|
||||
* <li> if no volume is found in the database, we throw an {@link InvalidParameterValueException};
|
||||
* <li> if there are snapshots operation on the volume we cannot delete it. Therefore, an {@link InvalidParameterValueException} is thrown;
|
||||
* <li> if the volume is still attached to a VM we throw an {@link InvalidParameterValueException};
|
||||
* <li> if volume state is in {@link Volume.State#UploadOp}, we check the {@link VolumeDataStoreVO}. Then, if the {@link VolumeDataStoreVO} for the given volume has download status of {@link VMTemplateStorageResourceAssoc.Status#DOWNLOAD_IN_PROGRESS}, an exception is throw;
|
||||
* <li> if the volume state is in {@link Volume.State#NotUploaded} or if the state is {@link Volume.State#UploadInProgress}, an {@link InvalidParameterValueException} is thrown;
|
||||
* <li> we also check if the user has access to the given volume using {@link AccountManager#checkAccess(Account, org.apache.cloudstack.acl.SecurityChecker.AccessType, boolean, String)}.
|
||||
* </ul>
|
||||
*
|
||||
* After all validations we return the volume object.
|
||||
*/
|
||||
protected VolumeVO retrieveAndValidateVolume(long volumeId, Account caller) {
|
||||
VolumeVO volume = _volsDao.findById(volumeId);
|
||||
if (volume == null) {
|
||||
throw new InvalidParameterValueException("Unable to find volume with ID: " + volumeId);
|
||||
}
|
||||
if (!_snapshotMgr.canOperateOnVolume(volume)) {
|
||||
throw new InvalidParameterValueException("There are snapshot operations in progress on the volume, unable to delete it");
|
||||
}
|
||||
if (volume.getInstanceId() != null) {
|
||||
throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM.");
|
||||
}
|
||||
if (volume.getState() == Volume.State.UploadOp) {
|
||||
VolumeDataStoreVO volumeStore = _volumeStoreDao.findByVolume(volume.getId());
|
||||
if (volumeStore.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS) {
|
||||
throw new InvalidParameterValueException("Please specify a volume that is not uploading");
|
||||
}
|
||||
}
|
||||
if (volume.getState() == Volume.State.NotUploaded || volume.getState() == Volume.State.UploadInProgress) {
|
||||
throw new InvalidParameterValueException("The volume is either getting uploaded or it may be initiated shortly, please wait for it to be completed");
|
||||
}
|
||||
_accountMgr.checkAccess(caller, null, true, volume);
|
||||
return volume;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the volume if possible and then decrement the following resource types.
|
||||
* <ul>
|
||||
* <li> {@link ResourceType#volume};
|
||||
* <li> {@link ResourceType#primary_storage}
|
||||
* </ul>
|
||||
*
|
||||
* A volume can be destroyed if it is not in any of the following states.
|
||||
* <ul>
|
||||
* <li> {@value Volume.State#Destroy};
|
||||
* <li> {@value Volume.State#Expunging};
|
||||
* <li> {@value Volume.State#Expunged}.
|
||||
* </ul>
|
||||
*
|
||||
* The volume is destroyed via {@link VolumeService#destroyVolume(long)} method.
|
||||
*/
|
||||
protected void destroyVolumeIfPossible(VolumeVO volume) {
|
||||
if (volume.getState() != Volume.State.Destroy && volume.getState() != Volume.State.Expunging && volume.getState() != Volume.State.Expunged) {
|
||||
volService.destroyVolume(volume.getId());
|
||||
|
||||
// Decrement the resource count for volumes and primary storage belonging user VM's only
|
||||
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume, volume.isDisplayVolume());
|
||||
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.primary_storage, volume.isDisplayVolume(), volume.getSize());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We will check if the given volume is in the primary storage. If it is, we will execute an asynchronous call to delete it there.
|
||||
* If the volume is not in the primary storage, we do nothing here.
|
||||
*/
|
||||
protected void expungeVolumesInPrimaryStorageIfNeeded(VolumeVO volume) throws InterruptedException, ExecutionException {
|
||||
VolumeInfo volOnPrimary = volFactory.getVolume(volume.getId(), DataStoreRole.Primary);
|
||||
if (volOnPrimary != null) {
|
||||
s_logger.info("Expunging volume " + volume.getId() + " from primary data store");
|
||||
AsyncCallFuture<VolumeApiResult> future = volService.expungeVolumeAsync(volOnPrimary);
|
||||
future.get();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We will check if the given volume is in the secondary storage. If the volume is not in the primary storage, we do nothing here.
|
||||
* If it is, we will execute an asynchronous call to delete it there. Then, we decrement the {@link ResourceType#secondary_storage} for the account that owns the volume.
|
||||
*/
|
||||
protected void expungeVolumesInSecondaryStorageIfNeeded(VolumeVO volume) throws InterruptedException, ExecutionException {
|
||||
VolumeInfo volOnSecondary = volFactory.getVolume(volume.getId(), DataStoreRole.Image);
|
||||
if (volOnSecondary != null) {
|
||||
s_logger.info("Expunging volume " + volume.getId() + " from secondary data store");
|
||||
AsyncCallFuture<VolumeApiResult> future2 = volService.expungeVolumeAsync(volOnSecondary);
|
||||
future2.get();
|
||||
|
||||
_resourceLimitMgr.decrementResourceCount(volOnSecondary.getAccountId(), ResourceType.secondary_storage, volOnSecondary.getSize());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean volumes cache entries (if they exist).
|
||||
*/
|
||||
protected void cleanVolumesCache(VolumeVO volume) {
|
||||
List<VolumeInfo> cacheVols = volFactory.listVolumeOnCache(volume.getId());
|
||||
if (CollectionUtils.isEmpty(cacheVols)) {
|
||||
return;
|
||||
}
|
||||
for (VolumeInfo volOnCache : cacheVols) {
|
||||
s_logger.info("Delete volume from image cache store: " + volOnCache.getDataStore().getName());
|
||||
volOnCache.delete();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean stateTransitTo(Volume vol, Volume.Event event) throws NoTransitionException {
|
||||
return _volStateMachine.transitTo(vol, event, null, _volsDao);
|
||||
}
|
||||
|
||||
|
|
@ -3198,4 +3245,4 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
return workJob;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -30,16 +30,20 @@ import java.lang.reflect.Field;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
|
||||
import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult;
|
||||
import org.apache.cloudstack.framework.async.AsyncCallFuture;
|
||||
import org.apache.cloudstack.framework.jobs.AsyncJobExecutionContext;
|
||||
import org.apache.cloudstack.framework.jobs.AsyncJobManager;
|
||||
import org.apache.cloudstack.framework.jobs.dao.AsyncJobJoinMapDao;
|
||||
|
|
@ -48,6 +52,8 @@ 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.db.VolumeDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
|
|
@ -63,6 +69,7 @@ import org.mockito.Spy;
|
|||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import com.cloud.configuration.Resource;
|
||||
import com.cloud.configuration.Resource.ResourceType;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
|
|
@ -73,6 +80,7 @@ import com.cloud.org.Grouping;
|
|||
import com.cloud.serializer.GsonHelper;
|
||||
import com.cloud.storage.Volume.Type;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.storage.snapshot.SnapshotManager;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountVO;
|
||||
|
|
@ -81,6 +89,7 @@ import com.cloud.user.User;
|
|||
import com.cloud.user.UserVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import com.cloud.utils.fsm.NoTransitionException;
|
||||
import com.cloud.vm.UserVmManager;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
|
|
@ -97,13 +106,17 @@ public class VolumeApiServiceImplTest {
|
|||
@InjectMocks
|
||||
private VolumeApiServiceImpl volumeApiServiceImpl;
|
||||
@Mock
|
||||
private VolumeDao _volumeDao;
|
||||
private SnapshotManager snapshotManagerMock;
|
||||
@Mock
|
||||
private AccountManager _accountMgr;
|
||||
private VolumeDataStoreDao volumeDataStoreDaoMock;
|
||||
@Mock
|
||||
private UserVmDao _userVmDao;
|
||||
private VolumeDao volumeDaoMock;
|
||||
@Mock
|
||||
private PrimaryDataStoreDao _storagePoolDao;
|
||||
private AccountManager accountManagerMock;
|
||||
@Mock
|
||||
private UserVmDao userVmDaoMock;
|
||||
@Mock
|
||||
private PrimaryDataStoreDao primaryDataStoreDaoMock;
|
||||
@Mock
|
||||
private VMSnapshotDao _vmSnapshotDao;
|
||||
@Mock
|
||||
|
|
@ -111,7 +124,7 @@ public class VolumeApiServiceImplTest {
|
|||
@Mock
|
||||
private AsyncJobJoinMapDao _joinMapDao;
|
||||
@Mock
|
||||
private VolumeDataFactory _volFactory;
|
||||
private VolumeDataFactory volumeDataFactoryMock;
|
||||
@Mock
|
||||
private VMInstanceDao _vmInstanceDao;
|
||||
@Mock
|
||||
|
|
@ -119,7 +132,7 @@ public class VolumeApiServiceImplTest {
|
|||
@Mock
|
||||
private SnapshotInfo snapshotInfoMock;
|
||||
@Mock
|
||||
private VolumeService volService;
|
||||
private VolumeService volumeServiceMock;
|
||||
@Mock
|
||||
private CreateVolumeCmd createVol;
|
||||
@Mock
|
||||
|
|
@ -127,7 +140,7 @@ public class VolumeApiServiceImplTest {
|
|||
@Mock
|
||||
private DataCenterDao _dcDao;
|
||||
@Mock
|
||||
private ResourceLimitService _resourceLimitMgr;
|
||||
private ResourceLimitService resourceLimitServiceMock;
|
||||
@Mock
|
||||
private AccountDao _accountDao;
|
||||
@Mock
|
||||
|
|
@ -142,10 +155,22 @@ public class VolumeApiServiceImplTest {
|
|||
private StoragePool storagePoolMock;
|
||||
private long storagePoolMockId = 1;
|
||||
@Mock
|
||||
private VolumeVO volumeVOMock;
|
||||
@Mock
|
||||
private DiskOfferingVO newDiskOfferingMock;
|
||||
|
||||
@Mock
|
||||
private VolumeVO volumeVoMock;
|
||||
@Mock
|
||||
private Account accountMock;
|
||||
@Mock
|
||||
private VolumeDataStoreVO volumeDataStoreVoMock;
|
||||
@Mock
|
||||
private AsyncCallFuture<VolumeApiResult> asyncCallFutureVolumeapiResultMock;
|
||||
|
||||
private long accountMockId = 456l;
|
||||
private long volumeMockId = 12313l;
|
||||
private long vmInstanceMockId = 1123l;
|
||||
private long volumeSizeMock = 456789921939l;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
Mockito.when(storagePoolMock.getId()).thenReturn(storagePoolMockId);
|
||||
|
|
@ -167,50 +192,50 @@ public class VolumeApiServiceImplTest {
|
|||
try {
|
||||
// volume of running vm id=1
|
||||
VolumeVO volumeOfRunningVm = new VolumeVO("root", 1L, 1L, 1L, 1L, 1L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
|
||||
when(_volumeDao.findById(1L)).thenReturn(volumeOfRunningVm);
|
||||
when(volumeDaoMock.findById(1L)).thenReturn(volumeOfRunningVm);
|
||||
|
||||
UserVmVO runningVm = new UserVmVO(1L, "vm", "vm", 1, HypervisorType.XenServer, 1L, false, false, 1L, 1L, 1, 1L, null, "vm", null);
|
||||
runningVm.setState(State.Running);
|
||||
runningVm.setDataCenterId(1L);
|
||||
when(_userVmDao.findById(1L)).thenReturn(runningVm);
|
||||
when(userVmDaoMock.findById(1L)).thenReturn(runningVm);
|
||||
|
||||
// volume of stopped vm id=2
|
||||
VolumeVO volumeOfStoppedVm = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
|
||||
volumeOfStoppedVm.setPoolId(1L);
|
||||
when(_volumeDao.findById(2L)).thenReturn(volumeOfStoppedVm);
|
||||
when(volumeDaoMock.findById(2L)).thenReturn(volumeOfStoppedVm);
|
||||
|
||||
UserVmVO stoppedVm = new UserVmVO(2L, "vm", "vm", 1, HypervisorType.XenServer, 1L, false, false, 1L, 1L, 1, 1L, null, "vm", null);
|
||||
stoppedVm.setState(State.Stopped);
|
||||
stoppedVm.setDataCenterId(1L);
|
||||
when(_userVmDao.findById(2L)).thenReturn(stoppedVm);
|
||||
when(userVmDaoMock.findById(2L)).thenReturn(stoppedVm);
|
||||
|
||||
// volume of hyperV vm id=3
|
||||
UserVmVO hyperVVm = new UserVmVO(3L, "vm", "vm", 1, HypervisorType.Hyperv, 1L, false, false, 1L, 1L, 1, 1L, null, "vm", null);
|
||||
hyperVVm.setState(State.Stopped);
|
||||
hyperVVm.setDataCenterId(1L);
|
||||
when(_userVmDao.findById(3L)).thenReturn(hyperVVm);
|
||||
when(userVmDaoMock.findById(3L)).thenReturn(hyperVVm);
|
||||
|
||||
VolumeVO volumeOfStoppeHyperVVm = new VolumeVO("root", 1L, 1L, 1L, 1L, 3L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
|
||||
volumeOfStoppeHyperVVm.setPoolId(1L);
|
||||
when(_volumeDao.findById(3L)).thenReturn(volumeOfStoppeHyperVVm);
|
||||
when(volumeDaoMock.findById(3L)).thenReturn(volumeOfStoppeHyperVVm);
|
||||
|
||||
StoragePoolVO unmanagedPool = new StoragePoolVO();
|
||||
|
||||
when(_storagePoolDao.findById(1L)).thenReturn(unmanagedPool);
|
||||
when(primaryDataStoreDaoMock.findById(1L)).thenReturn(unmanagedPool);
|
||||
|
||||
// volume of managed pool id=4
|
||||
StoragePoolVO managedPool = new StoragePoolVO();
|
||||
managedPool.setManaged(true);
|
||||
when(_storagePoolDao.findById(2L)).thenReturn(managedPool);
|
||||
when(primaryDataStoreDaoMock.findById(2L)).thenReturn(managedPool);
|
||||
VolumeVO managedPoolVolume = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
|
||||
managedPoolVolume.setPoolId(2L);
|
||||
when(_volumeDao.findById(4L)).thenReturn(managedPoolVolume);
|
||||
when(volumeDaoMock.findById(4L)).thenReturn(managedPoolVolume);
|
||||
|
||||
// non-root non-datadisk volume
|
||||
VolumeInfo volumeWithIncorrectVolumeType = Mockito.mock(VolumeInfo.class);
|
||||
when(volumeWithIncorrectVolumeType.getId()).thenReturn(5L);
|
||||
when(volumeWithIncorrectVolumeType.getVolumeType()).thenReturn(Volume.Type.ISO);
|
||||
when(_volFactory.getVolume(5L)).thenReturn(volumeWithIncorrectVolumeType);
|
||||
when(volumeDataFactoryMock.getVolume(5L)).thenReturn(volumeWithIncorrectVolumeType);
|
||||
|
||||
// correct root volume
|
||||
VolumeInfo correctRootVolume = Mockito.mock(VolumeInfo.class);
|
||||
|
|
@ -221,10 +246,10 @@ public class VolumeApiServiceImplTest {
|
|||
when(correctRootVolume.getState()).thenReturn(Volume.State.Ready);
|
||||
when(correctRootVolume.getTemplateId()).thenReturn(null);
|
||||
when(correctRootVolume.getPoolId()).thenReturn(1L);
|
||||
when(_volFactory.getVolume(6L)).thenReturn(correctRootVolume);
|
||||
when(volumeDataFactoryMock.getVolume(6L)).thenReturn(correctRootVolume);
|
||||
|
||||
VolumeVO correctRootVolumeVO = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
|
||||
when(_volumeDao.findById(6L)).thenReturn(correctRootVolumeVO);
|
||||
when(volumeDaoMock.findById(6L)).thenReturn(correctRootVolumeVO);
|
||||
|
||||
// managed root volume
|
||||
VolumeInfo managedVolume = Mockito.mock(VolumeInfo.class);
|
||||
|
|
@ -233,21 +258,21 @@ public class VolumeApiServiceImplTest {
|
|||
when(managedVolume.getVolumeType()).thenReturn(Volume.Type.ROOT);
|
||||
when(managedVolume.getInstanceId()).thenReturn(null);
|
||||
when(managedVolume.getPoolId()).thenReturn(2L);
|
||||
when(_volFactory.getVolume(7L)).thenReturn(managedVolume);
|
||||
when(volumeDataFactoryMock.getVolume(7L)).thenReturn(managedVolume);
|
||||
|
||||
VolumeVO managedVolume1 = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
|
||||
managedVolume1.setPoolId(2L);
|
||||
managedVolume1.setDataCenterId(1L);
|
||||
when(_volumeDao.findById(7L)).thenReturn(managedVolume1);
|
||||
when(volumeDaoMock.findById(7L)).thenReturn(managedVolume1);
|
||||
|
||||
// vm having root volume
|
||||
UserVmVO vmHavingRootVolume = new UserVmVO(4L, "vm", "vm", 1, HypervisorType.XenServer, 1L, false, false, 1L, 1L, 1, 1L, null, "vm", null);
|
||||
vmHavingRootVolume.setState(State.Stopped);
|
||||
vmHavingRootVolume.setDataCenterId(1L);
|
||||
when(_userVmDao.findById(4L)).thenReturn(vmHavingRootVolume);
|
||||
when(userVmDaoMock.findById(4L)).thenReturn(vmHavingRootVolume);
|
||||
List<VolumeVO> vols = new ArrayList<VolumeVO>();
|
||||
vols.add(new VolumeVO());
|
||||
when(_volumeDao.findByInstanceAndDeviceId(4L, 0L)).thenReturn(vols);
|
||||
when(volumeDaoMock.findByInstanceAndDeviceId(4L, 0L)).thenReturn(vols);
|
||||
|
||||
// volume in uploaded state
|
||||
VolumeInfo uploadedVolume = Mockito.mock(VolumeInfo.class);
|
||||
|
|
@ -257,13 +282,13 @@ public class VolumeApiServiceImplTest {
|
|||
when(uploadedVolume.getInstanceId()).thenReturn(null);
|
||||
when(uploadedVolume.getPoolId()).thenReturn(1L);
|
||||
when(uploadedVolume.getState()).thenReturn(Volume.State.Uploaded);
|
||||
when(_volFactory.getVolume(8L)).thenReturn(uploadedVolume);
|
||||
when(volumeDataFactoryMock.getVolume(8L)).thenReturn(uploadedVolume);
|
||||
|
||||
VolumeVO upVolume = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT);
|
||||
upVolume.setPoolId(1L);
|
||||
upVolume.setDataCenterId(1L);
|
||||
upVolume.setState(Volume.State.Uploaded);
|
||||
when(_volumeDao.findById(8L)).thenReturn(upVolume);
|
||||
when(volumeDaoMock.findById(8L)).thenReturn(upVolume);
|
||||
|
||||
// helper dao methods mock
|
||||
when(_vmSnapshotDao.findByVm(any(Long.class))).thenReturn(new ArrayList<VMSnapshotVO>());
|
||||
|
|
@ -279,7 +304,7 @@ public class VolumeApiServiceImplTest {
|
|||
}
|
||||
|
||||
// helper methods mock
|
||||
doNothing().when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class));
|
||||
doNothing().when(accountManagerMock).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class));
|
||||
doNothing().when(_jobMgr).updateAsyncJobAttachment(any(Long.class), any(String.class), any(Long.class));
|
||||
when(_jobMgr.submitAsyncJob(any(AsyncJobVO.class), any(String.class), any(Long.class))).thenReturn(1L);
|
||||
}
|
||||
|
|
@ -374,7 +399,7 @@ public class VolumeApiServiceImplTest {
|
|||
// volume not Ready
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testTakeSnapshotF1() throws ResourceAllocationException {
|
||||
when(_volFactory.getVolume(anyLong())).thenReturn(volumeInfoMock);
|
||||
when(volumeDataFactoryMock.getVolume(anyLong())).thenReturn(volumeInfoMock);
|
||||
when(volumeInfoMock.getState()).thenReturn(Volume.State.Allocated);
|
||||
when(volumeInfoMock.getPoolId()).thenReturn(1L);
|
||||
volumeApiServiceImpl.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null, false);
|
||||
|
|
@ -382,11 +407,11 @@ public class VolumeApiServiceImplTest {
|
|||
|
||||
@Test
|
||||
public void testTakeSnapshotF2() throws ResourceAllocationException {
|
||||
when(_volFactory.getVolume(anyLong())).thenReturn(volumeInfoMock);
|
||||
when(volumeDataFactoryMock.getVolume(anyLong())).thenReturn(volumeInfoMock);
|
||||
when(volumeInfoMock.getState()).thenReturn(Volume.State.Ready);
|
||||
when(volumeInfoMock.getInstanceId()).thenReturn(null);
|
||||
when(volumeInfoMock.getPoolId()).thenReturn(1L);
|
||||
when(volService.takeSnapshot(Mockito.any(VolumeInfo.class))).thenReturn(snapshotInfoMock);
|
||||
when(volumeServiceMock.takeSnapshot(Mockito.any(VolumeInfo.class))).thenReturn(snapshotInfoMock);
|
||||
volumeApiServiceImpl.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null, false);
|
||||
}
|
||||
|
||||
|
|
@ -422,7 +447,7 @@ public class VolumeApiServiceImplTest {
|
|||
|
||||
@Test
|
||||
public void testUpdateMissingRootDiskControllerWithValidChainInfo() {
|
||||
UserVmVO vm = _userVmDao.findById(1L);
|
||||
UserVmVO vm = userVmDaoMock.findById(1L);
|
||||
|
||||
Mockito.doNothing().when(userVmManager).persistDeviceBusInfo(any(UserVmVO.class), eq("scsi"));
|
||||
volumeApiServiceImpl.updateMissingRootDiskController(vm, "{\"diskDeviceBusName\":\"scsi0:0\",\"diskChain\":[\"[somedatastore] i-3-VM-somePath/ROOT-1.vmdk\"]}");
|
||||
|
|
@ -451,7 +476,7 @@ public class VolumeApiServiceImplTest {
|
|||
*/
|
||||
@Test
|
||||
public void testResourceLimitCheckForUploadedVolume() throws NoSuchFieldException, IllegalAccessException, ResourceAllocationException {
|
||||
doThrow(new ResourceAllocationException("primary storage resource limit check failed", Resource.ResourceType.primary_storage)).when(_resourceLimitMgr).checkResourceLimit(any(AccountVO.class),
|
||||
doThrow(new ResourceAllocationException("primary storage resource limit check failed", Resource.ResourceType.primary_storage)).when(resourceLimitServiceMock).checkResourceLimit(any(AccountVO.class),
|
||||
any(Resource.ResourceType.class), any(Long.class));
|
||||
UserVmVO vm = Mockito.mock(UserVmVO.class);
|
||||
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
|
||||
|
|
@ -459,12 +484,12 @@ public class VolumeApiServiceImplTest {
|
|||
when(volumeToAttach.getDataCenterId()).thenReturn(34L);
|
||||
when(volumeToAttach.getVolumeType()).thenReturn(Volume.Type.DATADISK);
|
||||
when(volumeToAttach.getInstanceId()).thenReturn(null);
|
||||
when(_userVmDao.findById(anyLong())).thenReturn(vm);
|
||||
when(userVmDaoMock.findById(anyLong())).thenReturn(vm);
|
||||
when(vm.getType()).thenReturn(VirtualMachine.Type.User);
|
||||
when(vm.getState()).thenReturn(State.Running);
|
||||
when(vm.getDataCenterId()).thenReturn(34L);
|
||||
when(_volumeDao.findByInstanceAndType(anyLong(), any(Volume.Type.class))).thenReturn(new ArrayList<>(10));
|
||||
when(_volFactory.getVolume(9L)).thenReturn(volumeToAttach);
|
||||
when(volumeDaoMock.findByInstanceAndType(anyLong(), any(Volume.Type.class))).thenReturn(new ArrayList<>(10));
|
||||
when(volumeDataFactoryMock.getVolume(9L)).thenReturn(volumeToAttach);
|
||||
when(volumeToAttach.getState()).thenReturn(Volume.State.Uploaded);
|
||||
DataCenterVO zoneWithDisabledLocalStorage = Mockito.mock(DataCenterVO.class);
|
||||
when(_dcDao.findById(anyLong())).thenReturn(zoneWithDisabledLocalStorage);
|
||||
|
|
@ -511,39 +536,39 @@ public class VolumeApiServiceImplTest {
|
|||
|
||||
@Test
|
||||
public void validateConditionsToReplaceDiskOfferingOfVolumeTestNoNewDiskOffering() {
|
||||
volumeApiServiceImpl.validateConditionsToReplaceDiskOfferingOfVolume(volumeVOMock, null, storagePoolMock);
|
||||
volumeApiServiceImpl.validateConditionsToReplaceDiskOfferingOfVolume(volumeVoMock, null, storagePoolMock);
|
||||
|
||||
Mockito.verify(volumeVOMock, times(0)).getVolumeType();
|
||||
Mockito.verify(volumeVoMock, times(0)).getVolumeType();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateConditionsToReplaceDiskOfferingOfVolumeTestRootVolume() {
|
||||
Mockito.when(volumeVOMock.getVolumeType()).thenReturn(Type.ROOT);
|
||||
Mockito.when(volumeVoMock.getVolumeType()).thenReturn(Type.ROOT);
|
||||
|
||||
volumeApiServiceImpl.validateConditionsToReplaceDiskOfferingOfVolume(volumeVOMock, newDiskOfferingMock, storagePoolMock);
|
||||
volumeApiServiceImpl.validateConditionsToReplaceDiskOfferingOfVolume(volumeVoMock, newDiskOfferingMock, storagePoolMock);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void validateConditionsToReplaceDiskOfferingOfVolumeTestTargetPoolSharedDiskOfferingLocal() {
|
||||
Mockito.when(volumeVOMock.getVolumeType()).thenReturn(Type.DATADISK);
|
||||
Mockito.when(volumeVoMock.getVolumeType()).thenReturn(Type.DATADISK);
|
||||
Mockito.when(newDiskOfferingMock.getUseLocalStorage()).thenReturn(true);
|
||||
Mockito.when(storagePoolMock.isShared()).thenReturn(true);
|
||||
|
||||
volumeApiServiceImpl.validateConditionsToReplaceDiskOfferingOfVolume(volumeVOMock, newDiskOfferingMock, storagePoolMock);
|
||||
volumeApiServiceImpl.validateConditionsToReplaceDiskOfferingOfVolume(volumeVoMock, newDiskOfferingMock, storagePoolMock);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void validateConditionsToReplaceDiskOfferingOfVolumeTestTargetPoolLocalDiskOfferingShared() {
|
||||
Mockito.when(volumeVOMock.getVolumeType()).thenReturn(Type.DATADISK);
|
||||
Mockito.when(volumeVoMock.getVolumeType()).thenReturn(Type.DATADISK);
|
||||
Mockito.when(newDiskOfferingMock.isShared()).thenReturn(true);
|
||||
Mockito.when(storagePoolMock.isLocal()).thenReturn(true);
|
||||
|
||||
volumeApiServiceImpl.validateConditionsToReplaceDiskOfferingOfVolume(volumeVOMock, newDiskOfferingMock, storagePoolMock);
|
||||
volumeApiServiceImpl.validateConditionsToReplaceDiskOfferingOfVolume(volumeVoMock, newDiskOfferingMock, storagePoolMock);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void validateConditionsToReplaceDiskOfferingOfVolumeTestTagsDoNotMatch() {
|
||||
Mockito.when(volumeVOMock.getVolumeType()).thenReturn(Type.DATADISK);
|
||||
Mockito.when(volumeVoMock.getVolumeType()).thenReturn(Type.DATADISK);
|
||||
|
||||
Mockito.when(newDiskOfferingMock.getUseLocalStorage()).thenReturn(false);
|
||||
Mockito.when(storagePoolMock.isShared()).thenReturn(true);
|
||||
|
|
@ -555,12 +580,12 @@ public class VolumeApiServiceImplTest {
|
|||
|
||||
Mockito.doReturn(null).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock);
|
||||
|
||||
volumeApiServiceImpl.validateConditionsToReplaceDiskOfferingOfVolume(volumeVOMock, newDiskOfferingMock, storagePoolMock);
|
||||
volumeApiServiceImpl.validateConditionsToReplaceDiskOfferingOfVolume(volumeVoMock, newDiskOfferingMock, storagePoolMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateConditionsToReplaceDiskOfferingOfVolumeTestEverythingWorking() {
|
||||
Mockito.when(volumeVOMock.getVolumeType()).thenReturn(Type.DATADISK);
|
||||
Mockito.when(volumeVoMock.getVolumeType()).thenReturn(Type.DATADISK);
|
||||
|
||||
Mockito.when(newDiskOfferingMock.getUseLocalStorage()).thenReturn(false);
|
||||
Mockito.when(storagePoolMock.isShared()).thenReturn(true);
|
||||
|
|
@ -572,9 +597,9 @@ public class VolumeApiServiceImplTest {
|
|||
|
||||
Mockito.doReturn("tag1").when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock);
|
||||
|
||||
volumeApiServiceImpl.validateConditionsToReplaceDiskOfferingOfVolume(volumeVOMock, newDiskOfferingMock, storagePoolMock);
|
||||
volumeApiServiceImpl.validateConditionsToReplaceDiskOfferingOfVolume(volumeVoMock, newDiskOfferingMock, storagePoolMock);
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(volumeVOMock, newDiskOfferingMock, storagePoolMock, volumeApiServiceImpl);
|
||||
InOrder inOrder = Mockito.inOrder(volumeVoMock, newDiskOfferingMock, storagePoolMock, volumeApiServiceImpl);
|
||||
inOrder.verify(storagePoolMock).isShared();
|
||||
inOrder.verify(newDiskOfferingMock).getUseLocalStorage();
|
||||
inOrder.verify(storagePoolMock).isLocal();
|
||||
|
|
@ -582,7 +607,385 @@ public class VolumeApiServiceImplTest {
|
|||
inOrder.verify(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock);
|
||||
inOrder.verify(newDiskOfferingMock).getTags();
|
||||
|
||||
inOrder.verify(volumeVOMock).getSize();
|
||||
inOrder.verify(volumeVoMock).getSize();
|
||||
inOrder.verify(newDiskOfferingMock).getDiskSize();
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void retrieveAndValidateVolumeTestVolumeNotFound() {
|
||||
Mockito.doReturn(null).when(volumeDaoMock).findById(volumeMockId);
|
||||
volumeApiServiceImpl.retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void retrieveAndValidateVolumeTestCannotOperateOnVolumeDueToSnapshot() {
|
||||
Mockito.doReturn(volumeVoMock).when(volumeDaoMock).findById(volumeMockId);
|
||||
Mockito.doReturn(false).when(snapshotManagerMock).canOperateOnVolume(volumeVoMock);
|
||||
|
||||
volumeApiServiceImpl.retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void retrieveAndValidateVolumeTestVolumePluggedIntoVm() {
|
||||
Mockito.doReturn(volumeVoMock).when(volumeDaoMock).findById(volumeMockId);
|
||||
Mockito.doReturn(vmInstanceMockId).when(volumeVoMock).getInstanceId();
|
||||
|
||||
Mockito.doReturn(true).when(snapshotManagerMock).canOperateOnVolume(volumeVoMock);
|
||||
|
||||
volumeApiServiceImpl.retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void retrieveAndValidateVolumeTestStateUploadOpAndDownloadInProgress() {
|
||||
Mockito.doReturn(volumeVoMock).when(volumeDaoMock).findById(volumeMockId);
|
||||
Mockito.doReturn(null).when(volumeVoMock).getInstanceId();
|
||||
Mockito.doReturn(Volume.State.UploadOp).when(volumeVoMock).getState();
|
||||
|
||||
Mockito.doReturn(true).when(snapshotManagerMock).canOperateOnVolume(volumeVoMock);
|
||||
Mockito.doReturn(volumeDataStoreVoMock).when(volumeDataStoreDaoMock).findByVolume(volumeMockId);
|
||||
Mockito.doReturn(VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS).when(volumeDataStoreVoMock).getDownloadState();
|
||||
|
||||
volumeApiServiceImpl.retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void retrieveAndValidateVolumeTestStateNotUploaded() {
|
||||
Mockito.doReturn(volumeVoMock).when(volumeDaoMock).findById(volumeMockId);
|
||||
Mockito.doReturn(null).when(volumeVoMock).getInstanceId();
|
||||
Mockito.doReturn(Volume.State.NotUploaded).when(volumeVoMock).getState();
|
||||
|
||||
Mockito.doReturn(true).when(snapshotManagerMock).canOperateOnVolume(volumeVoMock);
|
||||
|
||||
volumeApiServiceImpl.retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void retrieveAndValidateVolumeTestUploadInProgress() {
|
||||
Mockito.doReturn(volumeVoMock).when(volumeDaoMock).findById(volumeMockId);
|
||||
Mockito.doReturn(null).when(volumeVoMock).getInstanceId();
|
||||
Mockito.doReturn(Volume.State.UploadInProgress).when(volumeVoMock).getState();
|
||||
|
||||
Mockito.doReturn(true).when(snapshotManagerMock).canOperateOnVolume(volumeVoMock);
|
||||
|
||||
volumeApiServiceImpl.retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveAndValidateVolumeTest() {
|
||||
Mockito.doReturn(volumeVoMock).when(volumeDaoMock).findById(volumeMockId);
|
||||
Mockito.doReturn(null).when(volumeVoMock).getInstanceId();
|
||||
Mockito.doReturn(Volume.State.Ready).when(volumeVoMock).getState();
|
||||
|
||||
Mockito.doReturn(true).when(snapshotManagerMock).canOperateOnVolume(volumeVoMock);
|
||||
Mockito.doNothing().when(accountManagerMock).checkAccess(accountMock, null, true, volumeVoMock);
|
||||
volumeApiServiceImpl.retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
|
||||
Mockito.verify(accountManagerMock).checkAccess(accountMock, null, true, volumeVoMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destroyVolumeIfPossibleTestVolumeStateIsDestroy() {
|
||||
Mockito.doReturn(Volume.State.Destroy).when(volumeVoMock).getState();
|
||||
configureMocksForTestDestroyVolumeWhenVolume();
|
||||
|
||||
volumeApiServiceImpl.destroyVolumeIfPossible(volumeVoMock);
|
||||
|
||||
verifyMocksForTestDestroyVolumeWhenVolumeIsNotInRightState();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destroyVolumeIfPossibleTestVolumeStateIsExpunging() {
|
||||
Mockito.doReturn(Volume.State.Expunging).when(volumeVoMock).getState();
|
||||
configureMocksForTestDestroyVolumeWhenVolume();
|
||||
|
||||
volumeApiServiceImpl.destroyVolumeIfPossible(volumeVoMock);
|
||||
|
||||
verifyMocksForTestDestroyVolumeWhenVolumeIsNotInRightState();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destroyVolumeIfPossibleTestVolumeStateIsExpunged() {
|
||||
Mockito.doReturn(Volume.State.Expunged).when(volumeVoMock).getState();
|
||||
configureMocksForTestDestroyVolumeWhenVolume();
|
||||
|
||||
volumeApiServiceImpl.destroyVolumeIfPossible(volumeVoMock);
|
||||
|
||||
verifyMocksForTestDestroyVolumeWhenVolumeIsNotInRightState();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destroyVolumeIfPossibleTestVolumeStateReady() {
|
||||
Mockito.doReturn(Volume.State.Ready).when(volumeVoMock).getState();
|
||||
configureMocksForTestDestroyVolumeWhenVolume();
|
||||
|
||||
volumeApiServiceImpl.destroyVolumeIfPossible(volumeVoMock);
|
||||
|
||||
Mockito.verify(volumeServiceMock, Mockito.times(1)).destroyVolume(volumeMockId);
|
||||
Mockito.verify(resourceLimitServiceMock, Mockito.times(1)).decrementResourceCount(accountMockId, ResourceType.volume, true);
|
||||
Mockito.verify(resourceLimitServiceMock, Mockito.times(1)).decrementResourceCount(accountMockId, ResourceType.primary_storage, true, volumeSizeMock);
|
||||
}
|
||||
|
||||
private void verifyMocksForTestDestroyVolumeWhenVolumeIsNotInRightState() {
|
||||
Mockito.verify(volumeServiceMock, Mockito.times(0)).destroyVolume(volumeMockId);
|
||||
Mockito.verify(resourceLimitServiceMock, Mockito.times(0)).decrementResourceCount(accountMockId, ResourceType.volume, true);
|
||||
Mockito.verify(resourceLimitServiceMock, Mockito.times(0)).decrementResourceCount(accountMockId, ResourceType.primary_storage, true, volumeSizeMock);
|
||||
}
|
||||
|
||||
private void configureMocksForTestDestroyVolumeWhenVolume() {
|
||||
Mockito.doReturn(accountMockId).when(volumeVoMock).getAccountId();
|
||||
Mockito.doReturn(true).when(volumeVoMock).isDisplayVolume();
|
||||
|
||||
Mockito.doNothing().when(volumeServiceMock).destroyVolume(volumeMockId);
|
||||
Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.volume, true);
|
||||
Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.primary_storage, true, volumeSizeMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void expungeVolumesInPrimaryStorageIfNeededTestVolumeNotInPrimaryDataStore() throws InterruptedException, ExecutionException {
|
||||
Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock);
|
||||
Mockito.doReturn(null).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Primary);
|
||||
|
||||
volumeApiServiceImpl.expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
|
||||
|
||||
Mockito.verify(volumeServiceMock, Mockito.times(0)).expungeVolumeAsync(volumeInfoMock);
|
||||
Mockito.verify(asyncCallFutureVolumeapiResultMock, Mockito.times(0)).get();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void expungeVolumesInPrimaryStorageIfNeededTestVolumeInPrimaryDataStore() throws InterruptedException, ExecutionException {
|
||||
Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock);
|
||||
Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Primary);
|
||||
|
||||
volumeApiServiceImpl.expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
|
||||
|
||||
Mockito.verify(volumeServiceMock, Mockito.times(1)).expungeVolumeAsync(volumeInfoMock);
|
||||
Mockito.verify(asyncCallFutureVolumeapiResultMock, Mockito.times(1)).get();
|
||||
}
|
||||
|
||||
@Test(expected = InterruptedException.class)
|
||||
public void expungeVolumesInPrimaryStorageIfNeededTestThrowingInterruptedException() throws InterruptedException, ExecutionException {
|
||||
Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock);
|
||||
Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Primary);
|
||||
Mockito.doThrow(InterruptedException.class).when(asyncCallFutureVolumeapiResultMock).get();
|
||||
|
||||
volumeApiServiceImpl.expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
|
||||
}
|
||||
|
||||
@Test(expected = ExecutionException.class)
|
||||
public void expungeVolumesInPrimaryStorageIfNeededTestThrowingExecutionException() throws InterruptedException, ExecutionException {
|
||||
Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock);
|
||||
Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Primary);
|
||||
Mockito.doThrow(ExecutionException.class).when(asyncCallFutureVolumeapiResultMock).get();
|
||||
|
||||
volumeApiServiceImpl.expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void expungeVolumesInSecondaryStorageIfNeededTestVolumeNotFoundInSecondaryStorage() throws InterruptedException, ExecutionException {
|
||||
Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock);
|
||||
Mockito.doReturn(null).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Image);
|
||||
Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock);
|
||||
Mockito.doReturn(accountMockId).when(volumeInfoMock).getAccountId();
|
||||
Mockito.doReturn(volumeSizeMock).when(volumeInfoMock).getSize();
|
||||
|
||||
volumeApiServiceImpl.expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock);
|
||||
|
||||
Mockito.verify(volumeServiceMock, Mockito.times(0)).expungeVolumeAsync(volumeInfoMock);
|
||||
Mockito.verify(asyncCallFutureVolumeapiResultMock, Mockito.times(0)).get();
|
||||
Mockito.verify(resourceLimitServiceMock, Mockito.times(0)).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void expungeVolumesInSecondaryStorageIfNeededTestVolumeFoundInSecondaryStorage() throws InterruptedException, ExecutionException {
|
||||
Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock);
|
||||
Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Image);
|
||||
Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock);
|
||||
Mockito.doReturn(accountMockId).when(volumeInfoMock).getAccountId();
|
||||
Mockito.doReturn(volumeSizeMock).when(volumeInfoMock).getSize();
|
||||
|
||||
volumeApiServiceImpl.expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock);
|
||||
|
||||
Mockito.verify(volumeServiceMock, Mockito.times(1)).expungeVolumeAsync(volumeInfoMock);
|
||||
Mockito.verify(asyncCallFutureVolumeapiResultMock, Mockito.times(1)).get();
|
||||
Mockito.verify(resourceLimitServiceMock, Mockito.times(1)).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock);
|
||||
}
|
||||
|
||||
@Test(expected = InterruptedException.class)
|
||||
public void expungeVolumesInSecondaryStorageIfNeededTestthrowinInterruptedException() throws InterruptedException, ExecutionException {
|
||||
Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock);
|
||||
Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Image);
|
||||
Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock);
|
||||
Mockito.doReturn(accountMockId).when(volumeInfoMock).getAccountId();
|
||||
Mockito.doReturn(volumeSizeMock).when(volumeInfoMock).getSize();
|
||||
|
||||
Mockito.doThrow(InterruptedException.class).when(asyncCallFutureVolumeapiResultMock).get();
|
||||
|
||||
volumeApiServiceImpl.expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock);
|
||||
|
||||
}
|
||||
|
||||
@Test(expected = ExecutionException.class)
|
||||
public void expungeVolumesInSecondaryStorageIfNeededTestthrowinExecutionException() throws InterruptedException, ExecutionException {
|
||||
Mockito.doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).expungeVolumeAsync(volumeInfoMock);
|
||||
Mockito.doReturn(volumeInfoMock).when(volumeDataFactoryMock).getVolume(volumeMockId, DataStoreRole.Image);
|
||||
Mockito.doNothing().when(resourceLimitServiceMock).decrementResourceCount(accountMockId, ResourceType.secondary_storage, volumeSizeMock);
|
||||
Mockito.doReturn(accountMockId).when(volumeInfoMock).getAccountId();
|
||||
Mockito.doReturn(volumeSizeMock).when(volumeInfoMock).getSize();
|
||||
|
||||
Mockito.doThrow(ExecutionException.class).when(asyncCallFutureVolumeapiResultMock).get();
|
||||
|
||||
volumeApiServiceImpl.expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cleanVolumesCacheTest() {
|
||||
List<VolumeInfo> volumeInfos = new ArrayList<>();
|
||||
VolumeInfo volumeInfoMock1 = Mockito.mock(VolumeInfo.class);
|
||||
VolumeInfo volumeInfoMock2 = Mockito.mock(VolumeInfo.class);
|
||||
|
||||
DataStore dataStoreMock1 = Mockito.mock(DataStore.class);
|
||||
DataStore dataStoreMock2 = Mockito.mock(DataStore.class);
|
||||
Mockito.doReturn(dataStoreMock1).when(volumeInfoMock1).getDataStore();
|
||||
Mockito.doReturn(dataStoreMock2).when(volumeInfoMock2).getDataStore();
|
||||
|
||||
volumeInfos.add(volumeInfoMock1);
|
||||
volumeInfos.add(volumeInfoMock2);
|
||||
|
||||
Mockito.doReturn(volumeInfos).when(volumeDataFactoryMock).listVolumeOnCache(volumeMockId);
|
||||
|
||||
volumeApiServiceImpl.cleanVolumesCache(volumeVoMock);
|
||||
|
||||
Mockito.verify(dataStoreMock1).getName();
|
||||
Mockito.verify(dataStoreMock2).getName();
|
||||
|
||||
Mockito.verify(volumeInfoMock1).delete();
|
||||
Mockito.verify(volumeInfoMock2).delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteVolumeTestVolumeStateAllocated() throws InterruptedException, ExecutionException, NoTransitionException {
|
||||
Mockito.doReturn(Volume.State.Allocated).when(volumeVoMock).getState();
|
||||
|
||||
Mockito.doReturn(volumeVoMock).when(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
|
||||
Mockito.doNothing().when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
|
||||
Mockito.doNothing().when(volumeApiServiceImpl).expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock);
|
||||
Mockito.doNothing().when(volumeApiServiceImpl).cleanVolumesCache(volumeVoMock);
|
||||
|
||||
Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId);
|
||||
Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);
|
||||
|
||||
boolean result = volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock);
|
||||
|
||||
Assert.assertTrue(result);
|
||||
Mockito.verify(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
Mockito.verify(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
|
||||
Mockito.verify(volumeDaoMock).remove(volumeMockId);
|
||||
Mockito.verify(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);
|
||||
|
||||
Mockito.verify(volumeApiServiceImpl, Mockito.times(0)).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
|
||||
Mockito.verify(volumeApiServiceImpl, Mockito.times(0)).expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock);
|
||||
Mockito.verify(volumeApiServiceImpl, Mockito.times(0)).cleanVolumesCache(volumeVoMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteVolumeTestVolumeStateReady() throws InterruptedException, ExecutionException, NoTransitionException {
|
||||
Mockito.doReturn(Volume.State.Ready).when(volumeVoMock).getState();
|
||||
|
||||
Mockito.doReturn(volumeVoMock).when(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
|
||||
Mockito.doNothing().when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
|
||||
Mockito.doNothing().when(volumeApiServiceImpl).expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock);
|
||||
Mockito.doNothing().when(volumeApiServiceImpl).cleanVolumesCache(volumeVoMock);
|
||||
|
||||
Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId);
|
||||
Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);
|
||||
|
||||
boolean result = volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock);
|
||||
|
||||
Assert.assertTrue(result);
|
||||
Mockito.verify(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
Mockito.verify(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
|
||||
Mockito.verify(volumeDaoMock, Mockito.times(0)).remove(volumeMockId);
|
||||
Mockito.verify(volumeApiServiceImpl, Mockito.times(0)).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);
|
||||
|
||||
Mockito.verify(volumeApiServiceImpl, Mockito.times(1)).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
|
||||
Mockito.verify(volumeApiServiceImpl, Mockito.times(1)).expungeVolumesInSecondaryStorageIfNeeded(volumeVoMock);
|
||||
Mockito.verify(volumeApiServiceImpl, Mockito.times(1)).cleanVolumesCache(volumeVoMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteVolumeTestVolumeStateReadyThrowingInterruptedException() throws InterruptedException, ExecutionException, NoTransitionException {
|
||||
Mockito.doReturn(Volume.State.Ready).when(volumeVoMock).getState();
|
||||
|
||||
Mockito.doReturn(volumeVoMock).when(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
|
||||
Mockito.doThrow(InterruptedException.class).when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
|
||||
|
||||
Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId);
|
||||
Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);
|
||||
|
||||
boolean result = volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock);
|
||||
|
||||
Assert.assertFalse(result);
|
||||
Mockito.verify(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
Mockito.verify(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
|
||||
Mockito.verify(volumeDaoMock, Mockito.times(0)).remove(volumeMockId);
|
||||
Mockito.verify(volumeApiServiceImpl, Mockito.times(0)).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteVolumeTestVolumeStateReadyThrowingExecutionException() throws InterruptedException, ExecutionException, NoTransitionException {
|
||||
Mockito.doReturn(Volume.State.Ready).when(volumeVoMock).getState();
|
||||
|
||||
Mockito.doReturn(volumeVoMock).when(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
|
||||
Mockito.doThrow(ExecutionException.class).when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
|
||||
|
||||
Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId);
|
||||
Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);
|
||||
|
||||
boolean result = volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock);
|
||||
|
||||
Assert.assertFalse(result);
|
||||
Mockito.verify(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
Mockito.verify(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
|
||||
Mockito.verify(volumeDaoMock, Mockito.times(0)).remove(volumeMockId);
|
||||
Mockito.verify(volumeApiServiceImpl, Mockito.times(0)).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteVolumeTestVolumeStateReadyThrowingNoTransitionException() throws InterruptedException, ExecutionException, NoTransitionException {
|
||||
Mockito.doReturn(Volume.State.Ready).when(volumeVoMock).getState();
|
||||
|
||||
Mockito.doReturn(volumeVoMock).when(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
|
||||
Mockito.doThrow(NoTransitionException.class).when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
|
||||
|
||||
Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId);
|
||||
Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);
|
||||
|
||||
boolean result = volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock);
|
||||
|
||||
Assert.assertFalse(result);
|
||||
Mockito.verify(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
Mockito.verify(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
|
||||
Mockito.verify(volumeDaoMock, Mockito.times(0)).remove(volumeMockId);
|
||||
Mockito.verify(volumeApiServiceImpl, Mockito.times(0)).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void deleteVolumeTestVolumeStateReadyThrowingRuntimeException() throws InterruptedException, ExecutionException, NoTransitionException {
|
||||
Mockito.doReturn(Volume.State.Ready).when(volumeVoMock).getState();
|
||||
|
||||
Mockito.doReturn(volumeVoMock).when(volumeApiServiceImpl).retrieveAndValidateVolume(volumeMockId, accountMock);
|
||||
Mockito.doNothing().when(volumeApiServiceImpl).destroyVolumeIfPossible(volumeVoMock);
|
||||
Mockito.doThrow(RuntimeException.class).when(volumeApiServiceImpl).expungeVolumesInPrimaryStorageIfNeeded(volumeVoMock);
|
||||
|
||||
Mockito.doReturn(true).when(volumeDaoMock).remove(volumeMockId);
|
||||
Mockito.doReturn(true).when(volumeApiServiceImpl).stateTransitTo(volumeVoMock, Volume.Event.DestroyRequested);
|
||||
|
||||
volumeApiServiceImpl.deleteVolume(volumeMockId, accountMock);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue