mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			332 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			332 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| // Licensed to the Apache Software Foundation (ASF) under one
 | |
| // or more contributor license agreements.  See the NOTICE file
 | |
| // distributed with this work for additional information
 | |
| // regarding copyright ownership.  The ASF licenses this file
 | |
| // to you under the Apache License, Version 2.0 (the
 | |
| // "License"); you may not use this file except in compliance
 | |
| // with the License.  You may obtain a copy of the License at
 | |
| //
 | |
| //   http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing,
 | |
| // software distributed under the License is distributed on an
 | |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 | |
| // KIND, either express or implied.  See the License for the
 | |
| // specific language governing permissions and limitations
 | |
| // under the License.
 | |
| package com.cloud.storage;
 | |
| 
 | |
| import static org.mockito.Matchers.any;
 | |
| import static org.mockito.Mockito.doNothing;
 | |
| import static org.mockito.Mockito.when;
 | |
| 
 | |
| import java.lang.reflect.Field;
 | |
| import java.util.ArrayList;
 | |
| import java.util.List;
 | |
| import java.util.UUID;
 | |
| 
 | |
| import javax.inject.Inject;
 | |
| 
 | |
| import org.junit.After;
 | |
| import org.junit.Before;
 | |
| import org.junit.Rule;
 | |
| import org.junit.rules.ExpectedException;
 | |
| import org.mockito.Mock;
 | |
| import org.mockito.Mockito;
 | |
| import org.mockito.MockitoAnnotations;
 | |
| 
 | |
| import org.apache.cloudstack.acl.ControlledEntity;
 | |
| import org.apache.cloudstack.acl.SecurityChecker.AccessType;
 | |
| import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
 | |
| import org.apache.cloudstack.context.CallContext;
 | |
| import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
 | |
| import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
 | |
| import org.apache.cloudstack.framework.jobs.AsyncJobExecutionContext;
 | |
| import org.apache.cloudstack.framework.jobs.AsyncJobManager;
 | |
| import org.apache.cloudstack.framework.jobs.dao.AsyncJobJoinMapDao;
 | |
| import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
 | |
| import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 | |
| import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
 | |
| 
 | |
| import com.cloud.hypervisor.Hypervisor.HypervisorType;
 | |
| import com.cloud.storage.dao.VolumeDao;
 | |
| import com.cloud.user.Account;
 | |
| import com.cloud.user.AccountManager;
 | |
| import com.cloud.user.AccountVO;
 | |
| import com.cloud.user.UserVO;
 | |
| import com.cloud.utils.db.TransactionLegacy;
 | |
| import com.cloud.vm.UserVmVO;
 | |
| import com.cloud.vm.VirtualMachine.State;
 | |
| import com.cloud.vm.dao.UserVmDao;
 | |
| import com.cloud.vm.dao.VMInstanceDao;
 | |
| import com.cloud.vm.snapshot.VMSnapshotVO;
 | |
| import com.cloud.vm.snapshot.dao.VMSnapshotDao;
 | |
| 
 | |
