mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
This reverts commit 1c84ce4e23e3fd243022c6c533fc14c10439c6f3.
This commit is contained in:
parent
df99a29483
commit
802bf5fce7
@ -133,9 +133,7 @@ import com.cloud.dc.ClusterDetailsDao;
|
|||||||
import com.cloud.dc.DataCenter;
|
import com.cloud.dc.DataCenter;
|
||||||
import com.cloud.dc.DataCenterVO;
|
import com.cloud.dc.DataCenterVO;
|
||||||
import com.cloud.dc.Pod;
|
import com.cloud.dc.Pod;
|
||||||
import com.cloud.dc.dao.ClusterDao;
|
|
||||||
import com.cloud.dc.dao.DataCenterDao;
|
import com.cloud.dc.dao.DataCenterDao;
|
||||||
import com.cloud.dc.dao.HostPodDao;
|
|
||||||
import com.cloud.domain.Domain;
|
import com.cloud.domain.Domain;
|
||||||
import com.cloud.domain.dao.DomainDao;
|
import com.cloud.domain.dao.DomainDao;
|
||||||
import com.cloud.event.ActionEvent;
|
import com.cloud.event.ActionEvent;
|
||||||
@ -155,7 +153,6 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
|||||||
import com.cloud.hypervisor.HypervisorCapabilitiesVO;
|
import com.cloud.hypervisor.HypervisorCapabilitiesVO;
|
||||||
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
|
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
|
||||||
import com.cloud.offering.DiskOffering;
|
import com.cloud.offering.DiskOffering;
|
||||||
import com.cloud.org.Cluster;
|
|
||||||
import com.cloud.org.Grouping;
|
import com.cloud.org.Grouping;
|
||||||
import com.cloud.projects.Project;
|
import com.cloud.projects.Project;
|
||||||
import com.cloud.projects.ProjectManager;
|
import com.cloud.projects.ProjectManager;
|
||||||
@ -326,8 +323,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||||||
@Inject
|
@Inject
|
||||||
private VmWorkJobDao _workJobDao;
|
private VmWorkJobDao _workJobDao;
|
||||||
@Inject
|
@Inject
|
||||||
ClusterDao clusterDao;
|
|
||||||
@Inject
|
|
||||||
private ClusterDetailsDao _clusterDetailsDao;
|
private ClusterDetailsDao _clusterDetailsDao;
|
||||||
@Inject
|
@Inject
|
||||||
private StorageManager storageMgr;
|
private StorageManager storageMgr;
|
||||||
@ -351,8 +346,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||||||
protected ProjectManager projectManager;
|
protected ProjectManager projectManager;
|
||||||
@Inject
|
@Inject
|
||||||
protected StoragePoolDetailsDao storagePoolDetailsDao;
|
protected StoragePoolDetailsDao storagePoolDetailsDao;
|
||||||
@Inject
|
|
||||||
HostPodDao podDao;
|
|
||||||
|
|
||||||
|
|
||||||
protected Gson _gson;
|
protected Gson _gson;
|
||||||
@ -2387,98 +2380,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||||||
return attachVolumeToVM(command.getVirtualMachineId(), command.getId(), command.getDeviceId());
|
return attachVolumeToVM(command.getVirtualMachineId(), command.getId(), command.getDeviceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected VolumeVO getVmExistingVolumeForVolumeAttach(UserVmVO vm, VolumeInfo volumeToAttach) {
|
|
||||||
VolumeVO existingVolumeOfVm = null;
|
|
||||||
VMTemplateVO template = _templateDao.findById(vm.getTemplateId());
|
|
||||||
List<VolumeVO> rootVolumesOfVm = _volsDao.findByInstanceAndType(vm.getId(), Volume.Type.ROOT);
|
|
||||||
if (rootVolumesOfVm.size() > 1 && template != null && !template.isDeployAsIs()) {
|
|
||||||
throw new CloudRuntimeException("The VM " + vm.getHostName() + " has more than one ROOT volume and is in an invalid state.");
|
|
||||||
} else {
|
|
||||||
if (!rootVolumesOfVm.isEmpty()) {
|
|
||||||
existingVolumeOfVm = rootVolumesOfVm.get(0);
|
|
||||||
} else {
|
|
||||||
// locate data volume of the vm
|
|
||||||
List<VolumeVO> diskVolumesOfVm = _volsDao.findByInstanceAndType(vm.getId(), Volume.Type.DATADISK);
|
|
||||||
for (VolumeVO diskVolume : diskVolumesOfVm) {
|
|
||||||
if (diskVolume.getState() != Volume.State.Allocated) {
|
|
||||||
existingVolumeOfVm = diskVolume;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (existingVolumeOfVm == null) {
|
|
||||||
if (s_logger.isTraceEnabled()) {
|
|
||||||
s_logger.trace(String.format("No existing volume found for VM (%s/%s) to attach volume %s/%s",
|
|
||||||
vm.getName(), vm.getUuid(),
|
|
||||||
volumeToAttach.getName(), volumeToAttach.getUuid()));
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (s_logger.isTraceEnabled()) {
|
|
||||||
String msg = "attaching volume %s/%s to a VM (%s/%s) with an existing volume %s/%s on primary storage %s";
|
|
||||||
s_logger.trace(String.format(msg,
|
|
||||||
volumeToAttach.getName(), volumeToAttach.getUuid(),
|
|
||||||
vm.getName(), vm.getUuid(),
|
|
||||||
existingVolumeOfVm.getName(), existingVolumeOfVm.getUuid(),
|
|
||||||
existingVolumeOfVm.getPoolId()));
|
|
||||||
}
|
|
||||||
return existingVolumeOfVm;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected StoragePool getPoolForAllocatedOrUploadedVolumeForAttach(final VolumeInfo volumeToAttach, final UserVmVO vm) {
|
|
||||||
DataCenter zone = _dcDao.findById(vm.getDataCenterId());
|
|
||||||
Pair<Long, Long> clusterHostId = virtualMachineManager.findClusterAndHostIdForVm(vm, false);
|
|
||||||
long podId = vm.getPodIdToDeployIn();
|
|
||||||
if (clusterHostId.first() != null) {
|
|
||||||
Cluster cluster = clusterDao.findById(clusterHostId.first());
|
|
||||||
podId = cluster.getPodId();
|
|
||||||
}
|
|
||||||
Pod pod = podDao.findById(podId);
|
|
||||||
DiskOfferingVO offering = _diskOfferingDao.findById(volumeToAttach.getDiskOfferingId());
|
|
||||||
DiskProfile diskProfile = new DiskProfile(volumeToAttach.getId(), volumeToAttach.getVolumeType(),
|
|
||||||
volumeToAttach.getName(), volumeToAttach.getId(), volumeToAttach.getSize(), offering.getTagsArray(),
|
|
||||||
offering.isUseLocalStorage(), offering.isRecreatable(),
|
|
||||||
volumeToAttach.getTemplateId());
|
|
||||||
diskProfile.setHyperType(vm.getHypervisorType());
|
|
||||||
StoragePool pool = _volumeMgr.findStoragePool(diskProfile, zone, pod, clusterHostId.first(),
|
|
||||||
clusterHostId.second(), vm, Collections.emptySet());
|
|
||||||
if (pool == null) {
|
|
||||||
throw new CloudRuntimeException(String.format("Failed to find a primary storage for volume in state: %s", volumeToAttach.getState()));
|
|
||||||
}
|
|
||||||
return pool;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected VolumeInfo createVolumeOnPrimaryForAttachIfNeeded(final VolumeInfo volumeToAttach, final UserVmVO vm, VolumeVO existingVolumeOfVm) {
|
|
||||||
VolumeInfo newVolumeOnPrimaryStorage = volumeToAttach;
|
|
||||||
boolean volumeOnSecondary = volumeToAttach.getState() == Volume.State.Uploaded;
|
|
||||||
if (!Arrays.asList(Volume.State.Allocated, Volume.State.Uploaded).contains(volumeToAttach.getState())) {
|
|
||||||
return newVolumeOnPrimaryStorage;
|
|
||||||
}
|
|
||||||
//don't create volume on primary storage if its being attached to the vm which Root's volume hasn't been created yet
|
|
||||||
StoragePool destPrimaryStorage = null;
|
|
||||||
if (existingVolumeOfVm != null && !existingVolumeOfVm.getState().equals(Volume.State.Allocated)) {
|
|
||||||
destPrimaryStorage = _storagePoolDao.findById(existingVolumeOfVm.getPoolId());
|
|
||||||
if (s_logger.isTraceEnabled() && destPrimaryStorage != null) {
|
|
||||||
s_logger.trace(String.format("decided on target storage: %s/%s", destPrimaryStorage.getName(), destPrimaryStorage.getUuid()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (destPrimaryStorage == null) {
|
|
||||||
destPrimaryStorage = getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (volumeOnSecondary && Storage.StoragePoolType.PowerFlex.equals(destPrimaryStorage.getPoolType())) {
|
|
||||||
throw new InvalidParameterValueException("Cannot attach uploaded volume, this operation is unsupported on storage pool type " + destPrimaryStorage.getPoolType());
|
|
||||||
}
|
|
||||||
newVolumeOnPrimaryStorage = _volumeMgr.createVolumeOnPrimaryStorage(vm, volumeToAttach,
|
|
||||||
vm.getHypervisorType(), destPrimaryStorage);
|
|
||||||
} catch (NoTransitionException e) {
|
|
||||||
s_logger.debug("Failed to create volume on primary storage", e);
|
|
||||||
throw new CloudRuntimeException("Failed to create volume on primary storage", e);
|
|
||||||
}
|
|
||||||
return newVolumeOnPrimaryStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Volume orchestrateAttachVolumeToVM(Long vmId, Long volumeId, Long deviceId) {
|
private Volume orchestrateAttachVolumeToVM(Long vmId, Long volumeId, Long deviceId) {
|
||||||
VolumeInfo volumeToAttach = volFactory.getVolume(volumeId);
|
VolumeInfo volumeToAttach = volFactory.getVolume(volumeId);
|
||||||
|
|
||||||
@ -2487,8 +2388,63 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||||||
}
|
}
|
||||||
|
|
||||||
UserVmVO vm = _userVmDao.findById(vmId);
|
UserVmVO vm = _userVmDao.findById(vmId);
|
||||||
VolumeVO existingVolumeOfVm = getVmExistingVolumeForVolumeAttach(vm, volumeToAttach);
|
VolumeVO existingVolumeOfVm = null;
|
||||||
VolumeInfo newVolumeOnPrimaryStorage = createVolumeOnPrimaryForAttachIfNeeded(volumeToAttach, vm, existingVolumeOfVm);
|
VMTemplateVO template = _templateDao.findById(vm.getTemplateId());
|
||||||
|
List<VolumeVO> rootVolumesOfVm = _volsDao.findByInstanceAndType(vmId, Volume.Type.ROOT);
|
||||||
|
if (rootVolumesOfVm.size() > 1 && template != null && !template.isDeployAsIs()) {
|
||||||
|
throw new CloudRuntimeException("The VM " + vm.getHostName() + " has more than one ROOT volume and is in an invalid state.");
|
||||||
|
} else {
|
||||||
|
if (!rootVolumesOfVm.isEmpty()) {
|
||||||
|
existingVolumeOfVm = rootVolumesOfVm.get(0);
|
||||||
|
} else {
|
||||||
|
// locate data volume of the vm
|
||||||
|
List<VolumeVO> diskVolumesOfVm = _volsDao.findByInstanceAndType(vmId, Volume.Type.DATADISK);
|
||||||
|
for (VolumeVO diskVolume : diskVolumesOfVm) {
|
||||||
|
if (diskVolume.getState() != Volume.State.Allocated) {
|
||||||
|
existingVolumeOfVm = diskVolume;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (s_logger.isTraceEnabled()) {
|
||||||
|
String msg = "attaching volume %s/%s to a VM (%s/%s) with an existing volume %s/%s on primary storage %s";
|
||||||
|
if (existingVolumeOfVm != null) {
|
||||||
|
s_logger.trace(String.format(msg,
|
||||||
|
volumeToAttach.getName(), volumeToAttach.getUuid(),
|
||||||
|
vm.getName(), vm.getUuid(),
|
||||||
|
existingVolumeOfVm.getName(), existingVolumeOfVm.getUuid(),
|
||||||
|
existingVolumeOfVm.getPoolId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HypervisorType rootDiskHyperType = vm.getHypervisorType();
|
||||||
|
HypervisorType volumeToAttachHyperType = _volsDao.getHypervisorType(volumeToAttach.getId());
|
||||||
|
|
||||||
|
VolumeInfo newVolumeOnPrimaryStorage = volumeToAttach;
|
||||||
|
|
||||||
|
//don't create volume on primary storage if its being attached to the vm which Root's volume hasn't been created yet
|
||||||
|
StoragePoolVO destPrimaryStorage = null;
|
||||||
|
if (existingVolumeOfVm != null && !existingVolumeOfVm.getState().equals(Volume.State.Allocated)) {
|
||||||
|
destPrimaryStorage = _storagePoolDao.findById(existingVolumeOfVm.getPoolId());
|
||||||
|
if (s_logger.isTraceEnabled() && destPrimaryStorage != null) {
|
||||||
|
s_logger.trace(String.format("decided on target storage: %s/%s", destPrimaryStorage.getName(), destPrimaryStorage.getUuid()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean volumeOnSecondary = volumeToAttach.getState() == Volume.State.Uploaded;
|
||||||
|
|
||||||
|
if (destPrimaryStorage != null && (volumeToAttach.getState() == Volume.State.Allocated || volumeOnSecondary)) {
|
||||||
|
try {
|
||||||
|
if (volumeOnSecondary && destPrimaryStorage.getPoolType() == Storage.StoragePoolType.PowerFlex) {
|
||||||
|
throw new InvalidParameterValueException("Cannot attach uploaded volume, this operation is unsupported on storage pool type " + destPrimaryStorage.getPoolType());
|
||||||
|
}
|
||||||
|
newVolumeOnPrimaryStorage = _volumeMgr.createVolumeOnPrimaryStorage(vm, volumeToAttach, rootDiskHyperType, destPrimaryStorage);
|
||||||
|
} catch (NoTransitionException e) {
|
||||||
|
s_logger.debug("Failed to create volume on primary storage", e);
|
||||||
|
throw new CloudRuntimeException("Failed to create volume on primary storage", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// reload the volume from db
|
// reload the volume from db
|
||||||
newVolumeOnPrimaryStorage = volFactory.getVolume(newVolumeOnPrimaryStorage.getId());
|
newVolumeOnPrimaryStorage = volFactory.getVolume(newVolumeOnPrimaryStorage.getId());
|
||||||
@ -2507,17 +2463,19 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||||||
StoragePoolVO vmRootVolumePool = _storagePoolDao.findById(existingVolumeOfVm.getPoolId());
|
StoragePoolVO vmRootVolumePool = _storagePoolDao.findById(existingVolumeOfVm.getPoolId());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
HypervisorType volumeToAttachHyperType = _volsDao.getHypervisorType(volumeToAttach.getId());
|
|
||||||
newVolumeOnPrimaryStorage = _volumeMgr.moveVolume(newVolumeOnPrimaryStorage, vmRootVolumePool.getDataCenterId(), vmRootVolumePool.getPodId(), vmRootVolumePool.getClusterId(),
|
newVolumeOnPrimaryStorage = _volumeMgr.moveVolume(newVolumeOnPrimaryStorage, vmRootVolumePool.getDataCenterId(), vmRootVolumePool.getPodId(), vmRootVolumePool.getClusterId(),
|
||||||
volumeToAttachHyperType);
|
volumeToAttachHyperType);
|
||||||
} catch (ConcurrentOperationException | StorageUnavailableException e) {
|
} catch (ConcurrentOperationException e) {
|
||||||
|
s_logger.debug("move volume failed", e);
|
||||||
|
throw new CloudRuntimeException("move volume failed", e);
|
||||||
|
} catch (StorageUnavailableException e) {
|
||||||
s_logger.debug("move volume failed", e);
|
s_logger.debug("move volume failed", e);
|
||||||
throw new CloudRuntimeException("move volume failed", e);
|
throw new CloudRuntimeException("move volume failed", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VolumeVO newVol = _volsDao.findById(newVolumeOnPrimaryStorage.getId());
|
VolumeVO newVol = _volsDao.findById(newVolumeOnPrimaryStorage.getId());
|
||||||
// Getting the fresh vm object in case of volume migration to check the current state of VM
|
// Getting the fresh vm object in case of volume migration to check the current state of VM
|
||||||
if (moveVolumeNeeded) {
|
if (moveVolumeNeeded || volumeOnSecondary) {
|
||||||
vm = _userVmDao.findById(vmId);
|
vm = _userVmDao.findById(vmId);
|
||||||
if (vm == null) {
|
if (vm == null) {
|
||||||
throw new InvalidParameterValueException("VM not found.");
|
throw new InvalidParameterValueException("VM not found.");
|
||||||
@ -2701,6 +2659,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||||||
if (!_volsDao.findByInstanceAndDeviceId(vm.getId(), 0).isEmpty()) {
|
if (!_volsDao.findByInstanceAndDeviceId(vm.getId(), 0).isEmpty()) {
|
||||||
throw new InvalidParameterValueException("Vm already has root volume attached to it");
|
throw new InvalidParameterValueException("Vm already has root volume attached to it");
|
||||||
}
|
}
|
||||||
|
if (volumeToAttach.getState() == Volume.State.Uploaded) {
|
||||||
|
throw new InvalidParameterValueException("No support for Root volume attach in state " + Volume.State.Uploaded);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -45,7 +45,6 @@ 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.DetachVolumeCmd;
|
||||||
import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd;
|
import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd;
|
||||||
import org.apache.cloudstack.context.CallContext;
|
import org.apache.cloudstack.context.CallContext;
|
||||||
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
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.DataStoreManager;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
|
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
|
||||||
@ -87,12 +86,8 @@ import org.springframework.test.util.ReflectionTestUtils;
|
|||||||
import com.cloud.api.query.dao.ServiceOfferingJoinDao;
|
import com.cloud.api.query.dao.ServiceOfferingJoinDao;
|
||||||
import com.cloud.configuration.Resource;
|
import com.cloud.configuration.Resource;
|
||||||
import com.cloud.configuration.Resource.ResourceType;
|
import com.cloud.configuration.Resource.ResourceType;
|
||||||
import com.cloud.dc.ClusterVO;
|
|
||||||
import com.cloud.dc.DataCenterVO;
|
import com.cloud.dc.DataCenterVO;
|
||||||
import com.cloud.dc.HostPodVO;
|
|
||||||
import com.cloud.dc.dao.ClusterDao;
|
|
||||||
import com.cloud.dc.dao.DataCenterDao;
|
import com.cloud.dc.dao.DataCenterDao;
|
||||||
import com.cloud.dc.dao.HostPodDao;
|
|
||||||
import com.cloud.event.EventTypes;
|
import com.cloud.event.EventTypes;
|
||||||
import com.cloud.event.UsageEventUtils;
|
import com.cloud.event.UsageEventUtils;
|
||||||
import com.cloud.exception.InvalidParameterValueException;
|
import com.cloud.exception.InvalidParameterValueException;
|
||||||
@ -127,12 +122,10 @@ import com.cloud.utils.Pair;
|
|||||||
import com.cloud.utils.db.TransactionLegacy;
|
import com.cloud.utils.db.TransactionLegacy;
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
import com.cloud.utils.fsm.NoTransitionException;
|
import com.cloud.utils.fsm.NoTransitionException;
|
||||||
import com.cloud.vm.DiskProfile;
|
|
||||||
import com.cloud.vm.UserVmManager;
|
import com.cloud.vm.UserVmManager;
|
||||||
import com.cloud.vm.UserVmVO;
|
import com.cloud.vm.UserVmVO;
|
||||||
import com.cloud.vm.VirtualMachine;
|
import com.cloud.vm.VirtualMachine;
|
||||||
import com.cloud.vm.VirtualMachine.State;
|
import com.cloud.vm.VirtualMachine.State;
|
||||||
import com.cloud.vm.VirtualMachineManager;
|
|
||||||
import com.cloud.vm.dao.UserVmDao;
|
import com.cloud.vm.dao.UserVmDao;
|
||||||
import com.cloud.vm.dao.VMInstanceDao;
|
import com.cloud.vm.dao.VMInstanceDao;
|
||||||
import com.cloud.vm.snapshot.VMSnapshotVO;
|
import com.cloud.vm.snapshot.VMSnapshotVO;
|
||||||
@ -206,15 +199,6 @@ public class VolumeApiServiceImplTest {
|
|||||||
private DataStoreManager dataStoreMgr;
|
private DataStoreManager dataStoreMgr;
|
||||||
@Mock
|
@Mock
|
||||||
private SnapshotHelper snapshotHelper;
|
private SnapshotHelper snapshotHelper;
|
||||||
@Mock
|
|
||||||
VirtualMachineManager virtualMachineManager;
|
|
||||||
@Mock
|
|
||||||
HostPodDao podDao;
|
|
||||||
@Mock
|
|
||||||
ClusterDao clusterDao;
|
|
||||||
@Mock
|
|
||||||
VolumeOrchestrationService volumeOrchestrationService;
|
|
||||||
|
|
||||||
|
|
||||||
private DetachVolumeCmd detachCmd = new DetachVolumeCmd();
|
private DetachVolumeCmd detachCmd = new DetachVolumeCmd();
|
||||||
private Class<?> _detachCmdClass = detachCmd.getClass();
|
private Class<?> _detachCmdClass = detachCmd.getClass();
|
||||||
@ -1836,237 +1820,4 @@ public class VolumeApiServiceImplTest {
|
|||||||
|
|
||||||
volumeApiServiceImpl.validationsForCheckVolumeOperation(volume);
|
volumeApiServiceImpl.validationsForCheckVolumeOperation(volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
private UserVmVO getMockedVm() {
|
|
||||||
UserVmVO vm = Mockito.mock(UserVmVO.class);
|
|
||||||
Mockito.when(vm.getId()).thenReturn(1L);
|
|
||||||
Mockito.when(vm.getTemplateId()).thenReturn(10L);
|
|
||||||
Mockito.when(vm.getHostName()).thenReturn("test-vm");
|
|
||||||
return vm;
|
|
||||||
}
|
|
||||||
|
|
||||||
private VMTemplateVO getMockedTemplate() {
|
|
||||||
VMTemplateVO template = Mockito.mock(VMTemplateVO.class);
|
|
||||||
Mockito.when(template.isDeployAsIs()).thenReturn(false);
|
|
||||||
return template;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = CloudRuntimeException.class)
|
|
||||||
public void testGetVmExistingVolumeForVolumeAttach_MultipleRootVolumes_ThrowsException() {
|
|
||||||
UserVmVO vm = getMockedVm();
|
|
||||||
VMTemplateVO template = getMockedTemplate();
|
|
||||||
when(templateDao.findById(10L)).thenReturn(template);
|
|
||||||
when(volumeDaoMock.findByInstanceAndType(1L, Volume.Type.ROOT))
|
|
||||||
.thenReturn(Arrays.asList(Mockito.mock(VolumeVO.class), Mockito.mock(VolumeVO.class)));
|
|
||||||
volumeApiServiceImpl.getVmExistingVolumeForVolumeAttach(vm, Mockito.mock(VolumeInfo.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetVmExistingVolumeForVolumeAttach_SingleRootVolume() {
|
|
||||||
UserVmVO vm = getMockedVm();
|
|
||||||
VMTemplateVO template = getMockedTemplate();
|
|
||||||
VolumeVO rootVolume = Mockito.mock(VolumeVO.class);
|
|
||||||
Mockito.when(rootVolume.getId()).thenReturn(20L);
|
|
||||||
Mockito.when(templateDao.findById(10L)).thenReturn(template);
|
|
||||||
Mockito.when(volumeDaoMock.findByInstanceAndType(1L, Volume.Type.ROOT))
|
|
||||||
.thenReturn(Collections.singletonList(rootVolume));
|
|
||||||
VolumeVO result = volumeApiServiceImpl.getVmExistingVolumeForVolumeAttach(vm, Mockito.mock(VolumeInfo.class));
|
|
||||||
Assert.assertNotNull(result);
|
|
||||||
Assert.assertEquals(20L, result.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private VolumeVO getMockedDataVolume() {
|
|
||||||
VolumeVO volume = Mockito.mock(VolumeVO.class);
|
|
||||||
Mockito.when(volume.getId()).thenReturn(30L);
|
|
||||||
Mockito.when(volume.getState()).thenReturn(Volume.State.Ready);
|
|
||||||
return volume;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetVmExistingVolumeForVolumeAttach_NoRootVolume_DataDiskAvailable() {
|
|
||||||
UserVmVO vm = getMockedVm();
|
|
||||||
VMTemplateVO template = getMockedTemplate();
|
|
||||||
VolumeVO dataDisk = getMockedDataVolume();
|
|
||||||
List<VolumeVO> rootVolumes = Collections.emptyList();
|
|
||||||
List<VolumeVO> dataVolumes = Collections.singletonList(dataDisk);
|
|
||||||
Mockito.when(templateDao.findById(10L)).thenReturn(template);
|
|
||||||
Mockito.when(volumeDaoMock.findByInstanceAndType(1L, Volume.Type.ROOT)).thenReturn(rootVolumes);
|
|
||||||
Mockito.when(volumeDaoMock.findByInstanceAndType(1L, Volume.Type.DATADISK)).thenReturn(dataVolumes);
|
|
||||||
VolumeVO result = volumeApiServiceImpl.getVmExistingVolumeForVolumeAttach(vm, Mockito.mock(VolumeInfo.class));
|
|
||||||
Assert.assertNotNull(result);
|
|
||||||
Assert.assertEquals(30L, result.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetVmExistingVolumeForVolumeAttach_NoVolumesAtAll() {
|
|
||||||
UserVmVO vm = getMockedVm();
|
|
||||||
VMTemplateVO template = getMockedTemplate();
|
|
||||||
Mockito.when(templateDao.findById(10L)).thenReturn(template);
|
|
||||||
Mockito.when(volumeDaoMock.findByInstanceAndType(1L, Volume.Type.ROOT)).thenReturn(Collections.emptyList());
|
|
||||||
Mockito.when(volumeDaoMock.findByInstanceAndType(1L, Volume.Type.DATADISK)).thenReturn(Collections.emptyList());
|
|
||||||
VolumeVO result = volumeApiServiceImpl.getVmExistingVolumeForVolumeAttach(vm, Mockito.mock(VolumeInfo.class));
|
|
||||||
Assert.assertNull(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void mockDiskOffering() {
|
|
||||||
DiskOfferingVO offering = Mockito.mock(DiskOfferingVO.class);
|
|
||||||
Mockito.when(_diskOfferingDao.findById(1L)).thenReturn(offering);
|
|
||||||
Mockito.when(offering.isUseLocalStorage()).thenReturn(true);
|
|
||||||
Mockito.when(offering.isRecreatable()).thenReturn(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DataCenterVO mockZone() {
|
|
||||||
DataCenterVO zone = Mockito.mock(DataCenterVO.class);
|
|
||||||
Mockito.when(_dcDao.findById(1L)).thenReturn(zone);
|
|
||||||
return zone;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetPoolForAllocatedOrUploadedVolumeForAttach_Success() {
|
|
||||||
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
|
|
||||||
UserVmVO vm = Mockito.mock(UserVmVO.class);
|
|
||||||
ClusterVO cluster = Mockito.mock(ClusterVO.class);
|
|
||||||
HostPodVO pod = Mockito.mock(HostPodVO.class);
|
|
||||||
DataCenterVO zone = mockZone();
|
|
||||||
mockDiskOffering();
|
|
||||||
StoragePool pool = Mockito.mock(StoragePool.class);
|
|
||||||
when(vm.getDataCenterId()).thenReturn(1L);
|
|
||||||
when(virtualMachineManager.findClusterAndHostIdForVm(vm, false)).thenReturn(new Pair<>(1L, 2L));
|
|
||||||
when(clusterDao.findById(1L)).thenReturn(cluster);
|
|
||||||
when(cluster.getPodId()).thenReturn(1L);
|
|
||||||
when(podDao.findById(1L)).thenReturn(pod);
|
|
||||||
when(volumeToAttach.getDiskOfferingId()).thenReturn(1L);
|
|
||||||
when(volumeOrchestrationService.findStoragePool(any(DiskProfile.class), eq(zone), eq(pod), eq(1L), eq(2L), eq(vm), eq(Collections.emptySet())))
|
|
||||||
.thenReturn(pool);
|
|
||||||
StoragePool result = volumeApiServiceImpl.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
|
||||||
Assert.assertNotNull(result);
|
|
||||||
Assert.assertEquals(pool, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = CloudRuntimeException.class)
|
|
||||||
public void testGetPoolForAllocatedOrUploadedVolumeForAttach_NoPoolFound_ThrowsException() {
|
|
||||||
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
|
|
||||||
UserVmVO vm = Mockito.mock(UserVmVO.class);
|
|
||||||
DataCenterVO zone = mockZone();
|
|
||||||
Pair<Long, Long> clusterHostId = new Pair<>(1L, 2L);
|
|
||||||
ClusterVO cluster = Mockito.mock(ClusterVO.class);
|
|
||||||
HostPodVO pod = Mockito.mock(HostPodVO.class);
|
|
||||||
mockDiskOffering();
|
|
||||||
when(vm.getDataCenterId()).thenReturn(1L);
|
|
||||||
when(clusterDao.findById(1L)).thenReturn(cluster);
|
|
||||||
when(virtualMachineManager.findClusterAndHostIdForVm(vm, false)).thenReturn(clusterHostId);
|
|
||||||
when(podDao.findById(anyLong())).thenReturn(pod);
|
|
||||||
when(volumeToAttach.getDiskOfferingId()).thenReturn(1L);
|
|
||||||
when(volumeOrchestrationService.findStoragePool(any(DiskProfile.class), eq(zone), eq(pod), eq(1L), eq(2L), eq(vm), eq(Collections.emptySet())))
|
|
||||||
.thenReturn(null);
|
|
||||||
volumeApiServiceImpl.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetPoolForAllocatedOrUploadedVolumeForAttach_NoCluster() {
|
|
||||||
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
|
|
||||||
UserVmVO vm = Mockito.mock(UserVmVO.class);
|
|
||||||
DataCenterVO zone = mockZone();
|
|
||||||
HostPodVO pod = Mockito.mock(HostPodVO.class);
|
|
||||||
mockDiskOffering();
|
|
||||||
StoragePool pool = Mockito.mock(StoragePool.class);
|
|
||||||
when(vm.getDataCenterId()).thenReturn(1L);
|
|
||||||
when(vm.getPodIdToDeployIn()).thenReturn(2L);
|
|
||||||
when(virtualMachineManager.findClusterAndHostIdForVm(vm, false)).thenReturn(new Pair<>(null, 2L));
|
|
||||||
when(podDao.findById(2L)).thenReturn(pod);
|
|
||||||
when(volumeToAttach.getDiskOfferingId()).thenReturn(1L);
|
|
||||||
when(volumeOrchestrationService.findStoragePool(any(DiskProfile.class), eq(zone), eq(pod), eq(null), eq(2L), eq(vm), eq(Collections.emptySet())))
|
|
||||||
.thenReturn(pool);
|
|
||||||
StoragePool result = volumeApiServiceImpl.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
|
||||||
Assert.assertNotNull(result);
|
|
||||||
Assert.assertEquals(pool, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreateVolumeOnSecondaryForAttachIfNeeded_VolumeNotAllocatedOrUploaded() {
|
|
||||||
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
|
|
||||||
Mockito.when(volumeToAttach.getState()).thenReturn(Volume.State.Ready);
|
|
||||||
VolumeInfo result = volumeApiServiceImpl.createVolumeOnPrimaryForAttachIfNeeded(
|
|
||||||
volumeToAttach, Mockito.mock(UserVmVO.class), null);
|
|
||||||
Assert.assertSame(volumeToAttach, result);
|
|
||||||
Mockito.verifyNoInteractions(primaryDataStoreDaoMock, volumeOrchestrationService);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreateVolumeOnSecondaryForAttachIfNeeded_ExistingVolumeDeterminesStoragePool() {
|
|
||||||
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
|
|
||||||
Mockito.when(volumeToAttach.getState()).thenReturn(Volume.State.Uploaded);
|
|
||||||
UserVmVO vm = Mockito.mock(UserVmVO.class);
|
|
||||||
VolumeVO existingVolume = Mockito.mock(VolumeVO.class);
|
|
||||||
Mockito.when(existingVolume.getState()).thenReturn(Volume.State.Ready);
|
|
||||||
when(existingVolume.getPoolId()).thenReturn(1L);
|
|
||||||
StoragePoolVO destPrimaryStorage = Mockito.mock(StoragePoolVO.class);
|
|
||||||
Mockito.when(destPrimaryStorage.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem);
|
|
||||||
Mockito.when(primaryDataStoreDaoMock.findById(1L)).thenReturn(destPrimaryStorage);
|
|
||||||
VolumeInfo newVolumeOnPrimaryStorage = Mockito.mock(VolumeInfo.class);
|
|
||||||
try {
|
|
||||||
Mockito.when(volumeOrchestrationService.createVolumeOnPrimaryStorage(vm, volumeToAttach, vm.getHypervisorType(), destPrimaryStorage))
|
|
||||||
.thenReturn(newVolumeOnPrimaryStorage);
|
|
||||||
} catch (NoTransitionException nte) {
|
|
||||||
Assert.fail(nte.getMessage());
|
|
||||||
}
|
|
||||||
VolumeInfo result = volumeApiServiceImpl.createVolumeOnPrimaryForAttachIfNeeded(volumeToAttach, vm, existingVolume);
|
|
||||||
Assert.assertSame(newVolumeOnPrimaryStorage, result);
|
|
||||||
Mockito.verify(primaryDataStoreDaoMock).findById(1L);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreateVolumeOnPrimaryForAttachIfNeeded_UsesGetPoolForAttach() {
|
|
||||||
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
|
|
||||||
Mockito.when(volumeToAttach.getState()).thenReturn(Volume.State.Allocated);
|
|
||||||
UserVmVO vm = Mockito.mock(UserVmVO.class);
|
|
||||||
StoragePool destPrimaryStorage = Mockito.mock(StoragePool.class);
|
|
||||||
Mockito.doReturn(destPrimaryStorage).when(volumeApiServiceImpl)
|
|
||||||
.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
|
||||||
VolumeInfo newVolumeOnPrimaryStorage = Mockito.mock(VolumeInfo.class);
|
|
||||||
try {
|
|
||||||
Mockito.when(volumeOrchestrationService.createVolumeOnPrimaryStorage(
|
|
||||||
vm, volumeToAttach, vm.getHypervisorType(), destPrimaryStorage))
|
|
||||||
.thenReturn(newVolumeOnPrimaryStorage);
|
|
||||||
} catch (NoTransitionException nte) {
|
|
||||||
Assert.fail(nte.getMessage());
|
|
||||||
}
|
|
||||||
VolumeInfo result = volumeApiServiceImpl.createVolumeOnPrimaryForAttachIfNeeded(volumeToAttach, vm, null);
|
|
||||||
Assert.assertSame(newVolumeOnPrimaryStorage, result);
|
|
||||||
verify(volumeApiServiceImpl).getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = InvalidParameterValueException.class)
|
|
||||||
public void testCreateVolumeOnPrimaryForAttachIfNeeded_UnsupportedPoolType_ThrowsException() {
|
|
||||||
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
|
|
||||||
when(volumeToAttach.getState()).thenReturn(Volume.State.Uploaded);
|
|
||||||
UserVmVO vm = Mockito.mock(UserVmVO.class);
|
|
||||||
StoragePool destPrimaryStorage = Mockito.mock(StoragePool.class);
|
|
||||||
when(destPrimaryStorage.getPoolType()).thenReturn(Storage.StoragePoolType.PowerFlex);
|
|
||||||
Mockito.doReturn(destPrimaryStorage).when(volumeApiServiceImpl)
|
|
||||||
.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
|
||||||
volumeApiServiceImpl.createVolumeOnPrimaryForAttachIfNeeded(volumeToAttach, vm, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreateVolumeOnSecondaryForAttachIfNeeded_CreateVolumeFails_ThrowsException() {
|
|
||||||
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
|
|
||||||
Mockito.when(volumeToAttach.getState()).thenReturn(Volume.State.Uploaded);
|
|
||||||
UserVmVO vm = Mockito.mock(UserVmVO.class);
|
|
||||||
StoragePool destPrimaryStorage = Mockito.mock(StoragePool.class);
|
|
||||||
Mockito.when(destPrimaryStorage.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem);
|
|
||||||
Mockito.doReturn(destPrimaryStorage).when(volumeApiServiceImpl)
|
|
||||||
.getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
|
|
||||||
try {
|
|
||||||
Mockito.when(volumeOrchestrationService.createVolumeOnPrimaryStorage(vm, volumeToAttach, vm.getHypervisorType(), destPrimaryStorage))
|
|
||||||
.thenThrow(new NoTransitionException("Mocked exception"));
|
|
||||||
} catch (NoTransitionException nte) {
|
|
||||||
Assert.fail(nte.getMessage());
|
|
||||||
}
|
|
||||||
CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class, () ->
|
|
||||||
volumeApiServiceImpl.createVolumeOnPrimaryForAttachIfNeeded(volumeToAttach, vm, null)
|
|
||||||
);
|
|
||||||
Assert.assertTrue(exception.getMessage().contains("Failed to create volume on primary storage"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user