diff --git a/api/src/main/java/com/cloud/offering/DiskOffering.java b/api/src/main/java/com/cloud/offering/DiskOffering.java index 9407acfdec1..d74f5703cc9 100644 --- a/api/src/main/java/com/cloud/offering/DiskOffering.java +++ b/api/src/main/java/com/cloud/offering/DiskOffering.java @@ -69,6 +69,8 @@ public interface DiskOffering extends InfrastructureEntity, Identity, InternalId boolean isCustomized(); + boolean isShared(); + void setDiskSize(long diskSize); long getDiskSize(); @@ -99,7 +101,6 @@ public interface DiskOffering extends InfrastructureEntity, Identity, InternalId Long getBytesReadRateMaxLength(); - void setBytesWriteRate(Long bytesWriteRate); Long getBytesWriteRate(); @@ -112,7 +113,6 @@ public interface DiskOffering extends InfrastructureEntity, Identity, InternalId Long getBytesWriteRateMaxLength(); - void setIopsReadRate(Long iopsReadRate); Long getIopsReadRate(); @@ -133,7 +133,6 @@ public interface DiskOffering extends InfrastructureEntity, Identity, InternalId Long getIopsWriteRateMax(); - void setIopsWriteRateMaxLength(Long iopsWriteRateMaxLength); Long getIopsWriteRateMaxLength(); diff --git a/api/src/main/java/com/cloud/storage/VolumeApiService.java b/api/src/main/java/com/cloud/storage/VolumeApiService.java index 4140d51a800..19c2ebe455a 100644 --- a/api/src/main/java/com/cloud/storage/VolumeApiService.java +++ b/api/src/main/java/com/cloud/storage/VolumeApiService.java @@ -180,6 +180,8 @@ public interface VolumeApiService { */ boolean doesStoragePoolSupportDiskOfferingTags(StoragePool destPool, String diskOfferingTags); + boolean validateConditionsToReplaceDiskOfferingOfVolume(Volume volume, DiskOffering newDiskOffering, StoragePool destPool); + Volume destroyVolume(long volumeId, Account caller, boolean expunge, boolean forceExpunge); void destroyVolume(long volumeId); diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java index ccb5bba1c0a..168822c21eb 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java @@ -23,6 +23,7 @@ import java.util.Map; import java.util.Set; import com.cloud.exception.ResourceAllocationException; +import com.cloud.storage.Storage; import com.cloud.utils.Pair; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; @@ -182,10 +183,10 @@ public interface VolumeOrchestrationService { */ DiskProfile importVolume(Type type, String name, DiskOffering offering, Long sizeInBytes, Long minIops, Long maxIops, Long zoneId, HypervisorType hypervisorType, VirtualMachine vm, VirtualMachineTemplate template, - Account owner, Long deviceId, Long poolId, String path, String chainInfo); + Account owner, Long deviceId, Long poolId, Storage.StoragePoolType poolType, String path, String chainInfo); DiskProfile updateImportedVolume(Type type, DiskOffering offering, VirtualMachine vm, VirtualMachineTemplate template, - Long deviceId, Long poolId, String path, String chainInfo, DiskProfile diskProfile); + Long deviceId, Long poolId, Storage.StoragePoolType poolType, String path, String chainInfo, DiskProfile diskProfile); /** * Unmanage VM volumes diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ClusterScope.java b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ClusterScope.java index b0ed7d7d52b..68c7ed40d8f 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ClusterScope.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ClusterScope.java @@ -19,6 +19,7 @@ package org.apache.cloudstack.engine.subsystem.api.storage; import com.cloud.storage.ScopeType; +import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils; public class ClusterScope extends AbstractScope { private ScopeType type = ScopeType.CLUSTER; @@ -51,4 +52,9 @@ public class ClusterScope extends AbstractScope { return this.zoneId; } + @Override + public String toString() { + return String.format("ClusterScope %s", ReflectionToStringBuilderUtils.reflectOnlySelectedFields( + this, "zoneId", "clusterId", "podId")); + } } diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/HostScope.java b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/HostScope.java index 6e0bc618bfe..7e6ffe7d4f7 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/HostScope.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/HostScope.java @@ -19,8 +19,10 @@ package org.apache.cloudstack.engine.subsystem.api.storage; import com.cloud.storage.ScopeType; +import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils; public class HostScope extends AbstractScope { + private ScopeType type = ScopeType.HOST; private Long hostId; private Long clusterId; private Long zoneId; @@ -34,7 +36,7 @@ public class HostScope extends AbstractScope { @Override public ScopeType getScopeType() { - return ScopeType.HOST; + return this.type; } @Override @@ -49,4 +51,10 @@ public class HostScope extends AbstractScope { public Long getZoneId() { return zoneId; } + + @Override + public String toString() { + return String.format("HostScope %s", ReflectionToStringBuilderUtils.reflectOnlySelectedFields( + this, "zoneId", "clusterId", "hostId")); + } } diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ZoneScope.java b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ZoneScope.java index a0d75b5cc7c..fa704d05b1a 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ZoneScope.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ZoneScope.java @@ -19,6 +19,7 @@ package org.apache.cloudstack.engine.subsystem.api.storage; import com.cloud.storage.ScopeType; +import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils; public class ZoneScope extends AbstractScope { private ScopeType type = ScopeType.ZONE; @@ -39,4 +40,9 @@ public class ZoneScope extends AbstractScope { return this.zoneId; } + @Override + public String toString() { + return String.format("ZoneScope %s", ReflectionToStringBuilderUtils.reflectOnlySelectedFields( + this, "zoneId")); + } } diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index a8a92d6b3db..b3e672e2c17 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -2859,6 +2859,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } volume.setPath(result.getPath()); volume.setPoolId(pool.getId()); + volume.setPoolType(pool.getPoolType()); if (result.getChainInfo() != null) { volume.setChainInfo(result.getChainInfo()); } diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index 7af9b6b8492..2b759235ac8 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -1423,7 +1423,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati String volumeToString = getVolumeIdentificationInfos(volume); VolumeInfo vol = volFactory.getVolume(volume.getId()); - if (vol == null){ + if (vol == null) { throw new CloudRuntimeException(String.format("Volume migration failed because volume [%s] is null.", volumeToString)); } if (destPool == null) { @@ -2308,6 +2308,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati StoragePoolVO pool = _storagePoolDao.findByUuid(updatedDataStoreUUID); if (pool != null) { vol.setPoolId(pool.getId()); + vol.setPoolType(pool.getPoolType()); } } _volsDao.update(volumeId, vol); @@ -2317,7 +2318,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati @Override public DiskProfile importVolume(Type type, String name, DiskOffering offering, Long sizeInBytes, Long minIops, Long maxIops, Long zoneId, HypervisorType hypervisorType, VirtualMachine vm, VirtualMachineTemplate template, Account owner, - Long deviceId, Long poolId, String path, String chainInfo) { + Long deviceId, Long poolId, Storage.StoragePoolType poolType, String path, String chainInfo) { if (sizeInBytes == null) { sizeInBytes = offering.getDiskSize(); } @@ -2358,6 +2359,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati vol.setFormat(getSupportedImageFormatForCluster(hypervisorType)); vol.setPoolId(poolId); + vol.setPoolType(poolType); vol.setPath(path); vol.setChainInfo(chainInfo); vol.setState(Volume.State.Ready); @@ -2367,7 +2369,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati @Override public DiskProfile updateImportedVolume(Type type, DiskOffering offering, VirtualMachine vm, VirtualMachineTemplate template, - Long deviceId, Long poolId, String path, String chainInfo, DiskProfile diskProfile) { + Long deviceId, Long poolId, Storage.StoragePoolType poolType, String path, String chainInfo, DiskProfile diskProfile) { VolumeVO vol = _volsDao.findById(diskProfile.getVolumeId()); if (vm != null) { @@ -2401,6 +2403,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati vol.setFormat(getSupportedImageFormatForCluster(vm.getHypervisorType())); vol.setPoolId(poolId); + vol.setPoolType(poolType); vol.setPath(path); vol.setChainInfo(chainInfo); vol.setSize(diskProfile.getSize()); diff --git a/engine/orchestration/src/test/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestratorTest.java b/engine/orchestration/src/test/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestratorTest.java index 817ff02ef74..b4a26c17e2e 100644 --- a/engine/orchestration/src/test/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestratorTest.java +++ b/engine/orchestration/src/test/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestratorTest.java @@ -241,7 +241,7 @@ public class VolumeOrchestratorTest { volumeOrchestrator.importVolume(volumeType, name, diskOffering, sizeInBytes, null, null, zoneId, hypervisorType, null, null, owner, - deviceId, poolId, path, chainInfo); + deviceId, poolId, Storage.StoragePoolType.NetworkFilesystem, path, chainInfo); VolumeVO volume = volumeVOMockedConstructionConstruction.constructed().get(0); Mockito.verify(volume, Mockito.never()).setInstanceId(Mockito.anyLong()); diff --git a/engine/schema/src/main/java/com/cloud/storage/DiskOfferingVO.java b/engine/schema/src/main/java/com/cloud/storage/DiskOfferingVO.java index 79f5bcb5157..7f6b6d8adf0 100644 --- a/engine/schema/src/main/java/com/cloud/storage/DiskOfferingVO.java +++ b/engine/schema/src/main/java/com/cloud/storage/DiskOfferingVO.java @@ -577,11 +577,11 @@ public class DiskOfferingVO implements DiskOffering { @Override public void setEncrypt(boolean encrypt) { this.encrypt = encrypt; } + @Override public boolean isShared() { return !useLocalStorage; } - public boolean getDiskSizeStrictness() { return diskSizeStrictness; } diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/DiskOfferingDao.java b/engine/schema/src/main/java/com/cloud/storage/dao/DiskOfferingDao.java index f726bca3c5d..9beea003744 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/DiskOfferingDao.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/DiskOfferingDao.java @@ -31,6 +31,8 @@ public interface DiskOfferingDao extends GenericDao { List listAllBySizeAndProvisioningType(long size, Storage.ProvisioningType provisioningType); List findCustomDiskOfferings(); + List listByStorageTag(String tag); + List listAllActiveAndNonComputeDiskOfferings(); } diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/DiskOfferingDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/DiskOfferingDaoImpl.java index 93e74766277..4ca3fe9f12a 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/DiskOfferingDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/DiskOfferingDaoImpl.java @@ -26,6 +26,7 @@ import java.util.List; import javax.inject.Inject; import javax.persistence.EntityExistsException; +import com.cloud.offering.DiskOffering; import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao; import org.springframework.stereotype.Component; @@ -45,6 +46,8 @@ public class DiskOfferingDaoImpl extends GenericDaoBase im protected DiskOfferingDetailsDao detailsDao; protected final SearchBuilder UniqueNameSearch; + protected final SearchBuilder ActiveAndNonComputeSearch; + private final String SizeDiskOfferingSearch = "SELECT * FROM disk_offering WHERE " + "disk_size = ? AND provisioning_type = ? AND removed IS NULL"; @@ -56,6 +59,11 @@ public class DiskOfferingDaoImpl extends GenericDaoBase im UniqueNameSearch.and("name", UniqueNameSearch.entity().getUniqueName(), SearchCriteria.Op.EQ); UniqueNameSearch.done(); + ActiveAndNonComputeSearch = createSearchBuilder(); + ActiveAndNonComputeSearch.and("state", ActiveAndNonComputeSearch.entity().getState(), SearchCriteria.Op.EQ); + ActiveAndNonComputeSearch.and("computeOnly", ActiveAndNonComputeSearch.entity().isComputeOnly(), SearchCriteria.Op.EQ); + ActiveAndNonComputeSearch.done(); + _computeOnlyAttr = _allAttributes.get("computeOnly"); } @@ -164,4 +172,12 @@ public class DiskOfferingDaoImpl extends GenericDaoBase im sc.setParameters("tagEndLike", "%," + tag); return listBy(sc); } + + @Override + public List listAllActiveAndNonComputeDiskOfferings() { + SearchCriteria sc = ActiveAndNonComputeSearch.create(); + sc.setParameters("state", DiskOffering.State.Active); + sc.setParameters("computeOnly", false); + return listBy(sc); + } } diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java index f8b6bb3ed68..6814636bc66 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java @@ -822,6 +822,7 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol if (volume.getState() != Volume.State.Destroy) { volume.setState(Volume.State.Destroy); volume.setPoolId(null); + volume.setPoolType(null); volume.setInstanceId(null); update(volume.getId(), volume); remove(volume.getId()); diff --git a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java index 0b0065361d0..c494ca31594 100644 --- a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java +++ b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java @@ -18,9 +18,11 @@ */ package org.apache.cloudstack.storage.motion; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import javax.inject.Inject; @@ -67,6 +69,7 @@ import com.cloud.configuration.Config; import com.cloud.host.Host; import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; import com.cloud.storage.Snapshot.Type; import com.cloud.storage.SnapshotVO; import com.cloud.storage.StorageManager; @@ -85,6 +88,11 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { protected Logger logger = LogManager.getLogger(getClass()); private static final String NO_REMOTE_ENDPOINT_SSVM = "No remote endpoint to send command, check if host or ssvm is down?"; private static final String NO_REMOTE_ENDPOINT_WITH_ENCRYPTION = "No remote endpoint to send command, unable to find a valid endpoint. Requires encryption support: %s"; + private static final List SUPPORTED_POOL_TYPES_TO_BYPASS_SECONDARY_STORE = Arrays.asList( + StoragePoolType.NetworkFilesystem, + StoragePoolType.Filesystem, + StoragePoolType.RBD + ); @Inject EndPointSelector selector; @@ -240,7 +248,6 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { return dataTO; } - protected Answer copyObject(DataObject srcData, DataObject destData) { return copyObject(srcData, destData, null); } @@ -352,14 +359,12 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { Scope destScope = getZoneScope(destData.getDataStore().getScope()); DataStore cacheStore = cacheMgr.getCacheStorage(destScope); - boolean bypassSecondaryStorage = false; - if (srcData instanceof VolumeInfo && ((VolumeInfo)srcData).isDirectDownload()) { - bypassSecondaryStorage = true; - } + boolean bypassSecondaryStorage = canBypassSecondaryStorage(srcData, destData); boolean encryptionRequired = anyVolumeRequiresEncryption(srcData, destData); if (cacheStore == null) { if (bypassSecondaryStorage) { + logger.debug("Secondary storage is bypassed, copy volume between pools directly"); CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _copyvolumewait, VirtualMachineManager.ExecuteInSequence.value()); EndPoint ep = selector.select(srcData, destData, encryptionRequired); Answer answer = null; @@ -388,8 +393,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { answer = copyObject(srcData, objOnImageStore); if (answer == null || !answer.getResult()) { - if (answer != null) { - if (logger.isDebugEnabled()) logger.debug("copy to image store failed: " + answer.getDetails()); + if (answer != null && logger.isDebugEnabled()) { + logger.debug("copy to image store failed: {}", answer.getDetails()); } objOnImageStore.processEvent(Event.OperationFailed); imageStore.delete(objOnImageStore); @@ -411,8 +416,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { } if (answer == null || !answer.getResult()) { - if (answer != null) { - if (logger.isDebugEnabled()) logger.debug("copy to primary store failed: " + answer.getDetails()); + if (answer != null && logger.isDebugEnabled()) { + logger.debug("copy to primary store failed: {}", answer.getDetails()); } objOnImageStore.processEvent(Event.OperationFailed); imageStore.delete(objOnImageStore); @@ -423,7 +428,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { objOnImageStore.processEvent(Event.OperationFailed); imageStore.delete(objOnImageStore); } - logger.error("Failed to perform operation: "+ e.getLocalizedMessage()); + logger.error("Failed to perform operation: {}", e.getLocalizedMessage()); throw e; } @@ -448,7 +453,78 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { } return answer; } + } + private boolean canBypassSecondaryStorage(DataObject srcData, DataObject destData) { + if (srcData instanceof VolumeInfo) { + if (((VolumeInfo)srcData).isDirectDownload()) { + return true; + } + + if (destData instanceof VolumeInfo) { + Scope srcDataStoreScope = srcData.getDataStore().getScope(); + Scope destDataStoreScope = destData.getDataStore().getScope(); + logger.info("srcDataStoreScope: {}, srcData pool type: {}; destDataStoreScope: {}, destData pool type: {}", + srcDataStoreScope, ((VolumeInfo)srcData).getStoragePoolType(), destDataStoreScope, ((VolumeInfo)destData).getStoragePoolType()); + + if (srcDataStoreScope != null && destDataStoreScope != null && + SUPPORTED_POOL_TYPES_TO_BYPASS_SECONDARY_STORE.contains(((VolumeInfo)srcData).getStoragePoolType()) && + SUPPORTED_POOL_TYPES_TO_BYPASS_SECONDARY_STORE.contains(((VolumeInfo)destData).getStoragePoolType())) { + + return canDirectlyCopyBetweenDataStoreScopes(srcDataStoreScope, destDataStoreScope); + } + } + } + + return false; + } + + private boolean canDirectlyCopyBetweenDataStoreScopes(Scope srcDataStoreScope, Scope destDataStoreScope) { + if (srcDataStoreScope == null || destDataStoreScope == null) { + return false; + } + + if (srcDataStoreScope.isSameScope(destDataStoreScope)) { + return true; + } + + if (srcDataStoreScope.getScopeType() == ScopeType.HOST) { + if (destDataStoreScope.getScopeType() == ScopeType.CLUSTER && + (Objects.equals(((HostScope) srcDataStoreScope).getClusterId(), ((ClusterScope) destDataStoreScope).getScopeId()))) { + return true; + } + if (destDataStoreScope.getScopeType() == ScopeType.ZONE && + (Objects.equals(((HostScope) srcDataStoreScope).getZoneId(), ((ZoneScope) destDataStoreScope).getScopeId()))) { + return true; + } + } + + if (destDataStoreScope.getScopeType() == ScopeType.HOST) { + if (srcDataStoreScope.getScopeType() == ScopeType.CLUSTER && + (Objects.equals(((ClusterScope) srcDataStoreScope).getScopeId(), ((HostScope) destDataStoreScope).getClusterId()))) { + return true; + } + if (srcDataStoreScope.getScopeType() == ScopeType.ZONE && + (Objects.equals(((ZoneScope) srcDataStoreScope).getScopeId(), ((HostScope) destDataStoreScope).getZoneId()))) { + return true; + } + } + + if (srcDataStoreScope.getScopeType() == ScopeType.CLUSTER) { + if (destDataStoreScope.getScopeType() == ScopeType.ZONE && + (Objects.equals(((ClusterScope) srcDataStoreScope).getZoneId(), ((ZoneScope) destDataStoreScope).getScopeId()))) { + return true; + } + } + + if (destDataStoreScope.getScopeType() == ScopeType.CLUSTER) { + if (srcDataStoreScope.getScopeType() == ScopeType.ZONE && + (Objects.equals(((ZoneScope) srcDataStoreScope).getScopeId(), ((ClusterScope) destDataStoreScope).getZoneId()))) { + return true; + } + } + + return false; } protected Answer migrateVolumeToPool(DataObject srcData, DataObject destData) { @@ -492,6 +568,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { } volumeVo.setPodId(destPool.getPodId()); volumeVo.setPoolId(destPool.getId()); + volumeVo.setPoolType(destPool.getPoolType()); volumeVo.setLastPoolId(oldPoolId); // For SMB, pool credentials are also stored in the uri query string. We trim the query string // part here to make sure the credentials do not get stored in the db unencrypted. diff --git a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java index 0a211ab1934..fa8a7a79aa3 100644 --- a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java +++ b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java @@ -122,6 +122,7 @@ import com.cloud.storage.VMTemplateStoragePoolVO; import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Volume; +import com.cloud.storage.VolumeApiService; import com.cloud.storage.VolumeDetailVO; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.DiskOfferingDao; @@ -194,6 +195,8 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy { @Inject private VolumeService _volumeService; @Inject + public VolumeApiService _volumeApiService; + @Inject private StorageCacheManager cacheMgr; @Inject private EndPointSelector selector; @@ -796,6 +799,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy { volumeVO.setPodId(destPool.getPodId()); volumeVO.setPoolId(destPool.getId()); + volumeVO.setPoolType(destPool.getPoolType()); volumeVO.setLastPoolId(srcVolumeInfo.getPoolId()); _volumeDao.update(srcVolumeInfo.getId(), volumeVO); @@ -2348,11 +2352,22 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy { volumeVO.setFormat(ImageFormat.QCOW2); volumeVO.setLastId(srcVolumeInfo.getId()); + if (Objects.equals(srcVolumeInfo.getDiskOfferingId(), destVolumeInfo.getDiskOfferingId())) { + StoragePoolVO srcPoolVO = _storagePoolDao.findById(srcVolumeInfo.getPoolId()); + StoragePoolVO destPoolVO = _storagePoolDao.findById(destVolumeInfo.getPoolId()); + if (srcPoolVO != null && destPoolVO != null && + ((srcPoolVO.isShared() && destPoolVO.isLocal()) || (srcPoolVO.isLocal() && destPoolVO.isShared()))) { + Long offeringId = getSuitableDiskOfferingForVolumeOnPool(volumeVO, destPoolVO); + if (offeringId != null) { + volumeVO.setDiskOfferingId(offeringId); + } + } + } + _volumeDao.update(volumeVO.getId(), volumeVO); _volumeService.copyPoliciesBetweenVolumesAndDestroySourceVolumeAfterMigration(Event.OperationSuccessed, null, srcVolumeInfo, destVolumeInfo, false); - // Update the volume ID for snapshots on secondary storage if (!_snapshotDao.listByVolumeId(srcVolumeInfo.getId()).isEmpty()) { _snapshotDao.updateVolumeIds(srcVolumeInfo.getId(), destVolumeInfo.getId()); @@ -2394,17 +2409,32 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy { } } + private Long getSuitableDiskOfferingForVolumeOnPool(VolumeVO volume, StoragePoolVO pool) { + List diskOfferings = _diskOfferingDao.listAllActiveAndNonComputeDiskOfferings(); + for (DiskOfferingVO diskOffering : diskOfferings) { + try { + if (_volumeApiService.validateConditionsToReplaceDiskOfferingOfVolume(volume, diskOffering, pool)) { + logger.debug("Found suitable disk offering {} for the volume {}", diskOffering, volume); + return diskOffering.getId(); + } + } catch (Exception ignore) { + } + } + logger.warn("Unable to find suitable disk offering for the volume {}", volume); + return null; + } + private VolumeVO duplicateVolumeOnAnotherStorage(Volume volume, StoragePoolVO storagePoolVO) { Long lastPoolId = volume.getPoolId(); VolumeVO newVol = new VolumeVO(volume); - newVol.setInstanceId(null); newVol.setChainInfo(null); newVol.setPath(null); newVol.setFolder(null); newVol.setPodId(storagePoolVO.getPodId()); newVol.setPoolId(storagePoolVO.getId()); + newVol.setPoolType(storagePoolVO.getPoolType()); newVol.setLastPoolId(lastPoolId); newVol.setLastId(volume.getId()); diff --git a/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategyTest.java b/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategyTest.java index 67e3ea844d5..e167cc0a965 100755 --- a/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategyTest.java +++ b/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategyTest.java @@ -21,20 +21,34 @@ package org.apache.cloudstack.storage.motion; import static org.mockito.Mockito.when; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.never; import static org.mockito.Mockito.any; +import com.cloud.storage.Storage; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; +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.ClusterScope; +import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; +import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.framework.config.ConfigKey; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.storage.image.store.TemplateObject; import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; +import org.apache.cloudstack.storage.volume.VolumeObject; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; @@ -57,6 +71,10 @@ public class AncientDataMotionStrategyTest { StorageManager storageManager; @Mock StoragePool storagePool; + @Mock + StorageCacheManager cacheMgr; + @Mock + ConfigurationDao configDao; private static final long POOL_ID = 1l; private static final Boolean FULL_CLONE_FLAG = true; @@ -88,4 +106,186 @@ public class AncientDataMotionStrategyTest { verify(dataStoreTO, never()).setFullCloneFlag(any(Boolean.class)); } + @Test + public void testCanBypassSecondaryStorageForDirectDownload() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject()); + Mockito.doReturn(true).when(srcVolumeInfo).isDirectDownload(); + + VolumeObject destVolumeInfo = Mockito.spy(new VolumeObject()); + + Method method; + method = AncientDataMotionStrategy.class.getDeclaredMethod("canBypassSecondaryStorage", DataObject.class, DataObject.class); + method.setAccessible(true); + boolean canBypassSecondaryStorage = (boolean) method.invoke(strategy, srcVolumeInfo, destVolumeInfo); + Assert.assertTrue(canBypassSecondaryStorage); + } + + @Test + public void testCanBypassSecondaryStorageForUnsupportedDataObject() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject()); + + TemplateObject destTemplateInfo = Mockito.spy(new TemplateObject()); + + Method method; + method = AncientDataMotionStrategy.class.getDeclaredMethod("canBypassSecondaryStorage", DataObject.class, DataObject.class); + method.setAccessible(true); + boolean canBypassSecondaryStorage = (boolean) method.invoke(strategy, srcVolumeInfo, destTemplateInfo); + Assert.assertFalse(canBypassSecondaryStorage); + } + + @Test + public void testCanBypassSecondaryStorageForUnsupportedSrcPoolType() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject()); + DataStore srcDataStore = Mockito.mock(DataStore.class); + Mockito.doReturn(new ZoneScope(1L)).when(srcDataStore).getScope(); + Mockito.doReturn(srcDataStore).when(srcVolumeInfo).getDataStore(); + Mockito.doReturn(Storage.StoragePoolType.PowerFlex).when(srcVolumeInfo).getStoragePoolType(); + + VolumeObject destVolumeInfo = Mockito.spy(new VolumeObject()); + DataStore destDataStore = Mockito.mock(DataStore.class); + Mockito.doReturn(new ZoneScope(1L)).when(destDataStore).getScope(); + Mockito.doReturn(destDataStore).when(destVolumeInfo).getDataStore(); + Mockito.doReturn(Storage.StoragePoolType.NetworkFilesystem).when(destVolumeInfo).getStoragePoolType(); + + Method method; + method = AncientDataMotionStrategy.class.getDeclaredMethod("canBypassSecondaryStorage", DataObject.class, DataObject.class); + method.setAccessible(true); + boolean canBypassSecondaryStorage = (boolean) method.invoke(strategy, srcVolumeInfo, destVolumeInfo); + Assert.assertFalse(canBypassSecondaryStorage); + } + + @Test + public void testCanBypassSecondaryStorageForUnsupportedDestPoolType() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject()); + DataStore srcDataStore = Mockito.mock(DataStore.class); + Mockito.doReturn(new ZoneScope(1L)).when(srcDataStore).getScope(); + Mockito.doReturn(srcDataStore).when(srcVolumeInfo).getDataStore(); + Mockito.doReturn(Storage.StoragePoolType.NetworkFilesystem).when(srcVolumeInfo).getStoragePoolType(); + + VolumeObject destVolumeInfo = Mockito.spy(new VolumeObject()); + DataStore destDataStore = Mockito.mock(DataStore.class); + Mockito.doReturn(new ZoneScope(1L)).when(destDataStore).getScope(); + Mockito.doReturn(destDataStore).when(destVolumeInfo).getDataStore(); + Mockito.doReturn(Storage.StoragePoolType.Iscsi).when(destVolumeInfo).getStoragePoolType(); + + Method method; + method = AncientDataMotionStrategy.class.getDeclaredMethod("canBypassSecondaryStorage", DataObject.class, DataObject.class); + method.setAccessible(true); + boolean canBypassSecondaryStorage = (boolean) method.invoke(strategy, srcVolumeInfo, destVolumeInfo); + Assert.assertFalse(canBypassSecondaryStorage); + } + + @Test + public void testCanBypassSecondaryStorageWithZoneWideNFSPoolsInSameZone() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject()); + DataStore srcDataStore = Mockito.mock(DataStore.class); + Mockito.doReturn(new ZoneScope(1L)).when(srcDataStore).getScope(); + Mockito.doReturn(srcDataStore).when(srcVolumeInfo).getDataStore(); + Mockito.doReturn(Storage.StoragePoolType.NetworkFilesystem).when(srcVolumeInfo).getStoragePoolType(); + + VolumeObject destVolumeInfo = Mockito.spy(new VolumeObject()); + DataStore destDataStore = Mockito.mock(DataStore.class); + Mockito.doReturn(new ZoneScope(1L)).when(destDataStore).getScope(); + Mockito.doReturn(destDataStore).when(destVolumeInfo).getDataStore(); + Mockito.doReturn(Storage.StoragePoolType.NetworkFilesystem).when(destVolumeInfo).getStoragePoolType(); + + Method method; + method = AncientDataMotionStrategy.class.getDeclaredMethod("canBypassSecondaryStorage", DataObject.class, DataObject.class); + method.setAccessible(true); + boolean canBypassSecondaryStorage = (boolean) method.invoke(strategy, srcVolumeInfo, destVolumeInfo); + Assert.assertTrue(canBypassSecondaryStorage); + } + + @Test + public void testCanBypassSecondaryStorageWithClusterWideNFSPoolsInSameCluster() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject()); + DataStore srcDataStore = Mockito.mock(DataStore.class); + Mockito.doReturn(new ClusterScope(5L, 2L, 1L)).when(srcDataStore).getScope(); + Mockito.doReturn(srcDataStore).when(srcVolumeInfo).getDataStore(); + Mockito.doReturn(Storage.StoragePoolType.NetworkFilesystem).when(srcVolumeInfo).getStoragePoolType(); + + VolumeObject destVolumeInfo = Mockito.spy(new VolumeObject()); + DataStore destDataStore = Mockito.mock(DataStore.class); + Mockito.doReturn(new ClusterScope(5L, 2L, 1L)).when(destDataStore).getScope(); + Mockito.doReturn(destDataStore).when(destVolumeInfo).getDataStore(); + Mockito.doReturn(Storage.StoragePoolType.NetworkFilesystem).when(destVolumeInfo).getStoragePoolType(); + + Method method; + method = AncientDataMotionStrategy.class.getDeclaredMethod("canBypassSecondaryStorage", DataObject.class, DataObject.class); + method.setAccessible(true); + boolean canBypassSecondaryStorage = (boolean) method.invoke(strategy, srcVolumeInfo, destVolumeInfo); + Assert.assertTrue(canBypassSecondaryStorage); + } + + @Test + public void testCanBypassSecondaryStorageWithLocalAndClusterWideNFSPoolsInSameCluster() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject()); + DataStore srcDataStore = Mockito.mock(DataStore.class); + Mockito.doReturn(new HostScope(1L, 1L, 1L)).when(srcDataStore).getScope(); + Mockito.doReturn(srcDataStore).when(srcVolumeInfo).getDataStore(); + Mockito.doReturn(Storage.StoragePoolType.Filesystem).when(srcVolumeInfo).getStoragePoolType(); + + VolumeObject destVolumeInfo = Mockito.spy(new VolumeObject()); + DataStore destDataStore = Mockito.mock(DataStore.class); + Mockito.doReturn(new ClusterScope(1L, 1L, 1L)).when(destDataStore).getScope(); + Mockito.doReturn(destDataStore).when(destVolumeInfo).getDataStore(); + Mockito.doReturn(Storage.StoragePoolType.NetworkFilesystem).when(destVolumeInfo).getStoragePoolType(); + + Method method; + method = AncientDataMotionStrategy.class.getDeclaredMethod("canBypassSecondaryStorage", DataObject.class, DataObject.class); + method.setAccessible(true); + boolean canBypassSecondaryStorage = (boolean) method.invoke(strategy, srcVolumeInfo, destVolumeInfo); + Assert.assertTrue(canBypassSecondaryStorage); + + canBypassSecondaryStorage = (boolean) method.invoke(strategy, destVolumeInfo, srcVolumeInfo); + Assert.assertTrue(canBypassSecondaryStorage); + } + + @Test + public void testCanBypassSecondaryStorageWithLocalAndZoneWideNFSPoolsInSameZone() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject()); + DataStore srcDataStore = Mockito.mock(DataStore.class); + Mockito.doReturn(new HostScope(1L, 1L, 1L)).when(srcDataStore).getScope(); + Mockito.doReturn(srcDataStore).when(srcVolumeInfo).getDataStore(); + Mockito.doReturn(Storage.StoragePoolType.Filesystem).when(srcVolumeInfo).getStoragePoolType(); + + VolumeObject destVolumeInfo = Mockito.spy(new VolumeObject()); + DataStore destDataStore = Mockito.mock(DataStore.class); + Mockito.doReturn(new ZoneScope(1L)).when(destDataStore).getScope(); + Mockito.doReturn(destDataStore).when(destVolumeInfo).getDataStore(); + Mockito.doReturn(Storage.StoragePoolType.NetworkFilesystem).when(destVolumeInfo).getStoragePoolType(); + + Method method; + method = AncientDataMotionStrategy.class.getDeclaredMethod("canBypassSecondaryStorage", DataObject.class, DataObject.class); + method.setAccessible(true); + boolean canBypassSecondaryStorage = (boolean) method.invoke(strategy, srcVolumeInfo, destVolumeInfo); + Assert.assertTrue(canBypassSecondaryStorage); + + canBypassSecondaryStorage = (boolean) method.invoke(strategy, destVolumeInfo, srcVolumeInfo); + Assert.assertTrue(canBypassSecondaryStorage); + } + + @Test + public void testCanBypassSecondaryStorageWithClusterWideNFSAndZoneWideNFSPoolsInSameZone() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + VolumeObject srcVolumeInfo = Mockito.spy(new VolumeObject()); + DataStore srcDataStore = Mockito.mock(DataStore.class); + Mockito.doReturn(new ClusterScope(5L, 2L, 1L)).when(srcDataStore).getScope(); + Mockito.doReturn(srcDataStore).when(srcVolumeInfo).getDataStore(); + Mockito.doReturn(Storage.StoragePoolType.NetworkFilesystem).when(srcVolumeInfo).getStoragePoolType(); + + VolumeObject destVolumeInfo = Mockito.spy(new VolumeObject()); + DataStore destDataStore = Mockito.mock(DataStore.class); + Mockito.doReturn(new ZoneScope(1L)).when(destDataStore).getScope(); + Mockito.doReturn(destDataStore).when(destVolumeInfo).getDataStore(); + Mockito.doReturn(Storage.StoragePoolType.NetworkFilesystem).when(destVolumeInfo).getStoragePoolType(); + + Method method; + method = AncientDataMotionStrategy.class.getDeclaredMethod("canBypassSecondaryStorage", DataObject.class, DataObject.class); + method.setAccessible(true); + boolean canBypassSecondaryStorage = (boolean) method.invoke(strategy, srcVolumeInfo, destVolumeInfo); + Assert.assertTrue(canBypassSecondaryStorage); + + canBypassSecondaryStorage = (boolean) method.invoke(strategy, destVolumeInfo, srcVolumeInfo); + Assert.assertTrue(canBypassSecondaryStorage); + } } diff --git a/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java b/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java index a19fcb9eda8..6e933396871 100644 --- a/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java +++ b/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java @@ -345,6 +345,7 @@ public class DefaultVMSnapshotStrategy extends ManagerBase implements VMSnapshot StoragePool pool = primaryDataStoreDao.findPoolByUUID(volume.getDataStoreUuid()); if (pool != null && pool.getId() != volumeVO.getPoolId()) { volumeVO.setPoolId(pool.getId()); + volumeVO.setPoolType(pool.getPoolType()); } } if (StringUtils.isNotEmpty(volume.getPath())) { diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java index da6b1cfede3..061d18dc376 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java @@ -232,7 +232,13 @@ public class DefaultEndPointSelector implements EndPointSelector { // assumption, at least one of scope should be zone, find the least // scope - if (srcScope.getScopeType() != ScopeType.ZONE) { + if (srcScope.getScopeType() == ScopeType.HOST) { + selectedScope = srcScope; + poolId = srcStore.getId(); + } else if (destScope.getScopeType() == ScopeType.HOST) { + selectedScope = destScope; + poolId = destStore.getId(); + } else if (srcScope.getScopeType() != ScopeType.ZONE) { selectedScope = srcScope; poolId = srcStore.getId(); } else if (destScope.getScopeType() != ScopeType.ZONE) { diff --git a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java index 6a10c26cc0b..d0184359c8b 100644 --- a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java +++ b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java @@ -334,6 +334,7 @@ public class PrimaryDataStoreImpl implements PrimaryDataStore { VolumeVO vol = volumeDao.findById(obj.getId()); if (vol != null) { vol.setPoolId(getId()); + vol.setPoolType(getPoolType()); volumeDao.update(vol.getId(), vol); } } diff --git a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeDataFactoryImpl.java b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeDataFactoryImpl.java index 53fa21f3a79..5c2a774f8a2 100644 --- a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeDataFactoryImpl.java +++ b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeDataFactoryImpl.java @@ -30,6 +30,8 @@ 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.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +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; @@ -46,6 +48,8 @@ public class VolumeDataFactoryImpl implements VolumeDataFactory { DataStoreManager storeMgr; @Inject VMTemplateDao templateDao; + @Inject + PrimaryDataStoreDao storagePoolDao; @Override public VolumeInfo getVolume(long volumeId, DataStore store) { @@ -92,6 +96,10 @@ public class VolumeDataFactoryImpl implements VolumeDataFactory { vol = VolumeObject.getVolumeObject(store, volumeVO); } else { DataStore store = storeMgr.getDataStore(volumeVO.getPoolId(), DataStoreRole.Primary); + StoragePoolVO pool = storagePoolDao.findById(volumeVO.getPoolId()); + if (pool != null) { + volumeVO.setPoolType(pool.getPoolType()); + } vol = VolumeObject.getVolumeObject(store, volumeVO); } if (vol.getTemplateId() != null) { diff --git a/plugins/hypervisors/hyperv/src/main/java/org/apache/cloudstack/storage/motion/HypervStorageMotionStrategy.java b/plugins/hypervisors/hyperv/src/main/java/org/apache/cloudstack/storage/motion/HypervStorageMotionStrategy.java index 0e189d05000..55944a08242 100644 --- a/plugins/hypervisors/hyperv/src/main/java/org/apache/cloudstack/storage/motion/HypervStorageMotionStrategy.java +++ b/plugins/hypervisors/hyperv/src/main/java/org/apache/cloudstack/storage/motion/HypervStorageMotionStrategy.java @@ -155,6 +155,7 @@ public class HypervStorageMotionStrategy implements DataMotionStrategy { volumeVO.setPath(volumeTo.getPath()); volumeVO.setPodId(pool.getPodId()); volumeVO.setPoolId(pool.getId()); + volumeVO.setPoolType(pool.getPoolType()); volumeVO.setLastPoolId(oldPoolId); // For SMB, pool credentials are also stored in the uri query string. We trim the query string // part here to make sure the credentials do not get stored in the db unencrypted. diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java index 0bb621af171..7b56ba47db0 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java @@ -364,16 +364,7 @@ public class KVMStorageProcessor implements StorageProcessor { final TemplateObjectTO newTemplate = new TemplateObjectTO(); newTemplate.setPath(primaryVol.getName()); newTemplate.setSize(primaryVol.getSize()); - - if(List.of( - StoragePoolType.RBD, - StoragePoolType.PowerFlex, - StoragePoolType.Linstor, - StoragePoolType.FiberChannel).contains(primaryPool.getType())) { - newTemplate.setFormat(ImageFormat.RAW); - } else { - newTemplate.setFormat(ImageFormat.QCOW2); - } + newTemplate.setFormat(getFormat(primaryPool.getType())); data = newTemplate; } else if (destData.getObjectType() == DataObjectType.VOLUME) { final VolumeObjectTO volumeObjectTO = new VolumeObjectTO(); @@ -2990,7 +2981,7 @@ public class KVMStorageProcessor implements StorageProcessor { final VolumeObjectTO srcVol = (VolumeObjectTO)srcData; final VolumeObjectTO destVol = (VolumeObjectTO)destData; final ImageFormat srcFormat = srcVol.getFormat(); - final ImageFormat destFormat = destVol.getFormat(); + ImageFormat destFormat = destVol.getFormat(); final DataStoreTO srcStore = srcData.getDataStore(); final DataStoreTO destStore = destData.getDataStore(); final PrimaryDataStoreTO srcPrimaryStore = (PrimaryDataStoreTO)srcStore; @@ -3025,33 +3016,35 @@ public class KVMStorageProcessor implements StorageProcessor { volume.setFormat(PhysicalDiskFormat.valueOf(srcFormat.toString())); volume.setDispName(srcVol.getName()); volume.setVmName(srcVol.getVmName()); - - String destVolumeName = null; + KVMPhysicalDisk newVolume; + String destVolumeName; + destPool = storagePoolMgr.getStoragePool(destPrimaryStore.getPoolType(), destPrimaryStore.getUuid()); if (destPrimaryStore.isManaged()) { if (!storagePoolMgr.connectPhysicalDisk(destPrimaryStore.getPoolType(), destPrimaryStore.getUuid(), destVolumePath, destPrimaryStore.getDetails())) { logger.warn("Failed to connect dest volume {}, in storage pool {}", destVol, destPrimaryStore); } destVolumeName = derivePath(destPrimaryStore, destData, destPrimaryStore.getDetails()); } else { + PhysicalDiskFormat destPoolDefaultFormat = destPool.getDefaultFormat(); + destFormat = getFormat(destPoolDefaultFormat); final String volumeName = UUID.randomUUID().toString(); destVolumeName = volumeName + "." + destFormat.getFileExtension(); // Update path in the command for reconciliation - if (destData.getPath() == null) { + if (StringUtils.isBlank(destVolumePath)) { ((VolumeObjectTO) destData).setPath(destVolumeName); } } - destPool = storagePoolMgr.getStoragePool(destPrimaryStore.getPoolType(), destPrimaryStore.getUuid()); try { Volume.Type volumeType = srcVol.getVolumeType(); resource.createOrUpdateLogFileForCommand(cmd, Command.State.PROCESSING_IN_BACKEND); if (srcVol.getPassphrase() != null && (Volume.Type.ROOT.equals(volumeType) || Volume.Type.DATADISK.equals(volumeType))) { volume.setQemuEncryptFormat(QemuObject.EncryptFormat.LUKS); - storagePoolMgr.copyPhysicalDisk(volume, destVolumeName, destPool, cmd.getWaitInMillSeconds(), srcVol.getPassphrase(), destVol.getPassphrase(), srcVol.getProvisioningType()); + newVolume = storagePoolMgr.copyPhysicalDisk(volume, destVolumeName, destPool, cmd.getWaitInMillSeconds(), srcVol.getPassphrase(), destVol.getPassphrase(), srcVol.getProvisioningType()); } else { - storagePoolMgr.copyPhysicalDisk(volume, destVolumeName, destPool, cmd.getWaitInMillSeconds()); + newVolume = storagePoolMgr.copyPhysicalDisk(volume, destVolumeName, destPool, cmd.getWaitInMillSeconds()); } resource.createOrUpdateLogFileForCommand(cmd, Command.State.COMPLETED); } catch (Exception e) { // Any exceptions while copying the disk, should send failed answer with the error message @@ -3071,9 +3064,13 @@ public class KVMStorageProcessor implements StorageProcessor { } final VolumeObjectTO newVol = new VolumeObjectTO(); - String path = destPrimaryStore.isManaged() ? destVolumeName : destVolumePath + File.separator + destVolumeName; + String path = destVolumeName; + if (!destPrimaryStore.isManaged() && StringUtils.isNotBlank(destVolumePath)) { + path = destVolumePath + File.separator + destVolumeName; + } newVol.setPath(path); - newVol.setFormat(destFormat); + ImageFormat newVolumeFormat = getFormat(newVolume.getFormat()); + newVol.setFormat(newVolumeFormat); newVol.setEncryptFormat(destVol.getEncryptFormat()); return new CopyCmdAnswer(newVol); } catch (final CloudRuntimeException e) { @@ -3085,6 +3082,26 @@ public class KVMStorageProcessor implements StorageProcessor { } } + private Storage.ImageFormat getFormat(PhysicalDiskFormat format) { + if (format == null) { + return null; + } + + return ImageFormat.valueOf(format.toString().toUpperCase()); + } + + private Storage.ImageFormat getFormat(StoragePoolType poolType) { + if(List.of( + StoragePoolType.RBD, + StoragePoolType.PowerFlex, + StoragePoolType.Linstor, + StoragePoolType.FiberChannel).contains(poolType)) { + return ImageFormat.RAW; + } else { + return ImageFormat.QCOW2; + } + } + /** * True if location exists */ diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java index d5119ea55b7..02e5c08fa33 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java @@ -1116,7 +1116,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { // make room for encryption header on raw format, use LUKS if (format == PhysicalDiskFormat.RAW) { - destFile.setSize(destFile.getSize() - (16<<20)); + destFile.setSize(destFile.getSize() - (16 << 20)); destFile.setFormat(PhysicalDiskFormat.LUKS); } @@ -1593,7 +1593,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { String sourcePath = disk.getPath(); KVMPhysicalDisk newDisk; - logger.debug("copyPhysicalDisk: disk size:" + toHumanReadableSize(disk.getSize()) + ", virtualsize:" + toHumanReadableSize(disk.getVirtualSize())+" format:"+disk.getFormat()); + logger.debug("copyPhysicalDisk: disk size:{}, virtualsize:{} format:{}", toHumanReadableSize(disk.getSize()), toHumanReadableSize(disk.getVirtualSize()), disk.getFormat()); if (destPool.getType() != StoragePoolType.RBD) { if (disk.getFormat() == PhysicalDiskFormat.TAR) { newDisk = destPool.createPhysicalDisk(name, PhysicalDiskFormat.DIR, Storage.ProvisioningType.THIN, disk.getVirtualSize(), null); diff --git a/plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java b/plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java index b0cacf60a17..d2d319ed9d0 100644 --- a/plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java +++ b/plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java @@ -433,6 +433,7 @@ public class VmwareStorageMotionStrategy implements DataMotionStrategy { volumeVO.setFolder(pool.getPath()); volumeVO.setPodId(pool.getPodId()); volumeVO.setPoolId(pool.getId()); + volumeVO.setPoolType(pool.getPoolType()); volDao.update(volume.getId(), volumeVO); updated = true; break; diff --git a/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/driver/AdaptiveDataStoreDriverImpl.java b/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/driver/AdaptiveDataStoreDriverImpl.java index 40d99526394..2ccd2bab6cd 100644 --- a/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/driver/AdaptiveDataStoreDriverImpl.java +++ b/plugins/storage/volume/adaptive/src/main/java/org/apache/cloudstack/storage/datastore/driver/AdaptiveDataStoreDriverImpl.java @@ -857,6 +857,7 @@ public class AdaptiveDataStoreDriverImpl extends CloudStackPrimaryDataStoreDrive volumeVO.setPath(finalPath); volumeVO.setFormat(ImageFormat.RAW); volumeVO.setPoolId(storagePool.getId()); + volumeVO.setPoolType(storagePool.getPoolType()); volumeVO.setExternalUuid(managedVolume.getExternalUuid()); volumeVO.setDisplay(true); volumeVO.setDisplayVolume(true); diff --git a/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java index d2f0076f95f..e407bc6c2f3 100644 --- a/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java +++ b/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java @@ -505,6 +505,7 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri StoragePoolVO storagePoolVO = primaryStoreDao.findByUuid(datastoreUUID); if (storagePoolVO != null) { volumeVO.setPoolId(storagePoolVO.getId()); + volumeVO.setPoolType(storagePoolVO.getPoolType()); } else { logger.warn("Unable to find datastore {} while updating the new datastore of the volume {}", datastoreUUID, vol); } diff --git a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java index 306e9259936..d3b797e319f 100644 --- a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java +++ b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java @@ -868,6 +868,7 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver devPath = createVolume(volumeInfo, storagePool); volume.setFolder("/dev/"); volume.setPoolId(storagePool.getId()); + volume.setPoolType(storagePool.getPoolType()); volume.setUuid(vol.getUuid()); volume.setPath(vol.getUuid()); diff --git a/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/motion/StorPoolDataMotionStrategy.java b/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/motion/StorPoolDataMotionStrategy.java index f260c566986..5789ac50871 100644 --- a/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/motion/StorPoolDataMotionStrategy.java +++ b/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/motion/StorPoolDataMotionStrategy.java @@ -425,6 +425,7 @@ public class StorPoolDataMotionStrategy implements DataMotionStrategy { newVol.setFolder(null); newVol.setPodId(storagePoolVO.getPodId()); newVol.setPoolId(storagePoolVO.getId()); + newVol.setPoolType(storagePoolVO.getPoolType()); newVol.setLastPoolId(lastPoolId); return _volumeDao.persist(newVol); diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java index f51aca02af0..ef7d8505420 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -3675,6 +3675,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q String[] offeringTagsArray = (offeringTags == null || offeringTags.isEmpty()) ? new String[0] : offeringTags.split(","); if (!CollectionUtils.isSubCollection(Arrays.asList(requiredTagsArray), Arrays.asList(offeringTagsArray))) { iteratorForTagsChecking.remove(); + count--; } } } diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java index abaf0e3d0e5..77d947b2b3b 100644 --- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java @@ -3049,6 +3049,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C StoragePoolVO storagePoolVO = _storagePoolDao.findByUuid(datastoreName); if (storagePoolVO != null) { volumeVO.setPoolId(storagePoolVO.getId()); + volumeVO.setPoolType(storagePoolVO.getPoolType()); } else { logger.warn("Unable to find datastore {} while updating the new datastore of the volume {}", datastoreName, volumeVO); } diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index f4536e8549f..de6dd4ec67f 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -2937,8 +2937,10 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic List childDatastores = _storagePoolDao.listChildStoragePoolsInDatastoreCluster(storageId); Collections.shuffle(childDatastores); volume.setPoolId(childDatastores.get(0).getId()); + volume.setPoolType(childDatastores.get(0).getPoolType()); } else { volume.setPoolId(pool.getId()); + volume.setPoolType(pool.getPoolType()); } } @@ -3225,6 +3227,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic if (storagePoolVO != null) { VolumeVO volumeVO = _volsDao.findById(volumeId); volumeVO.setPoolId(storagePoolVO.getId()); + volumeVO.setPoolType(storagePoolVO.getPoolType()); _volsDao.update(volumeVO.getId(), volumeVO); } else { logger.warn("Unable to find datastore {} while updating the new datastore of the volume {}", datastoreName, volume); @@ -3645,12 +3648,16 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic * * If all of the above validations pass, we check if the size of the new disk offering is different from the volume. If it is, we log a warning message. */ - protected void validateConditionsToReplaceDiskOfferingOfVolume(VolumeVO volume, DiskOfferingVO newDiskOffering, StoragePool destPool) { + @Override + public boolean validateConditionsToReplaceDiskOfferingOfVolume(Volume volume, DiskOffering newDiskOffering, StoragePool destPool) { if (newDiskOffering == null) { - return; + return false; } - if ((destPool.isShared() && newDiskOffering.isUseLocalStorage()) || destPool.isLocal() && newDiskOffering.isShared()) { - throw new InvalidParameterValueException("You cannot move the volume to a shared storage and assign a disk offering for local storage and vice versa."); + if (destPool.isShared() && newDiskOffering.isUseLocalStorage()) { + throw new InvalidParameterValueException("You cannot move the volume to shared storage, with the disk offering configured for local storage."); + } + if (destPool.isLocal() && newDiskOffering.isShared()) { + throw new InvalidParameterValueException("You cannot move the volume to local storage, with the disk offering configured for shared storage."); } if (!doesStoragePoolSupportDiskOffering(destPool, newDiskOffering)) { throw new InvalidParameterValueException(String.format("Migration failed: target pool [%s, tags:%s] has no matching tags for volume [%s, uuid:%s, tags:%s]", destPool.getName(), @@ -3675,6 +3682,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic volume, oldDiskOffering, newDiskOffering); } logger.info("Changing disk offering to [{}] while migrating volume [{}].", newDiskOffering, volume); + return true; } /** diff --git a/server/src/main/java/org/apache/cloudstack/command/ReconcileCommandServiceImpl.java b/server/src/main/java/org/apache/cloudstack/command/ReconcileCommandServiceImpl.java index d0dcc1f86de..5edf05d1a5c 100644 --- a/server/src/main/java/org/apache/cloudstack/command/ReconcileCommandServiceImpl.java +++ b/server/src/main/java/org/apache/cloudstack/command/ReconcileCommandServiceImpl.java @@ -1064,6 +1064,7 @@ public class ReconcileCommandServiceImpl extends ManagerBase implements Reconcil logger.debug(String.format("Updating volume %s to %s state", sourceVolume, Volume.State.Ready)); sourceVolume.setState(Volume.State.Ready); sourceVolume.setPoolId(srcDataStore.getId()); // restore pool_id and update path + sourceVolume.setPoolType(srcDataStore.getPoolType()); sourceVolume.setPath(srcData.getPath()); sourceVolume.set_iScsiName(srcData.getPath()); sourceVolume.setUpdated(new Date()); @@ -1075,6 +1076,7 @@ public class ReconcileCommandServiceImpl extends ManagerBase implements Reconcil VolumeVO newVolume = (VolumeVO) newVol; newVolume.setInstanceId(null); newVolume.setPoolId(destDataStore.getId()); + newVolume.setPoolType(destDataStore.getPoolType()); newVolume.setState(Volume.State.Creating); newVolume.setPath(destData.getPath()); newVolume.set_iScsiName(destData.getPath()); diff --git a/server/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImpl.java b/server/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImpl.java index 9e1fc46e02e..383644f9aa2 100644 --- a/server/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImpl.java @@ -452,7 +452,7 @@ public class VolumeImportUnmanageManagerImpl implements VolumeImportUnmanageServ Account owner, StoragePoolVO pool, String volumeName) { DiskProfile diskProfile = volumeManager.importVolume(Volume.Type.DATADISK, volumeName, diskOffering, volume.getVirtualSize(), null, null, pool.getDataCenterId(), volume.getHypervisorType(), null, null, - owner, null, pool.getId(), volume.getPath(), null); + owner, null, pool.getId(), pool.getPoolType(), volume.getPath(), null); return volumeDao.findById(diskProfile.getVolumeId()); } diff --git a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java index 9f38182e4d5..187b315dd35 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java @@ -820,7 +820,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { } diskProfile.setSize(copyRemoteVolumeAnswer.getSize()); DiskProfile profile = volumeManager.updateImportedVolume(type, diskOffering, vm, template, deviceId, - storagePool.getId(), copyRemoteVolumeAnswer.getFilename(), chainInfo, diskProfile); + storagePool.getId(), storagePool.getPoolType(), copyRemoteVolumeAnswer.getFilename(), chainInfo, diskProfile); return new Pair<>(profile, storagePool); } @@ -836,7 +836,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { StoragePool storagePool = storagePools.get(0); DiskProfile profile = volumeManager.updateImportedVolume(type, diskOffering, vm, template, deviceId, - storagePool.getId(), diskPath, null, diskProfile); + storagePool.getId(), storagePool.getPoolType(), diskPath, null, diskProfile); return new Pair<>(profile, storagePool); } @@ -847,7 +847,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { StoragePool storagePool = primaryDataStoreDao.findById(poolId); DiskProfile profile = volumeManager.updateImportedVolume(type, diskOffering, vm, template, deviceId, - poolId, diskPath, null, diskProfile); + poolId, storagePool.getPoolType(), diskPath, null, diskProfile); return new Pair<>(profile, storagePool); } @@ -866,7 +866,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { } StoragePool storagePool = getStoragePool(disk, zone, cluster, diskOffering); DiskProfile profile = volumeManager.importVolume(type, name, diskOffering, diskSize, - minIops, maxIops, vm.getDataCenterId(), vm.getHypervisorType(), vm, template, owner, deviceId, storagePool.getId(), path, chainInfo); + minIops, maxIops, vm.getDataCenterId(), vm.getHypervisorType(), vm, template, owner, deviceId, storagePool.getId(), storagePool.getPoolType(), path, chainInfo); return new Pair(profile, storagePool); } diff --git a/server/src/test/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImplTest.java index 419acc0ca0b..9ee34d32a17 100644 --- a/server/src/test/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImplTest.java @@ -277,7 +277,7 @@ public class VolumeImportUnmanageManagerImplTest { doNothing().when(volumeApiService).validateCustomDiskOfferingSizeRange(anyLong()); doReturn(true).when(volumeApiService).doesStoragePoolSupportDiskOffering(any(), any()); doReturn(diskProfile).when(volumeManager).importVolume(any(), anyString(), any(), eq(virtualSize), isNull(), isNull(), anyLong(), - any(), isNull(), isNull(), any(), isNull(), anyLong(), anyString(), isNull()); + any(), isNull(), isNull(), any(), isNull(), anyLong(), any(), anyString(), isNull()); when(diskProfile.getVolumeId()).thenReturn(volumeId); when(volumeDao.findById(volumeId)).thenReturn(volumeVO); diff --git a/utils/src/test/java/org/apache/cloudstack/utils/reflectiontostringbuilderutils/ReflectionToStringBuilderUtilsTest.java b/utils/src/test/java/org/apache/cloudstack/utils/reflectiontostringbuilderutils/ReflectionToStringBuilderUtilsTest.java index afd033c7b04..9168ec0d2fa 100644 --- a/utils/src/test/java/org/apache/cloudstack/utils/reflectiontostringbuilderutils/ReflectionToStringBuilderUtilsTest.java +++ b/utils/src/test/java/org/apache/cloudstack/utils/reflectiontostringbuilderutils/ReflectionToStringBuilderUtilsTest.java @@ -53,7 +53,7 @@ public class ReflectionToStringBuilderUtilsTest extends TestCase { private static final String DEFAULT_MULTIPLE_VALUES_SEPARATOR = ","; @Before - public void setup(){ + public void setup() { classToReflect = String.class; classToReflectFieldsNamesList = ReflectionUtils.getAllFields(classToReflect).stream().map(objectField -> objectField.getName()).collect(Collectors.toList()); classToReflectRemovedField = classToReflectFieldsNamesList.remove(0);