package org.ovirt.engine.core.bll.storage.domain; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.ovirt.engine.core.bll.storage.domain.ImportHostedEngineStorageDomainCommand.SUPPORTED_DOMAIN_TYPES; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; import org.ovirt.engine.core.bll.BaseCommandTest; import org.ovirt.engine.core.bll.ValidateTestUtils; import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.bll.context.CompensationContext; import org.ovirt.engine.core.bll.context.EngineContext; import org.ovirt.engine.core.bll.hostedengine.HostedEngineHelper; import org.ovirt.engine.core.bll.interfaces.BackendInternal; import org.ovirt.engine.core.common.action.StorageDomainManagementParameter; import org.ovirt.engine.core.common.action.VdcActionParametersBase; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VdcReturnValueBase; import org.ovirt.engine.core.common.businessentities.StorageDomain; import org.ovirt.engine.core.common.businessentities.StorageDomainStatic; import org.ovirt.engine.core.common.businessentities.StoragePool; import org.ovirt.engine.core.common.businessentities.StoragePoolStatus; import org.ovirt.engine.core.common.businessentities.StorageServerConnections; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.storage.BaseDisk; import org.ovirt.engine.core.common.businessentities.storage.LUNs; import org.ovirt.engine.core.common.businessentities.storage.StorageType; import org.ovirt.engine.core.common.errors.EngineMessage; import org.ovirt.engine.core.common.interfaces.VDSBrokerFrontend; import org.ovirt.engine.core.common.queries.VdcQueryParametersBase; import org.ovirt.engine.core.common.queries.VdcQueryReturnValue; import org.ovirt.engine.core.common.queries.VdcQueryType; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.common.vdscommands.VDSParametersBase; import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dao.BaseDiskDao; import org.ovirt.engine.core.dao.StoragePoolDao; import org.ovirt.engine.core.dao.StorageServerConnectionDao; import org.ovirt.engine.core.dao.VdsDao; @RunWith(MockitoJUnitRunner.class) public class ImportHostedEngineStorageDomainCommandTest extends BaseCommandTest { private static final Guid HE_SP_ID = Guid.createGuidFromString("35000000-0000-0000-0000-000000000000"); private static final Guid HE_SD_ID = Guid.createGuidFromString("35100000-0000-0000-0000-000000000000"); private static final Guid HE_VDS_ID = Guid.createGuidFromString("35200000-0000-0000-0000-000000000000"); private static final Guid VG_ID = Guid.createGuidFromString("35300000-0000-0000-0000-000000000000"); private static final String ISCSIUSER = "iscsiuser"; private static final String ISCSIPASS = "iscsipass"; @Mock private HostedEngineHelper hostedEngineHelper; private StorageDomainManagementParameter parameters = new StorageDomainManagementParameter(); @InjectMocks @Spy private ImportHostedEngineStorageDomainCommand<StorageDomainManagementParameter> cmd = new ImportHostedEngineStorageDomainCommand<>( parameters, CommandContext.createContext(parameters.getSessionId())); @Mock private BackendInternal backend; @Mock private VdsDao vdsDao; @Mock private BaseDiskDao baseDiskDao; @Mock private VDSBrokerFrontend vdsBroker; @Mock private StoragePoolDao storagePoolDao; @Mock private StorageServerConnectionDao storageServerConnectionDao; @Before public void initTest() { prepareCommand(); } @Test public void failIfDcNotActive() throws Exception { mockGetExistingDomain(true); StoragePool pool = new StoragePool(); pool.setStatus(StoragePoolStatus.Uninitialized); when(storagePoolDao.get(HE_SP_ID)).thenReturn(pool); cmd.init(); cmd.validate(); ValidateTestUtils.assertValidationMessages( "", cmd, EngineMessage.ACTION_TYPE_FAILED_MASTER_STORAGE_DOMAIN_NOT_ACTIVE ); } @Test public void failsIfImported() throws Exception { when(hostedEngineHelper.getStorageDomain()).thenReturn(new StorageDomainStatic()); mockGetExistingDomain(true); cmd.init(); cmd.validate(); ValidateTestUtils.assertValidationMessages( "", cmd, EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_ALREADY_EXIST); verify(cmd, times(0)).executeCommand(); } @Test public void failsInNotImportedAndNotExists() throws Exception { mockGetExistingDomain(false); cmd.init(); ValidateTestUtils.runAndAssertValidateFailure( "", cmd, EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_NOT_EXIST); verify(backend, times(1)).runInternalQuery( eq(VdcQueryType.GetExistingStorageDomainList), any(VdcQueryParametersBase.class)); verify(cmd, times(0)).executeCommand(); } @Test public void storageTypeUnsupported() { StorageDomain sd = mockGetExistingDomain(true); sd.setStorageType(StorageType.CINDER); sd.setId(HE_SD_ID); cmd.init(); ValidateTestUtils.runAndAssertValidateFailure( "", cmd, EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_TYPE_UNSUPPORTED); verify(backend, times(1)).runInternalQuery( eq(VdcQueryType.GetExistingStorageDomainList), any(VdcQueryParametersBase.class)); verify(cmd, times(0)).executeCommand(); } @Test public void validatePass() { StorageDomain sd = mockGetExistingDomain(true); int i = new Random().nextInt(SUPPORTED_DOMAIN_TYPES.length); sd.setStorageType(SUPPORTED_DOMAIN_TYPES[i]); sd.setId(HE_SD_ID); cmd.init(); assertTrue(cmd.validate()); } @Test public void callConcreteAddSD() { StorageDomain sd = mockGetExistingDomain(true); sd.setStorageType(StorageType.NFS); sd.setId(HE_SD_ID); mockCommandCall(VdcActionType.AddExistingFileStorageDomain, true); mockCommandCall(VdcActionType.AttachStorageDomainToPool, true); cmd.init(); cmd.validate(); cmd.executeCommand(); verify(storageServerConnectionDao, times(1)) .save(sd.getStorageStaticData().getConnection()); verify(backend, times(1)).runInternalAction( eq(VdcActionType.AddExistingFileStorageDomain), any(VdcActionParametersBase.class), any(CommandContext.class)); } @Test public void callConcreteAddBlockSD() { StorageDomain sd = mockGetExistingDomain(true); sd.setId(HE_SD_ID); sd.setStorageType(StorageType.ISCSI); sd.setStorage(VG_ID.toString()); mockCommandCall(VdcActionType.RemoveDisk, false); mockCommandCall(VdcActionType.AddExistingBlockStorageDomain, true); doReturn(createVdsReturnValue(createSdLuns())) .when(vdsBroker).runVdsCommand(eq(VDSCommandType.GetDeviceList), any(VDSParametersBase.class)); mockCommandCall(VdcActionType.AttachStorageDomainToPool, true); cmd.init(); cmd.validate(); cmd.executeCommand(); verify(backend, times(1)).runInternalAction( eq(VdcActionType.RemoveDisk), any(VdcActionParametersBase.class)); verify(backend, times(1)).runInternalAction( eq(VdcActionType.AddExistingBlockStorageDomain), any(VdcActionParametersBase.class), any(CommandContext.class)); assertTrue(cmd.getReturnValue().getSucceeded()); assertEquals(cmd.getReturnValue().getActionReturnValue(), sd); assertEquals(ISCSIUSER, sd.getStorageStaticData().getConnection().getUserName()); assertEquals(ISCSIPASS, sd.getStorageStaticData().getConnection().getPassword()); assertEquals(sd.getStorageStaticData().getStorage(), VG_ID.toString()); } protected ArrayList<LUNs> createSdLuns() { LUNs lun = new LUNs(); lun.setVolumeGroupId(VG_ID.toString()); lun.setStorageDomainId(HE_SD_ID); ArrayList<StorageServerConnections> connections = new ArrayList<>(); StorageServerConnections connection = new StorageServerConnections(); connection.setUserName(ISCSIUSER); connection.setPassword(ISCSIPASS); connections.add(connection); lun.setLunConnections(connections); ArrayList<LUNs> luns = new ArrayList<>(); luns.add(lun); return luns; } private VDSReturnValue createVdsReturnValue(List<LUNs> luns) { VDSReturnValue vdsReturnValue = new VDSReturnValue(); vdsReturnValue.setSucceeded(true); vdsReturnValue.setReturnValue(luns); return vdsReturnValue; } private Object createQueryReturnValueWith(Object value) { VdcQueryReturnValue returnValue = new VdcQueryReturnValue(); returnValue.setSucceeded(true); returnValue.setReturnValue(value); return returnValue; } protected void prepareCommand() { parameters.setStoragePoolId(HE_SP_ID); parameters.setVdsId(HE_VDS_ID); parameters.setStorageDomainId(HE_SD_ID); // vds VDS vds = new VDS(); vds.setId(Guid.Empty); vds.setStoragePoolId(HE_SP_ID); when(vdsDao.get(any(Guid.class))).thenReturn(vds); List<BaseDisk> baseDisks = Collections.singletonList(new BaseDisk()); when(baseDiskDao.getDisksByAlias(anyString())).thenReturn(baseDisks); // Data center StoragePool pool = new StoragePool(); pool.setStatus(StoragePoolStatus.Up); pool.setId(HE_SP_ID); when(storagePoolDao.get(HE_SP_ID)).thenReturn(pool); // compensation CompensationContext compensationContext = mock(CompensationContext.class); when(cmd.getCompensationContext()).thenReturn(compensationContext); when(cmd.getContext()).thenReturn(new CommandContext(new EngineContext())); } private VdcReturnValueBase successfulReturnValue() { VdcReturnValueBase value = new VdcReturnValueBase(); value.setSucceeded(true); return value; } private void mockCommandCall(VdcActionType actionType, boolean withContext) { if (withContext) { doReturn(successfulReturnValue()) .when(backend).runInternalAction(eq(actionType), any(VdcActionParametersBase.class), any(CommandContext.class)); } else { doReturn(successfulReturnValue()) .when(backend).runInternalAction(eq(actionType), any(VdcActionParametersBase.class)); } } protected StorageDomain mockGetExistingDomain(boolean answerWithDomain) { StorageDomain sd = null; List<StorageDomain> domains = Collections.emptyList(); if (answerWithDomain) { sd = new StorageDomain(); sd.getStorageStaticData().setConnection(new StorageServerConnections()); domains = Collections.singletonList(sd); } doReturn(createQueryReturnValueWith(domains)) .when(backend).runInternalQuery( eq(VdcQueryType.GetExistingStorageDomainList), any(VdcQueryParametersBase.class)); return sd; } }