|
@@ -24,124 +24,85 @@ import static org.mockito.Mockito.spy;
|
|
import static org.mockito.Mockito.verify;
|
|
import static org.mockito.Mockito.verify;
|
|
|
|
|
|
import org.apache.hadoop.conf.Configuration;
|
|
import org.apache.hadoop.conf.Configuration;
|
|
-import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
|
|
|
|
import org.apache.hadoop.ha.HAServiceProtocol.HAServiceState;
|
|
import org.apache.hadoop.ha.HAServiceProtocol.HAServiceState;
|
|
-import org.apache.hadoop.ha.protocolPB.HAServiceProtocolClientSideTranslatorPB;
|
|
|
|
import org.apache.hadoop.ha.TestNodeFencer.AlwaysSucceedFencer;
|
|
import org.apache.hadoop.ha.TestNodeFencer.AlwaysSucceedFencer;
|
|
import org.apache.hadoop.ha.TestNodeFencer.AlwaysFailFencer;
|
|
import org.apache.hadoop.ha.TestNodeFencer.AlwaysFailFencer;
|
|
import static org.apache.hadoop.ha.TestNodeFencer.setupFencer;
|
|
import static org.apache.hadoop.ha.TestNodeFencer.setupFencer;
|
|
-import org.apache.hadoop.net.NetUtils;
|
|
|
|
import org.apache.hadoop.security.AccessControlException;
|
|
import org.apache.hadoop.security.AccessControlException;
|
|
|
|
|
|
import org.junit.Test;
|
|
import org.junit.Test;
|
|
|
|
+import org.mockito.Mockito;
|
|
|
|
+import org.mockito.internal.stubbing.answers.ThrowsException;
|
|
|
|
+import org.mockito.stubbing.Answer;
|
|
|
|
+
|
|
import static org.junit.Assert.*;
|
|
import static org.junit.Assert.*;
|
|
|
|
|
|
public class TestFailoverController {
|
|
public class TestFailoverController {
|
|
-
|
|
|
|
private InetSocketAddress svc1Addr = new InetSocketAddress("svc1", 1234);
|
|
private InetSocketAddress svc1Addr = new InetSocketAddress("svc1", 1234);
|
|
- private InetSocketAddress svc2Addr = new InetSocketAddress("svc2", 5678);
|
|
|
|
-
|
|
|
|
- private class DummyService implements HAServiceProtocol {
|
|
|
|
- HAServiceState state;
|
|
|
|
-
|
|
|
|
- DummyService(HAServiceState state) {
|
|
|
|
- this.state = state;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- public void monitorHealth() throws HealthCheckFailedException, IOException {
|
|
|
|
- // Do nothing
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- public void transitionToActive() throws ServiceFailedException, IOException {
|
|
|
|
- state = HAServiceState.ACTIVE;
|
|
|
|
- }
|
|
|
|
|
|
+ private InetSocketAddress svc2Addr = new InetSocketAddress("svc2", 5678);
|
|
|
|
|
|
- @Override
|
|
|
|
- public void transitionToStandby() throws ServiceFailedException, IOException {
|
|
|
|
- state = HAServiceState.STANDBY;
|
|
|
|
- }
|
|
|
|
|
|
+ HAServiceStatus STATE_NOT_READY = new HAServiceStatus(HAServiceState.STANDBY)
|
|
|
|
+ .setNotReadyToBecomeActive("injected not ready");
|
|
|
|
|
|
- @Override
|
|
|
|
- public HAServiceStatus getServiceStatus() throws IOException {
|
|
|
|
- HAServiceStatus ret = new HAServiceStatus(state);
|
|
|
|
- if (state == HAServiceState.STANDBY) {
|
|
|
|
- ret.setReadyToBecomeActive();
|
|
|
|
- }
|
|
|
|
- return ret;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private HAServiceState getServiceState() {
|
|
|
|
- return state;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
@Test
|
|
@Test
|
|
public void testFailoverAndFailback() throws Exception {
|
|
public void testFailoverAndFailback() throws Exception {
|
|
- DummyService svc1 = new DummyService(HAServiceState.ACTIVE);
|
|
|
|
- DummyService svc2 = new DummyService(HAServiceState.STANDBY);
|
|
|
|
- NodeFencer fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
+ DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
|
|
|
|
+ DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
|
|
|
|
+ svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
AlwaysSucceedFencer.fenceCalled = 0;
|
|
AlwaysSucceedFencer.fenceCalled = 0;
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, false, false);
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, false, false);
|
|
assertEquals(0, TestNodeFencer.AlwaysSucceedFencer.fenceCalled);
|
|
assertEquals(0, TestNodeFencer.AlwaysSucceedFencer.fenceCalled);
|
|
- assertEquals(HAServiceState.STANDBY, svc1.getServiceState());
|
|
|
|
- assertEquals(HAServiceState.ACTIVE, svc2.getServiceState());
|
|
|
|
|
|
+ assertEquals(HAServiceState.STANDBY, svc1.state);
|
|
|
|
+ assertEquals(HAServiceState.ACTIVE, svc2.state);
|
|
|
|
|
|
AlwaysSucceedFencer.fenceCalled = 0;
|
|
AlwaysSucceedFencer.fenceCalled = 0;
|
|
- FailoverController.failover(svc2, svc2Addr, svc1, svc1Addr, fencer, false, false);
|
|
|
|
|
|
+ FailoverController.failover(svc2, svc1, false, false);
|
|
assertEquals(0, TestNodeFencer.AlwaysSucceedFencer.fenceCalled);
|
|
assertEquals(0, TestNodeFencer.AlwaysSucceedFencer.fenceCalled);
|
|
- assertEquals(HAServiceState.ACTIVE, svc1.getServiceState());
|
|
|
|
- assertEquals(HAServiceState.STANDBY, svc2.getServiceState());
|
|
|
|
|
|
+ assertEquals(HAServiceState.ACTIVE, svc1.state);
|
|
|
|
+ assertEquals(HAServiceState.STANDBY, svc2.state);
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
public void testFailoverFromStandbyToStandby() throws Exception {
|
|
public void testFailoverFromStandbyToStandby() throws Exception {
|
|
- DummyService svc1 = new DummyService(HAServiceState.STANDBY);
|
|
|
|
- DummyService svc2 = new DummyService(HAServiceState.STANDBY);
|
|
|
|
- NodeFencer fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
+ DummyHAService svc1 = new DummyHAService(HAServiceState.STANDBY, svc1Addr);
|
|
|
|
+ DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
|
|
|
|
+ svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, false, false);
|
|
|
|
- assertEquals(HAServiceState.STANDBY, svc1.getServiceState());
|
|
|
|
- assertEquals(HAServiceState.ACTIVE, svc2.getServiceState());
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, false, false);
|
|
|
|
+ assertEquals(HAServiceState.STANDBY, svc1.state);
|
|
|
|
+ assertEquals(HAServiceState.ACTIVE, svc2.state);
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
public void testFailoverFromActiveToActive() throws Exception {
|
|
public void testFailoverFromActiveToActive() throws Exception {
|
|
- DummyService svc1 = new DummyService(HAServiceState.ACTIVE);
|
|
|
|
- DummyService svc2 = new DummyService(HAServiceState.ACTIVE);
|
|
|
|
- NodeFencer fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
+ DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
|
|
|
|
+ DummyHAService svc2 = new DummyHAService(HAServiceState.ACTIVE, svc2Addr);
|
|
|
|
+ svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
try {
|
|
try {
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, false, false);
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, false, false);
|
|
fail("Can't failover to an already active service");
|
|
fail("Can't failover to an already active service");
|
|
} catch (FailoverFailedException ffe) {
|
|
} catch (FailoverFailedException ffe) {
|
|
// Expected
|
|
// Expected
|
|
}
|
|
}
|
|
|
|
|
|
- assertEquals(HAServiceState.ACTIVE, svc1.getServiceState());
|
|
|
|
- assertEquals(HAServiceState.ACTIVE, svc2.getServiceState());
|
|
|
|
|
|
+ assertEquals(HAServiceState.ACTIVE, svc1.state);
|
|
|
|
+ assertEquals(HAServiceState.ACTIVE, svc2.state);
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
public void testFailoverWithoutPermission() throws Exception {
|
|
public void testFailoverWithoutPermission() throws Exception {
|
|
- DummyService svc1 = new DummyService(HAServiceState.ACTIVE) {
|
|
|
|
- @Override
|
|
|
|
- public HAServiceStatus getServiceStatus() throws IOException {
|
|
|
|
- throw new AccessControlException("Access denied");
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- DummyService svc2 = new DummyService(HAServiceState.STANDBY) {
|
|
|
|
- @Override
|
|
|
|
- public HAServiceStatus getServiceStatus() throws IOException {
|
|
|
|
- throw new AccessControlException("Access denied");
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- NodeFencer fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
+ DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
|
|
|
|
+ Mockito.doThrow(new AccessControlException("Access denied"))
|
|
|
|
+ .when(svc1.proxy).getServiceStatus();
|
|
|
|
+ DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
|
|
|
|
+ Mockito.doThrow(new AccessControlException("Access denied"))
|
|
|
|
+ .when(svc2.proxy).getServiceStatus();
|
|
|
|
+ svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
try {
|
|
try {
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, false, false);
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, false, false);
|
|
fail("Can't failover when access is denied");
|
|
fail("Can't failover when access is denied");
|
|
} catch (FailoverFailedException ffe) {
|
|
} catch (FailoverFailedException ffe) {
|
|
assertTrue(ffe.getCause().getMessage().contains("Access denied"));
|
|
assertTrue(ffe.getCause().getMessage().contains("Access denied"));
|
|
@@ -151,19 +112,13 @@ public class TestFailoverController {
|
|
|
|
|
|
@Test
|
|
@Test
|
|
public void testFailoverToUnreadyService() throws Exception {
|
|
public void testFailoverToUnreadyService() throws Exception {
|
|
- DummyService svc1 = new DummyService(HAServiceState.ACTIVE);
|
|
|
|
- DummyService svc2 = new DummyService(HAServiceState.STANDBY) {
|
|
|
|
- @Override
|
|
|
|
- public HAServiceStatus getServiceStatus() throws IOException {
|
|
|
|
- HAServiceStatus ret = new HAServiceStatus(HAServiceState.STANDBY);
|
|
|
|
- ret.setNotReadyToBecomeActive("injected not ready");
|
|
|
|
- return ret;
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- NodeFencer fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
+ DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
|
|
|
|
+ DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
|
|
|
|
+ Mockito.doReturn(STATE_NOT_READY).when(svc2.proxy).getServiceStatus();
|
|
|
|
+ svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
try {
|
|
try {
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, false, false);
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, false, false);
|
|
fail("Can't failover to a service that's not ready");
|
|
fail("Can't failover to a service that's not ready");
|
|
} catch (FailoverFailedException ffe) {
|
|
} catch (FailoverFailedException ffe) {
|
|
// Expected
|
|
// Expected
|
|
@@ -172,95 +127,88 @@ public class TestFailoverController {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- assertEquals(HAServiceState.ACTIVE, svc1.getServiceState());
|
|
|
|
- assertEquals(HAServiceState.STANDBY, svc2.getServiceState());
|
|
|
|
|
|
+ assertEquals(HAServiceState.ACTIVE, svc1.state);
|
|
|
|
+ assertEquals(HAServiceState.STANDBY, svc2.state);
|
|
|
|
|
|
// Forcing it means we ignore readyToBecomeActive
|
|
// Forcing it means we ignore readyToBecomeActive
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, false, true);
|
|
|
|
- assertEquals(HAServiceState.STANDBY, svc1.getServiceState());
|
|
|
|
- assertEquals(HAServiceState.ACTIVE, svc2.getServiceState());
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, false, true);
|
|
|
|
+ assertEquals(HAServiceState.STANDBY, svc1.state);
|
|
|
|
+ assertEquals(HAServiceState.ACTIVE, svc2.state);
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
public void testFailoverToUnhealthyServiceFailsAndFailsback() throws Exception {
|
|
public void testFailoverToUnhealthyServiceFailsAndFailsback() throws Exception {
|
|
- DummyService svc1 = new DummyService(HAServiceState.ACTIVE);
|
|
|
|
- DummyService svc2 = new DummyService(HAServiceState.STANDBY) {
|
|
|
|
- @Override
|
|
|
|
- public void monitorHealth() throws HealthCheckFailedException {
|
|
|
|
- throw new HealthCheckFailedException("Failed!");
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- NodeFencer fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
+ DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
|
|
|
|
+ DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
|
|
|
|
+ Mockito.doThrow(new HealthCheckFailedException("Failed!"))
|
|
|
|
+ .when(svc2.proxy).monitorHealth();
|
|
|
|
+ svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
try {
|
|
try {
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, false, false);
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, false, false);
|
|
fail("Failover to unhealthy service");
|
|
fail("Failover to unhealthy service");
|
|
} catch (FailoverFailedException ffe) {
|
|
} catch (FailoverFailedException ffe) {
|
|
// Expected
|
|
// Expected
|
|
}
|
|
}
|
|
- assertEquals(HAServiceState.ACTIVE, svc1.getServiceState());
|
|
|
|
- assertEquals(HAServiceState.STANDBY, svc2.getServiceState());
|
|
|
|
|
|
+ assertEquals(HAServiceState.ACTIVE, svc1.state);
|
|
|
|
+ assertEquals(HAServiceState.STANDBY, svc2.state);
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
public void testFailoverFromFaultyServiceSucceeds() throws Exception {
|
|
public void testFailoverFromFaultyServiceSucceeds() throws Exception {
|
|
- DummyService svc1 = new DummyService(HAServiceState.ACTIVE) {
|
|
|
|
- @Override
|
|
|
|
- public void transitionToStandby() throws ServiceFailedException {
|
|
|
|
- throw new ServiceFailedException("Failed!");
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- DummyService svc2 = new DummyService(HAServiceState.STANDBY);
|
|
|
|
- NodeFencer fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
+ DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
|
|
|
|
+ Mockito.doThrow(new ServiceFailedException("Failed!"))
|
|
|
|
+ .when(svc1.proxy).transitionToStandby();
|
|
|
|
+
|
|
|
|
+ DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
|
|
|
|
+ svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
AlwaysSucceedFencer.fenceCalled = 0;
|
|
AlwaysSucceedFencer.fenceCalled = 0;
|
|
try {
|
|
try {
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, false, false);
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, false, false);
|
|
} catch (FailoverFailedException ffe) {
|
|
} catch (FailoverFailedException ffe) {
|
|
fail("Faulty active prevented failover");
|
|
fail("Faulty active prevented failover");
|
|
}
|
|
}
|
|
|
|
|
|
// svc1 still thinks it's active, that's OK, it was fenced
|
|
// svc1 still thinks it's active, that's OK, it was fenced
|
|
assertEquals(1, AlwaysSucceedFencer.fenceCalled);
|
|
assertEquals(1, AlwaysSucceedFencer.fenceCalled);
|
|
- assertEquals("svc1:1234", AlwaysSucceedFencer.fencedSvc);
|
|
|
|
- assertEquals(HAServiceState.ACTIVE, svc1.getServiceState());
|
|
|
|
- assertEquals(HAServiceState.ACTIVE, svc2.getServiceState());
|
|
|
|
|
|
+ assertSame(svc1, AlwaysSucceedFencer.fencedSvc);
|
|
|
|
+ assertEquals(HAServiceState.ACTIVE, svc1.state);
|
|
|
|
+ assertEquals(HAServiceState.ACTIVE, svc2.state);
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
public void testFailoverFromFaultyServiceFencingFailure() throws Exception {
|
|
public void testFailoverFromFaultyServiceFencingFailure() throws Exception {
|
|
- DummyService svc1 = new DummyService(HAServiceState.ACTIVE) {
|
|
|
|
- @Override
|
|
|
|
- public void transitionToStandby() throws ServiceFailedException {
|
|
|
|
- throw new ServiceFailedException("Failed!");
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- DummyService svc2 = new DummyService(HAServiceState.STANDBY);
|
|
|
|
- NodeFencer fencer = setupFencer(AlwaysFailFencer.class.getName());
|
|
|
|
|
|
+ DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
|
|
|
|
+ Mockito.doThrow(new ServiceFailedException("Failed!"))
|
|
|
|
+ .when(svc1.proxy).transitionToStandby();
|
|
|
|
+
|
|
|
|
+ DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
|
|
|
|
+ svc1.fencer = svc2.fencer = setupFencer(AlwaysFailFencer.class.getName());
|
|
|
|
|
|
AlwaysFailFencer.fenceCalled = 0;
|
|
AlwaysFailFencer.fenceCalled = 0;
|
|
try {
|
|
try {
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, false, false);
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, false, false);
|
|
fail("Failed over even though fencing failed");
|
|
fail("Failed over even though fencing failed");
|
|
} catch (FailoverFailedException ffe) {
|
|
} catch (FailoverFailedException ffe) {
|
|
// Expected
|
|
// Expected
|
|
}
|
|
}
|
|
|
|
|
|
assertEquals(1, AlwaysFailFencer.fenceCalled);
|
|
assertEquals(1, AlwaysFailFencer.fenceCalled);
|
|
- assertEquals("svc1:1234", AlwaysFailFencer.fencedSvc);
|
|
|
|
- assertEquals(HAServiceState.ACTIVE, svc1.getServiceState());
|
|
|
|
- assertEquals(HAServiceState.STANDBY, svc2.getServiceState());
|
|
|
|
|
|
+ assertSame(svc1, AlwaysFailFencer.fencedSvc);
|
|
|
|
+ assertEquals(HAServiceState.ACTIVE, svc1.state);
|
|
|
|
+ assertEquals(HAServiceState.STANDBY, svc2.state);
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
public void testFencingFailureDuringFailover() throws Exception {
|
|
public void testFencingFailureDuringFailover() throws Exception {
|
|
- DummyService svc1 = new DummyService(HAServiceState.ACTIVE);
|
|
|
|
- DummyService svc2 = new DummyService(HAServiceState.STANDBY);
|
|
|
|
- NodeFencer fencer = setupFencer(AlwaysFailFencer.class.getName());
|
|
|
|
|
|
+ DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
|
|
|
|
+ DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
|
|
|
|
+ svc1.fencer = svc2.fencer = setupFencer(AlwaysFailFencer.class.getName());
|
|
|
|
|
|
AlwaysFailFencer.fenceCalled = 0;
|
|
AlwaysFailFencer.fenceCalled = 0;
|
|
try {
|
|
try {
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, true, false);
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, true, false);
|
|
fail("Failed over even though fencing requested and failed");
|
|
fail("Failed over even though fencing requested and failed");
|
|
} catch (FailoverFailedException ffe) {
|
|
} catch (FailoverFailedException ffe) {
|
|
// Expected
|
|
// Expected
|
|
@@ -269,90 +217,83 @@ public class TestFailoverController {
|
|
// If fencing was requested and it failed we don't try to make
|
|
// If fencing was requested and it failed we don't try to make
|
|
// svc2 active anyway, and we don't failback to svc1.
|
|
// svc2 active anyway, and we don't failback to svc1.
|
|
assertEquals(1, AlwaysFailFencer.fenceCalled);
|
|
assertEquals(1, AlwaysFailFencer.fenceCalled);
|
|
- assertEquals("svc1:1234", AlwaysFailFencer.fencedSvc);
|
|
|
|
- assertEquals(HAServiceState.STANDBY, svc1.getServiceState());
|
|
|
|
- assertEquals(HAServiceState.STANDBY, svc2.getServiceState());
|
|
|
|
|
|
+ assertSame(svc1, AlwaysFailFencer.fencedSvc);
|
|
|
|
+ assertEquals(HAServiceState.STANDBY, svc1.state);
|
|
|
|
+ assertEquals(HAServiceState.STANDBY, svc2.state);
|
|
}
|
|
}
|
|
|
|
|
|
- private HAServiceProtocol getProtocol(String target)
|
|
|
|
- throws IOException {
|
|
|
|
- InetSocketAddress addr = NetUtils.createSocketAddr(target);
|
|
|
|
- Configuration conf = new Configuration();
|
|
|
|
- // Lower the timeout so we quickly fail to connect
|
|
|
|
- conf.setInt(CommonConfigurationKeysPublic.IPC_CLIENT_CONNECT_MAX_RETRIES_KEY, 1);
|
|
|
|
- return new HAServiceProtocolClientSideTranslatorPB(addr, conf);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
@Test
|
|
@Test
|
|
public void testFailoverFromNonExistantServiceWithFencer() throws Exception {
|
|
public void testFailoverFromNonExistantServiceWithFencer() throws Exception {
|
|
- HAServiceProtocol svc1 = getProtocol("localhost:1234");
|
|
|
|
- DummyService svc2 = new DummyService(HAServiceState.STANDBY);
|
|
|
|
- NodeFencer fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
+ DummyHAService svc1 = spy(new DummyHAService(null, svc1Addr));
|
|
|
|
+ // Getting a proxy to a dead server will throw IOException on call,
|
|
|
|
+ // not on creation of the proxy.
|
|
|
|
+ HAServiceProtocol errorThrowingProxy = Mockito.mock(HAServiceProtocol.class,
|
|
|
|
+ new ThrowsException(new IOException("Could not connect to host")));
|
|
|
|
+ Mockito.doReturn(errorThrowingProxy).when(svc1).getProxy();
|
|
|
|
+ DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
|
|
|
|
+ svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
try {
|
|
try {
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, false, false);
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, false, false);
|
|
} catch (FailoverFailedException ffe) {
|
|
} catch (FailoverFailedException ffe) {
|
|
fail("Non-existant active prevented failover");
|
|
fail("Non-existant active prevented failover");
|
|
}
|
|
}
|
|
|
|
|
|
// Don't check svc1 because we can't reach it, but that's OK, it's been fenced.
|
|
// Don't check svc1 because we can't reach it, but that's OK, it's been fenced.
|
|
- assertEquals(HAServiceState.ACTIVE, svc2.getServiceState());
|
|
|
|
|
|
+ assertEquals(HAServiceState.ACTIVE, svc2.state);
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
public void testFailoverToNonExistantServiceFails() throws Exception {
|
|
public void testFailoverToNonExistantServiceFails() throws Exception {
|
|
- DummyService svc1 = new DummyService(HAServiceState.ACTIVE);
|
|
|
|
- HAServiceProtocol svc2 = getProtocol("localhost:1234");
|
|
|
|
- NodeFencer fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
+ DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
|
|
|
|
+ DummyHAService svc2 = spy(new DummyHAService(null, svc2Addr));
|
|
|
|
+ Mockito.doThrow(new IOException("Failed to connect"))
|
|
|
|
+ .when(svc2).getProxy(Mockito.<Configuration>any(),
|
|
|
|
+ Mockito.anyInt());
|
|
|
|
+ svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
try {
|
|
try {
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, false, false);
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, false, false);
|
|
fail("Failed over to a non-existant standby");
|
|
fail("Failed over to a non-existant standby");
|
|
} catch (FailoverFailedException ffe) {
|
|
} catch (FailoverFailedException ffe) {
|
|
// Expected
|
|
// Expected
|
|
}
|
|
}
|
|
|
|
|
|
- assertEquals(HAServiceState.ACTIVE, svc1.getServiceState());
|
|
|
|
|
|
+ assertEquals(HAServiceState.ACTIVE, svc1.state);
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
public void testFailoverToFaultyServiceFailsbackOK() throws Exception {
|
|
public void testFailoverToFaultyServiceFailsbackOK() throws Exception {
|
|
- DummyService svc1 = spy(new DummyService(HAServiceState.ACTIVE));
|
|
|
|
- DummyService svc2 = new DummyService(HAServiceState.STANDBY) {
|
|
|
|
- @Override
|
|
|
|
- public void transitionToActive() throws ServiceFailedException {
|
|
|
|
- throw new ServiceFailedException("Failed!");
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- NodeFencer fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
+ DummyHAService svc1 = spy(new DummyHAService(HAServiceState.ACTIVE, svc1Addr));
|
|
|
|
+ DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
|
|
|
|
+ Mockito.doThrow(new ServiceFailedException("Failed!"))
|
|
|
|
+ .when(svc2.proxy).transitionToActive();
|
|
|
|
+ svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
try {
|
|
try {
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, false, false);
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, false, false);
|
|
fail("Failover to already active service");
|
|
fail("Failover to already active service");
|
|
} catch (FailoverFailedException ffe) {
|
|
} catch (FailoverFailedException ffe) {
|
|
// Expected
|
|
// Expected
|
|
}
|
|
}
|
|
|
|
|
|
// svc1 went standby then back to active
|
|
// svc1 went standby then back to active
|
|
- verify(svc1).transitionToStandby();
|
|
|
|
- verify(svc1).transitionToActive();
|
|
|
|
- assertEquals(HAServiceState.ACTIVE, svc1.getServiceState());
|
|
|
|
- assertEquals(HAServiceState.STANDBY, svc2.getServiceState());
|
|
|
|
|
|
+ verify(svc1.proxy).transitionToStandby();
|
|
|
|
+ verify(svc1.proxy).transitionToActive();
|
|
|
|
+ assertEquals(HAServiceState.ACTIVE, svc1.state);
|
|
|
|
+ assertEquals(HAServiceState.STANDBY, svc2.state);
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
public void testWeDontFailbackIfActiveWasFenced() throws Exception {
|
|
public void testWeDontFailbackIfActiveWasFenced() throws Exception {
|
|
- DummyService svc1 = new DummyService(HAServiceState.ACTIVE);
|
|
|
|
- DummyService svc2 = new DummyService(HAServiceState.STANDBY) {
|
|
|
|
- @Override
|
|
|
|
- public void transitionToActive() throws ServiceFailedException {
|
|
|
|
- throw new ServiceFailedException("Failed!");
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- NodeFencer fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
+ DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
|
|
|
|
+ DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
|
|
|
|
+ Mockito.doThrow(new ServiceFailedException("Failed!"))
|
|
|
|
+ .when(svc2.proxy).transitionToActive();
|
|
|
|
+ svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
try {
|
|
try {
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, true, false);
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, true, false);
|
|
fail("Failed over to service that won't transition to active");
|
|
fail("Failed over to service that won't transition to active");
|
|
} catch (FailoverFailedException ffe) {
|
|
} catch (FailoverFailedException ffe) {
|
|
// Expected
|
|
// Expected
|
|
@@ -360,24 +301,21 @@ public class TestFailoverController {
|
|
|
|
|
|
// We failed to failover and did not failback because we fenced
|
|
// We failed to failover and did not failback because we fenced
|
|
// svc1 (we forced it), therefore svc1 and svc2 should be standby.
|
|
// svc1 (we forced it), therefore svc1 and svc2 should be standby.
|
|
- assertEquals(HAServiceState.STANDBY, svc1.getServiceState());
|
|
|
|
- assertEquals(HAServiceState.STANDBY, svc2.getServiceState());
|
|
|
|
|
|
+ assertEquals(HAServiceState.STANDBY, svc1.state);
|
|
|
|
+ assertEquals(HAServiceState.STANDBY, svc2.state);
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
public void testWeFenceOnFailbackIfTransitionToActiveFails() throws Exception {
|
|
public void testWeFenceOnFailbackIfTransitionToActiveFails() throws Exception {
|
|
- DummyService svc1 = new DummyService(HAServiceState.ACTIVE);
|
|
|
|
- DummyService svc2 = new DummyService(HAServiceState.STANDBY) {
|
|
|
|
- @Override
|
|
|
|
- public void transitionToActive() throws ServiceFailedException, IOException {
|
|
|
|
- throw new IOException("Failed!");
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- NodeFencer fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
+ DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
|
|
|
|
+ DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
|
|
|
|
+ Mockito.doThrow(new ServiceFailedException("Failed!"))
|
|
|
|
+ .when(svc2.proxy).transitionToActive();
|
|
|
|
+ svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
AlwaysSucceedFencer.fenceCalled = 0;
|
|
AlwaysSucceedFencer.fenceCalled = 0;
|
|
|
|
|
|
try {
|
|
try {
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, false, false);
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, false, false);
|
|
fail("Failed over to service that won't transition to active");
|
|
fail("Failed over to service that won't transition to active");
|
|
} catch (FailoverFailedException ffe) {
|
|
} catch (FailoverFailedException ffe) {
|
|
// Expected
|
|
// Expected
|
|
@@ -386,25 +324,22 @@ public class TestFailoverController {
|
|
// We failed to failover. We did not fence svc1 because it cooperated
|
|
// We failed to failover. We did not fence svc1 because it cooperated
|
|
// and we didn't force it, so we failed back to svc1 and fenced svc2.
|
|
// and we didn't force it, so we failed back to svc1 and fenced svc2.
|
|
// Note svc2 still thinks it's active, that's OK, we fenced it.
|
|
// Note svc2 still thinks it's active, that's OK, we fenced it.
|
|
- assertEquals(HAServiceState.ACTIVE, svc1.getServiceState());
|
|
|
|
|
|
+ assertEquals(HAServiceState.ACTIVE, svc1.state);
|
|
assertEquals(1, AlwaysSucceedFencer.fenceCalled);
|
|
assertEquals(1, AlwaysSucceedFencer.fenceCalled);
|
|
- assertEquals("svc2:5678", AlwaysSucceedFencer.fencedSvc);
|
|
|
|
|
|
+ assertSame(svc2, AlwaysSucceedFencer.fencedSvc);
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
public void testFailureToFenceOnFailbackFailsTheFailback() throws Exception {
|
|
public void testFailureToFenceOnFailbackFailsTheFailback() throws Exception {
|
|
- DummyService svc1 = new DummyService(HAServiceState.ACTIVE);
|
|
|
|
- DummyService svc2 = new DummyService(HAServiceState.STANDBY) {
|
|
|
|
- @Override
|
|
|
|
- public void transitionToActive() throws ServiceFailedException, IOException {
|
|
|
|
- throw new IOException("Failed!");
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- NodeFencer fencer = setupFencer(AlwaysFailFencer.class.getName());
|
|
|
|
|
|
+ DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
|
|
|
|
+ DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
|
|
|
|
+ Mockito.doThrow(new IOException("Failed!"))
|
|
|
|
+ .when(svc2.proxy).transitionToActive();
|
|
|
|
+ svc1.fencer = svc2.fencer = setupFencer(AlwaysFailFencer.class.getName());
|
|
AlwaysFailFencer.fenceCalled = 0;
|
|
AlwaysFailFencer.fenceCalled = 0;
|
|
|
|
|
|
try {
|
|
try {
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, false, false);
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, false, false);
|
|
fail("Failed over to service that won't transition to active");
|
|
fail("Failed over to service that won't transition to active");
|
|
} catch (FailoverFailedException ffe) {
|
|
} catch (FailoverFailedException ffe) {
|
|
// Expected
|
|
// Expected
|
|
@@ -413,35 +348,30 @@ public class TestFailoverController {
|
|
// We did not fence svc1 because it cooperated and we didn't force it,
|
|
// We did not fence svc1 because it cooperated and we didn't force it,
|
|
// we failed to failover so we fenced svc2, we failed to fence svc2
|
|
// we failed to failover so we fenced svc2, we failed to fence svc2
|
|
// so we did not failback to svc1, ie it's still standby.
|
|
// so we did not failback to svc1, ie it's still standby.
|
|
- assertEquals(HAServiceState.STANDBY, svc1.getServiceState());
|
|
|
|
|
|
+ assertEquals(HAServiceState.STANDBY, svc1.state);
|
|
assertEquals(1, AlwaysFailFencer.fenceCalled);
|
|
assertEquals(1, AlwaysFailFencer.fenceCalled);
|
|
- assertEquals("svc2:5678", AlwaysFailFencer.fencedSvc);
|
|
|
|
|
|
+ assertSame(svc2, AlwaysFailFencer.fencedSvc);
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
public void testFailbackToFaultyServiceFails() throws Exception {
|
|
public void testFailbackToFaultyServiceFails() throws Exception {
|
|
- DummyService svc1 = new DummyService(HAServiceState.ACTIVE) {
|
|
|
|
- @Override
|
|
|
|
- public void transitionToActive() throws ServiceFailedException {
|
|
|
|
- throw new ServiceFailedException("Failed!");
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- DummyService svc2 = new DummyService(HAServiceState.STANDBY) {
|
|
|
|
- @Override
|
|
|
|
- public void transitionToActive() throws ServiceFailedException {
|
|
|
|
- throw new ServiceFailedException("Failed!");
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- NodeFencer fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
+ DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
|
|
|
|
+ Mockito.doThrow(new ServiceFailedException("Failed!"))
|
|
|
|
+ .when(svc1.proxy).transitionToActive();
|
|
|
|
+ DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
|
|
|
|
+ Mockito.doThrow(new ServiceFailedException("Failed!"))
|
|
|
|
+ .when(svc2.proxy).transitionToActive();
|
|
|
|
+
|
|
|
|
+ svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
|
|
|
|
|
|
try {
|
|
try {
|
|
- FailoverController.failover(svc1, svc1Addr, svc2, svc2Addr, fencer, false, false);
|
|
|
|
|
|
+ FailoverController.failover(svc1, svc2, false, false);
|
|
fail("Failover to already active service");
|
|
fail("Failover to already active service");
|
|
} catch (FailoverFailedException ffe) {
|
|
} catch (FailoverFailedException ffe) {
|
|
// Expected
|
|
// Expected
|
|
}
|
|
}
|
|
|
|
|
|
- assertEquals(HAServiceState.STANDBY, svc1.getServiceState());
|
|
|
|
- assertEquals(HAServiceState.STANDBY, svc2.getServiceState());
|
|
|
|
|
|
+ assertEquals(HAServiceState.STANDBY, svc1.state);
|
|
|
|
+ assertEquals(HAServiceState.STANDBY, svc2.state);
|
|
}
|
|
}
|
|
}
|
|
}
|