| public class VolumeApiServiceImplTest {
 | |
|     @Inject
 | |
|     VolumeApiServiceImpl _svc = new VolumeApiServiceImpl();
 | |
|     @Mock
 | |
|     VolumeDao _volumeDao;
 | |
|     @Mock
 | |
|     AccountManager _accountMgr;
 | |
|     @Mock
 | |
|     UserVmDao _userVmDao;
 | |
|     @Mock
 | |
|     PrimaryDataStoreDao _storagePoolDao;
 | |
|     @Mock
 | |
|     VMSnapshotDao _vmSnapshotDao;
 | |
|     @Mock
 | |
|     AsyncJobManager _jobMgr;
 | |
|     @Mock
 | |
|     AsyncJobJoinMapDao _joinMapDao;
 | |
|     @Mock
 | |
|     VolumeDataFactory _volFactory;
 | |
| 
 | |
|     @Mock
 | |
|     VMInstanceDao _vmInstanceDao;
 | |
| 
 | |
|     DetachVolumeCmd detachCmd = new DetachVolumeCmd();
 | |
|     Class<?> _detachCmdClass = detachCmd.getClass();
 | |
| 
 | |
| 
 | |
|     @Before
 | |
|     public void setup() throws Exception {
 | |
|         MockitoAnnotations.initMocks(this);
 | |
|         _svc._volsDao = _volumeDao;
 | |
|         _svc._accountMgr = _accountMgr;
 | |
|         _svc._userVmDao = _userVmDao;
 | |
|         _svc._storagePoolDao = _storagePoolDao;
 | |
|         _svc._vmSnapshotDao = _vmSnapshotDao;
 | |
|         _svc._vmInstanceDao = _vmInstanceDao;
 | |
|         _svc._jobMgr = _jobMgr;
 | |
|         _svc.volFactory = _volFactory;
 | |
| 
 | |
|         // mock caller context
 | |
|         AccountVO account = new AccountVO("admin", 1L, "networkDomain", Account.ACCOUNT_TYPE_NORMAL, "uuid");
 | |
|         UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString());
 | |
|         CallContext.register(user, account);
 | |
|         // mock async context
 | |
|         AsyncJobExecutionContext context = new AsyncJobExecutionContext();
 | |
|         AsyncJobExecutionContext.init(_svc._jobMgr, _joinMapDao);
 | |
|         AsyncJobVO job = new AsyncJobVO();
 | |
|         context.setJob(job);
 | |
|         AsyncJobExecutionContext.setCurrentExecutionContext(context);
 | |
| 
 | |
|         TransactionLegacy txn = TransactionLegacy.open("runVolumeDaoImplTest");
 | |
|         try {
 | |
|             // volume of running vm id=1
 | |
|             VolumeVO volumeOfRunningVm = new VolumeVO("root", 1L, 1L, 1L, 1L, 1L, "root", "root", Storage.ProvisioningType.THIN, 1, null,
 | |
|                     null, "root", Volume.Type.ROOT);
 | |
|             when(_svc._volsDao.findById(1L)).thenReturn(volumeOfRunningVm);
 | |
| 
 | |
|             UserVmVO runningVm = new UserVmVO(1L, "vm", "vm", 1, HypervisorType.XenServer, 1L, false,
 | |
|                     false, 1L, 1L, 1L, null, "vm", null);
 | |
|             runningVm.setState(State.Running);
 | |
|             runningVm.setDataCenterId(1L);
 | |
|             when(_svc._userVmDao.findById(1L)).thenReturn(runningVm);
 | |
| 
 | |
|             // volume of stopped vm id=2
 | |
|             VolumeVO volumeOfStoppedVm = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null,
 | |
|                     null, "root", Volume.Type.ROOT);
 | |
|             volumeOfStoppedVm.setPoolId(1L);
 | |
|             when(_svc._volsDao.findById(2L)).thenReturn(volumeOfStoppedVm);
 | |
| 
 | |
|             UserVmVO stoppedVm = new UserVmVO(2L, "vm", "vm", 1, HypervisorType.XenServer, 1L, false,
 | |
|                     false, 1L, 1L, 1L, null, "vm", null);
 | |
|             stoppedVm.setState(State.Stopped);
 | |
|             stoppedVm.setDataCenterId(1L);
 | |
|             when(_svc._userVmDao.findById(2L)).thenReturn(stoppedVm);
 | |
| 
 | |
| 
 | |
|             // volume of hyperV vm id=3
 | |
|             UserVmVO hyperVVm = new UserVmVO(3L, "vm", "vm", 1, HypervisorType.Hyperv, 1L, false,
 | |
|                     false, 1L, 1L, 1L, null, "vm", null);
 | |
|             hyperVVm.setState(State.Stopped);
 | |
|             hyperVVm.setDataCenterId(1L);
 | |
|             when(_svc._userVmDao.findById(3L)).thenReturn(hyperVVm);
 | |
| 
 | |
|             VolumeVO volumeOfStoppeHyperVVm = new VolumeVO("root", 1L, 1L, 1L, 1L, 3L, "root", "root", Storage.ProvisioningType.THIN, 1, null,
 | |
|                     null, "root", Volume.Type.ROOT);
 | |
|             volumeOfStoppeHyperVVm.setPoolId(1L);
 | |
|             when(_svc._volsDao.findById(3L)).thenReturn(volumeOfStoppeHyperVVm);
 | |
| 
 | |
|             StoragePoolVO unmanagedPool = new StoragePoolVO();
 | |
|             when(_svc._storagePoolDao.findById(1L)).thenReturn(unmanagedPool);
 | |
| 
 | |
|             // volume of managed pool id=4
 | |
|             StoragePoolVO managedPool = new StoragePoolVO();
 | |
|             managedPool.setManaged(true);
 | |
|             when(_svc._storagePoolDao.findById(2L)).thenReturn(managedPool);
 | |
|             VolumeVO managedPoolVolume = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null,
 | |
|                     null, "root", Volume.Type.ROOT);
 | |
