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 to...@apache.org on 2012/04/11 07:40:28 UTC
svn commit: r1324566 - in
/hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common: ./
src/main/java/org/apache/hadoop/ha/
src/main/java/org/apache/hadoop/ha/protocolPB/ src/main/proto/
src/test/java/org/apache/hadoop/ha/
Author: todd
Date: Wed Apr 11 05:40:26 2012
New Revision: 1324566
URL: http://svn.apache.org/viewvc?rev=1324566&view=rev
Log:
HADOOP-8247. Add a config to enable auto-HA, which disables manual FailoverController. Contributed by Todd Lipcon.
Modified:
hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/CHANGES.HDFS-3042.txt
hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/FailoverController.java
hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAAdmin.java
hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocol.java
hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocolHelper.java
hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceTarget.java
hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/ZKFailoverController.java
hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolClientSideTranslatorPB.java
hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolServerSideTranslatorPB.java
hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/proto/HAServiceProtocol.proto
hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/DummyHAService.java
hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestFailoverController.java
hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestZKFailoverController.java
Modified: hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/CHANGES.HDFS-3042.txt
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/CHANGES.HDFS-3042.txt?rev=1324566&r1=1324565&r2=1324566&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/CHANGES.HDFS-3042.txt (original)
+++ hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/CHANGES.HDFS-3042.txt Wed Apr 11 05:40:26 2012
@@ -17,3 +17,5 @@ HADOOP-8257. TestZKFailoverControllerStr
HADOOP-8260. Replace ClientBaseWithFixes with our own modified copy of the class (todd)
HADOOP-8246. Auto-HA: automatically scope znode by nameservice ID (todd)
+
+HADOOP-8247. Add a config to enable auto-HA, which disables manual FailoverController (todd)
Modified: hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/FailoverController.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/FailoverController.java?rev=1324566&r1=1324565&r2=1324566&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/FailoverController.java (original)
+++ hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/FailoverController.java Wed Apr 11 05:40:26 2012
@@ -27,6 +27,8 @@ import org.apache.hadoop.classification.
import org.apache.hadoop.conf.Configuration;
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.ipc.RPC;
import com.google.common.base.Preconditions;
@@ -48,9 +50,12 @@ public class FailoverController {
private final Configuration conf;
+ private final RequestSource requestSource;
- public FailoverController(Configuration conf) {
+ public FailoverController(Configuration conf,
+ RequestSource source) {
this.conf = conf;
+ this.requestSource = source;
this.gracefulFenceTimeout = getGracefulFenceTimeout(conf);
this.rpcTimeoutToNewActive = getRpcTimeoutToNewActive(conf);
@@ -100,7 +105,7 @@ public class FailoverController {
toSvcStatus = toSvc.getServiceStatus();
} catch (IOException e) {
String msg = "Unable to get service state for " + target;
- LOG.error(msg, e);
+ LOG.error(msg + ": " + e.getLocalizedMessage());
throw new FailoverFailedException(msg, e);
}
@@ -122,7 +127,7 @@ public class FailoverController {
}
try {
- HAServiceProtocolHelper.monitorHealth(toSvc);
+ HAServiceProtocolHelper.monitorHealth(toSvc, createReqInfo());
} catch (HealthCheckFailedException hce) {
throw new FailoverFailedException(
"Can't failover to an unhealthy service", hce);
@@ -132,7 +137,10 @@ public class FailoverController {
}
}
-
+ private StateChangeRequestInfo createReqInfo() {
+ return new StateChangeRequestInfo(requestSource);
+ }
+
/**
* Try to get the HA state of the node at the given address. This
* function is guaranteed to be "quick" -- ie it has a short timeout
@@ -143,7 +151,7 @@ public class FailoverController {
HAServiceProtocol proxy = null;
try {
proxy = svc.getProxy(conf, gracefulFenceTimeout);
- proxy.transitionToStandby();
+ proxy.transitionToStandby(createReqInfo());
return true;
} catch (ServiceFailedException sfe) {
LOG.warn("Unable to gracefully make " + svc + " standby (" +
@@ -198,7 +206,8 @@ public class FailoverController {
Throwable cause = null;
try {
HAServiceProtocolHelper.transitionToActive(
- toSvc.getProxy(conf, rpcTimeoutToNewActive));
+ toSvc.getProxy(conf, rpcTimeoutToNewActive),
+ createReqInfo());
} catch (ServiceFailedException sfe) {
LOG.error("Unable to make " + toSvc + " active (" +
sfe.getMessage() + "). Failing back.");
Modified: hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAAdmin.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAAdmin.java?rev=1324566&r1=1324565&r2=1324566&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAAdmin.java (original)
+++ hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAAdmin.java Wed Apr 11 05:40:26 2012
@@ -19,11 +19,11 @@ package org.apache.hadoop.ha;
import java.io.IOException;
import java.io.PrintStream;
+import java.util.Arrays;
import java.util.Map;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.ParseException;
import org.apache.commons.logging.Log;
@@ -33,6 +33,8 @@ 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.StateChangeRequestInfo;
+import org.apache.hadoop.ha.HAServiceProtocol.RequestSource;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
@@ -49,6 +51,13 @@ public abstract class HAAdmin extends Co
private static final String FORCEFENCE = "forcefence";
private static final String FORCEACTIVE = "forceactive";
+
+ /**
+ * Undocumented flag which allows an administrator to use manual failover
+ * state transitions even when auto-failover is enabled. This is an unsafe
+ * operation, which is why it is not documented in the usage below.
+ */
+ private static final String FORCEMANUAL = "forcemanual";
private static final Log LOG = LogFactory.getLog(HAAdmin.class);
private int rpcTimeoutForChecks = -1;
@@ -79,6 +88,7 @@ public abstract class HAAdmin extends Co
/** Output stream for errors, for use in tests */
protected PrintStream errOut = System.err;
PrintStream out = System.out;
+ private RequestSource requestSource = RequestSource.REQUEST_BY_USER;
protected abstract HAServiceTarget resolveTarget(String string);
@@ -106,63 +116,83 @@ public abstract class HAAdmin extends Co
errOut.println("Usage: HAAdmin [" + cmd + " " + usage.args + "]");
}
- private int transitionToActive(final String[] argv)
+ private int transitionToActive(final CommandLine cmd)
throws IOException, ServiceFailedException {
- if (argv.length != 2) {
+ String[] argv = cmd.getArgs();
+ if (argv.length != 1) {
errOut.println("transitionToActive: incorrect number of arguments");
printUsage(errOut, "-transitionToActive");
return -1;
}
-
- HAServiceProtocol proto = resolveTarget(argv[1]).getProxy(
+ HAServiceTarget target = resolveTarget(argv[0]);
+ if (!checkManualStateManagementOK(target)) {
+ return -1;
+ }
+ HAServiceProtocol proto = target.getProxy(
getConf(), 0);
- HAServiceProtocolHelper.transitionToActive(proto);
+ HAServiceProtocolHelper.transitionToActive(proto, createReqInfo());
return 0;
}
- private int transitionToStandby(final String[] argv)
+ private int transitionToStandby(final CommandLine cmd)
throws IOException, ServiceFailedException {
- if (argv.length != 2) {
+ String[] argv = cmd.getArgs();
+ if (argv.length != 1) {
errOut.println("transitionToStandby: incorrect number of arguments");
printUsage(errOut, "-transitionToStandby");
return -1;
}
- HAServiceProtocol proto = resolveTarget(argv[1]).getProxy(
+ HAServiceTarget target = resolveTarget(argv[0]);
+ if (!checkManualStateManagementOK(target)) {
+ return -1;
+ }
+ HAServiceProtocol proto = target.getProxy(
getConf(), 0);
- HAServiceProtocolHelper.transitionToStandby(proto);
+ HAServiceProtocolHelper.transitionToStandby(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
+ * failover controllers should be doing state management, and it is generally
+ * an error to use the HAAdmin command line to do so.
+ *
+ * @param target the target to check
+ * @return true if manual state management is allowed
+ */
+ private boolean checkManualStateManagementOK(HAServiceTarget target) {
+ if (target.isAutoFailoverEnabled()) {
+ if (requestSource != RequestSource.REQUEST_BY_USER_FORCED) {
+ errOut.println(
+ "Automatic failover is enabled for " + target + "\n" +
+ "Refusing to manually manage HA state, since it may cause\n" +
+ "a split-brain scenario or other incorrect state.\n" +
+ "If you are very sure you know what you are doing, please \n" +
+ "specify the " + FORCEMANUAL + " flag.");
+ return false;
+ } else {
+ LOG.warn("Proceeding with manual HA state management even though\n" +
+ "automatic failover is enabled for " + target);
+ return true;
+ }
+ }
+ return true;
+ }
- private int failover(final String[] argv)
- throws IOException, ServiceFailedException {
- boolean forceFence = false;
- boolean forceActive = false;
-
- Options failoverOpts = new Options();
- // "-failover" isn't really an option but we need to add
- // it to appease CommandLineParser
- failoverOpts.addOption("failover", false, "failover");
- failoverOpts.addOption(FORCEFENCE, false, "force fencing");
- failoverOpts.addOption(FORCEACTIVE, false, "force failover");
+ private StateChangeRequestInfo createReqInfo() {
+ return new StateChangeRequestInfo(requestSource);
+ }
- CommandLineParser parser = new GnuParser();
- CommandLine cmd;
+ private int failover(CommandLine cmd)
+ throws IOException, ServiceFailedException {
+ boolean forceFence = cmd.hasOption(FORCEFENCE);
+ boolean forceActive = cmd.hasOption(FORCEACTIVE);
- try {
- cmd = parser.parse(failoverOpts, argv);
- forceFence = cmd.hasOption(FORCEFENCE);
- forceActive = cmd.hasOption(FORCEACTIVE);
- } catch (ParseException pe) {
- errOut.println("failover: incorrect arguments");
- printUsage(errOut, "-failover");
- return -1;
- }
-
int numOpts = cmd.getOptions() == null ? 0 : cmd.getOptions().length;
final String[] args = cmd.getArgs();
- if (numOpts > 2 || args.length != 2) {
+ if (numOpts > 3 || args.length != 2) {
errOut.println("failover: incorrect arguments");
printUsage(errOut, "-failover");
return -1;
@@ -171,7 +201,13 @@ public abstract class HAAdmin extends Co
HAServiceTarget fromNode = resolveTarget(args[0]);
HAServiceTarget toNode = resolveTarget(args[1]);
- FailoverController fc = new FailoverController(getConf());
+ if (!checkManualStateManagementOK(fromNode) ||
+ !checkManualStateManagementOK(toNode)) {
+ return -1;
+ }
+
+ FailoverController fc = new FailoverController(getConf(),
+ requestSource);
try {
fc.failover(fromNode, toNode, forceFence, forceActive);
@@ -183,18 +219,18 @@ public abstract class HAAdmin extends Co
return 0;
}
- private int checkHealth(final String[] argv)
+ private int checkHealth(final CommandLine cmd)
throws IOException, ServiceFailedException {
- if (argv.length != 2) {
+ String[] argv = cmd.getArgs();
+ if (argv.length != 1) {
errOut.println("checkHealth: incorrect number of arguments");
printUsage(errOut, "-checkHealth");
return -1;
}
-
- HAServiceProtocol proto = resolveTarget(argv[1]).getProxy(
+ HAServiceProtocol proto = resolveTarget(argv[0]).getProxy(
getConf(), rpcTimeoutForChecks);
try {
- HAServiceProtocolHelper.monitorHealth(proto);
+ HAServiceProtocolHelper.monitorHealth(proto, createReqInfo());
} catch (HealthCheckFailedException e) {
errOut.println("Health check failed: " + e.getLocalizedMessage());
return -1;
@@ -202,15 +238,16 @@ public abstract class HAAdmin extends Co
return 0;
}
- private int getServiceState(final String[] argv)
+ private int getServiceState(final CommandLine cmd)
throws IOException, ServiceFailedException {
- if (argv.length != 2) {
+ String[] argv = cmd.getArgs();
+ if (argv.length != 1) {
errOut.println("getServiceState: incorrect number of arguments");
printUsage(errOut, "-getServiceState");
return -1;
}
- HAServiceProtocol proto = resolveTarget(argv[1]).getProxy(
+ HAServiceProtocol proto = resolveTarget(argv[0]).getProxy(
getConf(), rpcTimeoutForChecks);
out.println(proto.getServiceStatus().getState());
return 0;
@@ -263,26 +300,101 @@ public abstract class HAAdmin extends Co
printUsage(errOut);
return -1;
}
+
+ if (!USAGE.containsKey(cmd)) {
+ errOut.println(cmd.substring(1) + ": Unknown command");
+ printUsage(errOut);
+ return -1;
+ }
+
+ Options opts = new Options();
+
+ // Add command-specific options
+ if ("-failover".equals(cmd)) {
+ addFailoverCliOpts(opts);
+ }
+ // Mutative commands take FORCEMANUAL option
+ if ("-transitionToActive".equals(cmd) ||
+ "-transitionToStandby".equals(cmd) ||
+ "-failover".equals(cmd)) {
+ opts.addOption(FORCEMANUAL, false,
+ "force manual control even if auto-failover is enabled");
+ }
+
+ CommandLine cmdLine = parseOpts(cmd, opts, argv);
+ if (cmdLine == null) {
+ // error already printed
+ return -1;
+ }
+
+ if (cmdLine.hasOption(FORCEMANUAL)) {
+ if (!confirmForceManual()) {
+ LOG.fatal("Aborted");
+ return -1;
+ }
+ // Instruct the NNs to honor this request even if they're
+ // configured for manual failover.
+ requestSource = RequestSource.REQUEST_BY_USER_FORCED;
+ }
if ("-transitionToActive".equals(cmd)) {
- return transitionToActive(argv);
+ return transitionToActive(cmdLine);
} else if ("-transitionToStandby".equals(cmd)) {
- return transitionToStandby(argv);
+ return transitionToStandby(cmdLine);
} else if ("-failover".equals(cmd)) {
- return failover(argv);
+ return failover(cmdLine);
} else if ("-getServiceState".equals(cmd)) {
- return getServiceState(argv);
+ return getServiceState(cmdLine);
} else if ("-checkHealth".equals(cmd)) {
- return checkHealth(argv);
+ return checkHealth(cmdLine);
} else if ("-help".equals(cmd)) {
return help(argv);
} else {
- errOut.println(cmd.substring(1) + ": Unknown command");
- printUsage(errOut);
- return -1;
+ // we already checked command validity above, so getting here
+ // would be a coding error
+ throw new AssertionError("Should not get here, command: " + cmd);
}
}
+ private boolean confirmForceManual() throws IOException {
+ return ToolRunner.confirmPrompt(
+ "You have specified the " + FORCEMANUAL + " flag. This flag is " +
+ "dangerous, as it can induce a split-brain scenario that WILL " +
+ "CORRUPT your HDFS namespace, possibly irrecoverably.\n" +
+ "\n" +
+ "It is recommended not to use this flag, but instead to shut down the " +
+ "cluster and disable automatic failover if you prefer to manually " +
+ "manage your HA state.\n" +
+ "\n" +
+ "You may abort safely by answering 'n' or hitting ^C now.\n" +
+ "\n" +
+ "Are you sure you want to continue?");
+ }
+
+ /**
+ * Add CLI options which are specific to the failover command and no
+ * others.
+ */
+ private void addFailoverCliOpts(Options failoverOpts) {
+ failoverOpts.addOption(FORCEFENCE, false, "force fencing");
+ failoverOpts.addOption(FORCEACTIVE, false, "force failover");
+ // Don't add FORCEMANUAL, since that's added separately for all commands
+ // that change state.
+ }
+
+ private CommandLine parseOpts(String cmdName, Options opts, String[] argv) {
+ try {
+ // Strip off the first arg, since that's just the command name
+ argv = Arrays.copyOfRange(argv, 1, argv.length);
+ return new GnuParser().parse(opts, argv);
+ } catch (ParseException pe) {
+ errOut.println(cmdName.substring(1) +
+ ": incorrect arguments");
+ printUsage(errOut, cmdName);
+ return null;
+ }
+ }
+
private int help(String[] argv) {
if (argv.length != 2) {
printUsage(errOut, "-help");
Modified: hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocol.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocol.java?rev=1324566&r1=1324565&r2=1324566&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocol.java (original)
+++ hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocol.java Wed Apr 11 05:40:26 2012
@@ -60,6 +60,31 @@ public interface HAServiceProtocol {
return name;
}
}
+
+ public static enum RequestSource {
+ REQUEST_BY_USER,
+ REQUEST_BY_USER_FORCED,
+ REQUEST_BY_ZKFC;
+ }
+
+ /**
+ * Information describing the source for a request to change state.
+ * This is used to differentiate requests from automatic vs CLI
+ * failover controllers, and in the future may include epoch
+ * information.
+ */
+ public static class StateChangeRequestInfo {
+ private final RequestSource source;
+
+ public StateChangeRequestInfo(RequestSource source) {
+ super();
+ this.source = source;
+ }
+
+ public RequestSource getSource() {
+ return source;
+ }
+ }
/**
* Monitor the health of service. This periodically called by the HA
@@ -95,7 +120,8 @@ public interface HAServiceProtocol {
* @throws IOException
* if other errors happen
*/
- public void transitionToActive() throws ServiceFailedException,
+ public void transitionToActive(StateChangeRequestInfo reqInfo)
+ throws ServiceFailedException,
AccessControlException,
IOException;
@@ -110,7 +136,8 @@ public interface HAServiceProtocol {
* @throws IOException
* if other errors happen
*/
- public void transitionToStandby() throws ServiceFailedException,
+ public void transitionToStandby(StateChangeRequestInfo reqInfo)
+ throws ServiceFailedException,
AccessControlException,
IOException;
Modified: hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocolHelper.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocolHelper.java?rev=1324566&r1=1324565&r2=1324566&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocolHelper.java (original)
+++ hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceProtocolHelper.java Wed Apr 11 05:40:26 2012
@@ -21,6 +21,7 @@ import java.io.IOException;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.ha.HAServiceProtocol.StateChangeRequestInfo;
import org.apache.hadoop.ipc.RemoteException;
/**
@@ -30,7 +31,8 @@ import org.apache.hadoop.ipc.RemoteExcep
@InterfaceAudience.Public
@InterfaceStability.Evolving
public class HAServiceProtocolHelper {
- public static void monitorHealth(HAServiceProtocol svc)
+ public static void monitorHealth(HAServiceProtocol svc,
+ StateChangeRequestInfo reqInfo)
throws IOException {
try {
svc.monitorHealth();
@@ -39,19 +41,21 @@ public class HAServiceProtocolHelper {
}
}
- public static void transitionToActive(HAServiceProtocol svc)
+ public static void transitionToActive(HAServiceProtocol svc,
+ StateChangeRequestInfo reqInfo)
throws IOException {
try {
- svc.transitionToActive();
+ svc.transitionToActive(reqInfo);
} catch (RemoteException e) {
throw e.unwrapRemoteException(ServiceFailedException.class);
}
}
- public static void transitionToStandby(HAServiceProtocol svc)
+ public static void transitionToStandby(HAServiceProtocol svc,
+ StateChangeRequestInfo reqInfo)
throws IOException {
try {
- svc.transitionToStandby();
+ svc.transitionToStandby(reqInfo);
} catch (RemoteException e) {
throw e.unwrapRemoteException(ServiceFailedException.class);
}
Modified: hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceTarget.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceTarget.java?rev=1324566&r1=1324565&r2=1324566&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceTarget.java (original)
+++ hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/HAServiceTarget.java Wed Apr 11 05:40:26 2012
@@ -99,4 +99,11 @@ public abstract class HAServiceTarget {
ret.put(HOST_SUBST_KEY, getAddress().getHostName());
ret.put(PORT_SUBST_KEY, String.valueOf(getAddress().getPort()));
}
+
+ /**
+ * @return true if auto failover should be considered enabled
+ */
+ public boolean isAutoFailoverEnabled() {
+ return false;
+ }
}
Modified: hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/ZKFailoverController.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/ZKFailoverController.java?rev=1324566&r1=1324565&r2=1324566&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/ZKFailoverController.java (original)
+++ hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/ZKFailoverController.java Wed Apr 11 05:40:26 2012
@@ -28,6 +28,8 @@ import org.apache.hadoop.HadoopIllegalAr
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ha.ActiveStandbyElector.ActiveStandbyElectorCallback;
+import org.apache.hadoop.ha.HAServiceProtocol.StateChangeRequestInfo;
+import org.apache.hadoop.ha.HAServiceProtocol.RequestSource;
import org.apache.hadoop.ha.HAZKUtil.ZKAuthInfo;
import org.apache.hadoop.ha.HealthMonitor.State;
import org.apache.hadoop.security.SecurityUtil;
@@ -72,6 +74,8 @@ public abstract class ZKFailoverControll
static final int ERR_CODE_NO_PARENT_ZNODE = 3;
/** Fencing is not properly configured */
static final int ERR_CODE_NO_FENCER = 4;
+ /** Automatic failover is not enabled */
+ static final int ERR_CODE_AUTO_FAILOVER_NOT_ENABLED = 5;
private Configuration conf;
@@ -112,6 +116,12 @@ public abstract class ZKFailoverControll
@Override
public int run(final String[] args) throws Exception {
+ if (!localTarget.isAutoFailoverEnabled()) {
+ LOG.fatal("Automatic failover is not enabled for " + localTarget + "." +
+ " Please ensure that automatic failover is enabled in the " +
+ "configuration before running the ZK failover controller.");
+ return ERR_CODE_AUTO_FAILOVER_NOT_ENABLED;
+ }
loginAsFCUser();
try {
return SecurityUtil.doAsLoginUserOrFatal(new PrivilegedAction<Integer>() {
@@ -300,7 +310,8 @@ public abstract class ZKFailoverControll
LOG.info("Trying to make " + localTarget + " active...");
try {
HAServiceProtocolHelper.transitionToActive(localTarget.getProxy(
- conf, FailoverController.getRpcTimeoutToNewActive(conf)));
+ conf, FailoverController.getRpcTimeoutToNewActive(conf)),
+ createReqInfo());
LOG.info("Successfully transitioned " + localTarget +
" to active state");
} catch (Throwable t) {
@@ -323,12 +334,16 @@ public abstract class ZKFailoverControll
}
}
+ private StateChangeRequestInfo createReqInfo() {
+ return new StateChangeRequestInfo(RequestSource.REQUEST_BY_ZKFC);
+ }
+
private synchronized void becomeStandby() {
LOG.info("ZK Election indicated that " + localTarget +
" should become standby");
try {
int timeout = FailoverController.getGracefulFenceTimeout(conf);
- localTarget.getProxy(conf, timeout).transitionToStandby();
+ localTarget.getProxy(conf, timeout).transitionToStandby(createReqInfo());
LOG.info("Successfully transitioned " + localTarget +
" to standby state");
} catch (Exception e) {
@@ -381,8 +396,8 @@ public abstract class ZKFailoverControll
HAServiceTarget target = dataToTarget(data);
LOG.info("Should fence: " + target);
- boolean gracefulWorked = new FailoverController(conf)
- .tryGracefulFence(target);
+ boolean gracefulWorked = new FailoverController(conf,
+ RequestSource.REQUEST_BY_ZKFC).tryGracefulFence(target);
if (gracefulWorked) {
// It's possible that it's in standby but just about to go into active,
// no? Is there some race here?
Modified: hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolClientSideTranslatorPB.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolClientSideTranslatorPB.java?rev=1324566&r1=1324565&r2=1324566&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolClientSideTranslatorPB.java (original)
+++ hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolClientSideTranslatorPB.java Wed Apr 11 05:40:26 2012
@@ -30,13 +30,14 @@ import org.apache.hadoop.ha.HAServicePro
import org.apache.hadoop.ha.HAServiceStatus;
import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.GetServiceStatusRequestProto;
import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.GetServiceStatusResponseProto;
+import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.HAStateChangeRequestInfoProto;
+import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.HARequestSource;
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.ipc.ProtobufHelper;
import org.apache.hadoop.ipc.ProtobufRpcEngine;
-import org.apache.hadoop.ipc.ProtocolSignature;
import org.apache.hadoop.ipc.ProtocolTranslator;
import org.apache.hadoop.ipc.RPC;
import org.apache.hadoop.security.UserGroupInformation;
@@ -57,10 +58,6 @@ public class HAServiceProtocolClientSide
private final static RpcController NULL_CONTROLLER = null;
private final static MonitorHealthRequestProto MONITOR_HEALTH_REQ =
MonitorHealthRequestProto.newBuilder().build();
- private final static TransitionToActiveRequestProto TRANSITION_TO_ACTIVE_REQ =
- TransitionToActiveRequestProto.newBuilder().build();
- private final static TransitionToStandbyRequestProto TRANSITION_TO_STANDBY_REQ =
- TransitionToStandbyRequestProto.newBuilder().build();
private final static GetServiceStatusRequestProto GET_SERVICE_STATUS_REQ =
GetServiceStatusRequestProto.newBuilder().build();
@@ -94,18 +91,25 @@ public class HAServiceProtocolClientSide
}
@Override
- public void transitionToActive() throws IOException {
+ public void transitionToActive(StateChangeRequestInfo reqInfo) throws IOException {
try {
- rpcProxy.transitionToActive(NULL_CONTROLLER, TRANSITION_TO_ACTIVE_REQ);
+ TransitionToActiveRequestProto req =
+ TransitionToActiveRequestProto.newBuilder()
+ .setReqInfo(convert(reqInfo)).build();
+
+ rpcProxy.transitionToActive(NULL_CONTROLLER, req);
} catch (ServiceException e) {
throw ProtobufHelper.getRemoteException(e);
}
}
@Override
- public void transitionToStandby() throws IOException {
+ public void transitionToStandby(StateChangeRequestInfo reqInfo) throws IOException {
try {
- rpcProxy.transitionToStandby(NULL_CONTROLLER, TRANSITION_TO_STANDBY_REQ);
+ TransitionToStandbyRequestProto req =
+ TransitionToStandbyRequestProto.newBuilder()
+ .setReqInfo(convert(reqInfo)).build();
+ rpcProxy.transitionToStandby(NULL_CONTROLLER, req);
} catch (ServiceException e) {
throw ProtobufHelper.getRemoteException(e);
}
@@ -143,6 +147,27 @@ public class HAServiceProtocolClientSide
}
}
+ private HAStateChangeRequestInfoProto convert(StateChangeRequestInfo reqInfo) {
+ HARequestSource src;
+ switch (reqInfo.getSource()) {
+ case REQUEST_BY_USER:
+ src = HARequestSource.REQUEST_BY_USER;
+ break;
+ case REQUEST_BY_USER_FORCED:
+ src = HARequestSource.REQUEST_BY_USER_FORCED;
+ break;
+ case REQUEST_BY_ZKFC:
+ src = HARequestSource.REQUEST_BY_ZKFC;
+ break;
+ default:
+ throw new IllegalArgumentException("Bad source: " + reqInfo.getSource());
+ }
+ return HAStateChangeRequestInfoProto.newBuilder()
+ .setReqSource(src)
+ .build();
+ }
+
+
@Override
public void close() {
RPC.stopProxy(rpcProxy);
Modified: hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolServerSideTranslatorPB.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolServerSideTranslatorPB.java?rev=1324566&r1=1324565&r2=1324566&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolServerSideTranslatorPB.java (original)
+++ hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/protocolPB/HAServiceProtocolServerSideTranslatorPB.java Wed Apr 11 05:40:26 2012
@@ -19,12 +19,17 @@ package org.apache.hadoop.ha.protocolPB;
import java.io.IOException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.ha.HAServiceProtocol;
+import org.apache.hadoop.ha.HAServiceProtocol.StateChangeRequestInfo;
+import org.apache.hadoop.ha.HAServiceProtocol.RequestSource;
import org.apache.hadoop.ha.HAServiceStatus;
import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.GetServiceStatusRequestProto;
import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.GetServiceStatusResponseProto;
+import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.HAStateChangeRequestInfoProto;
import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.HAServiceStateProto;
import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.MonitorHealthRequestProto;
import org.apache.hadoop.ha.proto.HAServiceProtocolProtos.MonitorHealthResponseProto;
@@ -56,6 +61,8 @@ public class HAServiceProtocolServerSide
TransitionToActiveResponseProto.newBuilder().build();
private static final TransitionToStandbyResponseProto TRANSITION_TO_STANDBY_RESP =
TransitionToStandbyResponseProto.newBuilder().build();
+ private static final Log LOG = LogFactory.getLog(
+ HAServiceProtocolServerSideTranslatorPB.class);
public HAServiceProtocolServerSideTranslatorPB(HAServiceProtocol server) {
this.server = server;
@@ -71,13 +78,33 @@ public class HAServiceProtocolServerSide
throw new ServiceException(e);
}
}
+
+ private StateChangeRequestInfo convert(HAStateChangeRequestInfoProto proto) {
+ RequestSource src;
+ switch (proto.getReqSource()) {
+ case REQUEST_BY_USER:
+ src = RequestSource.REQUEST_BY_USER;
+ break;
+ case REQUEST_BY_USER_FORCED:
+ src = RequestSource.REQUEST_BY_USER_FORCED;
+ break;
+ case REQUEST_BY_ZKFC:
+ src = RequestSource.REQUEST_BY_ZKFC;
+ break;
+ default:
+ LOG.warn("Unknown request source: " + proto.getReqSource());
+ src = null;
+ }
+
+ return new StateChangeRequestInfo(src);
+ }
@Override
public TransitionToActiveResponseProto transitionToActive(
RpcController controller, TransitionToActiveRequestProto request)
throws ServiceException {
try {
- server.transitionToActive();
+ server.transitionToActive(convert(request.getReqInfo()));
return TRANSITION_TO_ACTIVE_RESP;
} catch(IOException e) {
throw new ServiceException(e);
@@ -89,7 +116,7 @@ public class HAServiceProtocolServerSide
RpcController controller, TransitionToStandbyRequestProto request)
throws ServiceException {
try {
- server.transitionToStandby();
+ server.transitionToStandby(convert(request.getReqInfo()));
return TRANSITION_TO_STANDBY_RESP;
} catch(IOException e) {
throw new ServiceException(e);
Modified: hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/proto/HAServiceProtocol.proto
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/proto/HAServiceProtocol.proto?rev=1324566&r1=1324565&r2=1324566&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/proto/HAServiceProtocol.proto (original)
+++ hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/main/proto/HAServiceProtocol.proto Wed Apr 11 05:40:26 2012
@@ -27,6 +27,16 @@ enum HAServiceStateProto {
STANDBY = 2;
}
+enum HARequestSource {
+ REQUEST_BY_USER = 0;
+ REQUEST_BY_USER_FORCED = 1;
+ REQUEST_BY_ZKFC = 2;
+}
+
+message HAStateChangeRequestInfoProto {
+ required HARequestSource reqSource = 1;
+}
+
/**
* void request
*/
@@ -43,6 +53,7 @@ message MonitorHealthResponseProto {
* void request
*/
message TransitionToActiveRequestProto {
+ required HAStateChangeRequestInfoProto reqInfo = 1;
}
/**
@@ -55,6 +66,7 @@ message TransitionToActiveResponseProto
* void request
*/
message TransitionToStandbyRequestProto {
+ required HAStateChangeRequestInfoProto reqInfo = 1;
}
/**
Modified: hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/DummyHAService.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/DummyHAService.java?rev=1324566&r1=1324565&r2=1324566&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/DummyHAService.java (original)
+++ hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/DummyHAService.java Wed Apr 11 05:40:26 2012
@@ -98,6 +98,11 @@ class DummyHAService extends HAServiceTa
}
@Override
+ public boolean isAutoFailoverEnabled() {
+ return true;
+ }
+
+ @Override
public String toString() {
return "DummyHAService #" + index;
}
@@ -118,7 +123,7 @@ class DummyHAService extends HAServiceTa
}
@Override
- public void transitionToActive() throws ServiceFailedException,
+ public void transitionToActive(StateChangeRequestInfo req) throws ServiceFailedException,
AccessControlException, IOException {
checkUnreachable();
if (failToBecomeActive) {
@@ -131,7 +136,7 @@ class DummyHAService extends HAServiceTa
}
@Override
- public void transitionToStandby() throws ServiceFailedException,
+ public void transitionToStandby(StateChangeRequestInfo req) throws ServiceFailedException,
AccessControlException, IOException {
checkUnreachable();
if (sharedResource != null) {
Modified: hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestFailoverController.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestFailoverController.java?rev=1324566&r1=1324565&r2=1324566&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestFailoverController.java (original)
+++ hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestFailoverController.java Wed Apr 11 05:40:26 2012
@@ -27,6 +27,8 @@ import static org.mockito.Mockito.verify
import org.apache.hadoop.conf.Configuration;
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.ha.TestNodeFencer.AlwaysSucceedFencer;
import org.apache.hadoop.ha.TestNodeFencer.AlwaysFailFencer;
import static org.apache.hadoop.ha.TestNodeFencer.setupFencer;
@@ -117,7 +119,8 @@ public class TestFailoverController {
public void testFailoverToUnreadyService() throws Exception {
DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
- Mockito.doReturn(STATE_NOT_READY).when(svc2.proxy).getServiceStatus();
+ Mockito.doReturn(STATE_NOT_READY).when(svc2.proxy)
+ .getServiceStatus();
svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
try {
@@ -161,7 +164,7 @@ public class TestFailoverController {
public void testFailoverFromFaultyServiceSucceeds() throws Exception {
DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
Mockito.doThrow(new ServiceFailedException("Failed!"))
- .when(svc1.proxy).transitionToStandby();
+ .when(svc1.proxy).transitionToStandby(anyReqInfo());
DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
@@ -184,7 +187,7 @@ public class TestFailoverController {
public void testFailoverFromFaultyServiceFencingFailure() throws Exception {
DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
Mockito.doThrow(new ServiceFailedException("Failed!"))
- .when(svc1.proxy).transitionToStandby();
+ .when(svc1.proxy).transitionToStandby(anyReqInfo());
DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
svc1.fencer = svc2.fencer = setupFencer(AlwaysFailFencer.class.getName());
@@ -283,7 +286,7 @@ public class TestFailoverController {
DummyHAService svc1 = spy(new DummyHAService(HAServiceState.ACTIVE, svc1Addr));
DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
Mockito.doThrow(new ServiceFailedException("Failed!"))
- .when(svc2.proxy).transitionToActive();
+ .when(svc2.proxy).transitionToActive(anyReqInfo());
svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
try {
@@ -294,8 +297,8 @@ public class TestFailoverController {
}
// svc1 went standby then back to active
- verify(svc1.proxy).transitionToStandby();
- verify(svc1.proxy).transitionToActive();
+ verify(svc1.proxy).transitionToStandby(anyReqInfo());
+ verify(svc1.proxy).transitionToActive(anyReqInfo());
assertEquals(HAServiceState.ACTIVE, svc1.state);
assertEquals(HAServiceState.STANDBY, svc2.state);
}
@@ -305,7 +308,7 @@ public class TestFailoverController {
DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
Mockito.doThrow(new ServiceFailedException("Failed!"))
- .when(svc2.proxy).transitionToActive();
+ .when(svc2.proxy).transitionToActive(anyReqInfo());
svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
try {
@@ -326,7 +329,7 @@ public class TestFailoverController {
DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
Mockito.doThrow(new ServiceFailedException("Failed!"))
- .when(svc2.proxy).transitionToActive();
+ .when(svc2.proxy).transitionToActive(anyReqInfo());
svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
AlwaysSucceedFencer.fenceCalled = 0;
@@ -345,12 +348,16 @@ public class TestFailoverController {
assertSame(svc2, AlwaysSucceedFencer.fencedSvc);
}
+ private StateChangeRequestInfo anyReqInfo() {
+ return Mockito.<StateChangeRequestInfo>any();
+ }
+
@Test
public void testFailureToFenceOnFailbackFailsTheFailback() throws Exception {
DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
Mockito.doThrow(new IOException("Failed!"))
- .when(svc2.proxy).transitionToActive();
+ .when(svc2.proxy).transitionToActive(anyReqInfo());
svc1.fencer = svc2.fencer = setupFencer(AlwaysFailFencer.class.getName());
AlwaysFailFencer.fenceCalled = 0;
@@ -373,10 +380,10 @@ public class TestFailoverController {
public void testFailbackToFaultyServiceFails() throws Exception {
DummyHAService svc1 = new DummyHAService(HAServiceState.ACTIVE, svc1Addr);
Mockito.doThrow(new ServiceFailedException("Failed!"))
- .when(svc1.proxy).transitionToActive();
+ .when(svc1.proxy).transitionToActive(anyReqInfo());
DummyHAService svc2 = new DummyHAService(HAServiceState.STANDBY, svc2Addr);
Mockito.doThrow(new ServiceFailedException("Failed!"))
- .when(svc2.proxy).transitionToActive();
+ .when(svc2.proxy).transitionToActive(anyReqInfo());
svc1.fencer = svc2.fencer = setupFencer(AlwaysSucceedFencer.class.getName());
@@ -419,7 +426,8 @@ public class TestFailoverController {
private void doFailover(HAServiceTarget tgt1, HAServiceTarget tgt2,
boolean forceFence, boolean forceActive) throws FailoverFailedException {
- FailoverController fc = new FailoverController(conf);
+ FailoverController fc = new FailoverController(conf,
+ RequestSource.REQUEST_BY_USER);
fc.failover(tgt1, tgt2, forceFence, forceActive);
}
Modified: hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestZKFailoverController.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestZKFailoverController.java?rev=1324566&r1=1324565&r2=1324566&view=diff
==============================================================================
--- hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestZKFailoverController.java (original)
+++ hadoop/common/branches/HDFS-3042/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestZKFailoverController.java Wed Apr 11 05:40:26 2012
@@ -24,6 +24,7 @@ import java.security.NoSuchAlgorithmExce
import org.apache.commons.logging.impl.Log4JLogger;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ha.HAServiceProtocol.HAServiceState;
+import org.apache.hadoop.ha.HAServiceProtocol.StateChangeRequestInfo;
import org.apache.hadoop.ha.HealthMonitor.State;
import org.apache.hadoop.ha.MiniZKFCCluster.DummyZKFC;
import org.apache.log4j.Level;
@@ -129,6 +130,22 @@ public class TestZKFailoverController ex
}
/**
+ * Test that automatic failover won't run against a target that hasn't
+ * explicitly enabled the feature.
+ */
+ @Test(timeout=10000)
+ public void testWontRunWhenAutoFailoverDisabled() throws Exception {
+ DummyHAService svc = cluster.getService(1);
+ svc = Mockito.spy(svc);
+ Mockito.doReturn(false).when(svc).isAutoFailoverEnabled();
+
+ assertEquals(ZKFailoverController.ERR_CODE_AUTO_FAILOVER_NOT_ENABLED,
+ runFC(svc, "-formatZK"));
+ assertEquals(ZKFailoverController.ERR_CODE_AUTO_FAILOVER_NOT_ENABLED,
+ runFC(svc));
+ }
+
+ /**
* Test that, if ACLs are specified in the configuration, that
* it sets the ACLs when formatting the parent node.
*/
@@ -279,7 +296,7 @@ public class TestZKFailoverController ex
Mockito.verify(svc1.proxy, Mockito.timeout(2000).atLeastOnce())
- .transitionToActive();
+ .transitionToActive(Mockito.<StateChangeRequestInfo>any());
cluster.waitForHAState(0, HAServiceState.STANDBY);
cluster.waitForHAState(1, HAServiceState.STANDBY);