HADOOP-9524. Fix ShellCommandFencer to work on Windows. Contributed by Arpit Agarwal.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1476856 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Suresh Srinivas 2013-04-28 23:16:47 +00:00
parent ae393ab26e
commit 293fb1ec1e
3 changed files with 29 additions and 8 deletions

View File

@ -528,6 +528,9 @@ Trunk (Unreleased)
HADOOP-9490. LocalFileSystem#reportChecksumFailure not closing the HADOOP-9490. LocalFileSystem#reportChecksumFailure not closing the
checksum file handle before rename. (Ivan Mitic via suresh) checksum file handle before rename. (Ivan Mitic via suresh)
HADOOP-9524. Fix ShellCommandFencer to work on Windows.
(Arpit Agarwal via suresh)
Release 2.0.5-beta - UNRELEASED Release 2.0.5-beta - UNRELEASED

View File

@ -26,6 +26,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configured; import org.apache.hadoop.conf.Configured;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import org.apache.hadoop.util.Shell;
/** /**
* Fencing method that runs a shell command. It should be specified * Fencing method that runs a shell command. It should be specified
@ -33,8 +34,8 @@ import com.google.common.annotations.VisibleForTesting;
* <code> * <code>
* shell(/path/to/my/script.sh arg1 arg2 ...) * shell(/path/to/my/script.sh arg1 arg2 ...)
* </code><br> * </code><br>
* The string between '(' and ')' is passed directly to a bash shell and * The string between '(' and ')' is passed directly to a bash shell
* may not include any closing parentheses.<p> * (cmd.exe on Windows) and may not include any closing parentheses.<p>
* *
* The shell command will be run with an environment set up to contain * The shell command will be run with an environment set up to contain
* all of the current Hadoop configuration variables, with the '_' character * all of the current Hadoop configuration variables, with the '_' character
@ -58,11 +59,11 @@ public class ShellCommandFencer
/** Prefix for target parameters added to the environment */ /** Prefix for target parameters added to the environment */
private static final String TARGET_PREFIX = "target_"; private static final String TARGET_PREFIX = "target_";
@VisibleForTesting @VisibleForTesting
static Log LOG = LogFactory.getLog( static Log LOG = LogFactory.getLog(
ShellCommandFencer.class); ShellCommandFencer.class);
@Override @Override
public void checkArgs(String args) throws BadFencingConfigurationException { public void checkArgs(String args) throws BadFencingConfigurationException {
if (args == null || args.isEmpty()) { if (args == null || args.isEmpty()) {
@ -74,8 +75,14 @@ public class ShellCommandFencer
@Override @Override
public boolean tryFence(HAServiceTarget target, String cmd) { public boolean tryFence(HAServiceTarget target, String cmd) {
ProcessBuilder builder = new ProcessBuilder( ProcessBuilder builder;
"bash", "-e", "-c", cmd);
if (!Shell.WINDOWS) {
builder = new ProcessBuilder("bash", "-e", "-c", cmd);
} else {
builder = new ProcessBuilder("cmd.exe", "/c", cmd);
}
setConfAsEnvVars(builder.environment()); setConfAsEnvVars(builder.environment());
addTargetInfoAsEnvVars(target, builder.environment()); addTargetInfoAsEnvVars(target, builder.environment());

View File

@ -24,6 +24,7 @@ import java.util.List;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured; import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.util.Shell;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
@ -33,7 +34,12 @@ import com.google.common.collect.Lists;
public class TestNodeFencer { public class TestNodeFencer {
private HAServiceTarget MOCK_TARGET; private HAServiceTarget MOCK_TARGET;
// Fencer shell commands that always return true on Unix and Windows
// respectively. Lacking the POSIX 'true' command on Windows, we use
// the batch command 'rem'.
private static String FENCER_TRUE_COMMAND_UNIX = "shell(true)";
private static String FENCER_TRUE_COMMAND_WINDOWS = "shell(rem)";
@Before @Before
public void clearMockState() { public void clearMockState() {
@ -48,6 +54,11 @@ public class TestNodeFencer {
.when(MOCK_TARGET).getAddress(); .when(MOCK_TARGET).getAddress();
} }
private static String getFencerTrueCommand() {
return Shell.WINDOWS ?
FENCER_TRUE_COMMAND_WINDOWS : FENCER_TRUE_COMMAND_UNIX;
}
@Test @Test
public void testSingleFencer() throws BadFencingConfigurationException { public void testSingleFencer() throws BadFencingConfigurationException {
NodeFencer fencer = setupFencer( NodeFencer fencer = setupFencer(
@ -100,7 +111,7 @@ public class TestNodeFencer {
@Test @Test
public void testShortNameShell() throws BadFencingConfigurationException { public void testShortNameShell() throws BadFencingConfigurationException {
NodeFencer fencer = setupFencer("shell(true)"); NodeFencer fencer = setupFencer(getFencerTrueCommand());
assertTrue(fencer.fence(MOCK_TARGET)); assertTrue(fencer.fence(MOCK_TARGET));
} }