|             managedPoolVolume.setPoolId(2L);
 | |
|             when(_svc._volsDao.findById(4L)).thenReturn(managedPoolVolume);
 | |
| 
 | |
|             // non-root non-datadisk volume
 | |
|             VolumeInfo volumeWithIncorrectVolumeType = Mockito.mock(VolumeInfo.class);
 | |
|             when(volumeWithIncorrectVolumeType.getId()).thenReturn(5L);
 | |
|             when(volumeWithIncorrectVolumeType.getVolumeType()).thenReturn(Volume.Type.ISO);
 | |
|             when(_svc.volFactory.getVolume(5L)).thenReturn(volumeWithIncorrectVolumeType);
 | |
| 
 | |
|             // correct root volume
 | |
|             VolumeInfo correctRootVolume = Mockito.mock(VolumeInfo.class);
 | |
|             when(correctRootVolume.getId()).thenReturn(6L);
 | |
|             when(correctRootVolume.getDataCenterId()).thenReturn(1L);
 | |
|             when(correctRootVolume.getVolumeType()).thenReturn(Volume.Type.ROOT);
 | |
|             when(correctRootVolume.getInstanceId()).thenReturn(null);
 | |
|             when(_svc.volFactory.getVolume(6L)).thenReturn(correctRootVolume);
 | |
| 
 | |
|             VolumeVO correctRootVolumeVO = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null,
 | |
|                     null, "root", Volume.Type.ROOT);
 | |
|             when(_svc._volsDao.findById(6L)).thenReturn(correctRootVolumeVO);
 | |
| 
 | |
|             // managed root volume
 | |
|             VolumeInfo managedVolume = Mockito.mock(VolumeInfo.class);
 | |
|             when(managedVolume.getId()).thenReturn(7L);
 | |
|             when(managedVolume.getDataCenterId()).thenReturn(1L);
 | |
|             when(managedVolume.getVolumeType()).thenReturn(Volume.Type.ROOT);
 | |
|             when(managedVolume.getInstanceId()).thenReturn(null);
 | |
|             when(managedVolume.getPoolId()).thenReturn(2L);
 | |
|             when(_svc.volFactory.getVolume(7L)).thenReturn(managedVolume);
 | |
| 
 | |
|             VolumeVO managedVolume1 = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null,
 | |
|                     null, "root", Volume.Type.ROOT);
 | |
|             managedVolume1.setPoolId(2L);
 | |
|             managedVolume1.setDataCenterId(1L);
 | |
|             when(_svc._volsDao.findById(7L)).thenReturn(managedVolume1);
 | |
| 
 | |
|             // vm having root volume
 | |
|             UserVmVO vmHavingRootVolume = new UserVmVO(4L, "vm", "vm", 1, HypervisorType.XenServer, 1L, false,
 | |
|                     false, 1L, 1L, 1L, null, "vm", null);
 | |
