mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-11-04 00:02:37 +01:00 
			
		
		
		
	Allow encrypted volume migration for PowerFlex volumes (#7757)
This commit is contained in:
		
							parent
							
								
									cee7a713aa
								
							
						
					
					
						commit
						80ca3acf15
					
				@ -2999,6 +2999,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 | 
			
		||||
            throw new InvalidParameterValueException("Volume cannot be migrated, please remove all VM snapshots for VM to which this volume is attached");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        StoragePoolVO srcStoragePoolVO = _storagePoolDao.findById(vol.getPoolId());
 | 
			
		||||
 | 
			
		||||
        // OfflineVmwareMigration: extract this block as method and check if it is subject to regression
 | 
			
		||||
        if (vm != null && State.Running.equals(vm.getState())) {
 | 
			
		||||
            // Check if the VM is GPU enabled.
 | 
			
		||||
@ -3020,16 +3022,15 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 | 
			
		||||
                    liveMigrateVolume = capabilities.isStorageMotionSupported();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                StoragePoolVO storagePoolVO = _storagePoolDao.findById(vol.getPoolId());
 | 
			
		||||
                if (liveMigrateVolume && HypervisorType.KVM.equals(host.getHypervisorType()) && !storagePoolVO.getPoolType().equals(Storage.StoragePoolType.PowerFlex)) {
 | 
			
		||||
                if (liveMigrateVolume && HypervisorType.KVM.equals(host.getHypervisorType()) && !srcStoragePoolVO.getPoolType().equals(Storage.StoragePoolType.PowerFlex)) {
 | 
			
		||||
                    StoragePoolVO destinationStoragePoolVo = _storagePoolDao.findById(storagePoolId);
 | 
			
		||||
 | 
			
		||||
                    if (isSourceOrDestNotOnStorPool(storagePoolVO, destinationStoragePoolVo)) {
 | 
			
		||||
                    if (isSourceOrDestNotOnStorPool(srcStoragePoolVO, destinationStoragePoolVo)) {
 | 
			
		||||
                        throw new InvalidParameterValueException("KVM does not support volume live migration due to the limited possibility to refresh VM XML domain. " +
 | 
			
		||||
                                "Therefore, to live migrate a volume between storage pools, one must migrate the VM to a different host as well to force the VM XML domain update. " +
 | 
			
		||||
                                "Use 'migrateVirtualMachineWithVolumes' instead.");
 | 
			
		||||
                    }
 | 
			
		||||
                    srcAndDestOnStorPool = isSourceAndDestOnStorPool(storagePoolVO, destinationStoragePoolVo);
 | 
			
		||||
                    srcAndDestOnStorPool = isSourceAndDestOnStorPool(srcStoragePoolVO, destinationStoragePoolVo);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -3043,7 +3044,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (vol.getPassphraseId() != null && !srcAndDestOnStorPool) {
 | 
			
		||||
        if (vol.getPassphraseId() != null && !srcAndDestOnStorPool && !srcStoragePoolVO.getPoolType().equals(Storage.StoragePoolType.PowerFlex)) {
 | 
			
		||||
            throw new InvalidParameterValueException("Migration of encrypted volumes is unsupported");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -17,6 +17,7 @@
 | 
			
		||||
package com.cloud.storage;
 | 
			
		||||
 | 
			
		||||
import static org.junit.Assert.assertEquals;
 | 
			
		||||
import static org.junit.Assert.fail;
 | 
			
		||||
import static org.mockito.Matchers.any;
 | 
			
		||||
import static org.mockito.Matchers.anyLong;
 | 
			
		||||
import static org.mockito.Matchers.anyObject;
 | 
			
		||||
@ -40,8 +41,11 @@ import org.apache.cloudstack.acl.ControlledEntity;
 | 
			
		||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
 | 
			
		||||
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
 | 
			
		||||
import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
 | 
			
		||||
import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd;
 | 
			
		||||
import org.apache.cloudstack.context.CallContext;
 | 
			
		||||
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.PrimaryDataStore;
 | 
			
		||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
 | 
			
		||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
 | 
			
		||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
 | 
			
		||||
@ -52,6 +56,7 @@ 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.snapshot.SnapshotHelper;
 | 
			
		||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
 | 
			
		||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
 | 
			
		||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 | 
			
		||||
@ -114,6 +119,7 @@ import com.cloud.user.ResourceLimitService;
 | 
			
		||||
import com.cloud.user.User;
 | 
			
		||||
import com.cloud.user.UserVO;
 | 
			
		||||
import com.cloud.user.dao.AccountDao;
 | 
			
		||||
import com.cloud.utils.exception.CloudRuntimeException;
 | 
			
		||||
import com.cloud.utils.db.TransactionLegacy;
 | 
			
		||||
import com.cloud.utils.fsm.NoTransitionException;
 | 
			
		||||
import com.cloud.vm.UserVmManager;
 | 
			
		||||
@ -169,6 +175,8 @@ public class VolumeApiServiceImplTest {
 | 
			
		||||
    @Mock
 | 
			
		||||
    private CreateVolumeCmd createVol;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private MigrateVolumeCmd migrateVolumeCmd;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private UserVmManager userVmManager;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private DataCenterDao _dcDao;
 | 
			
		||||
@ -188,6 +196,10 @@ public class VolumeApiServiceImplTest {
 | 
			
		||||
    private ServiceOfferingDao serviceOfferingDao;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private DiskOfferingDao _diskOfferingDao;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private DataStoreManager dataStoreMgr;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private SnapshotHelper snapshotHelper;
 | 
			
		||||
 | 
			
		||||
    private DetachVolumeCmd detachCmd = new DetachVolumeCmd();
 | 
			
		||||
    private Class<?> _detachCmdClass = detachCmd.getClass();
 | 
			
		||||
@ -218,6 +230,9 @@ public class VolumeApiServiceImplTest {
 | 
			
		||||
    @Mock
 | 
			
		||||
    private ProjectManager projectManagerMock;
 | 
			
		||||
 | 
			
		||||
    @Mock
 | 
			
		||||
    private StorageManager storageMgr;
 | 
			
		||||
 | 
			
		||||
    private long accountMockId = 456l;
 | 
			
		||||
    private long volumeMockId = 12313l;
 | 
			
		||||
    private long vmInstanceMockId = 1123l;
 | 
			
		||||
@ -1579,4 +1594,41 @@ public class VolumeApiServiceImplTest {
 | 
			
		||||
        Mockito.when(host.getHypervisorType()).thenReturn(HypervisorType.KVM);
 | 
			
		||||
        Assert.assertFalse(volumeApiServiceImpl.isSendCommandForVmVolumeAttachDetach(host, Mockito.mock(StoragePoolVO.class)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Below test covers both allowing encrypted volume migration for PowerFlex storage and expect error on storagepool compatibility
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testStoragePoolCompatibilityAndAllowEncryptedVolumeMigrationForPowerFlexStorage() {
 | 
			
		||||
        try {
 | 
			
		||||
            Mockito.when(migrateVolumeCmd.getVolumeId()).thenReturn(1L);
 | 
			
		||||
            Mockito.when(migrateVolumeCmd.getStoragePoolId()).thenReturn(2L);
 | 
			
		||||
            VolumeVO vol = Mockito.mock(VolumeVO.class);
 | 
			
		||||
            Mockito.when(volumeDaoMock.findById(1L)).thenReturn(vol);
 | 
			
		||||
            Mockito.when(volumeDaoMock.getHypervisorType(1L)).thenReturn(HypervisorType.KVM);
 | 
			
		||||
            Mockito.when(vol.getState()).thenReturn(Volume.State.Ready);
 | 
			
		||||
            Mockito.when(vol.getPoolId()).thenReturn(1L);
 | 
			
		||||
            Mockito.when(vol.getInstanceId()).thenReturn(null);
 | 
			
		||||
            Mockito.when(vol.getDiskOfferingId()).thenReturn(1L);
 | 
			
		||||
            DiskOfferingVO diskOffering = Mockito.mock(DiskOfferingVO.class);
 | 
			
		||||
            Mockito.when(_diskOfferingDao.findById(1L)).thenReturn(diskOffering);
 | 
			
		||||
 | 
			
		||||
            StoragePoolVO srcStoragePoolVOMock = Mockito.mock(StoragePoolVO.class);
 | 
			
		||||
            StoragePool destPool = Mockito.mock(StoragePool.class);
 | 
			
		||||
            PrimaryDataStore dataStore = Mockito.mock(PrimaryDataStore.class);
 | 
			
		||||
 | 
			
		||||
            Mockito.when(vol.getPassphraseId()).thenReturn(1L);
 | 
			
		||||
            Mockito.when(primaryDataStoreDaoMock.findById(1L)).thenReturn(srcStoragePoolVOMock);
 | 
			
		||||
            Mockito.when(srcStoragePoolVOMock.getPoolType()).thenReturn(Storage.StoragePoolType.PowerFlex);
 | 
			
		||||
            Mockito.when(dataStoreMgr.getDataStore(2L, DataStoreRole.Primary)).thenReturn( dataStore);
 | 
			
		||||
            Mockito.doNothing().when(snapshotHelper).checkKvmVolumeSnapshotsOnlyInPrimaryStorage(vol, HypervisorType.KVM);
 | 
			
		||||
            Mockito.when(destPool.getUuid()).thenReturn("bd525970-3d2a-4230-880d-261892129ef3");
 | 
			
		||||
 | 
			
		||||
            Mockito.when(storageMgr.storagePoolCompatibleWithVolumePool(destPool, vol)).thenReturn(false);
 | 
			
		||||
 | 
			
		||||
            volumeApiServiceImpl.migrateVolume(migrateVolumeCmd);
 | 
			
		||||
        } catch (InvalidParameterValueException e) {
 | 
			
		||||
            fail("Unexpected InvalidParameterValueException was thrown");
 | 
			
		||||
        } catch (CloudRuntimeException e) {
 | 
			
		||||
            // test passed
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user