Author: kihwal
Date: Wed May 14 20:46:38 2014
New Revision: 1594710
URL: http://svn.apache.org/r1594710
Log:
svn merge -c 1594709 merging from trunk to branch-2 to fix:HDFS-2949. Add check
to active state transition to prevent operator-induced split brain. Contributed
by Rushabh S Shah.
Modified:
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAAdmin.java
Modified:
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAAdmin.java
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAAdmin.java?rev=1594710&r1=1594709&r2=1594710&view=diff
==============================================================================
---
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAAdmin.java
(original)
+++
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAAdmin.java
Wed May 14 20:46:38 2014
@@ -20,6 +20,7 @@ package org.apache.hadoop.ha;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Map;
import org.apache.commons.cli.Options;
@@ -33,6 +34,7 @@ import org.apache.hadoop.classification.
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.CommonConfigurationKeys;
+import org.apache.hadoop.ha.HAServiceProtocol.HAServiceState;
import org.apache.hadoop.ha.HAServiceProtocol.StateChangeRequestInfo;
import org.apache.hadoop.ha.HAServiceProtocol.RequestSource;
import org.apache.hadoop.util.Tool;
@@ -66,7 +68,7 @@ public abstract class HAAdmin extends Co
protected final static Map<String, UsageInfo> USAGE =
ImmutableMap.<String, UsageInfo>builder()
.put("-transitionToActive",
- new UsageInfo("<serviceId>", "Transitions the service into Active
state"))
+ new UsageInfo(" <serviceId> [--"+FORCEACTIVE+"]", "Transitions the
service into Active state"))
.put("-transitionToStandby",
new UsageInfo("<serviceId>", "Transitions the service into Standby
state"))
.put("-failover",
@@ -100,6 +102,10 @@ public abstract class HAAdmin extends Co
}
protected abstract HAServiceTarget resolveTarget(String string);
+
+ protected Collection<String> getTargetIds(String targetNodeToActivate) {
+ return Arrays.asList(new String[]{targetNodeToActivate});
+ }
protected String getUsageString() {
return "Usage: HAAdmin";
@@ -133,6 +139,11 @@ public abstract class HAAdmin extends Co
printUsage(errOut, "-transitionToActive");
return -1;
}
+ /* returns true if other target node is active or some exception occurred
+ and forceActive was not set */
+ if(isOtherTargetNodeActive(argv[0], cmd.hasOption(FORCEACTIVE))) {
+ return -1;
+ }
HAServiceTarget target = resolveTarget(argv[0]);
if (!checkManualStateManagementOK(target)) {
return -1;
@@ -142,7 +153,48 @@ public abstract class HAAdmin extends Co
HAServiceProtocolHelper.transitionToActive(proto, createReqInfo());
return 0;
}
-
+
+ /**
+ * Checks whether other target node is active or not
+ * @param targetNodeToActivate
+ * @return true if other target node is active or some other exception
+ * occurred and forceActive was set otherwise false
+ * @throws IOException
+ */
+ private boolean isOtherTargetNodeActive(String targetNodeToActivate, boolean
forceActive)
+ throws IOException {
+ Collection<String> targetIds = getTargetIds(targetNodeToActivate);
+ if(targetIds == null) {
+ errOut.println("transitionToActive: No target node in the "
+ + "current configuration");
+ printUsage(errOut, "-transitionToActive");
+ return true;
+ }
+ targetIds.remove(targetNodeToActivate);
+ for(String targetId : targetIds) {
+ HAServiceTarget target = resolveTarget(targetId);
+ if (!checkManualStateManagementOK(target)) {
+ return true;
+ }
+ try {
+ HAServiceProtocol proto = target.getProxy(getConf(), 5000);
+ if(proto.getServiceStatus().getState() == HAServiceState.ACTIVE) {
+ errOut.println("transitionToActive: Node " + targetId +" is already
active");
+ printUsage(errOut, "-transitionToActive");
+ return true;
+ }
+ } catch (Exception e) {
+ //If forceActive switch is false then return true
+ if(!forceActive) {
+ errOut.println("Unexpected error occurred " + e.getMessage());
+ printUsage(errOut, "-transitionToActive");
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
private int transitionToStandby(final CommandLine cmd)
throws IOException, ServiceFailedException {
String[] argv = cmd.getArgs();
@@ -364,6 +416,9 @@ public abstract class HAAdmin extends Co
if ("-failover".equals(cmd)) {
addFailoverCliOpts(opts);
}
+ if("-transitionToActive".equals(cmd)) {
+ addTransitionToActiveCliOpts(opts);
+ }
// Mutative commands take FORCEMANUAL option
if ("-transitionToActive".equals(cmd) ||
"-transitionToStandby".equals(cmd) ||
@@ -433,6 +488,14 @@ public abstract class HAAdmin extends Co
// that change state.
}
+ /**
+ * Add CLI options which are specific to the transitionToActive command and
+ * no others.
+ */
+ private void addTransitionToActiveCliOpts(Options transitionToActiveCliOpts)
{
+ transitionToActiveCliOpts.addOption(FORCEACTIVE, false, "force active");
+ }
+
private CommandLine parseOpts(String cmdName, Options opts, String[] argv) {
try {
// Strip off the first arg, since that's just the command name