|             vmHavingRootVolume.setState(State.Stopped);
 | |
|             vmHavingRootVolume.setDataCenterId(1L);
 | |
|             when(_svc._userVmDao.findById(4L)).thenReturn(vmHavingRootVolume);
 | |
|             List<VolumeVO> vols = new ArrayList<VolumeVO>();
 | |
|             vols.add(new VolumeVO());
 | |
|             when(_svc._volsDao.findByInstanceAndDeviceId(4L, 0L)).thenReturn(vols);
 | |
| 
 | |
|             // volume in uploaded state
 | |
|             VolumeInfo uploadedVolume = Mockito.mock(VolumeInfo.class);
 | |
|             when(uploadedVolume.getId()).thenReturn(8L);
 | |
|             when(uploadedVolume.getDataCenterId()).thenReturn(1L);
 | |
|             when(uploadedVolume.getVolumeType()).thenReturn(Volume.Type.ROOT);
 | |
|             when(uploadedVolume.getInstanceId()).thenReturn(null);
 | |
|             when(uploadedVolume.getPoolId()).thenReturn(1L);
 | |
|             when(uploadedVolume.getState()).thenReturn(Volume.State.Uploaded);
 | |
|             when(_svc.volFactory.getVolume(8L)).thenReturn(uploadedVolume);
 | |
| 
 | |
|             VolumeVO upVolume = new VolumeVO("root", 1L, 1L, 1L, 1L, 2L, "root", "root", Storage.ProvisioningType.THIN, 1, null,
 | |
|                     null, "root", Volume.Type.ROOT);
 | |
|             upVolume.setPoolId(1L);
 | |
|             upVolume.setDataCenterId(1L);
 | |
|             upVolume.setState(Volume.State.Uploaded);
 | |
|             when(_svc._volsDao.findById(8L)).thenReturn(upVolume);
 | |
| 
 | |
|             // helper dao methods mock
 | |
|             when(_svc._vmSnapshotDao.findByVm(any(Long.class))).thenReturn(new ArrayList<VMSnapshotVO>());
 | |
|             when(_svc._vmInstanceDao.findById(any(Long.class))).thenReturn(stoppedVm);
 | |
| 
 | |
|         } finally {
 | |
|             txn.close("runVolumeDaoImplTest");
 | |
|         }
 | |
| 
 | |
|         // helper methods mock
 | |
|         doNothing().when(_svc._accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class));
 | |
|         doNothing().when(_svc._jobMgr).updateAsyncJobAttachment(any(Long.class), any(String.class), any(Long.class));
 | |
|         when(_svc._jobMgr.submitAsyncJob(any(AsyncJobVO.class), any(String.class), any(Long.class))).thenReturn(1L);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * TESTS FOR DETACH ROOT VOLUME, COUNT=4
 | |
|      * @throws Exception
 | |
|      */
 | |
| 
 | |
|     //@Test(expected = InvalidParameterValueException.class)
 | |
|     public void testDetachVolumeFromRunningVm() throws NoSuchFieldException, IllegalAccessException {
 | |
|         Field dedicateIdField = _detachCmdClass.getDeclaredField("id");
 | |
|         dedicateIdField.setAccessible(true);
 | |
|         dedicateIdField.set(detachCmd, 1L);
 | |
|         _svc.detachVolumeFromVM(detachCmd);
 | |
|     }
 | |
| 
 | |
|     //@Test(expected = InvalidParameterValueException.class)
 | |
|     public void testDetachVolumeFromStoppedHyperVVm() throws NoSuchFieldException, IllegalAccessException {
 | |
|         Field dedicateIdField = _detachCmdClass.getDeclaredField("id");
 | |
|         dedicateIdField.setAccessible(true);
 | |
|         dedicateIdField.set(detachCmd, 3L);
 | |
|         _svc.detachVolumeFromVM(detachCmd);
 | |
|     }
 | |
| 
 | |
