package org.ovirt.engine.core.bll.gluster; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.Collections; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; import org.ovirt.engine.core.bll.ValidateTestUtils; import org.ovirt.engine.core.bll.validator.gluster.GlusterBrickValidator; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.action.gluster.GlusterVolumeRemoveBricksParameters; import org.ovirt.engine.core.common.asynctasks.gluster.GlusterAsyncTask; import org.ovirt.engine.core.common.asynctasks.gluster.GlusterTaskType; import org.ovirt.engine.core.common.businessentities.VDSStatus; import org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity; import org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeTaskStatusEntity; import org.ovirt.engine.core.common.errors.EngineError; import org.ovirt.engine.core.common.errors.EngineMessage; import org.ovirt.engine.core.common.errors.VDSError; import org.ovirt.engine.core.common.job.JobExecutionStatus; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; import org.ovirt.engine.core.compat.Guid; @RunWith(MockitoJUnitRunner.class) public class StopRemoveGlusterVolumeBricksCommandTest extends AbstractRemoveGlusterVolumeBricksCommandTest { private final Guid volumeWithRemoveBricksTaskCompleted = new Guid("b2cb2f73-fab3-4a42-93f0-d5e4c069a43e"); /** * The command under test. */ @Spy @InjectMocks private StopRemoveGlusterVolumeBricksCommand cmd = new StopRemoveGlusterVolumeBricksCommand(new GlusterVolumeRemoveBricksParameters(), null); private void setVolumeId(Guid volumeId) { cmd.setGlusterVolumeId(volumeId); cmd.getParameters().setBricks(getBricks(volumeId)); } @Before public void prepareMocks() { GlusterBrickValidator brickValidator = spy(cmd.getBrickValidator()); doReturn(brickDao).when(brickValidator).getGlusterBrickDao(); doReturn(brickValidator).when(cmd).getBrickValidator(); doReturn(getVds(VDSStatus.Up)).when(cmd).getUpServer(); doReturn(getVolumeWithRemoveBricksTask(volumeWithRemoveBricksTask)).when(volumeDao) .getById(volumeWithRemoveBricksTask); doReturn(getBricks(volumeWithoutRemoveBricksTask)).when(brickDao) .getGlusterVolumeBricksByTaskId(any()); doReturn(getVolumeWithRemoveBricksTaskCompleted(volumeWithRemoveBricksTaskCompleted)).when(volumeDao) .getById(volumeWithRemoveBricksTaskCompleted); doReturn(getVolume(volumeWithoutAsyncTask)).when(volumeDao).getById(volumeWithoutAsyncTask); doReturn(getVolumeWithoutRemoveBricksTask(volumeWithoutRemoveBricksTask)).when(volumeDao) .getById(volumeWithoutRemoveBricksTask); } private Object getVolumeWithRemoveBricksTaskCompleted(Guid volumeId) { GlusterVolumeEntity volume = getVolumeWithRemoveBricksTask(volumeId); volume.getAsyncTask().setStatus(JobExecutionStatus.FINISHED); return volume; } @Override protected GlusterVolumeEntity getVolumeWithRemoveBricksTask(Guid volumeId) { GlusterVolumeEntity volume = getVolume(volumeId); GlusterAsyncTask asyncTask = new GlusterAsyncTask(); asyncTask.setStatus(JobExecutionStatus.STARTED); asyncTask.setType(GlusterTaskType.REMOVE_BRICK); volume.setAsyncTask(asyncTask); return volume; } private void mockBackend(boolean succeeded, EngineError errorCode) { doNothing().when(cmd).endStepJobAborted(any()); doNothing().when(cmd).releaseVolumeLock(); VDSReturnValue vdsReturnValue = new VDSReturnValue(); vdsReturnValue.setSucceeded(succeeded); if (!succeeded) { vdsReturnValue.setVdsError(new VDSError(errorCode, "")); } else { vdsReturnValue.setReturnValue(new GlusterVolumeTaskStatusEntity()); } when(vdsBrokerFrontend.runVdsCommand(eq(VDSCommandType.StopRemoveGlusterVolumeBricks), any())).thenReturn(vdsReturnValue); } @Test public void testExecuteCommand() { setVolumeId(volumeWithRemoveBricksTask); mockBackend(true, null); ValidateTestUtils.runAndAssertValidateSuccess(cmd); cmd.executeCommand(); verify(cmd, times(1)).endStepJobAborted(any()); verify(cmd, times(1)).releaseVolumeLock(); assertEquals(AuditLogType.GLUSTER_VOLUME_REMOVE_BRICKS_STOP, cmd.getAuditLogTypeValue()); } @Test public void executeCommandWhenFailed() { setVolumeId(volumeWithRemoveBricksTask); mockBackend(false, EngineError.GlusterVolumeRemoveBricksStopFailed); ValidateTestUtils.runAndAssertValidateSuccess(cmd); cmd.executeCommand(); verify(cmd, never()).endStepJobAborted(any()); verify(cmd, never()).releaseVolumeLock(); assertEquals(AuditLogType.GLUSTER_VOLUME_REMOVE_BRICKS_STOP_FAILED, cmd.getAuditLogTypeValue()); } @Test public void validateSucceedsOnVolumeWithRemoveBricksTask() { setVolumeId(volumeWithRemoveBricksTask); ValidateTestUtils.runAndAssertValidateSuccess(cmd); } // This happens in retain bricks scenario, where user can call stop remove brick after migrating the data @Test public void validateSucceedsOnVolumeWithRemoveBricksTaskCompleted() { setVolumeId(volumeWithRemoveBricksTaskCompleted); ValidateTestUtils.runAndAssertValidateSuccess(cmd); } @Test public void validateFailsOnVolumeWithoutAsyncTask() { setVolumeId(volumeWithoutAsyncTask); ValidateTestUtils.runAndAssertValidateFailure(cmd, EngineMessage.ACTION_TYPE_FAILED_GLUSTER_VOLUME_INVALID_TASK_TYPE); } @Test public void validateFailsOnVolumeWithoutRemoveBricksTask() { setVolumeId(volumeWithoutRemoveBricksTask); ValidateTestUtils.runAndAssertValidateFailure(cmd, EngineMessage.ACTION_TYPE_FAILED_GLUSTER_VOLUME_INVALID_TASK_TYPE); } @Test public void validateFailsOnNull() { cmd.getParameters().setBricks(getBricks(volumeWithRemoveBricksTaskCompleted)); ValidateTestUtils.runAndAssertValidateFailure(cmd, EngineMessage.ACTION_TYPE_FAILED_GLUSTER_VOLUME_INVALID); } @Test public void validateFailsWithEmptyBricksList() { cmd.getParameters().setBricks(Collections.emptyList()); ValidateTestUtils.runAndAssertValidateFailure(cmd, EngineMessage.ACTION_TYPE_FAILED_GLUSTER_VOLUME_INVALID); } @Test public void validateFailsWithInvalidNoOfBricks() { cmd.setGlusterVolumeId(volumeWithRemoveBricksTask); cmd.getParameters().setBricks(getInvalidNoOfBricks(volumeWithRemoveBricksTask)); ValidateTestUtils.runAndAssertValidateFailure(cmd, EngineMessage.ACTION_TYPE_FAILED_GLUSTER_VOLUME_REMOVE_BRICKS_PARAMS_INVALID); } @Test public void validateFailsWithInvalidBricks() { cmd.setGlusterVolumeId(volumeWithRemoveBricksTask); cmd.getParameters().setBricks(getInvalidBricks(volumeWithRemoveBricksTask)); ValidateTestUtils.runAndAssertValidateFailure(cmd, EngineMessage.ACTION_TYPE_FAILED_GLUSTER_VOLUME_REMOVE_BRICKS_PARAMS_INVALID); } }