package org.ovirt.engine.core.bll.pm;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.OngoingStubbing;
import org.ovirt.engine.core.common.businessentities.FencingPolicy;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.pm.FenceActionType;
import org.ovirt.engine.core.common.businessentities.pm.FenceAgent;
import org.ovirt.engine.core.common.businessentities.pm.FenceOperationResult;
import org.ovirt.engine.core.common.businessentities.pm.FenceOperationResult.Status;
import org.ovirt.engine.core.common.businessentities.pm.PowerStatus;
import org.ovirt.engine.core.common.config.ConfigValues;
import org.ovirt.engine.core.utils.MockConfigRule;
@RunWith(MockitoJUnitRunner.class)
public class SingleAgentFenceActionExecutorTest {
@ClassRule
public static MockConfigRule configRule =
new MockConfigRule(
MockConfigRule.mockConfig(ConfigValues.FenceStartStatusRetries, 1),
MockConfigRule.mockConfig(ConfigValues.FenceStopStatusRetries, 1),
MockConfigRule.mockConfig(ConfigValues.FenceStartStatusDelayBetweenRetriesInSec, 0),
MockConfigRule.mockConfig(ConfigValues.FenceStopStatusDelayBetweenRetriesInSec, 0));
@Mock
FenceAgentExecutor fenceAgentExecutor;
@Mock
FenceAgent fenceAgent;
@Mock
VDS fencedHost;
private SingleAgentFenceActionExecutor executor;
@Before
public void setup() {
executor = spy(new SingleAgentFenceActionExecutor(fencedHost, fenceAgent, new FencingPolicy()));
doReturn(fenceAgentExecutor).when(executor).createAgentExecutor();
doReturn(0).when(executor).getSleepBeforeFirstAttempt();
doReturn(0).when(executor).getUnknownResultLimit();
doNothing().when(executor).auditVerifyStatusRetryLimitExceeded(any(FenceActionType.class));
doReturn("host1").when(fencedHost).getHostName();
}
/**
* Test successful status action
*/
@Test
public void successfulGetStatus() {
FenceOperationResult expectedResult =
new FenceOperationResult(Status.SUCCESS, PowerStatus.ON);
FenceOperationResult[] expectedResults = {
expectedResult
};
mockFenceActionResults(expectedResults);
FenceOperationResult result = executor.fence(FenceActionType.STATUS);
validateResult(expectedResult, result);
}
/**
* Test failed status action
*/
@Test
public void failedGetStatus() {
FenceOperationResult expectedResult =
new FenceOperationResult(Status.ERROR, PowerStatus.UNKNOWN);
FenceOperationResult[] expectedResults = {
expectedResult
};
mockFenceActionResults(expectedResults);
FenceOperationResult result = executor.fence(FenceActionType.STATUS);
validateResult(expectedResult, result);
}
/**
* Test successful start action
*/
@Test
public void successfulStart() {
FenceOperationResult expectedResult =
new FenceOperationResult(Status.SUCCESS, PowerStatus.ON);
FenceOperationResult[] expectedResults = {
// result of start action
new FenceOperationResult(Status.SUCCESS, PowerStatus.UNKNOWN),
// result of 1st status action
expectedResult
};
mockFenceActionResults(expectedResults);
FenceOperationResult result = executor.fence(FenceActionType.START);
validateResult(expectedResult, result);
}
/**
* Test successful start action with 1 status retry
*/
@Test
public void successfulStartWithStatusRetry() {
FenceOperationResult expectedResult =
new FenceOperationResult(Status.SUCCESS, PowerStatus.ON);
FenceOperationResult[] expectedResults = {
// result of start action
new FenceOperationResult(Status.SUCCESS, PowerStatus.UNKNOWN),
// result of 1st status action
new FenceOperationResult(Status.SUCCESS, PowerStatus.ON),
expectedResult
};
mockFenceActionResults(expectedResults);
FenceOperationResult result = executor.fence(FenceActionType.START);
validateResult(expectedResult, result);
}
/**
* Test start action with status retries exceeded
*/
@Test
public void failedStartStatusRetriesExceeded() {
FenceOperationResult expectedResult =
new FenceOperationResult(Status.ERROR, PowerStatus.OFF);
FenceOperationResult[] expectedResults = {
// result of 1st start action
new FenceOperationResult(Status.SUCCESS, PowerStatus.UNKNOWN),
// result of 1st status action
new FenceOperationResult(Status.SUCCESS, PowerStatus.OFF),
// result of 2nd status action
new FenceOperationResult(Status.SUCCESS, PowerStatus.OFF),
// result of 2nd start action
new FenceOperationResult(Status.SUCCESS, PowerStatus.UNKNOWN),
// result of 1st status action
new FenceOperationResult(Status.SUCCESS, PowerStatus.OFF),
// result of 2nd status action
new FenceOperationResult(Status.SUCCESS, PowerStatus.OFF),
};
mockFenceActionResults(expectedResults);
FenceOperationResult result = executor.fence(FenceActionType.START);
validateResult(expectedResult, result);
}
/**
* Test start action with UNKNOWN power status limit exceeded
*/
@Test
public void failedStartUnknownStatusLimitExceeded() {
FenceOperationResult expectedResult =
new FenceOperationResult(Status.ERROR, PowerStatus.UNKNOWN);
FenceOperationResult[] expectedResults = {
// result of 1st start action
new FenceOperationResult(Status.SUCCESS, PowerStatus.UNKNOWN),
// result of 1st status action
new FenceOperationResult(Status.SUCCESS, PowerStatus.UNKNOWN),
// result of 2nd start action
new FenceOperationResult(Status.SUCCESS, PowerStatus.UNKNOWN),
// result of 1st status action
new FenceOperationResult(Status.SUCCESS, PowerStatus.UNKNOWN),
};
mockFenceActionResults(expectedResults);
FenceOperationResult result = executor.fence(FenceActionType.START);
validateResult(expectedResult, result);
}
/**
* Test start action with UNKNOWN power status limit exceeded on 1st attempt, but 2nd attempt is successful
*/
@Test
public void successfulStartUnknownStatusLimitExceededOn1stAttempt() {
FenceOperationResult expectedResult =
new FenceOperationResult(Status.SUCCESS, PowerStatus.ON);
FenceOperationResult[] expectedResults = {
// result of 1st start action
new FenceOperationResult(Status.SUCCESS, PowerStatus.UNKNOWN),
// result of 1st status action
new FenceOperationResult(Status.SUCCESS, PowerStatus.UNKNOWN),
// result of 2nd start action
new FenceOperationResult(Status.SUCCESS, PowerStatus.UNKNOWN),
// result of 1st status action
new FenceOperationResult(Status.SUCCESS, PowerStatus.ON),
};
mockFenceActionResults(expectedResults);
FenceOperationResult result = executor.fence(FenceActionType.START);
validateResult(expectedResult, result);
}
/**
* Test successful start action, when the 1st start attempt failed, but the 2nd one was successful
*/
@Test
public void successfulStartWithStartRetry() {
FenceOperationResult expectedResult =
new FenceOperationResult(Status.SUCCESS, PowerStatus.ON);
FenceOperationResult[] expectedResults = {
// result of the 1st start action
new FenceOperationResult(Status.ERROR, PowerStatus.UNKNOWN),
// result of the 2nd start action
new FenceOperationResult(Status.SUCCESS, PowerStatus.UNKNOWN),
// result of status action
expectedResult
};
mockFenceActionResults(expectedResults);
FenceOperationResult result = executor.fence(FenceActionType.START);
validateResult(expectedResult, result);
}
/**
* Test failed stop action, when the 1st start attempt failed and retrying fence for stop is not allowed
*/
@Test
public void failedStopWithStopRetry() {
FenceOperationResult expectedResult =
new FenceOperationResult(Status.ERROR, PowerStatus.UNKNOWN);
FenceOperationResult[] expectedResults = {
// result of the 1st stop action
new FenceOperationResult(Status.ERROR, PowerStatus.UNKNOWN),
};
mockFenceActionResults(expectedResults);
FenceOperationResult result = executor.fence(FenceActionType.STOP);
validateResult(expectedResult, result);
}
protected void mockFenceActionResults(FenceOperationResult[] results) {
OngoingStubbing<FenceOperationResult> fenceMethodResult =
when(fenceAgentExecutor.fence(any(FenceActionType.class), any(FenceAgent.class)));
for (FenceOperationResult result : results) {
fenceMethodResult = fenceMethodResult.thenReturn(result);
}
}
protected void validateResult(FenceOperationResult expected, FenceOperationResult actual) {
assertNotNull(actual);
assertEquals(expected.getStatus(), actual.getStatus());
assertEquals(expected.getPowerStatus(), actual.getPowerStatus());
}
}