|     //@Test(expected = InvalidParameterValueException.class)
 | |
|     public void testDetachVolumeOfManagedDataStore() throws NoSuchFieldException, IllegalAccessException {
 | |
|         Field dedicateIdField = _detachCmdClass.getDeclaredField("id");
 | |
|         dedicateIdField.setAccessible(true);
 | |
|         dedicateIdField.set(detachCmd, 4L);
 | |
|         _svc.detachVolumeFromVM(detachCmd);
 | |
|     }
 | |
| 
 | |
|     @Rule
 | |
|     public ExpectedException thrown = ExpectedException.none();
 | |
| 
 | |
|     //@Test
 | |
|     public void testDetachVolumeFromStoppedXenVm() throws NoSuchFieldException, IllegalAccessException {
 | |
|         thrown.expect(NullPointerException.class);
 | |
|         Field dedicateIdField = _detachCmdClass.getDeclaredField("id");
 | |
|         dedicateIdField.setAccessible(true);
 | |
|         dedicateIdField.set(detachCmd, 2L);
 | |
|         _svc.detachVolumeFromVM(detachCmd);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * TESTS FOR ATTACH ROOT VOLUME, COUNT=7
 | |
|      */
 | |
| 
 | |
|     // Negative test - try to attach non-root non-datadisk volume
 | |
|     //@Test(expected = InvalidParameterValueException.class)
 | |
|     public void attachIncorrectDiskType() throws NoSuchFieldException, IllegalAccessException {
 | |
|         _svc.attachVolumeToVM(1L, 5L, 0L);
 | |
|     }
 | |
| 
 | |
|     // Negative test - attach root volume to running vm
 | |
|     //@Test(expected = InvalidParameterValueException.class)
 | |
|     public void attachRootDiskToRunningVm() throws NoSuchFieldException, IllegalAccessException {
 | |
|         _svc.attachVolumeToVM(1L, 6L, 0L);
 | |
|     }
 | |
| 
 | |
|     // Negative test - attach root volume to non-xen vm
 | |
|     //@Test(expected = InvalidParameterValueException.class)
 | |
|     public void attachRootDiskToHyperVm() throws NoSuchFieldException, IllegalAccessException {
 | |
|         _svc.attachVolumeToVM(3L, 6L, 0L);
 | |
|     }
 | |
| 
 | |
|     // Negative test - attach root volume from the managed data store
 | |
|     //@Test(expected = InvalidParameterValueException.class)
 | |
|     public void attachRootDiskOfManagedDataStore() throws NoSuchFieldException, IllegalAccessException {
 | |
|         _svc.attachVolumeToVM(2L, 7L, 0L);
 | |
|     }
 | |
| 
 | |
|     // Negative test - root volume can't be attached to the vm already having a root volume attached
 | |
|     //@Test(expected = InvalidParameterValueException.class)
 | |
|     public void attachRootDiskToVmHavingRootDisk() throws NoSuchFieldException, IllegalAccessException {
 | |
|         _svc.attachVolumeToVM(4L, 6L, 0L);
 | |
|     }
 | |
| 
 | |
|     // Negative test - root volume in uploaded state can't be attached
 | |
|     //@Test(expected = InvalidParameterValueException.class)
 | |
|     public void attachRootInUploadedState() throws NoSuchFieldException, IllegalAccessException {
 | |
|         _svc.attachVolumeToVM(2L, 8L, 0L);
 | |
|     }
 | |
| 
 | |
|     // Positive test - attach ROOT volume in correct state, to the vm not having root volume attached
 | |
|     //@Test
 | |
|     public void attachRootVolumePositive() throws NoSuchFieldException, IllegalAccessException {
 | |
|         thrown.expect(NullPointerException.class);
 | |
|         _svc.attachVolumeToVM(2L, 6L, 0L);
 | |
|     }
 | |
| 
 | |
|     @After
 | |
|     public void tearDown() {
 | |
|         CallContext.unregister();
 | |
|     }
 | |
| }
 |