diff --git a/api/src/com/cloud/storage/VolumeApiService.java b/api/src/com/cloud/storage/VolumeApiService.java index d5a31d3365d..cf13cd671a9 100644 --- a/api/src/com/cloud/storage/VolumeApiService.java +++ b/api/src/com/cloud/storage/VolumeApiService.java @@ -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); diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java index f93f4efac83..e27b7516868 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java @@ -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); diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java index 04aefbec31f..c56fef70b75 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java @@ -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 createVolumeAsync(VolumeInfo volume, DataStore store); /** * Delete volume - * - * @param volumeId - * @return - * @throws ConcurrentOperationException */ AsyncCallFuture expungeVolumeAsync(VolumeInfo volume); - /** - * - */ boolean cloneVolume(long volumeId, long baseVolId); - /** - * - */ AsyncCallFuture createVolumeFromSnapshot(VolumeInfo volume, DataStore store, SnapshotInfo snapshot); VolumeEntity getVolumeEntity(long volumeId); - AsyncCallFuture createManagedStorageVolumeFromTemplateAsync(VolumeInfo volumeInfo, long destDataStoreId, - TemplateInfo srcTemplateInfo, long destHostId); + AsyncCallFuture createManagedStorageVolumeFromTemplateAsync(VolumeInfo volumeInfo, long destDataStoreId, TemplateInfo srcTemplateInfo, long destHostId); - AsyncCallFuture createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId, - TemplateInfo template); + AsyncCallFuture createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId, TemplateInfo template); AsyncCallFuture copyVolume(VolumeInfo srcVolume, DataStore destStore); @@ -93,11 +78,11 @@ public interface VolumeService { AsyncCallFuture migrateVolumes(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost); - boolean destroyVolume(long volumeId) throws ConcurrentOperationException; + void destroyVolume(long volumeId); AsyncCallFuture registerVolume(VolumeInfo volume, DataStore store); - public Pair registerVolumeForPostUpload(VolumeInfo volume, DataStore store); + public Pair registerVolumeForPostUpload(VolumeInfo volume, DataStore store); AsyncCallFuture resize(VolumeInfo volume); @@ -108,5 +93,4 @@ public interface VolumeService { SnapshotInfo takeSnapshot(VolumeInfo volume); VolumeInfo updateHypervisorSnapshotReserveForVolume(DiskOffering diskOffering, long volumeId, HypervisorType hyperType); - -} +} \ No newline at end of file diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index f02fdc495f9..a9035d4100f 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -30,8 +30,6 @@ import java.util.concurrent.ExecutionException; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.log4j.Logger; - import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; @@ -67,6 +65,7 @@ import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; +import org.apache.log4j.Logger; import com.cloud.agent.api.to.DataTO; import com.cloud.agent.api.to.DiskTO; @@ -225,8 +224,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati // Find a destination storage pool with the specified criteria DiskOffering diskOffering = _entityMgr.findById(DiskOffering.class, volume.getDiskOfferingId()); - DiskProfile dskCh = new DiskProfile(volume.getId(), volume.getVolumeType(), volume.getName(), diskOffering.getId(), diskOffering.getDiskSize(), - diskOffering.getTagsArray(), diskOffering.getUseLocalStorage(), diskOffering.isRecreatable(), null); + DiskProfile dskCh = new DiskProfile(volume.getId(), volume.getVolumeType(), volume.getName(), diskOffering.getId(), diskOffering.getDiskSize(), diskOffering.getTagsArray(), + diskOffering.getUseLocalStorage(), diskOffering.isRecreatable(), null); dskCh.setHyperType(dataDiskHyperType); storageMgr.setDiskProfileThrottling(dskCh, null, diskOffering); @@ -249,17 +248,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } public VolumeVO allocateDuplicateVolumeVO(Volume oldVol, Long templateId) { - VolumeVO newVol = new VolumeVO(oldVol.getVolumeType(), - oldVol.getName(), - oldVol.getDataCenterId(), - oldVol.getDomainId(), - oldVol.getAccountId(), - oldVol.getDiskOfferingId(), - oldVol.getProvisioningType(), - oldVol.getSize(), - oldVol.getMinIops(), - oldVol.getMaxIops(), - oldVol.get_iScsiName()); + VolumeVO newVol = new VolumeVO(oldVol.getVolumeType(), oldVol.getName(), oldVol.getDataCenterId(), oldVol.getDomainId(), oldVol.getAccountId(), oldVol.getDiskOfferingId(), + oldVol.getProvisioningType(), oldVol.getSize(), oldVol.getMinIops(), oldVol.getMaxIops(), oldVol.get_iScsiName()); if (templateId != null) { newVol.setTemplateId(templateId); } else { @@ -398,8 +388,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati DataStoreRole dataStoreRole = getDataStoreRole(snapshot); SnapshotInfo snapInfo = snapshotFactory.getSnapshot(snapshot.getId(), dataStoreRole); - - if(snapInfo == null && dataStoreRole == DataStoreRole.Image) { + if (snapInfo == null && dataStoreRole == DataStoreRole.Image) { // snapshot is not backed up to secondary, let's do that now. snapInfo = snapshotFactory.getSnapshot(snapshot.getId(), DataStoreRole.Primary); @@ -480,8 +469,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati throw new CloudRuntimeException("Template " + template.getName() + " has not been completely downloaded to zone " + dc.getId()); } - return new DiskProfile(volume.getId(), volume.getVolumeType(), volume.getName(), diskOffering.getId(), ss.getSize(), diskOffering.getTagsArray(), - diskOffering.getUseLocalStorage(), diskOffering.isRecreatable(), Storage.ImageFormat.ISO != template.getFormat() ? template.getId() : null); + return new DiskProfile(volume.getId(), volume.getVolumeType(), volume.getName(), diskOffering.getId(), ss.getSize(), diskOffering.getTagsArray(), diskOffering.getUseLocalStorage(), + diskOffering.isRecreatable(), Storage.ImageFormat.ISO != template.getFormat() ? template.getId() : null); } else { return new DiskProfile(volume.getId(), volume.getVolumeType(), volume.getName(), diskOffering.getId(), diskOffering.getDiskSize(), diskOffering.getTagsArray(), diskOffering.getUseLocalStorage(), diskOffering.isRecreatable(), null); @@ -489,8 +478,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } @DB - public VolumeInfo copyVolumeFromSecToPrimary(VolumeInfo volume, VirtualMachine vm, VirtualMachineTemplate template, DataCenter dc, Pod pod, Long clusterId, - ServiceOffering offering, DiskOffering diskOffering, List avoids, long size, HypervisorType hyperType) throws NoTransitionException { + public VolumeInfo copyVolumeFromSecToPrimary(VolumeInfo volume, VirtualMachine vm, VirtualMachineTemplate template, DataCenter dc, Pod pod, Long clusterId, ServiceOffering offering, + DiskOffering diskOffering, List avoids, long size, HypervisorType hyperType) throws NoTransitionException { final HashSet avoidPools = new HashSet(avoids); DiskProfile dskCh = createDiskCharacteristics(volume, template, dc, diskOffering); @@ -519,8 +508,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } @DB - public VolumeInfo createVolume(VolumeInfo volume, VirtualMachine vm, VirtualMachineTemplate template, DataCenter dc, Pod pod, Long clusterId, ServiceOffering offering, - DiskOffering diskOffering, List avoids, long size, HypervisorType hyperType) { + public VolumeInfo createVolume(VolumeInfo volume, VirtualMachine vm, VirtualMachineTemplate template, DataCenter dc, Pod pod, Long clusterId, ServiceOffering offering, DiskOffering diskOffering, + List avoids, long size, HypervisorType hyperType) { // update the volume's hv_ss_reserve (hypervisor snapshot reserve) from a disk offering (used for managed storage) volume = volService.updateHypervisorSnapshotReserveForVolume(diskOffering, volume.getId(), hyperType); @@ -656,12 +645,13 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } protected DiskProfile toDiskProfile(Volume vol, DiskOffering offering) { - return new DiskProfile(vol.getId(), vol.getVolumeType(), vol.getName(), offering.getId(), vol.getSize(), offering.getTagsArray(), offering.getUseLocalStorage(), - offering.isRecreatable(), vol.getTemplateId()); + return new DiskProfile(vol.getId(), vol.getVolumeType(), vol.getName(), offering.getId(), vol.getSize(), offering.getTagsArray(), offering.getUseLocalStorage(), offering.isRecreatable(), + vol.getTemplateId()); } @Override - public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, VirtualMachine vm, VirtualMachineTemplate template, Account owner, Long deviceId) { + public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, VirtualMachine vm, VirtualMachineTemplate template, Account owner, + Long deviceId) { if (size == null) { size = offering.getDiskSize(); } else { @@ -671,17 +661,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati minIops = minIops != null ? minIops : offering.getMinIops(); maxIops = maxIops != null ? maxIops : offering.getMaxIops(); - VolumeVO vol = new VolumeVO(type, - name, - vm.getDataCenterId(), - owner.getDomainId(), - owner.getId(), - offering.getId(), - offering.getProvisioningType(), - size, - minIops, - maxIops, - null); + VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), offering.getProvisioningType(), size, minIops, maxIops, null); if (vm != null) { vol.setInstanceId(vm.getId()); } @@ -719,11 +699,12 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } @Override - public DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering offering, Long rootDisksize, Long minIops, Long maxIops, VirtualMachineTemplate template, VirtualMachine vm, Account owner) { + public DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering offering, Long rootDisksize, Long minIops, Long maxIops, VirtualMachineTemplate template, VirtualMachine vm, + Account owner) { assert (template.getFormat() != ImageFormat.ISO) : "ISO is not a template really...."; Long size = _tmpltMgr.getTemplateSize(template.getId(), vm.getDataCenterId()); - if (rootDisksize != null ) { + if (rootDisksize != null) { rootDisksize = rootDisksize * 1024 * 1024 * 1024; if (rootDisksize > size) { s_logger.debug("Using root disk size of " + rootDisksize + " Bytes for volume " + name); @@ -736,17 +717,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati minIops = minIops != null ? minIops : offering.getMinIops(); maxIops = maxIops != null ? maxIops : offering.getMaxIops(); - VolumeVO vol = new VolumeVO(type, - name, - vm.getDataCenterId(), - owner.getDomainId(), - owner.getId(), - offering.getId(), - offering.getProvisioningType(), - size, - minIops, - maxIops, - null); + VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), offering.getProvisioningType(), size, minIops, maxIops, null); vol.setFormat(getSupportedImageFormatForCluster(template.getHypervisorType())); if (vm != null) { vol.setInstanceId(vm.getId()); @@ -767,7 +738,6 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati vol.setDisplayVolume(userVm.isDisplayVm()); } - vol = _volsDao.persist(vol); // Create event and update resource count for volumes if vm is a user vm @@ -817,16 +787,15 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } } - private VolumeInfo copyVolume(StoragePool rootDiskPool, VolumeInfo volume, VirtualMachine vm, VirtualMachineTemplate rootDiskTmplt, DataCenter dcVO, Pod pod, - DiskOffering diskVO, ServiceOffering svo, HypervisorType rootDiskHyperType) throws NoTransitionException { + private VolumeInfo copyVolume(StoragePool rootDiskPool, VolumeInfo volume, VirtualMachine vm, VirtualMachineTemplate rootDiskTmplt, DataCenter dcVO, Pod pod, DiskOffering diskVO, + ServiceOffering svo, HypervisorType rootDiskHyperType) throws NoTransitionException { if (!isSupportedImageFormatForCluster(volume, rootDiskHyperType)) { - throw new InvalidParameterValueException("Failed to attach volume to VM since volumes format " + volume.getFormat().getFileExtension() - + " is not compatible with the vm hypervisor type"); + throw new InvalidParameterValueException("Failed to attach volume to VM since volumes format " + volume.getFormat().getFileExtension() + " is not compatible with the vm hypervisor type"); } - VolumeInfo volumeOnPrimary = copyVolumeFromSecToPrimary(volume, vm, rootDiskTmplt, dcVO, pod, rootDiskPool.getClusterId(), svo, diskVO, new ArrayList(), - volume.getSize(), rootDiskHyperType); + VolumeInfo volumeOnPrimary = copyVolumeFromSecToPrimary(volume, vm, rootDiskTmplt, dcVO, pod, rootDiskPool.getClusterId(), svo, diskVO, new ArrayList(), volume.getSize(), + rootDiskHyperType); return volumeOnPrimary; } @@ -871,8 +840,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati long vmTemplateId = vm.getTemplateId(); if (volTemplateId != null && volTemplateId.longValue() != vmTemplateId) { if (s_logger.isDebugEnabled()) { - s_logger.debug("switchVolume: Old Volume's templateId: " + volTemplateId + " does not match the VM's templateId: " + vmTemplateId - + ", updating templateId in the new Volume"); + s_logger.debug("switchVolume: Old Volume's templateId: " + volTemplateId + " does not match the VM's templateId: " + vmTemplateId + ", updating templateId in the new Volume"); } templateIdToUse = vmTemplateId; } @@ -1108,8 +1076,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati for (VolumeVO vol : vols) { VolumeInfo volumeInfo = volFactory.getVolume(vol.getId()); DataTO volTO = volumeInfo.getTO(); - DiskTO disk = storageMgr.getDiskWithThrottling(volTO, vol.getVolumeType(), vol.getDeviceId(), vol.getPath(), - vm.getServiceOfferingId(), vol.getDiskOfferingId()); + DiskTO disk = storageMgr.getDiskWithThrottling(volTO, vol.getVolumeType(), vol.getDeviceId(), vol.getPath(), vm.getServiceOfferingId(), vol.getDiskOfferingId()); DataStore dataStore = dataStoreMgr.getDataStore(vol.getPoolId(), DataStoreRole.Primary); disk.setDetails(getDetails(volumeInfo, dataStore)); @@ -1217,7 +1184,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } else { storageMigrationEnabled = StorageMigrationEnabled.value(); } - if(storageMigrationEnabled){ + if (storageMigrationEnabled) { if (s_logger.isDebugEnabled()) { s_logger.debug("Shared volume " + vol + " will be migrated on storage pool " + assignedPool + " assigned by deploymentPlanner"); } @@ -1237,8 +1204,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } } else { if (vol.getPoolId() == null) { - throw new StorageUnavailableException("Volume has no pool associate and also no storage pool assigned in DeployDestination, Unable to create " + vol, - Volume.class, vol.getId()); + throw new StorageUnavailableException("Volume has no pool associate and also no storage pool assigned in DeployDestination, Unable to create " + vol, Volume.class, vol.getId()); } if (s_logger.isDebugEnabled()) { s_logger.debug("No need to recreate the volume: " + vol + ", since it already has a pool assigned: " + vol.getPoolId() + ", adding disk to VM"); @@ -1319,8 +1285,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati long hostId = vm.getVirtualMachine().getHostId(); future = volService.createManagedStorageVolumeFromTemplateAsync(volume, destPool.getId(), templ, hostId); - } - else { + } else { future = volService.createVolumeFromTemplateAsync(volume, destPool.getId(), templ); } } @@ -1398,7 +1363,6 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati if (oldHostId != hostId) { Host oldHost = _hostDao.findById(oldHostId); - Host host = _hostDao.findById(hostId); DataStore storagePool = dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary); storageMgr.removeStoragePoolFromCluster(oldHostId, vol.get_iScsiName(), pool); @@ -1417,8 +1381,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati VolumeInfo volumeInfo = volFactory.getVolume(vol.getId()); DataTO volTO = volumeInfo.getTO(); - DiskTO disk = storageMgr.getDiskWithThrottling(volTO, vol.getVolumeType(), vol.getDeviceId(), vol.getPath(), - vm.getServiceOfferingId(), vol.getDiskOfferingId()); + DiskTO disk = storageMgr.getDiskWithThrottling(volTO, vol.getVolumeType(), vol.getDeviceId(), vol.getPath(), vm.getServiceOfferingId(), vol.getDiskOfferingId()); DataStore dataStore = dataStoreMgr.getDataStore(vol.getPoolId(), DataStoreRole.Primary); disk.setDetails(getDetails(volumeInfo, dataStore)); @@ -1434,13 +1397,12 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati cloneType = UserVmCloneType.full; } UserVmCloneSettingVO cloneSettingVO = _vmCloneSettingDao.findByVmId(vm.getId()); - if (cloneSettingVO != null){ - if (! cloneSettingVO.getCloneType().equals(cloneType.toString())){ + if (cloneSettingVO != null) { + if (!cloneSettingVO.getCloneType().equals(cloneType.toString())) { cloneSettingVO.setCloneType(cloneType.toString()); _vmCloneSettingDao.update(cloneSettingVO.getVmId(), cloneSettingVO); } - } - else { + } else { UserVmCloneSettingVO vmCloneSettingVO = new UserVmCloneSettingVO(vm.getId(), cloneType.toString()); _vmCloneSettingDao.persist(vmCloneSettingVO); } @@ -1465,8 +1427,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati return true; } - public static final ConfigKey MaxVolumeSize = new ConfigKey(Long.class, "storage.max.volume.size", "Storage", "2000", "The maximum size for a volume (in GB).", - true); + public static final ConfigKey MaxVolumeSize = new ConfigKey(Long.class, "storage.max.volume.size", "Storage", "2000", "The maximum size for a volume (in GB).", true); public static final ConfigKey RecreatableSystemVmEnabled = new ConfigKey(Boolean.class, "recreate.systemvm.enabled", "Advanced", "false", "If true, will recreate system vm root disk whenever starting system vm", true); @@ -1478,8 +1439,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati "Enable/disable storage migration across primary storage", true); static final ConfigKey VolumeUrlCheck = new ConfigKey("Advanced", Boolean.class, "volume.url.check", "true", - "Check the url for a volume before downloading it from the management server. Set to flase when you managment has no internet access.", - true); + "Check the url for a volume before downloading it from the management server. Set to flase when you managment has no internet access.", true); @Override public ConfigKey[] getConfigKeys() { @@ -1507,9 +1467,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati _volsDao.remove(volume.getId()); } - if(volume.getState().equals(Volume.State.Attaching)) { - s_logger.warn("Vol: " + volume.getName() + " failed to attach to VM: " + _userVmDao.findById(vmId).getHostName() + - " on last mgt server stop, changing state back to Ready"); + if (volume.getState().equals(Volume.State.Attaching)) { + s_logger.warn("Vol: " + volume.getName() + " failed to attach to VM: " + _userVmDao.findById(vmId).getHostName() + " on last mgt server stop, changing state back to Ready"); volume.setState(Volume.State.Ready); _volsDao.update(volumeId, volume); } @@ -1549,8 +1508,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati @Override public void cleanupStorageJobs() { //clean up failure jobs related to volume - List jobs = _jobMgr.findFailureAsyncJobs(VmWorkAttachVolume.class.getName(), - VmWorkMigrateVolume.class.getName(), VmWorkTakeVolumeSnapshot.class.getName()); + List jobs = _jobMgr.findFailureAsyncJobs(VmWorkAttachVolume.class.getName(), VmWorkMigrateVolume.class.getName(), VmWorkTakeVolumeSnapshot.class.getName()); for (AsyncJobVO job : jobs) { try { @@ -1592,8 +1550,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } // FIXME - All this is boiler plate code and should be done as part of state transition. This shouldn't be part of orchestrator. // publish usage event for the volume - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), Volume.class.getName(), + volume.getUuid(), volume.isDisplayVolume()); _resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume, volume.isDisplay()); _resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.primary_storage, volume.isDisplay(), new Long(volume.getSize())); } catch (Exception e) { @@ -1619,13 +1577,16 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati VolumeVO vol = _volsDao.findById(volumeId); boolean needUpdate = false; // Volume path is not getting updated in the DB, need to find reason and fix the issue. - if (vol.getPath() == null) + if (vol.getPath() == null) { return; - if (!vol.getPath().equalsIgnoreCase(path)) + } + if (!vol.getPath().equalsIgnoreCase(path)) { needUpdate = true; + } - if (chainInfo != null && (vol.getChainInfo() == null || !chainInfo.equalsIgnoreCase(vol.getChainInfo()))) + if (chainInfo != null && (vol.getChainInfo() == null || !chainInfo.equalsIgnoreCase(vol.getChainInfo()))) { needUpdate = true; + } if (needUpdate) { s_logger.info("Update volume disk chain info. vol: " + vol.getId() + ", " + vol.getPath() + " -> " + path + ", " + vol.getChainInfo() + " -> " + chainInfo); diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java index 36313058e92..d2979f7415d 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java @@ -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 _future; - public ManagedCreateBaseImageContext(AsyncCompletionCallback callback, VolumeInfo volumeInfo, - PrimaryDataStore primaryDatastore, TemplateInfo templateInfo, AsyncCallFuture future) { + public ManagedCreateBaseImageContext(AsyncCompletionCallback callback, VolumeInfo volumeInfo, PrimaryDataStore primaryDatastore, TemplateInfo templateInfo, + AsyncCallFuture future) { super(callback); _volumeInfo = volumeInfo; @@ -488,8 +485,8 @@ public class VolumeServiceImpl implements VolumeService { final DataObject destObj; long templatePoolId; - public CreateBaseImageContext(AsyncCompletionCallback callback, VolumeInfo volume, PrimaryDataStore datastore, TemplateInfo srcTemplate, - AsyncCallFuture future, DataObject destObj, long templatePoolId) { + public CreateBaseImageContext(AsyncCompletionCallback callback, VolumeInfo volume, PrimaryDataStore datastore, TemplateInfo srcTemplate, AsyncCallFuture 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 context = - new CreateBaseImageContext(null, volume, dataStore, template, future, templateOnPrimaryStoreObj, templatePoolRefId); + CreateBaseImageContext context = new CreateBaseImageContext(null, volume, dataStore, template, future, templateOnPrimaryStoreObj, templatePoolRefId); AsyncCallbackDispatcher 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 callback, - ManagedCreateBaseImageContext context) { + protected Void managedCopyBaseImageCallback(AsyncCallbackDispatcher callback, ManagedCreateBaseImageContext 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 callback, DataObject vo, DataStore primaryStore, DataObject templateOnStore, - AsyncCallFuture future, SnapshotInfo snapshot) { + public CreateVolumeFromBaseImageContext(AsyncCompletionCallback callback, DataObject vo, DataStore primaryStore, DataObject templateOnStore, AsyncCallFuture 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 context = - new CreateVolumeFromBaseImageContext(null, volumeOnPrimaryStorage, pd, templateOnPrimaryStore, future, null); + CreateVolumeFromBaseImageContext context = new CreateVolumeFromBaseImageContext(null, volumeOnPrimaryStorage, pd, templateOnPrimaryStore, future, null); AsyncCallbackDispatcher 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 callback, - CreateVolumeFromBaseImageContext context) { + protected Void createVolumeFromBaseImageCallBack(AsyncCallbackDispatcher callback, CreateVolumeFromBaseImageContext 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 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 copyContext = new CreateBaseImageContext<>( - null, null, destPrimaryDataStore, srcTemplateInfo, - copyTemplateFuture, templateOnPrimary, templatePoolRefId - ); + // copy the template from sec storage to the created volume + CreateBaseImageContext copyContext = new CreateBaseImageContext<>(null, null, destPrimaryDataStore, srcTemplateInfo, copyTemplateFuture, templateOnPrimary, + templatePoolRefId); AsyncCallbackDispatcher 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 future) { + private void createManagedVolumeCloneTemplateAsync(VolumeInfo volumeInfo, TemplateInfo templateOnPrimary, PrimaryDataStore destPrimaryDataStore, AsyncCallFuture 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 context = - new CreateVolumeFromBaseImageContext<>(null, volumeInfo, destPrimaryDataStore, templateOnPrimary, future, null); + CreateVolumeFromBaseImageContext context = new CreateVolumeFromBaseImageContext<>(null, volumeInfo, destPrimaryDataStore, templateOnPrimary, future, null); AsyncCallbackDispatcher 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 future) { + private void createManagedVolumeCopyTemplateAsync(VolumeInfo volumeInfo, PrimaryDataStore primaryDataStore, TemplateInfo srcTemplateInfo, Host destHost, AsyncCallFuture 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 context = new ManagedCreateBaseImageContext(null, volumeInfo, - primaryDataStore, srcTemplateInfo, future); + ManagedCreateBaseImageContext context = new ManagedCreateBaseImageContext(null, volumeInfo, primaryDataStore, srcTemplateInfo, future); AsyncCallbackDispatcher 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 createManagedStorageVolumeFromTemplateAsync(VolumeInfo volumeInfo, long destDataStoreId, - TemplateInfo srcTemplateInfo, long destHostId) { + public AsyncCallFuture 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 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 context = - new CreateVolumeFromBaseImageContext(null, volume, store, volumeOnStore, future, snapshot); + CreateVolumeFromBaseImageContext context = new CreateVolumeFromBaseImageContext(null, volume, store, volumeOnStore, future, snapshot); AsyncCallbackDispatcher 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 callback, - CreateVolumeFromBaseImageContext context) { + protected Void createVolumeFromSnapshotCallback(AsyncCallbackDispatcher callback, CreateVolumeFromBaseImageContext 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 future; - public CopyVolumeContext(AsyncCompletionCallback callback, AsyncCallFuture future, VolumeInfo srcVolume, VolumeInfo destVolume, - DataStore destStore) { + public CopyVolumeContext(AsyncCompletionCallback callback, AsyncCallFuture 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 callback, CopyVolumeContext context) { + protected Void copyVolumeFromImageToPrimaryCallback(AsyncCallbackDispatcher callback, CopyVolumeContext 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 callback, CopyVolumeContext context) { + protected Void copyVolumeFromPrimaryToImageCallback(AsyncCallbackDispatcher callback, CopyVolumeContext 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 callback, AsyncCallFuture future, VolumeInfo srcVolume, VolumeInfo destVolume, - DataStore destStore) { + public MigrateVolumeContext(AsyncCompletionCallback callback, AsyncCallFuture 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 callback, MigrateVmWithVolumesContext context) { + protected Void migrateVmWithVolumesCallBack(AsyncCallbackDispatcher callback, MigrateVmWithVolumesContext context) { Map volumeToPool = context.volumeToPool; CopyCommandResult result = callback.getResult(); AsyncCallFuture future = context.future; @@ -1715,7 +1670,7 @@ public class VolumeServiceImpl implements VolumeService { } @Override - public Pair registerVolumeForPostUpload(VolumeInfo volume, DataStore store) { + public Pair 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 callback, CreateVolumeContext 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 entry : volumeInfos.entrySet()) { + for (Map.Entry 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); diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 46799c76cb0..610789f5de2 100644 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -38,12 +38,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import javax.inject.Inject; -import javax.naming.ConfigurationException; -import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd; import org.apache.cloudstack.api.command.admin.storage.CreateSecondaryStagingStoreCmd; import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd; @@ -64,11 +59,13 @@ import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; import org.apache.cloudstack.engine.subsystem.api.storage.ImageStoreProvider; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; @@ -82,8 +79,8 @@ import org.apache.cloudstack.framework.async.AsyncCallFuture; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.cloudstack.storage.command.DettachCommand; import org.apache.cloudstack.managed.context.ManagedContextRunnable; +import org.apache.cloudstack.storage.command.DettachCommand; import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; @@ -98,6 +95,9 @@ import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao; import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO; import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity; import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; @@ -176,7 +176,6 @@ import com.cloud.user.dao.UserDao; import com.cloud.utils.DateUtil; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; -import com.cloud.utils.StringUtils; import com.cloud.utils.UriUtils; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.component.ManagerBase; @@ -467,7 +466,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } @Override - public boolean configure(String name, Map params) throws ConfigurationException { + public boolean configure(String name, Map params) { Map configs = _configDao.getConfiguration("management-server", params); @@ -476,8 +475,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C _agentMgr.registerForHostEvents(new StoragePoolMonitor(this, _storagePoolDao, _dataStoreProviderMgr), true, false, true); - s_logger.info("Storage cleanup enabled: " + StorageCleanupEnabled.value() + ", interval: " + StorageCleanupInterval.value() + ", delay: " + StorageCleanupDelay.value() + - ", template cleanup enabled: " + TemplateCleanupEnabled.value()); + s_logger.info("Storage cleanup enabled: " + StorageCleanupEnabled.value() + ", interval: " + StorageCleanupInterval.value() + ", delay: " + StorageCleanupDelay.value() + + ", template cleanup enabled: " + TemplateCleanupEnabled.value()); String cleanupInterval = configs.get("extract.url.cleanup.interval"); _downloadUrlCleanupInterval = NumbersUtil.parseInt(cleanupInterval, 7200); @@ -525,7 +524,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 @@ -586,8 +585,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } if (pool == null) { //the path can be different, but if they have the same uuid, assume they are the same storage - pool = _storagePoolDao.findPoolByHostPath(host.getDataCenterId(), host.getPodId(), hostAddress, null, - pInfo.getUuid()); + pool = _storagePoolDao.findPoolByHostPath(host.getDataCenterId(), host.getPodId(), hostAddress, null, pInfo.getUuid()); if (pool != null) { s_logger.debug("Found a storage pool: " + pInfo.getUuid() + ", but with different hostpath " + pInfo.getHostPath() + ", still treat it as the same pool"); } @@ -628,8 +626,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } @Override - public PrimaryDataStoreInfo createPool(CreateStoragePoolCmd cmd) throws ResourceInUseException, IllegalArgumentException, UnknownHostException, - ResourceUnavailableException { + public PrimaryDataStoreInfo createPool(CreateStoragePoolCmd cmd) throws ResourceInUseException, IllegalArgumentException, UnknownHostException, ResourceUnavailableException { String providerName = cmd.getStorageProviderName(); DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(providerName); @@ -675,7 +672,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } else { throw new InvalidParameterValueException("Missing parameter hypervisor. Hypervisor type is required to create zone wide primary storage."); } - if (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.VMware && hypervisorType != HypervisorType.Hyperv && hypervisorType != HypervisorType.LXC && hypervisorType != HypervisorType.Any) { + if (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.VMware && hypervisorType != HypervisorType.Hyperv && hypervisorType != HypervisorType.LXC + && hypervisorType != HypervisorType.Any) { throw new InvalidParameterValueException("zone wide storage pool is not supported for hypervisor type " + hypervisor); } } @@ -716,7 +714,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C lifeCycle.attachZone(store, zoneScope, hypervisorType); } } catch (Exception e) { - s_logger.debug("Failed to add data store: "+e.getMessage(), e); + s_logger.debug("Failed to add data store: " + e.getMessage(), e); try { // clean up the db, just absorb the exception thrown in deletion with error logged, so that user can get error for adding data store // not deleting data store. @@ -726,7 +724,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } catch (Exception ex) { s_logger.debug("Failed to clean up storage pool: " + ex.getMessage()); } - throw new CloudRuntimeException("Failed to add data store: "+e.getMessage(), e); + throw new CloudRuntimeException("Failed to add data store: " + e.getMessage(), e); } return (PrimaryDataStoreInfo)_dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Primary); @@ -752,8 +750,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C @ActionEvent(eventType = EventTypes.EVENT_DISABLE_PRIMARY_STORAGE, eventDescription = "disable storage pool") private void disablePrimaryStoragePool(StoragePoolVO primaryStorage) { if (!primaryStorage.getStatus().equals(StoragePoolStatus.Up)) { - throw new InvalidParameterValueException("Primary storage with id " + primaryStorage.getId() + " cannot be disabled. Storage pool state : " + - primaryStorage.getStatus().toString()); + throw new InvalidParameterValueException("Primary storage with id " + primaryStorage.getId() + " cannot be disabled. Storage pool state : " + primaryStorage.getStatus().toString()); } DataStoreProvider provider = _dataStoreProviderMgr.getDataStoreProvider(primaryStorage.getStorageProviderName()); @@ -765,8 +762,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C @ActionEvent(eventType = EventTypes.EVENT_ENABLE_PRIMARY_STORAGE, eventDescription = "enable storage pool") private void enablePrimaryStoragePool(StoragePoolVO primaryStorage) { if (!primaryStorage.getStatus().equals(StoragePoolStatus.Disabled)) { - throw new InvalidParameterValueException("Primary storage with id " + primaryStorage.getId() + " cannot be enabled. Storage pool state : " + - primaryStorage.getStatus().toString()); + throw new InvalidParameterValueException("Primary storage with id " + primaryStorage.getId() + " cannot be enabled. Storage pool state : " + primaryStorage.getStatus().toString()); } DataStoreProvider provider = _dataStoreProviderMgr.getDataStoreProvider(primaryStorage.getStorageProviderName()); @@ -863,8 +859,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C final Answer answer = _agentMgr.easySend(hostId, cmd); if (answer == null || !answer.getResult()) { - String errMsg = "Error interacting with host (related to DeleteStoragePoolCommand)" + - (StringUtils.isNotBlank(answer.getDetails()) ? ": " + answer.getDetails() : ""); + String errMsg = "Error interacting with host (related to DeleteStoragePoolCommand)" + (StringUtils.isNotBlank(answer.getDetails()) ? ": " + answer.getDetails() : ""); s_logger.error(errMsg); @@ -965,8 +960,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C // All this is for the inaccuracy of floats for big number multiplication. BigDecimal overProvFactor = getStorageOverProvisioningFactor(storagePool.getId()); totalOverProvCapacity = overProvFactor.multiply(new BigDecimal(storagePool.getCapacityBytes())).longValue(); - s_logger.debug("Found storage pool " + storagePool.getName() + " of type " + storagePool.getPoolType().toString() + " with overprovisioning factor " - + overProvFactor.toString()); + s_logger.debug("Found storage pool " + storagePool.getName() + " of type " + storagePool.getPoolType().toString() + " with overprovisioning factor " + overProvFactor.toString()); s_logger.debug("Total over provisioned capacity calculated is " + overProvFactor + " * " + storagePool.getCapacityBytes()); } else { s_logger.debug("Found storage pool " + storagePool.getName() + " of type " + storagePool.getPoolType().toString()); @@ -992,19 +986,18 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C if (storagePool.getScope() == ScopeType.HOST) { List stoargePoolHostVO = _storagePoolHostDao.listByPoolId(storagePool.getId()); - if(stoargePoolHostVO != null && !stoargePoolHostVO.isEmpty()){ + if (stoargePoolHostVO != null && !stoargePoolHostVO.isEmpty()) { HostVO host = _hostDao.findById(stoargePoolHostVO.get(0).getHostId()); - if(host != null){ + if (host != null) { capacityState = (host.getResourceState() == ResourceState.Disabled) ? CapacityState.Disabled : CapacityState.Enabled; } } } if (capacities.size() == 0) { - CapacityVO capacity = - new CapacityVO(storagePool.getId(), storagePool.getDataCenterId(), storagePool.getPodId(), storagePool.getClusterId(), allocated, totalOverProvCapacity, - capacityType); + CapacityVO capacity = new CapacityVO(storagePool.getId(), storagePool.getDataCenterId(), storagePool.getPodId(), storagePool.getClusterId(), allocated, totalOverProvCapacity, + capacityType); capacity.setCapacityState(capacityState); _capacityDao.persist(capacity); } else { @@ -1016,8 +1009,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C _capacityDao.update(capacity.getId(), capacity); } } - s_logger.debug("Successfully set Capacity - " + totalOverProvCapacity + " for capacity type - " + capacityType + " , DataCenterId - " + - storagePool.getDataCenterId() + ", HostOrPoolId - " + storagePool.getId() + ", PodId " + storagePool.getPodId()); + s_logger.debug("Successfully set Capacity - " + totalOverProvCapacity + " for capacity type - " + capacityType + " , DataCenterId - " + storagePool.getDataCenterId() + ", HostOrPoolId - " + + storagePool.getId() + ", PodId " + storagePool.getPodId()); } @Override @@ -1045,8 +1038,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C hostIds.removeAll(hostIdsToAvoid); } if (hostIds == null || hostIds.isEmpty()) { - throw new StorageUnavailableException("Unable to send command to the pool " + pool.getId() + " due to there is no enabled hosts up in this cluster", - pool.getId()); + throw new StorageUnavailableException("Unable to send command to the pool " + pool.getId() + " due to there is no enabled hosts up in this cluster", pool.getId()); } for (Long hostId : hostIds) { try { @@ -1088,20 +1080,19 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C try { List unusedTemplatesInPool = _tmpltMgr.getUnusedTemplatesInPool(pool); - s_logger.debug("Storage pool garbage collector found " + unusedTemplatesInPool.size() + " templates to clean up in storage pool: " + - pool.getName()); + s_logger.debug("Storage pool garbage collector found " + unusedTemplatesInPool.size() + " templates to clean up in storage pool: " + pool.getName()); for (VMTemplateStoragePoolVO templatePoolVO : unusedTemplatesInPool) { if (templatePoolVO.getDownloadState() != VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { - s_logger.debug("Storage pool garbage collector is skipping template with ID: " + templatePoolVO.getTemplateId() + - " on pool " + templatePoolVO.getPoolId() + " because it is not completely downloaded."); + s_logger.debug("Storage pool garbage collector is skipping template with ID: " + templatePoolVO.getTemplateId() + " on pool " + templatePoolVO.getPoolId() + + " because it is not completely downloaded."); continue; } if (!templatePoolVO.getMarkedForGC()) { templatePoolVO.setMarkedForGC(true); _vmTemplatePoolDao.update(templatePoolVO.getId(), templatePoolVO); - s_logger.debug("Storage pool garbage collector has marked template with ID: " + templatePoolVO.getTemplateId() + - " on pool " + templatePoolVO.getPoolId() + " for garbage collection."); + s_logger.debug("Storage pool garbage collector has marked template with ID: " + templatePoolVO.getTemplateId() + " on pool " + templatePoolVO.getPoolId() + + " for garbage collection."); continue; } @@ -1114,8 +1105,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } //destroy snapshots in destroying state in snapshot_store_ref - List ssSnapshots = _snapshotStoreDao.listByState(ObjectInDataStoreStateMachine.State.Destroying); - for(SnapshotDataStoreVO ssSnapshotVO : ssSnapshots){ + List ssSnapshots = _snapshotStoreDao.listByState(ObjectInDataStoreStateMachine.State.Destroying); + for (SnapshotDataStoreVO ssSnapshotVO : ssSnapshots) { try { _snapshotService.deleteSnapshot(snapshotFactory.getSnapshot(ssSnapshotVO.getSnapshotId(), DataStoreRole.Image)); } catch (Exception e) { @@ -1125,7 +1116,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C cleanupSecondaryStorage(recurring); - List vols = _volsDao.listVolumesToBeDestroyed(new Date(System.currentTimeMillis() - ((long) StorageCleanupDelay.value() << 10))); + List vols = _volsDao.listVolumesToBeDestroyed(new Date(System.currentTimeMillis() - ((long)StorageCleanupDelay.value() << 10))); for (VolumeVO vol : vols) { try { // If this fails, just log a warning. It's ideal if we clean up the host-side clustered file @@ -1179,10 +1170,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 @@ -1286,8 +1274,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C if (cluster.getHypervisorType() == HypervisorType.KVM) { volService.revokeAccess(volumeInfo, host, volumeInfo.getDataStore()); - } - else { + } else { DataTO volTO = volFactory.getVolume(volume.getId()).getTO(); DiskTO disk = new DiskTO(volTO, volume.getDeviceId(), volume.getPath(), volume.getVolumeType()); @@ -1367,8 +1354,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C try { long storeId = store.getId(); List destroyedTemplateStoreVOs = _templateStoreDao.listDestroyed(storeId); - s_logger.debug("Secondary storage garbage collector found " + destroyedTemplateStoreVOs.size() + - " templates to cleanup on template_store_ref for store: " + store.getName()); + s_logger.debug("Secondary storage garbage collector found " + destroyedTemplateStoreVOs.size() + " templates to cleanup on template_store_ref for store: " + store.getName()); for (TemplateDataStoreVO destroyedTemplateStoreVO : destroyedTemplateStoreVOs) { if (s_logger.isDebugEnabled()) { s_logger.debug("Deleting template store DB entry: " + destroyedTemplateStoreVO); @@ -1384,8 +1370,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C for (DataStore store : imageStores) { try { List destroyedSnapshotStoreVOs = _snapshotStoreDao.listDestroyed(store.getId()); - s_logger.debug("Secondary storage garbage collector found " + destroyedSnapshotStoreVOs.size() + - " snapshots to cleanup on snapshot_store_ref for store: " + store.getName()); + s_logger.debug("Secondary storage garbage collector found " + destroyedSnapshotStoreVOs.size() + " snapshots to cleanup on snapshot_store_ref for store: " + store.getName()); for (SnapshotDataStoreVO destroyedSnapshotStoreVO : destroyedSnapshotStoreVOs) { // check if this snapshot has child SnapshotInfo snap = snapshotFactory.getSnapshot(destroyedSnapshotStoreVO.getSnapshotId(), store); @@ -1416,8 +1401,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C for (DataStore store : imageStores) { try { List destroyedStoreVOs = _volumeStoreDao.listDestroyed(store.getId()); - s_logger.debug("Secondary storage garbage collector found " + destroyedStoreVOs.size() + " volumes to cleanup on volume_store_ref for store: " + - store.getName()); + s_logger.debug("Secondary storage garbage collector found " + destroyedStoreVOs.size() + " volumes to cleanup on volume_store_ref for store: " + store.getName()); for (VolumeDataStoreVO destroyedStoreVO : destroyedStoreVOs) { if (s_logger.isDebugEnabled()) { s_logger.debug("Deleting volume store DB entry: " + destroyedStoreVO); @@ -1459,8 +1443,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } if (!primaryStorage.getStatus().equals(StoragePoolStatus.Up) && !primaryStorage.getStatus().equals(StoragePoolStatus.ErrorInMaintenance)) { - throw new InvalidParameterValueException("Primary storage with id " + primaryStorageId + " is not ready for migration, as the status is:" + - primaryStorage.getStatus().toString()); + throw new InvalidParameterValueException("Primary storage with id " + primaryStorageId + " is not ready for migration, as the status is:" + primaryStorage.getStatus().toString()); } DataStoreProvider provider = _dataStoreProviderMgr.getDataStoreProvider(primaryStorage.getStorageProviderName()); @@ -1486,8 +1469,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } if (primaryStorage.getStatus().equals(StoragePoolStatus.Up) || primaryStorage.getStatus().equals(StoragePoolStatus.PrepareForMaintenance)) { - throw new StorageUnavailableException("Primary storage with id " + primaryStorageId + " is not ready to complete migration, as the status is:" + - primaryStorage.getStatus().toString(), primaryStorageId); + throw new StorageUnavailableException("Primary storage with id " + primaryStorageId + " is not ready to complete migration, as the status is:" + primaryStorage.getStatus().toString(), + primaryStorageId); } DataStoreProvider provider = _dataStoreProviderMgr.getDataStoreProvider(primaryStorage.getStorageProviderName()); @@ -1498,7 +1481,6 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C return (PrimaryDataStoreInfo)_dataStoreMgr.getDataStore(primaryStorage.getId(), DataStoreRole.Primary); } - protected class StorageGarbageCollector extends ManagedContextRunnable { public StorageGarbageCollector() { @@ -1533,9 +1515,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C for (Long poolId : poolIds) { StoragePoolVO pool = _storagePoolDao.findById(poolId); // check if pool is in an inconsistent state - if (pool != null && - (pool.getStatus().equals(StoragePoolStatus.ErrorInMaintenance) || pool.getStatus().equals(StoragePoolStatus.PrepareForMaintenance) || pool.getStatus() - .equals(StoragePoolStatus.CancelMaintenance))) { + if (pool != null && (pool.getStatus().equals(StoragePoolStatus.ErrorInMaintenance) || pool.getStatus().equals(StoragePoolStatus.PrepareForMaintenance) + || pool.getStatus().equals(StoragePoolStatus.CancelMaintenance))) { _storagePoolWorkDao.removePendingJobsOnMsRestart(vo.getMsid(), poolId); pool.setStatus(StoragePoolStatus.ErrorInMaintenance); _storagePoolDao.update(poolId, pool); @@ -1740,13 +1721,13 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C if (stats != null) { double usedPercentage = ((double)stats.getByteUsed() / (double)totalSize); if (s_logger.isDebugEnabled()) { - s_logger.debug("Checking pool " + pool.getId() + " for storage, totalSize: " + pool.getCapacityBytes() + ", usedBytes: " + stats.getByteUsed() + - ", usedPct: " + usedPercentage + ", disable threshold: " + storageUsedThreshold); + s_logger.debug("Checking pool " + pool.getId() + " for storage, totalSize: " + pool.getCapacityBytes() + ", usedBytes: " + stats.getByteUsed() + ", usedPct: " + usedPercentage + + ", disable threshold: " + storageUsedThreshold); } if (usedPercentage >= storageUsedThreshold) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Insufficient space on pool: " + pool.getId() + " since its usage percentage: " + usedPercentage + - " has crossed the pool.storage.capacity.disablethreshold: " + storageUsedThreshold); + s_logger.debug("Insufficient space on pool: " + pool.getId() + " since its usage percentage: " + usedPercentage + " has crossed the pool.storage.capacity.disablethreshold: " + + storageUsedThreshold); } return false; } @@ -1804,7 +1785,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } // allocated space includes templates - if(s_logger.isDebugEnabled()) { + if (s_logger.isDebugEnabled()) { s_logger.debug("Destination pool id: " + pool.getId()); } @@ -1853,12 +1834,10 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C if (pool.getPoolType().supportsOverProvisioning()) { BigDecimal overProvFactor = getStorageOverProvisioningFactor(pool.getId()); - 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("Total over-provisioned capacity calculated is " + overProvFactor + " * " + pool.getCapacityBytes()); + s_logger.debug("Found storage pool " + poolVO.getName() + " of type " + pool.getPoolType().toString() + " with overprovisioning factor " + overProvFactor.toString()); + s_logger.debug("Total over provisioned capacity calculated is " + overProvFactor + " * " + pool.getCapacityBytes()); } else { totalOverProvCapacity = pool.getCapacityBytes(); @@ -1869,31 +1848,20 @@ 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: " + 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: " + 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; } 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: " + pool.getId() + " for volume allocation: " + volumes.toString() + ", not enough storage, maxSize : " + totalOverProvCapacity + + ", totalAllocatedSize : " + allocatedSizeWithTemplate + ", askingSize : " + totalAskingSize); return false; } @@ -2007,8 +1975,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } @Override - public ImageStore discoverImageStore(String name, String url, String providerName, Long zoneId, Map details) throws IllegalArgumentException, DiscoveryException, - InvalidParameterValueException { + public ImageStore discoverImageStore(String name, String url, String providerName, Long zoneId, Map details) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException { DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(providerName); if (storeProvider == null) { @@ -2056,10 +2023,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } Account account = CallContext.current().getCallingAccount(); - if (Grouping.AllocationState.Disabled == zone.getAllocationState() - && !_accountMgr.isRootAdmin(account.getId())) { - PermissionDeniedException ex = new PermissionDeniedException( - "Cannot perform this operation, Zone with specified id is currently disabled"); + if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getId())) { + PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation, Zone with specified id is currently disabled"); ex.addProxyObject(zone.getUuid(), "dcId"); throw ex; } @@ -2080,7 +2045,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C try { store = lifeCycle.initialize(params); } catch (Exception e) { - if(s_logger.isDebugEnabled()) { + if (s_logger.isDebugEnabled()) { s_logger.debug("Failed to add data store: " + e.getMessage(), e); } throw new CloudRuntimeException("Failed to add data store: " + e.getMessage(), e); @@ -2106,8 +2071,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } @Override - public ImageStore migrateToObjectStore(String name, String url, String providerName, Map details) throws IllegalArgumentException, DiscoveryException, - InvalidParameterValueException { + public ImageStore migrateToObjectStore(String name, String url, String providerName, Map details) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException { // check if current cloud is ready to migrate, we only support cloud with only NFS secondary storages List imgStores = _imageStoreDao.listImageStores(); List nfsStores = new ArrayList(); @@ -2261,8 +2225,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C Account account = CallContext.current().getCallingAccount(); if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getId())) { - PermissionDeniedException ex = new PermissionDeniedException( - "Cannot perform this operation, Zone with specified id is currently disabled"); + PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation, Zone with specified id is currently disabled"); ex.addProxyObject(zone.getUuid(), "dcId"); throw ex; } @@ -2281,8 +2244,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C try { store = lifeCycle.initialize(params); } catch (Exception e) { - s_logger.debug("Failed to add data store: "+e.getMessage(), e); - throw new CloudRuntimeException("Failed to add data store: "+e.getMessage(), e); + s_logger.debug("Failed to add data store: " + e.getMessage(), e); + throw new CloudRuntimeException("Failed to add data store: " + e.getMessage(), e); } return (ImageStore)_dataStoreMgr.getDataStore(store.getId(), DataStoreRole.ImageCache); @@ -2351,18 +2314,18 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } @Override - public void cleanupDownloadUrls(){ + public void cleanupDownloadUrls() { // Cleanup expired volume URLs List volumesOnImageStoreList = _volumeStoreDao.listVolumeDownloadUrls(); HashSet expiredVolumeIds = new HashSet(); HashSet activeVolumeIds = new HashSet(); - for(VolumeDataStoreVO volumeOnImageStore : volumesOnImageStoreList){ + for (VolumeDataStoreVO volumeOnImageStore : volumesOnImageStoreList) { long volumeId = volumeOnImageStore.getVolumeId(); try { long downloadUrlCurrentAgeInSecs = DateUtil.getTimeDifference(DateUtil.now(), volumeOnImageStore.getExtractUrlCreated()); - if(downloadUrlCurrentAgeInSecs < _downloadUrlExpirationInterval){ // URL hasnt expired yet + if (downloadUrlCurrentAgeInSecs < _downloadUrlExpirationInterval) { // URL hasnt expired yet activeVolumeIds.add(volumeId); continue; } @@ -2370,19 +2333,17 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C s_logger.debug("Removing download url " + volumeOnImageStore.getExtractUrl() + " for volume id " + volumeId); // Remove it from image store - ImageStoreEntity secStore = (ImageStoreEntity) _dataStoreMgr.getDataStore(volumeOnImageStore.getDataStoreId(), DataStoreRole.Image); + ImageStoreEntity secStore = (ImageStoreEntity)_dataStoreMgr.getDataStore(volumeOnImageStore.getDataStoreId(), DataStoreRole.Image); secStore.deleteExtractUrl(volumeOnImageStore.getInstallPath(), volumeOnImageStore.getExtractUrl(), Upload.Type.VOLUME); - // Now expunge it from DB since this entry was created only for download purpose + // Now expunge it from DB since this entry was created only for download purpose _volumeStoreDao.expunge(volumeOnImageStore.getId()); - }catch(Throwable th){ - s_logger.warn("Caught exception while deleting download url " +volumeOnImageStore.getExtractUrl() + - " for volume id " + volumeOnImageStore.getVolumeId(), th); + } catch (Throwable th) { + s_logger.warn("Caught exception while deleting download url " + volumeOnImageStore.getExtractUrl() + " for volume id " + volumeOnImageStore.getVolumeId(), th); } } - for(Long volumeId : expiredVolumeIds) - { - if(activeVolumeIds.contains(volumeId)) { + for (Long volumeId : expiredVolumeIds) { + if (activeVolumeIds.contains(volumeId)) { continue; } Volume volume = _volumeDao.findById(volumeId); @@ -2393,27 +2354,26 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C // Cleanup expired template URLs List templatesOnImageStoreList = _templateStoreDao.listTemplateDownloadUrls(); - for(TemplateDataStoreVO templateOnImageStore : templatesOnImageStoreList){ + for (TemplateDataStoreVO templateOnImageStore : templatesOnImageStoreList) { try { long downloadUrlCurrentAgeInSecs = DateUtil.getTimeDifference(DateUtil.now(), templateOnImageStore.getExtractUrlCreated()); - if(downloadUrlCurrentAgeInSecs < _downloadUrlExpirationInterval){ // URL hasnt expired yet + if (downloadUrlCurrentAgeInSecs < _downloadUrlExpirationInterval) { // URL hasnt expired yet continue; } s_logger.debug("Removing download url " + templateOnImageStore.getExtractUrl() + " for template id " + templateOnImageStore.getTemplateId()); // Remove it from image store - ImageStoreEntity secStore = (ImageStoreEntity) _dataStoreMgr.getDataStore(templateOnImageStore.getDataStoreId(), DataStoreRole.Image); + ImageStoreEntity secStore = (ImageStoreEntity)_dataStoreMgr.getDataStore(templateOnImageStore.getDataStoreId(), DataStoreRole.Image); secStore.deleteExtractUrl(templateOnImageStore.getInstallPath(), templateOnImageStore.getExtractUrl(), Upload.Type.TEMPLATE); // Now remove download details from DB. templateOnImageStore.setExtractUrl(null); templateOnImageStore.setExtractUrlCreated(null); _templateStoreDao.update(templateOnImageStore.getId(), templateOnImageStore); - }catch(Throwable th){ - s_logger.warn("caught exception while deleting download url " +templateOnImageStore.getExtractUrl() + - " for template id " +templateOnImageStore.getTemplateId(), th); + } catch (Throwable th) { + s_logger.warn("caught exception while deleting download url " + templateOnImageStore.getExtractUrl() + " for template id " + templateOnImageStore.getTemplateId(), th); } } } @@ -2504,7 +2464,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C public DiskTO getDiskWithThrottling(final DataTO volTO, final Volume.Type volumeType, final long deviceId, final String path, final long offeringId, final long diskOfferingId) { DiskTO disk = null; if (volTO != null && volTO instanceof VolumeObjectTO) { - VolumeObjectTO volumeTO = (VolumeObjectTO) volTO; + VolumeObjectTO volumeTO = (VolumeObjectTO)volTO; ServiceOffering offering = _entityMgr.findById(ServiceOffering.class, offeringId); DiskOffering diskOffering = _entityMgr.findById(DiskOffering.class, diskOfferingId); if (volumeType == Volume.Type.ROOT) { diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java index 69dfd1d86f3..5e3bf54da19 100644 --- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java @@ -16,6 +16,72 @@ // under the License. package com.cloud.storage; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import javax.inject.Inject; + +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; +import org.apache.cloudstack.api.command.user.volume.ExtractVolumeCmd; +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 org.apache.cloudstack.api.response.GetUploadParamsResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; +import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.Scope; +import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; +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.config.ConfigKey; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.framework.jobs.AsyncJob; +import org.apache.cloudstack.framework.jobs.AsyncJobExecutionContext; +import org.apache.cloudstack.framework.jobs.AsyncJobManager; +import org.apache.cloudstack.framework.jobs.Outcome; +import org.apache.cloudstack.framework.jobs.dao.VmWorkJobDao; +import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO; +import org.apache.cloudstack.framework.jobs.impl.OutcomeImpl; +import org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO; +import org.apache.cloudstack.jobs.JobInfo; +import org.apache.cloudstack.storage.command.AttachAnswer; +import org.apache.cloudstack.storage.command.AttachCommand; +import org.apache.cloudstack.storage.command.DettachCommand; +import org.apache.cloudstack.storage.command.TemplateOrVolumePostUploadCommand; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +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.apache.cloudstack.storage.image.datastore.ImageStoreEntity; +import org.apache.cloudstack.utils.identity.ManagementServerNode; +import org.apache.cloudstack.utils.imagestore.ImageStoreUtil; +import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; +import org.apache.commons.collections.CollectionUtils; +import org.apache.log4j.Logger; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; + import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.ModifyTargetsCommand; @@ -111,75 +177,12 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonParseException; -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; -import org.apache.cloudstack.api.command.user.volume.ExtractVolumeCmd; -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 org.apache.cloudstack.api.response.GetUploadParamsResponse; -import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; -import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; -import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; -import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; -import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.Scope; -import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; -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.config.ConfigKey; -import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.cloudstack.framework.jobs.AsyncJob; -import org.apache.cloudstack.framework.jobs.AsyncJobExecutionContext; -import org.apache.cloudstack.framework.jobs.AsyncJobManager; -import org.apache.cloudstack.framework.jobs.Outcome; -import org.apache.cloudstack.framework.jobs.dao.VmWorkJobDao; -import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO; -import org.apache.cloudstack.framework.jobs.impl.OutcomeImpl; -import org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO; -import org.apache.cloudstack.jobs.JobInfo; -import org.apache.cloudstack.storage.command.AttachAnswer; -import org.apache.cloudstack.storage.command.AttachCommand; -import org.apache.cloudstack.storage.command.DettachCommand; -import org.apache.cloudstack.storage.command.TemplateOrVolumePostUploadCommand; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -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.apache.cloudstack.storage.image.datastore.ImageStoreEntity; -import org.apache.cloudstack.utils.identity.ManagementServerNode; -import org.apache.cloudstack.utils.imagestore.ImageStoreUtil; -import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; -import org.apache.log4j.Logger; -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; - -import javax.inject.Inject; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ExecutionException; - public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiService, VmWorkJobHandler { private final static Logger s_logger = Logger.getLogger(VolumeApiServiceImpl.class); public static final String VM_WORK_JOB_HANDLER = VolumeApiServiceImpl.class.getSimpleName(); + @Inject + private UserVmManager _userVmMgr; @Inject VolumeOrchestrationService _volumeMgr; @Inject @@ -251,21 +254,18 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic @Inject ClusterDetailsDao _clusterDetailsDao; @Inject - UserVmManager _userVmMgr; - protected Gson _gson; - @Inject StorageManager storageMgr; + protected Gson _gson; + private List _storagePoolAllocators; VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this); - static final ConfigKey VmJobCheckInterval = new ConfigKey("Advanced", Long.class, "vm.job.check.interval", "3000", - "Interval in milliseconds to check if the job is complete", false); + static final ConfigKey VmJobCheckInterval = new ConfigKey("Advanced", Long.class, "vm.job.check.interval", "3000", "Interval in milliseconds to check if the job is complete", false); static final ConfigKey VolumeUrlCheck = new ConfigKey("Advanced", Boolean.class, "volume.url.check", "true", - "Check the url for a volume before downloading it from the management server. Set to false when you managment has no internet access.", - true); + "Check the url for a volume before downloading it from the management server. Set to false when you managment has no internet access.", true); private long _maxVolumeSizeInGb; private final StateMachine2 _volStateMachine; @@ -336,7 +336,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic EndPoint ep = pair.first(); DataObject dataObject = pair.second(); - GetUploadParamsResponse response = new GetUploadParamsResponse(); String ssvmUrlDomain = _configDao.getValue(Config.SecStorageSecureCopyCert.key()); @@ -358,13 +357,11 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic response.setTimeout(expires); String key = _configDao.getValue(Config.SSVMPSK.key()); - /* - * encoded metadata using the post upload config key - */ - TemplateOrVolumePostUploadCommand command = - new TemplateOrVolumePostUploadCommand(vol.getId(), vol.getUuid(), volumeStore.getInstallPath(), cmd.getChecksum(), vol.getType().toString(), - vol.getName(), vol.getFormat().toString(), dataObject.getDataStore().getUri(), - dataObject.getDataStore().getRole().toString()); + /* + * encoded metadata using the post upload config key + */ + TemplateOrVolumePostUploadCommand command = new TemplateOrVolumePostUploadCommand(vol.getId(), vol.getUuid(), volumeStore.getInstallPath(), cmd.getChecksum(), vol.getType().toString(), + vol.getName(), vol.getFormat().toString(), dataObject.getDataStore().getUri(), dataObject.getDataStore().getRole().toString()); command.setLocalPath(volumeStore.getLocalDownloadPath()); //using the existing max upload size configuration command.setProcessTimeout(NumbersUtil.parseLong(_configDao.getValue("vmware.package.ova.timeout"), 3600)); @@ -384,8 +381,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic }); } - private boolean validateVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, - String format, Long diskOfferingId) throws ResourceAllocationException { + private boolean validateVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, String format, Long diskOfferingId) throws ResourceAllocationException { // permission check Account volumeOwner = _accountMgr.getActiveAccountById(ownerId); @@ -406,8 +402,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } //validating the url only when url is not null. url can be null incase of form based post upload - if (url != null ) { - if( url.toLowerCase().contains("file://")) { + if (url != null) { + if (url.toLowerCase().contains("file://")) { throw new InvalidParameterValueException("File:// type urls are currently unsupported"); } UriUtils.validateUrl(format, url); @@ -431,8 +427,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic // Check that the the disk offering specified is valid if (diskOfferingId != null) { DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId); - if ((diskOffering == null) || diskOffering.getRemoved() != null - || !DiskOfferingVO.Type.Disk.equals(diskOffering.getType())) { + if ((diskOffering == null) || diskOffering.getRemoved() != null || !DiskOfferingVO.Type.Disk.equals(diskOffering.getType())) { throw new InvalidParameterValueException("Please specify a valid disk offering."); } if (!diskOffering.isCustomized()) { @@ -454,8 +449,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } @DB - protected VolumeVO persistVolume(final Account owner, final Long zoneId, final String volumeName, final String url, - final String format, final Long diskOfferingId, final Volume.State state) { + protected VolumeVO persistVolume(final Account owner, final Long zoneId, final String volumeName, final String url, final String format, final Long diskOfferingId, final Volume.State state) { return Transaction.execute(new TransactionCallback() { @Override public VolumeVO doInTransaction(TransactionStatus status) { @@ -596,12 +590,11 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic if (size == null) { throw new InvalidParameterValueException("This disk offering requires a custom size specified"); } - Long customDiskOfferingMaxSize = _volumeMgr.CustomDiskOfferingMaxSize.value(); - Long customDiskOfferingMinSize = _volumeMgr.CustomDiskOfferingMinSize.value(); + Long customDiskOfferingMaxSize = VolumeOrchestrationService.CustomDiskOfferingMaxSize.value(); + Long customDiskOfferingMinSize = VolumeOrchestrationService.CustomDiskOfferingMinSize.value(); if ((sizeInGB < customDiskOfferingMinSize) || (sizeInGB > customDiskOfferingMaxSize)) { - throw new InvalidParameterValueException("Volume size: " + sizeInGB + "GB is out of allowed range. Max: " + customDiskOfferingMaxSize + " Min:" - + customDiskOfferingMinSize); + throw new InvalidParameterValueException("Volume size: " + sizeInGB + "GB is out of allowed range. Max: " + customDiskOfferingMaxSize + " Min:" + customDiskOfferingMinSize); } } @@ -725,15 +718,14 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic String userSpecifiedName = getVolumeNameFromCommand(cmd); - VolumeVO volume = commitVolume(cmd, caller, owner, displayVolume, zoneId, diskOfferingId, provisioningType, size, - minIops, maxIops, parentVolume, userSpecifiedName, _uuidMgr.generateUuid(Volume.class, cmd.getCustomId())); + VolumeVO volume = commitVolume(cmd, caller, owner, displayVolume, zoneId, diskOfferingId, provisioningType, size, minIops, maxIops, parentVolume, userSpecifiedName, + _uuidMgr.generateUuid(Volume.class, cmd.getCustomId())); return volume; } - private VolumeVO commitVolume(final CreateVolumeCmd cmd, final Account caller, final Account owner, final Boolean displayVolume, - final Long zoneId, final Long diskOfferingId, final Storage.ProvisioningType provisioningType, final Long size, final Long minIops, final Long maxIops, final VolumeVO parentVolume, - final String userSpecifiedName, final String uuid) { + private VolumeVO commitVolume(final CreateVolumeCmd cmd, final Account caller, final Account owner, final Boolean displayVolume, final Long zoneId, final Long diskOfferingId, + final Storage.ProvisioningType provisioningType, final Long size, final Long minIops, final Long maxIops, final VolumeVO parentVolume, final String userSpecifiedName, final String uuid) { return Transaction.execute(new TransactionCallback() { @Override public VolumeVO doInTransaction(TransactionStatus status) { @@ -761,8 +753,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic volume = _volsDao.persist(volume); if (cmd.getSnapshotId() == null && displayVolume) { // for volume created from snapshot, create usage event after volume creation - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - diskOfferingId, null, size, Volume.class.getName(), volume.getUuid(), displayVolume); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), diskOfferingId, null, size, + Volume.class.getName(), volume.getUuid(), displayVolume); } CallContext.current().setEventDetails("Volume Id: " + volume.getId()); @@ -847,8 +839,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic createdVolume = _volumeMgr.createVolumeFromSnapshot(volume, snapshot, vm); VolumeVO volumeVo = _volsDao.findById(createdVolume.getId()); - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, createdVolume.getAccountId(), createdVolume.getDataCenterId(), createdVolume.getId(), - createdVolume.getName(), createdVolume.getDiskOfferingId(), null, createdVolume.getSize(), Volume.class.getName(), createdVolume.getUuid(), volumeVo.isDisplayVolume()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, createdVolume.getAccountId(), createdVolume.getDataCenterId(), createdVolume.getId(), createdVolume.getName(), + createdVolume.getDiskOfferingId(), null, createdVolume.getSize(), Volume.class.getName(), createdVolume.getUuid(), volumeVo.isDisplayVolume()); return volumeVo; } @@ -888,14 +880,13 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic HypervisorType hypervisorType = _volsDao.getHypervisorType(volume.getId()); - if (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.XenServer && - hypervisorType != HypervisorType.VMware && hypervisorType != HypervisorType.Any && hypervisorType != HypervisorType.None ) { + if (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.XenServer && hypervisorType != HypervisorType.VMware && hypervisorType != HypervisorType.Any + && hypervisorType != HypervisorType.None) { throw new InvalidParameterValueException("Hypervisor " + hypervisorType + " does not support rootdisksize override"); } if (volume.getState() != Volume.State.Ready && volume.getState() != Volume.State.Allocated) { - throw new InvalidParameterValueException("Volume should be in ready or allocated state before attempting a resize. Volume " + - volume.getUuid() + " is in state " + volume.getState() + "."); + throw new InvalidParameterValueException("Volume should be in ready or allocated state before attempting a resize. Volume " + volume.getUuid() + " is in state " + volume.getState() + "."); } // if we are to use the existing disk offering @@ -906,14 +897,13 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic // if the caller is looking to change the size of the volume if (newSize != null) { if (!diskOffering.isCustomized() && !volume.getVolumeType().equals(Volume.Type.ROOT)) { - throw new InvalidParameterValueException("To change a volume's size without providing a new disk offering, its current disk offering must be " + - "customizable or it must be a root volume (if providing a disk offering, make sure it is different from the current disk offering)."); + throw new InvalidParameterValueException("To change a volume's size without providing a new disk offering, its current disk offering must be " + + "customizable or it must be a root volume (if providing a disk offering, make sure it is different from the current disk offering)."); } // convert from bytes to GiB newSize = newSize << 30; - } - else { + } else { // no parameter provided; just use the original size of the volume newSize = volume.getSize(); } @@ -924,8 +914,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic if (!volume.getVolumeType().equals(Volume.Type.ROOT) && (diskOffering.isCustomizedIops() == null || !diskOffering.isCustomizedIops())) { throw new InvalidParameterValueException("The current disk offering does not support customization of the 'Min IOPS' parameter."); } - } - else { + } else { // no parameter provided; just use the original min IOPS of the volume newMinIops = volume.getMinIops(); } @@ -936,8 +925,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic if (!volume.getVolumeType().equals(Volume.Type.ROOT) && (diskOffering.isCustomizedIops() == null || !diskOffering.isCustomizedIops())) { throw new InvalidParameterValueException("The current disk offering does not support customization of the 'Max IOPS' parameter."); } - } - else { + } else { // no parameter provided; just use the original max IOPS of the volume newMaxIops = volume.getMaxIops(); } @@ -991,8 +979,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic newMaxIops = cmd.getMaxIops() != null ? cmd.getMaxIops() : volume.getMaxIops(); validateIops(newMinIops, newMaxIops); - } - else { + } else { newMinIops = newDiskOffering.getMinIops(); newMaxIops = newDiskOffering.getMaxIops(); } @@ -1041,8 +1028,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic * the actual disk size. */ if (currentSize > newSize && !shrinkOk) { - throw new InvalidParameterValueException("Going from existing size of " + currentSize + " to size of " + newSize + " would shrink the volume." + - "Need to sign off by supplying the shrinkok parameter with value of true."); + throw new InvalidParameterValueException("Going from existing size of " + currentSize + " to size of " + newSize + " would shrink the volume." + + "Need to sign off by supplying the shrinkok parameter with value of true."); } if (newSize > currentSize) { @@ -1076,14 +1063,14 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic UserVmVO userVm = _userVmDao.findById(volume.getInstanceId()); if (userVm != null) { - if (volume.getVolumeType().equals(Volume.Type.ROOT) && userVm.getPowerState()!= VirtualMachine.PowerState.PowerOff && hypervisorType == HypervisorType.VMware){ + if (volume.getVolumeType().equals(Volume.Type.ROOT) && userVm.getPowerState() != VirtualMachine.PowerState.PowerOff && hypervisorType == HypervisorType.VMware) { s_logger.error(" For ROOT volume resize VM should be in Power Off state."); - throw new InvalidParameterValueException("VM current state is : "+userVm.getPowerState()+ ". But VM should be in "+VirtualMachine.PowerState.PowerOff+" state."); + throw new InvalidParameterValueException("VM current state is : " + userVm.getPowerState() + ". But VM should be in " + VirtualMachine.PowerState.PowerOff + " state."); } // serialize VM operation AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext(); - if ( jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) { + if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) { // avoid re-entrance VmWorkJobVO placeHolder = null; @@ -1091,14 +1078,14 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic placeHolder = createPlaceHolderWork(userVm.getId()); try { - return orchestrateResizeVolume(volume.getId(), currentSize, newSize, newMinIops, newMaxIops, - newHypervisorSnapshotReserve, newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk); + return orchestrateResizeVolume(volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve, + newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk); } finally { _workJobDao.expunge(placeHolder.getId()); } } else { - Outcome outcome = resizeVolumeThroughJobQueue(userVm.getId(), volume.getId(), currentSize, newSize, newMinIops, newMaxIops, - newHypervisorSnapshotReserve, newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk); + Outcome outcome = resizeVolumeThroughJobQueue(userVm.getId(), volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve, + newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk); try { outcome.get(); @@ -1113,17 +1100,13 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic if (jobResult != null) { if (jobResult instanceof ConcurrentOperationException) { throw (ConcurrentOperationException)jobResult; - } - else if (jobResult instanceof ResourceAllocationException) { + } else if (jobResult instanceof ResourceAllocationException) { throw (ResourceAllocationException)jobResult; - } - else if (jobResult instanceof RuntimeException) { + } else if (jobResult instanceof RuntimeException) { throw (RuntimeException)jobResult; - } - else if (jobResult instanceof Throwable) { + } else if (jobResult instanceof Throwable) { throw new RuntimeException("Unexpected exception", (Throwable)jobResult); - } - else if (jobResult instanceof Long) { + } else if (jobResult instanceof Long) { return _volsDao.findById((Long)jobResult); } } @@ -1132,8 +1115,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } } - return orchestrateResizeVolume(volume.getId(), currentSize, newSize, newMinIops, newMaxIops, - newHypervisorSnapshotReserve, newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk); + return orchestrateResizeVolume(volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve, newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, + shrinkOk); } private void validateIops(Long minIops, Long maxIops) { @@ -1148,8 +1131,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } } - private VolumeVO orchestrateResizeVolume(long volumeId, long currentSize, long newSize, Long newMinIops, Long newMaxIops, - Integer newHypervisorSnapshotReserve, Long newDiskOfferingId, boolean shrinkOk) { + private VolumeVO orchestrateResizeVolume(long volumeId, long currentSize, long newSize, Long newMinIops, Long newMaxIops, Integer newHypervisorSnapshotReserve, Long newDiskOfferingId, + boolean shrinkOk) { VolumeVO volume = _volsDao.findById(volumeId); UserVmVO userVm = _userVmDao.findById(volume.getInstanceId()); StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId()); @@ -1186,8 +1169,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } } - ResizeVolumePayload payload = new ResizeVolumePayload(newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve, - shrinkOk, instanceName, hosts, isManaged); + ResizeVolumePayload payload = new ResizeVolumePayload(newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve, shrinkOk, instanceName, hosts, isManaged); try { VolumeInfo vol = volFactory.getVolume(volume.getId()); @@ -1259,92 +1241,139 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } } - @Override @DB + @Override @ActionEvent(eventType = EventTypes.EVENT_VOLUME_DELETE, eventDescription = "deleting volume") - 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"); - } - + /** + * 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) { + 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 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 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 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 { + /** + * Clean volumes cache entries (if they exist). + */ + protected void cleanVolumesCache(VolumeVO volume) { + List 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(); + } + } + + /** + * 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 future2 = volService.expungeVolumeAsync(volOnSecondary); + future2.get(); + + _resourceLimitMgr.decrementResourceCount(volOnSecondary.getAccountId(), ResourceType.secondary_storage, volOnSecondary.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 future = volService.expungeVolumeAsync(volOnPrimary); + future.get(); + } + } + + /** + * Destroy the volume if possible and then decrement the following resource types. + *
    + *
  • {@link ResourceType#volume}; + *
  • {@link ResourceType#primary_storage} + *
+ * + * A volume can be destroyed if it is not in any of the following states. + *
    + *
  • {@value Volume.State#Destroy}; + *
  • {@value Volume.State#Expunging}; + *
  • {@value Volume.State#Expunged}. + *
+ * + * 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()); + } + } + + /** + * Retrieves and validates the volume for the {@link #deleteVolume(long, Account)} method. The following validation are executed. + *
    + *
  • if no volume is found in the database, we throw an {@link InvalidParameterValueException}; + *
  • if there are snapshots operation on the volume we cannot delete it. Therefore, an {@link InvalidParameterValueException} is thrown; + *
  • if the volume is still attached to a VM we throw an {@link InvalidParameterValueException}; + *
  • 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; + *
  • if the volume state is in {@link Volume.State#NotUploaded} or if the state is {@link Volume.State#UploadInProgress}, an {@link InvalidParameterValueException} is thrown; + *
  • 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)}. + *
+ * + * 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; + } + + protected boolean stateTransitTo(Volume vol, Volume.Event event) throws NoTransitionException { return _volStateMachine.transitTo(vol, event, null, _volsDao); } @@ -1410,14 +1439,14 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic if (moveVolumeNeeded) { PrimaryDataStoreInfo primaryStore = (PrimaryDataStoreInfo)newVolumeOnPrimaryStorage.getDataStore(); if (primaryStore.isLocal()) { - throw new CloudRuntimeException("Failed to attach local data volume " + volumeToAttach.getName() + " to VM " + vm.getDisplayName() - + " as migration of local data volume is not allowed"); + throw new CloudRuntimeException( + "Failed to attach local data volume " + volumeToAttach.getName() + " to VM " + vm.getDisplayName() + " as migration of local data volume is not allowed"); } StoragePoolVO vmRootVolumePool = _storagePoolDao.findById(exstingVolumeOfVm.getPoolId()); try { - newVolumeOnPrimaryStorage = _volumeMgr.moveVolume(newVolumeOnPrimaryStorage, vmRootVolumePool.getDataCenterId(), vmRootVolumePool.getPodId(), - vmRootVolumePool.getClusterId(), volumeToAttachHyperType); + newVolumeOnPrimaryStorage = _volumeMgr.moveVolume(newVolumeOnPrimaryStorage, vmRootVolumePool.getDataCenterId(), vmRootVolumePool.getPodId(), vmRootVolumePool.getClusterId(), + volumeToAttachHyperType); } catch (ConcurrentOperationException e) { s_logger.debug("move volume failed", e); throw new CloudRuntimeException("move volume failed", e); @@ -1496,7 +1525,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic List existingDataVolumes = _volsDao.findByInstanceAndType(vmId, Volume.Type.DATADISK); int maxAttachableDataVolumesSupported = getMaxDataVolumesSupported(vm); if (existingDataVolumes.size() >= maxAttachableDataVolumesSupported) { - throw new InvalidParameterValueException("The specified VM already has the maximum number of data disks (" + maxAttachableDataVolumesSupported + ") attached. Please specify another VM."); + throw new InvalidParameterValueException( + "The specified VM already has the maximum number of data disks (" + maxAttachableDataVolumesSupported + ") attached. Please specify another VM."); } } @@ -1519,14 +1549,13 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic // permission check _accountMgr.checkAccess(caller, null, true, volumeToAttach, vm); - if (!(Volume.State.Allocated.equals(volumeToAttach.getState()) || Volume.State.Ready.equals(volumeToAttach.getState()) || Volume.State.Uploaded.equals(volumeToAttach - .getState()))) { + if (!(Volume.State.Allocated.equals(volumeToAttach.getState()) || Volume.State.Ready.equals(volumeToAttach.getState()) || Volume.State.Uploaded.equals(volumeToAttach.getState()))) { throw new InvalidParameterValueException("Volume state must be in Allocated, Ready or in Uploaded state"); } Account owner = _accountDao.findById(volumeToAttach.getAccountId()); - if(!(volumeToAttach.getState() == Volume.State.Allocated || volumeToAttach.getState() == Volume.State.Ready)){ + if (!(volumeToAttach.getState() == Volume.State.Allocated || volumeToAttach.getState() == Volume.State.Ready)) { try { _resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, volumeToAttach.getSize()); } catch (ResourceAllocationException e) { @@ -1586,15 +1615,15 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob()); if (jobResult != null) { - if (jobResult instanceof ConcurrentOperationException) + if (jobResult instanceof ConcurrentOperationException) { throw (ConcurrentOperationException)jobResult; - else if (jobResult instanceof InvalidParameterValueException) + } else if (jobResult instanceof InvalidParameterValueException) { throw (InvalidParameterValueException)jobResult; - else if (jobResult instanceof RuntimeException) + } else if (jobResult instanceof RuntimeException) { throw (RuntimeException)jobResult; - else if (jobResult instanceof Throwable) + } else if (jobResult instanceof Throwable) { throw new RuntimeException("Unexpected exception", (Throwable)jobResult); - else if (jobResult instanceof Long) { + } else if (jobResult instanceof Long) { vol = _volsDao.findById((Long)jobResult); } } @@ -1608,14 +1637,15 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic VolumeVO volume = _volsDao.findById(volumeId); - if(volume == null) + if (volume == null) { throw new InvalidParameterValueException("The volume id doesn't exist"); + } if (path != null) { volume.setPath(path); } - if(chainInfo != null){ + if (chainInfo != null) { volume.setChainInfo(chainInfo); } @@ -1647,9 +1677,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic return volume; } - @Override - public void updateDisplay(Volume volume, Boolean displayVolume){ + public void updateDisplay(Volume volume, Boolean displayVolume) { // 1. Resource limit changes updateResourceCount(volume, displayVolume); @@ -1657,41 +1686,42 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic saveUsageEvent(volume, displayVolume); // 3. Set the flag - if (displayVolume != null && displayVolume != volume.isDisplayVolume()){ + if (displayVolume != null && displayVolume != volume.isDisplayVolume()) { // FIXME - Confused - typecast for now. ((VolumeVO)volume).setDisplayVolume(displayVolume); - _volsDao.update(volume.getId(), (VolumeVO) volume); + _volsDao.update(volume.getId(), (VolumeVO)volume); } } - private void updateResourceCount(Volume volume, Boolean displayVolume){ + private void updateResourceCount(Volume volume, Boolean displayVolume) { // Update only when the flag has changed. - if (displayVolume != null && displayVolume != volume.isDisplayVolume()){ + if (displayVolume != null && displayVolume != volume.isDisplayVolume()) { _resourceLimitMgr.changeResourceCount(volume.getAccountId(), ResourceType.volume, displayVolume); _resourceLimitMgr.changeResourceCount(volume.getAccountId(), ResourceType.primary_storage, displayVolume, new Long(volume.getSize())); } } - private void saveUsageEvent(Volume volume, Boolean displayVolume){ + private void saveUsageEvent(Volume volume, Boolean displayVolume) { // Update only when the flag has changed && only when volume in a non-destroyed state. - if ((displayVolume != null && displayVolume != volume.isDisplayVolume()) && !isVolumeDestroyed(volume)){ - if (displayVolume){ + if ((displayVolume != null && displayVolume != volume.isDisplayVolume()) && !isVolumeDestroyed(volume)) { + if (displayVolume) { // flag turned 1 equivalent to freshly created volume - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), volume.getUuid()); - }else { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), volume.getDiskOfferingId(), + volume.getTemplateId(), volume.getSize(), Volume.class.getName(), volume.getUuid()); + } else { // flag turned 0 equivalent to deleting a volume - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - Volume.class.getName(), volume.getUuid()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), Volume.class.getName(), + volume.getUuid()); } } } - private boolean isVolumeDestroyed(Volume volume){ - if(volume.getState() == Volume.State.Destroy || volume.getState() == Volume.State.Expunging && volume.getState() == Volume.State.Expunged) + private boolean isVolumeDestroyed(Volume volume) { + if (volume.getState() == Volume.State.Destroy || volume.getState() == Volume.State.Expunging && volume.getState() == Volume.State.Expunged) { return true; + } return false; } @@ -1699,8 +1729,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic @ActionEvent(eventType = EventTypes.EVENT_VOLUME_DETACH, eventDescription = "detaching volume", async = true) public Volume detachVolumeFromVM(DetachVolumeCmd cmmd) { Account caller = CallContext.current().getCallingAccount(); - if ((cmmd.getId() == null && cmmd.getDeviceId() == null && cmmd.getVirtualMachineId() == null) - || (cmmd.getId() != null && (cmmd.getDeviceId() != null || cmmd.getVirtualMachineId() != null)) + if ((cmmd.getId() == null && cmmd.getDeviceId() == null && cmmd.getVirtualMachineId() == null) || (cmmd.getId() != null && (cmmd.getDeviceId() != null || cmmd.getVirtualMachineId() != null)) || (cmmd.getId() == null && (cmmd.getDeviceId() == null || cmmd.getVirtualMachineId() == null))) { throw new InvalidParameterValueException("Please provide either a volume id, or a tuple(device id, instance id)"); } @@ -1792,14 +1821,14 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob()); if (jobResult != null) { - if (jobResult instanceof ConcurrentOperationException) + if (jobResult instanceof ConcurrentOperationException) { throw (ConcurrentOperationException)jobResult; - else if (jobResult instanceof RuntimeException) + } else if (jobResult instanceof RuntimeException) { throw (RuntimeException)jobResult; - else if (jobResult instanceof Throwable) + } else if (jobResult instanceof Throwable) { throw new RuntimeException("Unexpected exception", (Throwable)jobResult); - else if (jobResult instanceof Long) { - vol = _volsDao.findById((Long) jobResult); + } else if (jobResult instanceof Long) { + vol = _volsDao.findById((Long)jobResult); } } return vol; @@ -1807,8 +1836,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } private void validateRootVolumeDetachAttach(VolumeVO volume, UserVmVO vm) { - if (!(vm.getHypervisorType() == HypervisorType.XenServer || vm.getHypervisorType() == HypervisorType.VMware || vm.getHypervisorType() == HypervisorType.KVM || vm.getHypervisorType() == HypervisorType.Simulator)) { - throw new InvalidParameterValueException("Root volume detach is not supported for hypervisor type " + vm.getHypervisorType() ); + if (!(vm.getHypervisorType() == HypervisorType.XenServer || vm.getHypervisorType() == HypervisorType.VMware || vm.getHypervisorType() == HypervisorType.KVM + || vm.getHypervisorType() == HypervisorType.Simulator)) { + throw new InvalidParameterValueException("Root volume detach is not supported for hypervisor type " + vm.getHypervisorType()); } if (!(vm.getState() == State.Stopped) || (vm.getState() == State.Destroyed)) { throw new InvalidParameterValueException("Root volume detach can happen only when vm is in states: " + State.Stopped.toString() + " or " + State.Destroyed.toString()); @@ -1958,8 +1988,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic 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); @@ -1997,7 +2026,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic if (vm != null && vm.getState() == State.Running) { // Check if the VM is GPU enabled. - if(_serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) { + if (_serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) { throw new InvalidParameterValueException("Live Migration of GPU enabled VM is not supported"); } // Check if the underlying hypervisor supports storage motion. @@ -2029,8 +2058,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic if (destPool == null) { throw new InvalidParameterValueException("Failed to find the destination storage pool: " + storagePoolId); } else if (destPool.isInMaintenance()) { - throw new InvalidParameterValueException("Cannot migrate volume " + vol + "to the destination storage pool " + destPool.getName() + - " as the storage pool is in maintenance mode."); + throw new InvalidParameterValueException("Cannot migrate volume " + vol + "to the destination storage pool " + destPool.getName() + " as the storage pool is in maintenance mode."); } if (_volumeMgr.volumeOnSharedStoragePool(vol)) { @@ -2049,8 +2077,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic if (!liveMigrateVolume && vol.volumeType.equals(Volume.Type.ROOT)) { Long hostId = vm.getHostId() != null ? vm.getHostId() : vm.getLastHostId(); HostVO host = _hostDao.findById(hostId); - if (host != null) + if (host != null) { srcClusterId = host.getClusterId(); + } if (srcClusterId != null && destPool.getClusterId() != null && !srcClusterId.equals(destPool.getClusterId())) { String srcDcName = _clusterDetailsDao.getVmwareDcName(srcClusterId); String destDcName = _clusterDetailsDao.getVmwareDcName(destPool.getClusterId()); @@ -2093,12 +2122,13 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob()); if (jobResult != null) { - if (jobResult instanceof ConcurrentOperationException) + if (jobResult instanceof ConcurrentOperationException) { throw (ConcurrentOperationException)jobResult; - else if (jobResult instanceof RuntimeException) + } else if (jobResult instanceof RuntimeException) { throw (RuntimeException)jobResult; - else if (jobResult instanceof Throwable) + } else if (jobResult instanceof Throwable) { throw new RuntimeException("Unexpected exception", (Throwable)jobResult); + } } // retrieve the migrated new volume from job result @@ -2128,7 +2158,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } catch (StorageUnavailableException e) { s_logger.debug("Failed to migrate volume", e); throw new CloudRuntimeException(e.getMessage()); - } catch (Exception e) { + } catch (Exception e) { s_logger.debug("Failed to migrate volume", e); throw new CloudRuntimeException(e.getMessage()); } @@ -2175,8 +2205,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } VMInstanceVO vm = null; - if (volume.getInstanceId() != null) + if (volume.getInstanceId() != null) { vm = _vmInstanceDao.findById(volume.getInstanceId()); + } if (vm != null) { // serialize VM operation @@ -2205,12 +2236,13 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob()); if (jobResult != null) { - if (jobResult instanceof ConcurrentOperationException) + if (jobResult instanceof ConcurrentOperationException) { throw (ConcurrentOperationException)jobResult; - else if (jobResult instanceof ResourceAllocationException) + } else if (jobResult instanceof ResourceAllocationException) { throw (ResourceAllocationException)jobResult; - else if (jobResult instanceof Throwable) + } else if (jobResult instanceof Throwable) { throw new RuntimeException("Unexpected exception", (Throwable)jobResult); + } } return _snapshotDao.findById(snapshotId); @@ -2227,8 +2259,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } } - private Snapshot orchestrateTakeVolumeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, - boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup) + private Snapshot orchestrateTakeVolumeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup) throws ResourceAllocationException { VolumeInfo volume = volFactory.getVolume(volumeId); @@ -2276,7 +2307,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot."); } - if (ImageFormat.DIR.equals(volume.getFormat())){ + if (ImageFormat.DIR.equals(volume.getFormat())) { throw new InvalidParameterValueException("Snapshot not supported for volume:" + volumeId); } @@ -2337,9 +2368,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot."); } - if ( volume.getTemplateId() != null ) { - VMTemplateVO template = _templateDao.findById(volume.getTemplateId()); - if( template != null && template.getTemplateType() == Storage.TemplateType.SYSTEM ) { + if (volume.getTemplateId() != null) { + VMTemplateVO template = _templateDao.findById(volume.getTemplateId()); + if (template != null && template.getTemplateType() == Storage.TemplateType.SYSTEM) { throw new InvalidParameterValueException("VolumeId: " + volumeId + " is for System VM , Creating snapshot against System VM volumes is not supported"); } } @@ -2384,8 +2415,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic // instance is stopped if (volume.getInstanceId() != null && ApiDBUtils.findVMInstanceById(volume.getInstanceId()).getState() != State.Stopped) { s_logger.debug("Invalid state of the volume with ID: " + volumeId + ". It should be either detached or the VM should be in stopped state."); - PermissionDeniedException ex = new PermissionDeniedException( - "Invalid state of the volume with specified ID. It should be either detached or the VM should be in stopped state."); + PermissionDeniedException ex = new PermissionDeniedException("Invalid state of the volume with specified ID. It should be either detached or the VM should be in stopped state."); ex.addProxyObject(volume.getUuid(), "volumeId"); throw ex; } @@ -2449,12 +2479,13 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob()); if (jobResult != null) { - if (jobResult instanceof ConcurrentOperationException) + if (jobResult instanceof ConcurrentOperationException) { throw (ConcurrentOperationException)jobResult; - else if (jobResult instanceof RuntimeException) + } else if (jobResult instanceof RuntimeException) { throw (RuntimeException)jobResult; - else if (jobResult instanceof Throwable) + } else if (jobResult instanceof Throwable) { throw new RuntimeException("Unexpected exception", (Throwable)jobResult); + } } // retrieve the entity url from job result @@ -2652,8 +2683,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic if (host != null) { try { volService.grantAccess(volFactory.getVolume(volumeToAttach.getId()), host, dataStore); - } - catch (Exception e) { + } catch (Exception e) { volService.revokeAccess(volFactory.getVolume(volumeToAttach.getId()), host, dataStore); throw new CloudRuntimeException(e.getMessage()); @@ -2661,9 +2691,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } if (sendCommand) { - if (host != null && host.getHypervisorType() == HypervisorType.KVM && - volumeToAttachStoragePool.isManaged() && - volumeToAttach.getPath() == null) { + if (host != null && host.getHypervisorType() == HypervisorType.KVM && volumeToAttachStoragePool.isManaged() && volumeToAttach.getPath() == null) { volumeToAttach.setPath(volumeToAttach.get_iScsiName()); _volsDao.update(volumeToAttach.getId(), volumeToAttach); @@ -2673,8 +2701,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic deviceId = getDeviceId(vm, deviceId); - DiskTO disk = storageMgr.getDiskWithThrottling(volTO, volumeToAttach.getVolumeType(), deviceId, volumeToAttach.getPath(), - vm.getServiceOfferingId(), volumeToAttach.getDiskOfferingId()); + DiskTO disk = storageMgr.getDiskWithThrottling(volTO, volumeToAttach.getVolumeType(), deviceId, volumeToAttach.getPath(), vm.getServiceOfferingId(), + volumeToAttach.getDiskOfferingId()); AttachCommand cmd = new AttachCommand(disk, vm.getInstanceName()); @@ -2703,12 +2731,12 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic controllerInfo.put(VmDetailConstants.ROOT_DISK_CONTROLLER, vm.getDetail(VmDetailConstants.ROOT_DISK_CONTROLLER)); controllerInfo.put(VmDetailConstants.DATA_DISK_CONTROLLER, vm.getDetail(VmDetailConstants.DATA_DISK_CONTROLLER)); cmd.setControllerInfo(controllerInfo); - s_logger.debug("Attach volume id:" + volumeToAttach.getId() + " on VM id:" + vm.getId() + " has controller info:" + controllerInfo); + s_logger.debug("Attach volume id:" + volumeToAttach.getId() + " on VM id:" + vm.getId() + " has controller info:" + controllerInfo); try { answer = (AttachAnswer)_agentMgr.send(hostId, cmd); } catch (Exception e) { - if(host!=null) { + if (host != null) { volService.revokeAccess(volFactory.getVolume(volumeToAttach.getId()), host, dataStore); } throw new CloudRuntimeException(errorMsg + " due to: " + e.getMessage()); @@ -2766,7 +2794,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } finally { Volume.Event ev = Volume.Event.OperationFailed; VolumeInfo volInfo = volFactory.getVolume(volumeToAttach.getId()); - if(attached) { + if (attached) { ev = Volume.Event.OperationSucceeded; s_logger.debug("Volume: " + volInfo.getName() + " successfully attached to VM: " + volInfo.getAttachedVmName()); } else { @@ -2803,7 +2831,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic int maxDeviceId = maxDevices - 1; List vols = _volsDao.findByInstance(vm.getId()); if (deviceId != null) { - if (deviceId.longValue() < 0 || deviceId.longValue() > maxDeviceId || deviceId.longValue() == 3) { + if (deviceId.longValue() < 0 || deviceId.longValue() > maxDeviceId || deviceId.longValue() == 3) { throw new RuntimeException("deviceId should be 0,1,2,4-" + maxDeviceId); } for (VolumeVO vol : vols) { @@ -2832,7 +2860,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic @Override public boolean configure(String name, Map params) { - String maxVolumeSizeInGbString = _configDao.getValue(Config.MaxVolumeSize.toString()); _maxVolumeSizeInGb = NumbersUtil.parseLong(maxVolumeSizeInGbString, 2000); return true; @@ -2855,8 +2882,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic public boolean checkCondition() { AsyncJobVO jobVo = _entityMgr.findById(AsyncJobVO.class, job.getId()); assert (jobVo != null); - if (jobVo == null || jobVo.getStatus() != JobInfo.Status.IN_PROGRESS) + if (jobVo == null || jobVo.getStatus() != JobInfo.Status.IN_PROGRESS) { return true; + } return false; } @@ -2873,8 +2901,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic public boolean checkCondition() { AsyncJobVO jobVo = _entityMgr.findById(AsyncJobVO.class, job.getId()); assert (jobVo != null); - if (jobVo == null || jobVo.getStatus() != JobInfo.Status.IN_PROGRESS) + if (jobVo == null || jobVo.getStatus() != JobInfo.Status.IN_PROGRESS) { return true; + } return false; } @@ -2897,8 +2926,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic public boolean checkCondition() { AsyncJobVO jobVo = _entityMgr.findById(AsyncJobVO.class, job.getId()); assert (jobVo != null); - if (jobVo == null || jobVo.getStatus() != JobInfo.Status.IN_PROGRESS) + if (jobVo == null || jobVo.getStatus() != JobInfo.Status.IN_PROGRESS) { return true; + } return false; } @@ -2933,8 +2963,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic workJob.setRelated(AsyncJobExecutionContext.getOriginJobId()); // save work context info (there are some duplications) - VmWorkAttachVolume workInfo = new VmWorkAttachVolume(callingUser.getId(), callingAccount.getId(), vm.getId(), - VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId, deviceId); + VmWorkAttachVolume workInfo = new VmWorkAttachVolume(callingUser.getId(), callingAccount.getId(), vm.getId(), VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId, deviceId); workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo)); _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId()); @@ -2968,8 +2997,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic workJob.setRelated(AsyncJobExecutionContext.getOriginJobId()); // save work context info (there are some duplications) - VmWorkDetachVolume workInfo = new VmWorkDetachVolume(callingUser.getId(), callingAccount.getId(), vm.getId(), - VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId); + VmWorkDetachVolume workInfo = new VmWorkDetachVolume(callingUser.getId(), callingAccount.getId(), vm.getId(), VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId); workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo)); _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId()); @@ -2979,9 +3007,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic return new VmJobVolumeOutcome(workJob, volumeId); } - public Outcome resizeVolumeThroughJobQueue(final Long vmId, final long volumeId, final long currentSize, final long newSize, - final Long newMinIops, final Long newMaxIops, final Integer newHypervisorSnapshotReserve, - final Long newServiceOfferingId, final boolean shrinkOk) { + public Outcome resizeVolumeThroughJobQueue(final Long vmId, final long volumeId, final long currentSize, final long newSize, final Long newMinIops, final Long newMaxIops, + final Integer newHypervisorSnapshotReserve, final Long newServiceOfferingId, final boolean shrinkOk) { final CallContext context = CallContext.current(); final User callingUser = context.getCallingUser(); final Account callingAccount = context.getCallingAccount(); @@ -3001,19 +3028,18 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic workJob.setRelated(AsyncJobExecutionContext.getOriginJobId()); // save work context info (there are some duplications) - VmWorkResizeVolume workInfo = new VmWorkResizeVolume(callingUser.getId(), callingAccount.getId(), vm.getId(), - VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId, currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve, newServiceOfferingId, shrinkOk); + VmWorkResizeVolume workInfo = new VmWorkResizeVolume(callingUser.getId(), callingAccount.getId(), vm.getId(), VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId, currentSize, newSize, + newMinIops, newMaxIops, newHypervisorSnapshotReserve, newServiceOfferingId, shrinkOk); workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo)); _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId()); AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(workJob.getId()); - return new VmJobVolumeOutcome(workJob,volumeId); + return new VmJobVolumeOutcome(workJob, volumeId); } - public Outcome extractVolumeThroughJobQueue(final Long vmId, final long volumeId, - final long zoneId) { + public Outcome extractVolumeThroughJobQueue(final Long vmId, final long volumeId, final long zoneId) { final CallContext context = CallContext.current(); final User callingUser = context.getCallingUser(); @@ -3034,8 +3060,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic workJob.setRelated(AsyncJobExecutionContext.getOriginJobId()); // save work context info (there are some duplications) - VmWorkExtractVolume workInfo = new VmWorkExtractVolume(callingUser.getId(), callingAccount.getId(), vm.getId(), - VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId, zoneId); + VmWorkExtractVolume workInfo = new VmWorkExtractVolume(callingUser.getId(), callingAccount.getId(), vm.getId(), VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId, zoneId); workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo)); _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId()); @@ -3045,8 +3070,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic return new VmJobVolumeUrlOutcome(workJob); } - public Outcome migrateVolumeThroughJobQueue(final Long vmId, final long volumeId, - final long destPoolId, final boolean liveMigrate) { + public Outcome migrateVolumeThroughJobQueue(final Long vmId, final long volumeId, final long destPoolId, final boolean liveMigrate) { final CallContext context = CallContext.current(); final User callingUser = context.getCallingUser(); @@ -3067,19 +3091,18 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic workJob.setRelated(AsyncJobExecutionContext.getOriginJobId()); // save work context info (there are some duplications) - VmWorkMigrateVolume workInfo = new VmWorkMigrateVolume(callingUser.getId(), callingAccount.getId(), vm.getId(), - VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId, destPoolId, liveMigrate); + VmWorkMigrateVolume workInfo = new VmWorkMigrateVolume(callingUser.getId(), callingAccount.getId(), vm.getId(), VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId, destPoolId, liveMigrate); workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo)); _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId()); AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(workJob.getId()); - return new VmJobVolumeOutcome(workJob,volumeId); + return new VmJobVolumeOutcome(workJob, volumeId); } - public Outcome takeVolumeSnapshotThroughJobQueue(final Long vmId, final Long volumeId, - final Long policyId, final Long snapshotId, final Long accountId, final boolean quiesceVm, final Snapshot.LocationType locationType, final boolean asyncBackup) { + public Outcome takeVolumeSnapshotThroughJobQueue(final Long vmId, final Long volumeId, final Long policyId, final Long snapshotId, final Long accountId, final boolean quiesceVm, + final Snapshot.LocationType locationType, final boolean asyncBackup) { final CallContext context = CallContext.current(); final User callingUser = context.getCallingUser(); @@ -3100,8 +3123,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic workJob.setRelated(AsyncJobExecutionContext.getOriginJobId()); // save work context info (there are some duplications) - VmWorkTakeVolumeSnapshot workInfo = new VmWorkTakeVolumeSnapshot( - callingUser.getId(), accountId != null ? accountId : callingAccount.getId(), vm.getId(), + VmWorkTakeVolumeSnapshot workInfo = new VmWorkTakeVolumeSnapshot(callingUser.getId(), accountId != null ? accountId : callingAccount.getId(), vm.getId(), VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId, policyId, snapshotId, quiesceVm, locationType, asyncBackup); workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo)); @@ -3109,7 +3131,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(workJob.getId()); - return new VmJobSnapshotOutcome(workJob,snapshotId); + return new VmJobSnapshotOutcome(workJob, snapshotId); } @ReflectionUse @@ -3122,39 +3144,33 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic private Pair orchestrateAttachVolumeToVM(VmWorkAttachVolume work) throws Exception { Volume vol = orchestrateAttachVolumeToVM(work.getVmId(), work.getVolumeId(), work.getDeviceId()); - return new Pair(JobInfo.Status.SUCCEEDED, - _jobMgr.marshallResultObject(new Long(vol.getId()))); + return new Pair(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(new Long(vol.getId()))); } @ReflectionUse private Pair orchestrateDetachVolumeFromVM(VmWorkDetachVolume work) throws Exception { Volume vol = orchestrateDetachVolumeFromVM(work.getVmId(), work.getVolumeId()); - return new Pair(JobInfo.Status.SUCCEEDED, - _jobMgr.marshallResultObject(new Long(vol.getId()))); + return new Pair(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(new Long(vol.getId()))); } @ReflectionUse private Pair orchestrateResizeVolume(VmWorkResizeVolume work) throws Exception { - Volume vol = orchestrateResizeVolume(work.getVolumeId(), work.getCurrentSize(), work.getNewSize(), work.getNewMinIops(), work.getNewMaxIops(), - work.getNewHypervisorSnapshotReserve(), work.getNewServiceOfferingId(), work.isShrinkOk()); - return new Pair(JobInfo.Status.SUCCEEDED, - _jobMgr.marshallResultObject(new Long(vol.getId()))); + Volume vol = orchestrateResizeVolume(work.getVolumeId(), work.getCurrentSize(), work.getNewSize(), work.getNewMinIops(), work.getNewMaxIops(), work.getNewHypervisorSnapshotReserve(), + work.getNewServiceOfferingId(), work.isShrinkOk()); + return new Pair(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(new Long(vol.getId()))); } @ReflectionUse private Pair orchestrateMigrateVolume(VmWorkMigrateVolume work) throws Exception { Volume newVol = orchestrateMigrateVolume(work.getVolumeId(), work.getDestPoolId(), work.isLiveMigrate()); - return new Pair(JobInfo.Status.SUCCEEDED, - _jobMgr.marshallResultObject(new Long(newVol.getId()))); + return new Pair(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(new Long(newVol.getId()))); } @ReflectionUse private Pair orchestrateTakeVolumeSnapshot(VmWorkTakeVolumeSnapshot work) throws Exception { Account account = _accountDao.findById(work.getAccountId()); - orchestrateTakeVolumeSnapshot(work.getVolumeId(), work.getPolicyId(), work.getSnapshotId(), - account, work.isQuiesceVm(), work.getLocationType(), work.isAsyncBackup()); - return new Pair(JobInfo.Status.SUCCEEDED, - _jobMgr.marshallResultObject(work.getSnapshotId())); + orchestrateTakeVolumeSnapshot(work.getVolumeId(), work.getPolicyId(), work.getSnapshotId(), account, work.isQuiesceVm(), work.getLocationType(), work.isAsyncBackup()); + return new Pair(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(work.getSnapshotId())); } @Override diff --git a/server/test/com/cloud/storage/VolumeApiServiceImplTest.java b/server/test/com/cloud/storage/VolumeApiServiceImplTest.java index 16f39bcddff..366fd225ae9 100644 --- a/server/test/com/cloud/storage/VolumeApiServiceImplTest.java +++ b/server/test/com/cloud/storage/VolumeApiServiceImplTest.java @@ -16,63 +16,8 @@ // under the License. package com.cloud.storage; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.dao.DataCenterDao; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.org.Grouping; -import com.cloud.serializer.GsonHelper; -import com.cloud.storage.dao.VolumeDao; -import com.cloud.user.Account; -import com.cloud.user.AccountManager; -import com.cloud.user.AccountVO; -import com.cloud.user.User; -import com.cloud.user.UserVO; -import com.cloud.utils.db.TransactionLegacy; -import com.cloud.vm.UserVmManager; -import com.cloud.vm.UserVmVO; -import com.cloud.vm.VirtualMachine; -import com.cloud.vm.VirtualMachine.State; -import com.cloud.vm.dao.UserVmDao; -import com.cloud.vm.dao.VMInstanceDao; -import com.cloud.vm.snapshot.VMSnapshotVO; -import com.cloud.vm.snapshot.dao.VMSnapshotDao; -import com.cloud.user.dao.AccountDao; -import com.cloud.user.ResourceLimitService; -import com.cloud.configuration.Resource; -import com.cloud.host.dao.HostDao; -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.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.framework.jobs.AsyncJobExecutionContext; -import org.apache.cloudstack.framework.jobs.AsyncJobManager; -import org.apache.cloudstack.framework.jobs.dao.AsyncJobJoinMapDao; -import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.Assert; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -import javax.inject.Inject; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyString; @@ -83,78 +28,154 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +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; +import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +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; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +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; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.org.Grouping; +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; +import com.cloud.user.ResourceLimitService; +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; +import com.cloud.vm.VirtualMachine.State; +import com.cloud.vm.dao.UserVmDao; +import com.cloud.vm.dao.VMInstanceDao; +import com.cloud.vm.snapshot.VMSnapshotVO; +import com.cloud.vm.snapshot.dao.VMSnapshotDao; + +@RunWith(MockitoJUnitRunner.class) public class VolumeApiServiceImplTest { - @Inject - VolumeApiServiceImpl _svc = new VolumeApiServiceImpl(); + + @Spy + @InjectMocks + private VolumeApiServiceImpl volumeApiServiceImpl = new VolumeApiServiceImpl(); @Mock - VolumeDao _volumeDao; + private VolumeDao volumeDaoMock; @Mock - AccountManager _accountMgr; + private SnapshotManager snapshotManagerMock; @Mock - UserVmDao _userVmDao; + private VolumeDataStoreDao volumeDataStoreDaoMock; @Mock - PrimaryDataStoreDao _storagePoolDao; + private AccountManager accountManagerMock; @Mock - VMSnapshotDao _vmSnapshotDao; + private VolumeService volumeServiceMock; @Mock - AsyncJobManager _jobMgr; + private ResourceLimitService resourceLimitServiceMock; @Mock - AsyncJobJoinMapDao _joinMapDao; - @Mock - VolumeDataFactory _volFactory; + private VolumeDataFactory volumeDataFactoryMock; @Mock - VMInstanceDao _vmInstanceDao; + private UserVmDao userVmDaoMock; @Mock - VolumeInfo volumeInfoMock; + private PrimaryDataStoreDao primaryDataStoreDaoMock; @Mock - SnapshotInfo snapshotInfoMock; + private VMSnapshotDao vmSnapshotDaoMock; @Mock - VolumeService volService; + private AsyncJobManager asyncJobManagerMock; @Mock - CreateVolumeCmd createVol; + private AsyncJobJoinMapDao asyncJobJoinMapDaoMock; @Mock - UserVmManager _userVmMgr; + private UserVmManager userVmManagerMock; @Mock - DataCenterDao _dcDao; + private VMInstanceDao vMInstanceDaoMock; @Mock - ResourceLimitService _resourceLimitMgr; + private SnapshotInfo snapshotInfoMock; @Mock - AccountDao _accountDao; + private CreateVolumeCmd createVolumeCmdMock; @Mock - HostDao _hostDao; + private DataCenterDao dataCenterDaoMock; + @Mock + private AccountDao accountDaoMock; + @Mock + private HostDao hostdaoMock; DetachVolumeCmd detachCmd = new DetachVolumeCmd(); Class _detachCmdClass = detachCmd.getClass(); + @Mock + private Account accountMock; + @Mock + private VolumeVO volumeVoMock; + @Mock + private VolumeDataStoreVO volumeDataStoreVoMock; + @Mock + private AsyncCallFuture asyncCallFutureVolumeapiResultMock; + @Mock + private VolumeInfo volumeInfoMock; + + private long accountMockId = 456l; + private long volumeMockId = 12313l; + private long vmInstanceMockId = 1123l; + private long volumeSizeMock = 456789921939l; @Before public void setup() throws Exception { - MockitoAnnotations.initMocks(this); - _svc._volsDao = _volumeDao; - _svc._accountMgr = _accountMgr; - _svc._userVmDao = _userVmDao; - _svc._storagePoolDao = _storagePoolDao; - _svc._vmSnapshotDao = _vmSnapshotDao; - _svc._vmInstanceDao = _vmInstanceDao; - _svc._jobMgr = _jobMgr; - _svc.volFactory = _volFactory; - _svc.volService = volService; - _svc._userVmMgr = _userVmMgr; - _svc._dcDao = _dcDao; - _svc._resourceLimitMgr = _resourceLimitMgr; - _svc._accountDao = _accountDao; - _svc._hostDao = _hostDao; - _svc._gson = GsonHelper.getGsonLogger(); + Mockito.doReturn(volumeMockId).when(volumeDataStoreVoMock).getVolumeId(); + Mockito.doReturn(volumeMockId).when(volumeVoMock).getId(); + Mockito.doReturn(accountMockId).when(accountMock).getId(); + Mockito.doReturn(volumeSizeMock).when(volumeVoMock).getSize(); + Mockito.doReturn(Mockito.mock(VolumeApiResult.class)).when(asyncCallFutureVolumeapiResultMock).get(); // mock caller context AccountVO account = new AccountVO("admin", 1L, "networkDomain", Account.ACCOUNT_TYPE_NORMAL, "uuid"); - AccountVO account2 = new AccountVO("Account2", 2L, "networkDomain", Account.ACCOUNT_TYPE_NORMAL, "uuid"); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); CallContext.register(user, account); // mock async context AsyncJobExecutionContext context = new AsyncJobExecutionContext(); - AsyncJobExecutionContext.init(_svc._jobMgr, _joinMapDao); + AsyncJobExecutionContext.init(volumeApiServiceImpl._jobMgr, asyncJobJoinMapDaoMock); AsyncJobVO job = new AsyncJobVO(); context.setJob(job); AsyncJobExecutionContext.setCurrentExecutionContext(context); @@ -162,59 +183,51 @@ public class VolumeApiServiceImplTest { TransactionLegacy txn = TransactionLegacy.open("runVolumeDaoImplTest"); 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(_svc._volsDao.findById(1L)).thenReturn(volumeOfRunningVm); + VolumeVO volumeOfRunningVm = new VolumeVO("root", 1L, 1L, 1L, 1L, 1L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT); + when(volumeApiServiceImpl._volsDao.findById(1L)).thenReturn(volumeOfRunningVm); - UserVmVO runningVm = new UserVmVO(1L, "vm", "vm", 1, HypervisorType.XenServer, 1L, false, - false, 1L, 1L, 1, 1L, null, "vm", null); + 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(_svc._userVmDao.findById(1L)).thenReturn(runningVm); + when(volumeApiServiceImpl._userVmDao.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); + 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(_svc._volsDao.findById(2L)).thenReturn(volumeOfStoppedVm); + when(volumeApiServiceImpl._volsDao.findById(2L)).thenReturn(volumeOfStoppedVm); - UserVmVO stoppedVm = new UserVmVO(2L, "vm", "vm", 1, HypervisorType.XenServer, 1L, false, - false, 1L, 1L, 1, 1L, null, "vm", null); + 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(_svc._userVmDao.findById(2L)).thenReturn(stoppedVm); - + when(volumeApiServiceImpl._userVmDao.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); + 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(_svc._userVmDao.findById(3L)).thenReturn(hyperVVm); + when(volumeApiServiceImpl._userVmDao.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); + 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(_svc._volsDao.findById(3L)).thenReturn(volumeOfStoppeHyperVVm); + when(volumeApiServiceImpl._volsDao.findById(3L)).thenReturn(volumeOfStoppeHyperVVm); StoragePoolVO unmanagedPool = new StoragePoolVO(); - when(_svc._storagePoolDao.findById(1L)).thenReturn(unmanagedPool); + when(volumeApiServiceImpl._storagePoolDao.findById(1L)).thenReturn(unmanagedPool); // volume of managed pool id=4 StoragePoolVO managedPool = new StoragePoolVO(); managedPool.setManaged(true); - when(_svc._storagePoolDao.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); + when(volumeApiServiceImpl._storagePoolDao.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(_svc._volsDao.findById(4L)).thenReturn(managedPoolVolume); + when(volumeApiServiceImpl._volsDao.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(_svc.volFactory.getVolume(5L)).thenReturn(volumeWithIncorrectVolumeType); + when(volumeApiServiceImpl.volFactory.getVolume(5L)).thenReturn(volumeWithIncorrectVolumeType); // correct root volume VolumeInfo correctRootVolume = Mockito.mock(VolumeInfo.class); @@ -225,11 +238,10 @@ public class VolumeApiServiceImplTest { when(correctRootVolume.getState()).thenReturn(Volume.State.Ready); when(correctRootVolume.getTemplateId()).thenReturn(null); when(correctRootVolume.getPoolId()).thenReturn(1L); - when(_svc.volFactory.getVolume(6L)).thenReturn(correctRootVolume); + when(volumeApiServiceImpl.volFactory.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(_svc._volsDao.findById(6L)).thenReturn(correctRootVolumeVO); + VolumeVO correctRootVolumeVO = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null, null, "root", Volume.Type.ROOT); + when(volumeApiServiceImpl._volsDao.findById(6L)).thenReturn(correctRootVolumeVO); // managed root volume VolumeInfo managedVolume = Mockito.mock(VolumeInfo.class); @@ -238,23 +250,21 @@ public class VolumeApiServiceImplTest { when(managedVolume.getVolumeType()).thenReturn(Volume.Type.ROOT); when(managedVolume.getInstanceId()).thenReturn(null); when(managedVolume.getPoolId()).thenReturn(2L); - when(_svc.volFactory.getVolume(7L)).thenReturn(managedVolume); + when(volumeApiServiceImpl.volFactory.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); + 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(_svc._volsDao.findById(7L)).thenReturn(managedVolume1); + when(volumeApiServiceImpl._volsDao.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); + 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(_svc._userVmDao.findById(4L)).thenReturn(vmHavingRootVolume); + when(volumeApiServiceImpl._userVmDao.findById(4L)).thenReturn(vmHavingRootVolume); List vols = new ArrayList(); vols.add(new VolumeVO()); - when(_svc._volsDao.findByInstanceAndDeviceId(4L, 0L)).thenReturn(vols); + when(volumeApiServiceImpl._volsDao.findByInstanceAndDeviceId(4L, 0L)).thenReturn(vols); // volume in uploaded state VolumeInfo uploadedVolume = Mockito.mock(VolumeInfo.class); @@ -264,32 +274,31 @@ public class VolumeApiServiceImplTest { when(uploadedVolume.getInstanceId()).thenReturn(null); when(uploadedVolume.getPoolId()).thenReturn(1L); when(uploadedVolume.getState()).thenReturn(Volume.State.Uploaded); - when(_svc.volFactory.getVolume(8L)).thenReturn(uploadedVolume); + when(volumeApiServiceImpl.volFactory.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); + 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(_svc._volsDao.findById(8L)).thenReturn(upVolume); + when(volumeApiServiceImpl._volsDao.findById(8L)).thenReturn(upVolume); // helper dao methods mock - when(_svc._vmSnapshotDao.findByVm(any(Long.class))).thenReturn(new ArrayList()); - when(_svc._vmInstanceDao.findById(any(Long.class))).thenReturn(stoppedVm); + when(volumeApiServiceImpl._vmSnapshotDao.findByVm(any(Long.class))).thenReturn(new ArrayList()); + when(volumeApiServiceImpl._vmInstanceDao.findById(any(Long.class))).thenReturn(stoppedVm); DataCenterVO enabledZone = Mockito.mock(DataCenterVO.class); when(enabledZone.getAllocationState()).thenReturn(Grouping.AllocationState.Enabled); - when(_svc._dcDao.findById(anyLong())).thenReturn(enabledZone); + when(volumeApiServiceImpl._dcDao.findById(anyLong())).thenReturn(enabledZone); } finally { txn.close("runVolumeDaoImplTest"); } // helper methods mock - doNothing().when(_svc._accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class)); - doNothing().when(_svc._jobMgr).updateAsyncJobAttachment(any(Long.class), any(String.class), any(Long.class)); - when(_svc._jobMgr.submitAsyncJob(any(AsyncJobVO.class), any(String.class), any(Long.class))).thenReturn(1L); + doNothing().when(volumeApiServiceImpl._accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class)); + doNothing().when(volumeApiServiceImpl._jobMgr).updateAsyncJobAttachment(any(Long.class), any(String.class), any(Long.class)); + when(volumeApiServiceImpl._jobMgr.submitAsyncJob(any(AsyncJobVO.class), any(String.class), any(Long.class))).thenReturn(1L); } /** @@ -302,7 +311,7 @@ public class VolumeApiServiceImplTest { Field dedicateIdField = _detachCmdClass.getDeclaredField("id"); dedicateIdField.setAccessible(true); dedicateIdField.set(detachCmd, 1L); - _svc.detachVolumeFromVM(detachCmd); + volumeApiServiceImpl.detachVolumeFromVM(detachCmd); } @Test(expected = InvalidParameterValueException.class) @@ -310,7 +319,7 @@ public class VolumeApiServiceImplTest { Field dedicateIdField = _detachCmdClass.getDeclaredField("id"); dedicateIdField.setAccessible(true); dedicateIdField.set(detachCmd, 3L); - _svc.detachVolumeFromVM(detachCmd); + volumeApiServiceImpl.detachVolumeFromVM(detachCmd); } @Test(expected = InvalidParameterValueException.class) @@ -318,7 +327,7 @@ public class VolumeApiServiceImplTest { Field dedicateIdField = _detachCmdClass.getDeclaredField("id"); dedicateIdField.setAccessible(true); dedicateIdField.set(detachCmd, 4L); - _svc.detachVolumeFromVM(detachCmd); + volumeApiServiceImpl.detachVolumeFromVM(detachCmd); } @Rule @@ -330,7 +339,7 @@ public class VolumeApiServiceImplTest { Field dedicateIdField = _detachCmdClass.getDeclaredField("id"); dedicateIdField.setAccessible(true); dedicateIdField.set(detachCmd, 2L); - _svc.detachVolumeFromVM(detachCmd); + volumeApiServiceImpl.detachVolumeFromVM(detachCmd); } /** @@ -340,101 +349,101 @@ public class VolumeApiServiceImplTest { // Negative test - try to attach non-root non-datadisk volume @Test(expected = InvalidParameterValueException.class) public void attachIncorrectDiskType() throws NoSuchFieldException, IllegalAccessException { - _svc.attachVolumeToVM(1L, 5L, 0L); + volumeApiServiceImpl.attachVolumeToVM(1L, 5L, 0L); } // Negative test - attach root volume to running vm @Test(expected = InvalidParameterValueException.class) public void attachRootDiskToRunningVm() throws NoSuchFieldException, IllegalAccessException { - _svc.attachVolumeToVM(1L, 6L, 0L); + volumeApiServiceImpl.attachVolumeToVM(1L, 6L, 0L); } // Negative test - attach root volume to non-xen vm @Test(expected = InvalidParameterValueException.class) public void attachRootDiskToHyperVm() throws NoSuchFieldException, IllegalAccessException { - _svc.attachVolumeToVM(3L, 6L, 0L); + volumeApiServiceImpl.attachVolumeToVM(3L, 6L, 0L); } // Negative test - attach root volume from the managed data store @Test(expected = InvalidParameterValueException.class) public void attachRootDiskOfManagedDataStore() throws NoSuchFieldException, IllegalAccessException { - _svc.attachVolumeToVM(2L, 7L, 0L); + volumeApiServiceImpl.attachVolumeToVM(2L, 7L, 0L); } // Negative test - root volume can't be attached to the vm already having a root volume attached @Test(expected = InvalidParameterValueException.class) public void attachRootDiskToVmHavingRootDisk() throws NoSuchFieldException, IllegalAccessException { - _svc.attachVolumeToVM(4L, 6L, 0L); + volumeApiServiceImpl.attachVolumeToVM(4L, 6L, 0L); } // Negative test - root volume in uploaded state can't be attached @Test(expected = InvalidParameterValueException.class) public void attachRootInUploadedState() throws NoSuchFieldException, IllegalAccessException { - _svc.attachVolumeToVM(2L, 8L, 0L); + volumeApiServiceImpl.attachVolumeToVM(2L, 8L, 0L); } // Positive test - attach ROOT volume in correct state, to the vm not having root volume attached @Test public void attachRootVolumePositive() throws NoSuchFieldException, IllegalAccessException { thrown.expect(NullPointerException.class); - _svc.attachVolumeToVM(2L, 6L, 0L); + volumeApiServiceImpl.attachVolumeToVM(2L, 6L, 0L); } // 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); - _svc.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null, false); + volumeApiServiceImpl.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null, false); } @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); - _svc.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null, false); + when(volumeServiceMock.takeSnapshot(Mockito.any(VolumeInfo.class))).thenReturn(snapshotInfoMock); + volumeApiServiceImpl.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null, false); } @Test public void testNullGetVolumeNameFromCmd() { - when(createVol.getVolumeName()).thenReturn(null); - Assert.assertNotNull(_svc.getVolumeNameFromCommand(createVol)); + when(createVolumeCmdMock.getVolumeName()).thenReturn(null); + Assert.assertNotNull(volumeApiServiceImpl.getVolumeNameFromCommand(createVolumeCmdMock)); } @Test public void testEmptyGetVolumeNameFromCmd() { - when(createVol.getVolumeName()).thenReturn(""); - Assert.assertNotNull(_svc.getVolumeNameFromCommand(createVol)); + when(createVolumeCmdMock.getVolumeName()).thenReturn(""); + Assert.assertNotNull(volumeApiServiceImpl.getVolumeNameFromCommand(createVolumeCmdMock)); } @Test public void testBlankGetVolumeNameFromCmd() { - when(createVol.getVolumeName()).thenReturn(" "); - Assert.assertNotNull(_svc.getVolumeNameFromCommand(createVol)); + when(createVolumeCmdMock.getVolumeName()).thenReturn(" "); + Assert.assertNotNull(volumeApiServiceImpl.getVolumeNameFromCommand(createVolumeCmdMock)); } @Test public void testNonEmptyGetVolumeNameFromCmd() { - when(createVol.getVolumeName()).thenReturn("abc"); - Assert.assertSame(_svc.getVolumeNameFromCommand(createVol), "abc"); + when(createVolumeCmdMock.getVolumeName()).thenReturn("abc"); + Assert.assertSame(volumeApiServiceImpl.getVolumeNameFromCommand(createVolumeCmdMock), "abc"); } @Test public void testUpdateMissingRootDiskControllerWithNullChainInfo() { - _svc.updateMissingRootDiskController(null, null); - verify(_svc._userVmMgr, times(0)).persistDeviceBusInfo(any(UserVmVO.class), anyString()); + volumeApiServiceImpl.updateMissingRootDiskController(null, null); + verify(userVmManagerMock, times(0)).persistDeviceBusInfo(any(UserVmVO.class), anyString()); } @Test public void testUpdateMissingRootDiskControllerWithValidChainInfo() { - UserVmVO vm = _svc._userVmDao.findById(1L); + UserVmVO vm = userVmDaoMock.findById(1L); assert vm.getType() == VirtualMachine.Type.User; - _svc.updateMissingRootDiskController(vm, "{\"diskDeviceBusName\":\"scsi0:0\",\"diskChain\":[\"[somedatastore] i-3-VM-somePath/ROOT-1.vmdk\"]}"); - verify(_svc._userVmMgr, times(1)).persistDeviceBusInfo(any(UserVmVO.class), eq("scsi")); + volumeApiServiceImpl.updateMissingRootDiskController(vm, "{\"diskDeviceBusName\":\"scsi0:0\",\"diskChain\":[\"[somedatastore] i-3-VM-somePath/ROOT-1.vmdk\"]}"); + verify(userVmManagerMock, times(1)).persistDeviceBusInfo(any(UserVmVO.class), eq("scsi")); } @Test @@ -443,7 +452,7 @@ public class VolumeApiServiceImplTest { */ public void testAllocSnapshotNonManagedStorageArchive() { try { - _svc.allocSnapshot(6L, 1L, "test", Snapshot.LocationType.SECONDARY); + volumeApiServiceImpl.allocSnapshot(6L, 1L, "test", Snapshot.LocationType.SECONDARY); } catch (InvalidParameterValueException e) { Assert.assertEquals(e.getMessage(), "VolumeId: 6 LocationType is supported only for managed storage"); return; @@ -462,33 +471,411 @@ 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(_svc._resourceLimitMgr).checkResourceLimit(any(AccountVO.class), any(Resource.ResourceType.class), any(Long.class)); + doThrow(new ResourceAllocationException("primary storage resource limit check failed", Resource.ResourceType.primary_storage)).when(volumeApiServiceImpl._resourceLimitMgr) + .checkResourceLimit(any(AccountVO.class), any(Resource.ResourceType.class), any(Long.class)); UserVmVO vm = Mockito.mock(UserVmVO.class); VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class); when(volumeToAttach.getId()).thenReturn(9L); 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(_svc._volsDao.findByInstanceAndType(anyLong(), any(Volume.Type.class))).thenReturn(new ArrayList(10)); - when(_svc.volFactory.getVolume(9L)).thenReturn(volumeToAttach); + when(volumeApiServiceImpl._volsDao.findByInstanceAndType(anyLong(), any(Volume.Type.class))).thenReturn(new ArrayList<>(10)); + when(volumeApiServiceImpl.volFactory.getVolume(9L)).thenReturn(volumeToAttach); when(volumeToAttach.getState()).thenReturn(Volume.State.Uploaded); DataCenterVO zoneWithDisabledLocalStorage = Mockito.mock(DataCenterVO.class); - when(_svc._dcDao.findById(anyLong())).thenReturn(zoneWithDisabledLocalStorage); + when(volumeApiServiceImpl._dcDao.findById(anyLong())).thenReturn(zoneWithDisabledLocalStorage); when(zoneWithDisabledLocalStorage.isLocalStorageEnabled()).thenReturn(true); try { - _svc.attachVolumeToVM(2L, 9L, null); + volumeApiServiceImpl.attachVolumeToVM(2L, 9L, null); } catch (InvalidParameterValueException e) { Assert.assertEquals(e.getMessage(), ("primary storage resource limit check failed")); } } - @After public void tearDown() { CallContext.unregister(); } + + @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 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); + + 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); + + 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); + + 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); + + 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); + + 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); + } }