You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by cl...@apache.org on 2019/06/28 23:06:07 UTC
[hadoop] 04/50: HDFS-13286. [SBN read] Add haadmin commands to
transition between standby and observer. Contributed by Chao Sun.
This is an automated email from the ASF dual-hosted git repository.
cliang pushed a commit to branch branch-3.2
in repository https://gitbox.apache.org/repos/asf/hadoop.git
commit 49d7bb6a92026ab34eb1a9f06c059b0f98c2698b
Author: Erik Krogen <xk...@apache.org>
AuthorDate: Fri May 4 12:22:12 2018 -0700
HDFS-13286. [SBN read] Add haadmin commands to transition between standby and observer. Contributed by Chao Sun.
---
.../org/apache/hadoop/ha/FailoverController.java | 2 +-
.../main/java/org/apache/hadoop/ha/HAAdmin.java | 42 +++++++++++++++++++++
.../org/apache/hadoop/ha/HAServiceProtocol.java | 18 +++++++++
.../apache/hadoop/ha/HAServiceProtocolHelper.java | 9 +++++
.../java/org/apache/hadoop/ha/HAServiceTarget.java | 7 ++++
.../HAServiceProtocolClientSideTranslatorPB.java | 16 ++++++++
.../HAServiceProtocolServerSideTranslatorPB.java | 20 ++++++++++
.../src/main/proto/HAServiceProtocol.proto | 20 ++++++++++
.../java/org/apache/hadoop/ha/DummyHAService.java | 18 ++++++++-
.../java/org/apache/hadoop/ha/MiniZKFCCluster.java | 4 ++
.../resolver/FederationNamenodeServiceState.java | 3 ++
.../apache/hadoop/hdfs/protocolPB/PBHelper.java | 4 ++
.../hdfs/server/datanode/BPServiceActor.java | 2 +-
.../hadoop/hdfs/server/namenode/FSNamesystem.java | 3 +-
.../hadoop/hdfs/server/namenode/NameNode.java | 27 ++++++++-----
.../hdfs/server/namenode/NameNodeRpcServer.java | 8 ++++
.../hdfs/server/namenode/ha/StandbyState.java | 12 +++---
.../hadoop/hdfs/tools/NNHAServiceTarget.java | 5 +++
.../hadoop-hdfs/src/main/proto/HdfsServer.proto | 1 +
.../apache/hadoop/hdfs/tools/TestDFSHAAdmin.java | 6 +++
.../hdfs/tools/TestDFSHAAdminMiniCluster.java | 44 ++++++++++++++++++++++
.../yarn/server/resourcemanager/AdminService.java | 7 ++++
22 files changed, 258 insertions(+), 20 deletions(-)
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/FailoverController.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/FailoverController.java
index b86ae29..4fc52d5 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/FailoverController.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/FailoverController.java
@@ -129,7 +129,7 @@ public class FailoverController {
if (!toSvcStatus.getState().equals(HAServiceState.STANDBY)) {
throw new FailoverFailedException(
- "Can't failover to an active service");
+ "Can't failover to an " + toSvcStatus.getState() + " service");
}
if (!toSvcStatus.isReadyToBecomeActive()) {
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAAdmin.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAAdmin.java
index e955979..59e20d7 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAAdmin.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAAdmin.java
@@ -72,6 +72,9 @@ public abstract class HAAdmin extends Configured implements Tool {
new UsageInfo("[--"+FORCEACTIVE+"] <serviceId>", "Transitions the service into Active state"))
.put("-transitionToStandby",
new UsageInfo("<serviceId>", "Transitions the service into Standby state"))
+ .put("-transitionToObserver",
+ new UsageInfo("<serviceId>",
+ "Transitions the service into Observer state"))
.put("-failover",
new UsageInfo("[--"+FORCEFENCE+"] [--"+FORCEACTIVE+"] <serviceId> <serviceId>",
"Failover from the first service to the second.\n" +
@@ -221,6 +224,28 @@ public abstract class HAAdmin extends Configured implements Tool {
HAServiceProtocolHelper.transitionToStandby(proto, createReqInfo());
return 0;
}
+
+ private int transitionToObserver(final CommandLine cmd)
+ throws IOException, ServiceFailedException {
+ String[] argv = cmd.getArgs();
+ if (argv.length != 1) {
+ errOut.println("transitionToObserver: incorrect number of arguments");
+ printUsage(errOut, "-transitionToObserver");
+ return -1;
+ }
+
+ HAServiceTarget target = resolveTarget(argv[0]);
+ if (!checkSupportObserver(target)) {
+ return -1;
+ }
+ if (!checkManualStateManagementOK(target)) {
+ return -1;
+ }
+ HAServiceProtocol proto = target.getProxy(getConf(), 0);
+ HAServiceProtocolHelper.transitionToObserver(proto, createReqInfo());
+ return 0;
+ }
+
/**
* Ensure that we are allowed to manually manage the HA state of the target
* service. If automatic failover is configured, then the automatic
@@ -249,6 +274,21 @@ public abstract class HAAdmin extends Configured implements Tool {
return true;
}
+ /**
+ * Check if the target supports the Observer state.
+ * @param target the target to check
+ * @return true if the target support Observer state, false otherwise.
+ */
+ private boolean checkSupportObserver(HAServiceTarget target) {
+ if (target.supportObserver()) {
+ return true;
+ } else {
+ errOut.println(
+ "The target " + target + " doesn't support Observer state.");
+ return false;
+ }
+ }
+
private StateChangeRequestInfo createReqInfo() {
return new StateChangeRequestInfo(requestSource);
}
@@ -461,6 +501,8 @@ public abstract class HAAdmin extends Configured implements Tool {
return transitionToActive(cmdLine);
} else if ("-transitionToStandby".equals(cmd)) {
return transitionToStandby(cmdLine);
+ } else if ("-transitionToObserver".equals(cmd)) {
+ return transitionToObserver(cmdLine);
} else if ("-failover".equals(cmd)) {
return failover(cmdLine);
} else if ("-getServiceState".equals(cmd)) {
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocol.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocol.java
index 7099de8..74a3d12 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocol.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocol.java
@@ -51,6 +51,7 @@ public interface HAServiceProtocol {
INITIALIZING("initializing"),
ACTIVE("active"),
STANDBY("standby"),
+ OBSERVER("observer"),
STOPPING("stopping");
private String name;
@@ -149,6 +150,23 @@ public interface HAServiceProtocol {
IOException;
/**
+ * Request service to transition to observer state. No operation, if the
+ * service is already in observer state.
+ *
+ * @throws ServiceFailedException
+ * if transition from standby to observer fails.
+ * @throws AccessControlException
+ * if access is denied.
+ * @throws IOException
+ * if other errors happen
+ */
+ @Idempotent
+ void transitionToObserver(StateChangeRequestInfo reqInfo)
+ throws ServiceFailedException,
+ AccessControlException,
+ IOException;
+
+ /**
* Return the current status of the service. The status indicates
* the current <em>state</em> (e.g ACTIVE/STANDBY) as well as
* some additional information.
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocolHelper.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocolHelper.java
index 58d4a7f..a2441fb 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocolHelper.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocolHelper.java
@@ -60,4 +60,13 @@ public class HAServiceProtocolHelper {
throw e.unwrapRemoteException(ServiceFailedException.class);
}
}
+
+ public static void transitionToObserver(HAServiceProtocol svc,
+ StateChangeRequestInfo reqInfo) throws IOException {
+ try {
+ svc.transitionToObserver(reqInfo);
+ } catch (RemoteException e) {
+ throw e.unwrapRemoteException(ServiceFailedException.class);
+ }
+ }
}
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceTarget.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceTarget.java
index 98aab99..4a2a21b 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceTarget.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceTarget.java
@@ -170,4 +170,11 @@ public abstract class HAServiceTarget {
public boolean isAutoFailoverEnabled() {
return false;
}
+
+ /**
+ * @return true if this target supports the Observer state, false otherwise.
+ */
+ public boolean supportObserver() {
+ return false;
+ }
}
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolClientSideTranslatorPB.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolClientSideTranslatorPB.java
index 589ccd1..fec519f 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolClientSideTranslatorPB.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolClientSideTranslatorPB.java
@@ -36,6 +36,7 @@ import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.HAServiceStateProto;
import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.MonitorHealthRequestProto;
import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.TransitionToActiveRequestProto;
import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.TransitionToStandbyRequestProto;
+import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.TransitionToObserverRequestProto;
import org.apache.hadoop.ipc.ProtobufHelper;
import org.apache.hadoop.ipc.ProtobufRpcEngine;
import org.apache.hadoop.ipc.ProtocolTranslator;
@@ -116,6 +117,19 @@ public class HAServiceProtocolClientSideTranslatorPB implements
}
@Override
+ public void transitionToObserver(StateChangeRequestInfo reqInfo)
+ throws IOException {
+ try {
+ TransitionToObserverRequestProto req =
+ TransitionToObserverRequestProto.newBuilder()
+ .setReqInfo(convert(reqInfo)).build();
+ rpcProxy.transitionToObserver(NULL_CONTROLLER, req);
+ } catch (ServiceException e) {
+ throw ProtobufHelper.getRemoteException(e);
+ }
+ }
+
+ @Override
public HAServiceStatus getServiceStatus() throws IOException {
GetServiceStatusResponseProto status;
try {
@@ -141,6 +155,8 @@ public class HAServiceProtocolClientSideTranslatorPB implements
return HAServiceState.ACTIVE;
case STANDBY:
return HAServiceState.STANDBY;
+ case OBSERVER:
+ return HAServiceState.OBSERVER;
case INITIALIZING:
default:
return HAServiceState.INITIALIZING;
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolServerSideTranslatorPB.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolServerSideTranslatorPB.java
index 7f75582..72787cf 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolServerSideTranslatorPB.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolServerSideTranslatorPB.java
@@ -35,6 +35,8 @@ import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.TransitionToActiveRequ
import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.TransitionToActiveResponseProto;
import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.TransitionToStandbyRequestProto;
import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.TransitionToStandbyResponseProto;
+import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.TransitionToObserverRequestProto;
+import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.TransitionToObserverResponseProto;
import org.apache.hadoop.ipc.ProtocolSignature;
import org.apache.hadoop.ipc.RPC;
@@ -61,6 +63,9 @@ public class HAServiceProtocolServerSideTranslatorPB implements
TransitionToActiveResponseProto.newBuilder().build();
private static final TransitionToStandbyResponseProto TRANSITION_TO_STANDBY_RESP =
TransitionToStandbyResponseProto.newBuilder().build();
+ private static final TransitionToObserverResponseProto
+ TRANSITION_TO_OBSERVER_RESP =
+ TransitionToObserverResponseProto.newBuilder().build();
private static final Logger LOG = LoggerFactory.getLogger(
HAServiceProtocolServerSideTranslatorPB.class);
@@ -124,6 +129,18 @@ public class HAServiceProtocolServerSideTranslatorPB implements
}
@Override
+ public TransitionToObserverResponseProto transitionToObserver(
+ RpcController controller, TransitionToObserverRequestProto request)
+ throws ServiceException {
+ try {
+ server.transitionToObserver(convert(request.getReqInfo()));
+ return TRANSITION_TO_OBSERVER_RESP;
+ } catch (IOException e) {
+ throw new ServiceException(e);
+ }
+ }
+
+ @Override
public GetServiceStatusResponseProto getServiceStatus(RpcController controller,
GetServiceStatusRequestProto request) throws ServiceException {
HAServiceStatus s;
@@ -141,6 +158,9 @@ public class HAServiceProtocolServerSideTranslatorPB implements
case STANDBY:
retState = HAServiceStateProto.STANDBY;
break;
+ case OBSERVER:
+ retState = HAServiceStateProto.OBSERVER;
+ break;
case INITIALIZING:
default:
retState = HAServiceStateProto.INITIALIZING;
diff --git a/hadoop-common-project/hadoop-common/src/main/proto/HAServiceProtocol.proto b/hadoop-common-project/hadoop-common/src/main/proto/HAServiceProtocol.proto
index e0060f2..16ee9a2 100644
--- a/hadoop-common-project/hadoop-common/src/main/proto/HAServiceProtocol.proto
+++ b/hadoop-common-project/hadoop-common/src/main/proto/HAServiceProtocol.proto
@@ -32,6 +32,7 @@ enum HAServiceStateProto {
INITIALIZING = 0;
ACTIVE = 1;
STANDBY = 2;
+ OBSERVER = 3;
}
enum HARequestSource {
@@ -85,6 +86,19 @@ message TransitionToStandbyResponseProto {
/**
* void request
*/
+message TransitionToObserverRequestProto {
+ required HAStateChangeRequestInfoProto reqInfo = 1;
+}
+
+/**
+ * void response
+ */
+message TransitionToObserverResponseProto {
+}
+
+/**
+ * void request
+ */
message GetServiceStatusRequestProto {
}
@@ -127,6 +141,12 @@ service HAServiceProtocolService {
returns(TransitionToStandbyResponseProto);
/**
+ * Request service to transition to observer state.
+ */
+ rpc transitionToObserver(TransitionToObserverRequestProto)
+ returns(TransitionToObserverResponseProto);
+
+ /**
* Get the current status of the service.
*/
rpc getServiceStatus(GetServiceStatusRequestProto)
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/DummyHAService.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/DummyHAService.java
index 6f01be8..51112be 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/DummyHAService.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/DummyHAService.java
@@ -56,7 +56,8 @@ class DummyHAService extends HAServiceTarget {
InetSocketAddress address, healthMonitorAddress;
boolean isHealthy = true;
boolean actUnreachable = false;
- boolean failToBecomeActive, failToBecomeStandby, failToFence;
+ boolean failToBecomeActive, failToBecomeStandby, failToBecomeObserver,
+ failToFence;
DummySharedResource sharedResource;
public int fenceCount = 0;
@@ -217,6 +218,11 @@ class DummyHAService extends HAServiceTarget {
}
@Override
+ public boolean supportObserver() {
+ return true;
+ }
+
+ @Override
public String toString() {
return "DummyHAService #" + index;
}
@@ -264,6 +270,16 @@ class DummyHAService extends HAServiceTarget {
}
@Override
+ public void transitionToObserver(StateChangeRequestInfo req)
+ throws ServiceFailedException, AccessControlException, IOException {
+ checkUnreachable();
+ if (failToBecomeObserver) {
+ throw new ServiceFailedException("injected failure");
+ }
+ state = HAServiceState.OBSERVER;
+ }
+
+ @Override
public HAServiceStatus getServiceStatus() throws IOException {
checkUnreachable();
HAServiceStatus ret = new HAServiceStatus(state);
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/MiniZKFCCluster.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/MiniZKFCCluster.java
index 9146e01..f63d267 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/MiniZKFCCluster.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/MiniZKFCCluster.java
@@ -187,6 +187,10 @@ public class MiniZKFCCluster {
svcs.get(idx).actUnreachable = unreachable;
}
+ public void setFailToBecomeObserver(int idx, boolean doFail) {
+ svcs.get(idx).failToBecomeObserver = doFail;
+ }
+
/**
* Wait for the given HA service to enter the given HA state.
* This is based on the state of ZKFC, not the state of HA service.
diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/resolver/FederationNamenodeServiceState.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/resolver/FederationNamenodeServiceState.java
index 7907e30..ed8f8c0 100644
--- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/resolver/FederationNamenodeServiceState.java
+++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/resolver/FederationNamenodeServiceState.java
@@ -35,6 +35,9 @@ public enum FederationNamenodeServiceState {
case ACTIVE:
return FederationNamenodeServiceState.ACTIVE;
case STANDBY:
+ // TODO: we should probably have a separate state OBSERVER for RBF and
+ // treat it differently.
+ case OBSERVER:
return FederationNamenodeServiceState.STANDBY;
case INITIALIZING:
return FederationNamenodeServiceState.UNAVAILABLE;
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocolPB/PBHelper.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocolPB/PBHelper.java
index ac01348..baec6fa 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocolPB/PBHelper.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocolPB/PBHelper.java
@@ -779,6 +779,8 @@ public class PBHelper {
return HAServiceState.ACTIVE;
case STANDBY:
return HAServiceState.STANDBY;
+ case OBSERVER:
+ return HAServiceState.OBSERVER;
default:
throw new IllegalArgumentException("Unexpected HAServiceStateProto:"
+ s);
@@ -794,6 +796,8 @@ public class PBHelper {
return NNHAStatusHeartbeatProto.State.ACTIVE;
case STANDBY:
return NNHAStatusHeartbeatProto.State.STANDBY;
+ case OBSERVER:
+ return NNHAStatusHeartbeatProto.State.OBSERVER;
default:
throw new IllegalArgumentException("Unexpected HAServiceState:"
+ s);
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/BPServiceActor.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/BPServiceActor.java
index aa614c9..93af5ec 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/BPServiceActor.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/BPServiceActor.java
@@ -912,7 +912,7 @@ class BPServiceActor implements Runnable {
scheduler.scheduleHeartbeat();
// HDFS-9917,Standby NN IBR can be very huge if standby namenode is down
// for sometime.
- if (state == HAServiceState.STANDBY) {
+ if (state == HAServiceState.STANDBY || state == HAServiceState.OBSERVER) {
ibrManager.clearIBRs();
}
}
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java
index 42259c8..63eed2d 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java
@@ -1729,7 +1729,8 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
return haEnabled;
}
- return HAServiceState.STANDBY == haContext.getState().getServiceState();
+ return HAServiceState.STANDBY == haContext.getState().getServiceState() ||
+ HAServiceState.OBSERVER == haContext.getState().getServiceState();
}
/**
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java
index f98ae80..7d354b2 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java
@@ -1763,25 +1763,35 @@ public class NameNode extends ReconfigurableBase implements
throw new ServiceFailedException("HA for namenode is not enabled");
}
if (state == OBSERVER_STATE) {
- // TODO: we may need to remove this when enabling failover for observer
throw new ServiceFailedException(
- "Cannot transition from Observer to Active");
+ "Cannot transition from '" + OBSERVER_STATE + "' to '" +
+ ACTIVE_STATE + "'");
}
state.setState(haContext, ACTIVE_STATE);
}
-
- synchronized void transitionToStandby()
+
+ synchronized void transitionToStandby()
throws ServiceFailedException, AccessControlException {
namesystem.checkSuperuserPrivilege();
if (!haEnabled) {
throw new ServiceFailedException("HA for namenode is not enabled");
}
- if (state == OBSERVER_STATE) {
- // TODO: we may need to remove this when enabling failover for observer
+ state.setState(haContext, STANDBY_STATE);
+ }
+
+ synchronized void transitionToObserver()
+ throws ServiceFailedException, AccessControlException {
+ namesystem.checkSuperuserPrivilege();
+ if (!haEnabled) {
+ throw new ServiceFailedException("HA for namenode is not enabled");
+ }
+ // Transition from ACTIVE to OBSERVER is forbidden.
+ if (state == ACTIVE_STATE) {
throw new ServiceFailedException(
- "Cannot transition from Observer to Standby");
+ "Cannot transition from '" + ACTIVE_STATE + "' to '" +
+ OBSERVER_STATE + "'");
}
- state.setState(haContext, STANDBY_STATE);
+ state.setState(haContext, OBSERVER_STATE);
}
synchronized HAServiceStatus getServiceStatus()
@@ -1835,7 +1845,6 @@ public class NameNode extends ReconfigurableBase implements
@Override // NameNodeStatusMXBean
public String getState() {
- // TODO: maybe we should return a different result for observer namenode?
String servStateStr = "";
HAServiceState servState = getServiceState();
if (null != servState) {
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNodeRpcServer.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNodeRpcServer.java
index a39bbe2..e8cec39 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNodeRpcServer.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNodeRpcServer.java
@@ -1756,6 +1756,14 @@ public class NameNodeRpcServer implements NamenodeProtocols {
}
@Override // HAServiceProtocol
+ public synchronized void transitionToObserver(StateChangeRequestInfo req)
+ throws ServiceFailedException, AccessControlException, IOException {
+ checkNNStartup();
+ nn.checkHaStateChange(req);
+ nn.transitionToObserver();
+ }
+
+ @Override // HAServiceProtocol
public synchronized HAServiceStatus getServiceStatus()
throws AccessControlException, ServiceFailedException, IOException {
checkNNStartup();
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/ha/StandbyState.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/ha/StandbyState.java
index 9a21888..ac3e7f7 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/ha/StandbyState.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/ha/StandbyState.java
@@ -39,6 +39,7 @@ import org.apache.hadoop.ipc.StandbyException;
*/
@InterfaceAudience.Private
public class StandbyState extends HAState {
+ // TODO: consider implementing a ObserverState instead of using the flag.
private final boolean isObserver;
public StandbyState() {
@@ -46,21 +47,18 @@ public class StandbyState extends HAState {
}
public StandbyState(boolean isObserver) {
- super(HAServiceState.STANDBY);
+ super(isObserver ? HAServiceState.OBSERVER : HAServiceState.STANDBY);
this.isObserver = isObserver;
}
@Override
public void setState(HAContext context, HAState s) throws ServiceFailedException {
- if (s == NameNode.ACTIVE_STATE) {
+ if (s == NameNode.ACTIVE_STATE ||
+ (!isObserver && s == NameNode.OBSERVER_STATE) ||
+ (isObserver && s == NameNode.STANDBY_STATE)) {
setStateInternal(context, s);
return;
}
- if (isObserver && s == NameNode.STANDBY_STATE) {
- // To guard against the exception in the following super call.
- // The other case, standby -> observer, should not happen.
- return;
- }
super.setState(context, s);
}
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/NNHAServiceTarget.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/NNHAServiceTarget.java
index a598c3d..c4527e5 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/NNHAServiceTarget.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/NNHAServiceTarget.java
@@ -186,4 +186,9 @@ public class NNHAServiceTarget extends HAServiceTarget {
public boolean isAutoFailoverEnabled() {
return autoFailoverEnabled;
}
+
+ @Override
+ public boolean supportObserver() {
+ return true;
+ }
}
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/proto/HdfsServer.proto b/hadoop-hdfs-project/hadoop-hdfs/src/main/proto/HdfsServer.proto
index e50883a..85cfb6c 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/proto/HdfsServer.proto
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/proto/HdfsServer.proto
@@ -212,6 +212,7 @@ message NNHAStatusHeartbeatProto {
enum State {
ACTIVE = 0;
STANDBY = 1;
+ OBSERVER = 2;
}
required State state = 1;
required uint64 txid = 2;
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/tools/TestDFSHAAdmin.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/tools/TestDFSHAAdmin.java
index 528ac4b..dda6f6c 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/tools/TestDFSHAAdmin.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/tools/TestDFSHAAdmin.java
@@ -276,6 +276,12 @@ public class TestDFSHAAdmin {
}
@Test
+ public void testTransitionToObserver() throws Exception {
+ assertEquals(0, runTool("-transitionToObserver", "nn1"));
+ Mockito.verify(mockProtocol).transitionToObserver(anyReqInfo());
+ }
+
+ @Test
public void testFailoverWithNoFencerConfigured() throws Exception {
Mockito.doReturn(STANDBY_READY_RESULT).when(mockProtocol).getServiceStatus();
assertEquals(-1, runTool("-failover", "nn1", "nn2"));
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/tools/TestDFSHAAdminMiniCluster.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/tools/TestDFSHAAdminMiniCluster.java
index dff9866..fc569d0 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/tools/TestDFSHAAdminMiniCluster.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/tools/TestDFSHAAdminMiniCluster.java
@@ -116,6 +116,50 @@ public class TestDFSHAAdminMiniCluster {
assertFalse(nnode2.isStandbyState());
assertEquals(0, runTool("-transitionToStandby", "nn2"));
assertTrue(nnode2.isStandbyState());
+ assertEquals(0, runTool("-transitionToObserver", "nn2"));
+ assertFalse(nnode2.isStandbyState());
+ assertTrue(nnode2.isObserverState());
+ }
+
+ @Test
+ public void testObserverTransition() throws Exception {
+ NameNode nnode1 = cluster.getNameNode(0);
+ assertTrue(nnode1.isStandbyState());
+
+ // Should be able to transition from STANDBY to OBSERVER
+ assertEquals(0, runTool("-transitionToObserver", "nn1"));
+ assertFalse(nnode1.isStandbyState());
+ assertTrue(nnode1.isObserverState());
+
+ // Transition from Observer to Observer should be no-op
+ assertEquals(0, runTool("-transitionToObserver", "nn1"));
+ assertTrue(nnode1.isObserverState());
+
+ // Should also be able to transition back from OBSERVER to STANDBY
+ assertEquals(0, runTool("-transitionToStandby", "nn1"));
+ assertTrue(nnode1.isStandbyState());
+ assertFalse(nnode1.isObserverState());
+ }
+
+ @Test
+ public void testObserverIllegalTransition() throws Exception {
+ NameNode nnode1 = cluster.getNameNode(0);
+ assertTrue(nnode1.isStandbyState());
+ assertEquals(0, runTool("-transitionToActive", "nn1"));
+ assertFalse(nnode1.isStandbyState());
+ assertTrue(nnode1.isActiveState());
+
+ // Should NOT be able to transition from ACTIVE to OBSERVER
+ assertEquals(-1, runTool("-transitionToObserver", "nn1"));
+ assertTrue(nnode1.isActiveState());
+
+ // Should NOT be able to transition from OBSERVER to ACTIVE
+ assertEquals(0, runTool("-transitionToStandby", "nn1"));
+ assertTrue(nnode1.isStandbyState());
+ assertEquals(0, runTool("-transitionToObserver", "nn1"));
+ assertTrue(nnode1.isObserverState());
+ assertEquals(-1, runTool("-transitionToActive", "nn1"));
+ assertFalse(nnode1.isActiveState());
}
@Test
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/AdminService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/AdminService.java
index 880741a..e97a13b 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/AdminService.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/AdminService.java
@@ -362,6 +362,13 @@ public class AdminService extends CompositeService implements
}
}
+ @Override
+ public synchronized void transitionToObserver(
+ StateChangeRequestInfo reqInfo) throws IOException {
+ // Should NOT get here, as RMHAServiceTarget doesn't support observer.
+ throw new ServiceFailedException("Does not support transition to Observer");
+ }
+
/**
* Return the HA status of this RM. This includes the current state and
* whether the RM is ready to become active.
---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org