diff --git a/hadoop-mapreduce-project/CHANGES.txt b/hadoop-mapreduce-project/CHANGES.txt index d2aba338d9f..74f25008f67 100644 --- a/hadoop-mapreduce-project/CHANGES.txt +++ b/hadoop-mapreduce-project/CHANGES.txt @@ -91,6 +91,9 @@ Release 0.23.1 - Unreleased MAPREDUCE-3331. Improvement to single node cluster setup documentation for 0.23 (Anupam Seth via mahadev) + MAPREDUCE-3102. Changed NodeManager to fail fast when LinuxContainerExecutor + has wrong configuration or permissions. (Hitesh Shah via vinodkv) + OPTIMIZATIONS BUG FIXES diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java index 3122592209b..6c3667ae5f9 100644 --- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java @@ -62,6 +62,13 @@ public abstract class ContainerExecutor implements Configurable { return conf; } + /** + * Run the executor initialization steps. + * Verify that the necessary configs, permissions are in place. + * @throws IOException + */ + public abstract void init() throws IOException; + /** * Prepare the environment for containers in this application to execute. * For $x in local.dirs diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/DefaultContainerExecutor.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/DefaultContainerExecutor.java index f3a3a224fee..9c252b142d4 100644 --- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/DefaultContainerExecutor.java +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/DefaultContainerExecutor.java @@ -69,6 +69,11 @@ public class DefaultContainerExecutor extends ContainerExecutor { this.lfs = lfs; } + @Override + public void init() throws IOException { + // nothing to do or verify here + } + @Override public void startLocalizer(Path nmPrivateContainerTokensPath, InetSocketAddress nmAddr, String user, String appId, String locId, diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java index a3cb8d77ab9..2ecf2b302e3 100644 --- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java @@ -100,6 +100,29 @@ public class LinuxContainerExecutor extends ContainerExecutor { : conf.get(YarnConfiguration.NM_LINUX_CONTAINER_EXECUTOR_PATH, defaultPath); } + @Override + public void init() throws IOException { + // Send command to executor which will just start up, + // verify configuration/permissions and exit + List command = new ArrayList( + Arrays.asList(containerExecutorExe, + "--checksetup")); + String[] commandArray = command.toArray(new String[command.size()]); + ShellCommandExecutor shExec = new ShellCommandExecutor(commandArray); + if (LOG.isDebugEnabled()) { + LOG.debug("checkLinuxExecutorSetup: " + Arrays.toString(commandArray)); + } + try { + shExec.execute(); + } catch (ExitCodeException e) { + int exitCode = shExec.getExitCode(); + LOG.warn("Exit code from container is : " + exitCode); + logOutput(shExec.getOutput()); + throw new IOException("Linux container executor not configured properly" + + " (error=" + exitCode + ")", e); + } + } + @Override public void startLocalizer(Path nmPrivateContainerTokensPath, InetSocketAddress nmAddr, String user, String appId, String locId, diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeManager.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeManager.java index 319d5a04c82..94971d365e7 100644 --- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeManager.java +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/NodeManager.java @@ -110,6 +110,11 @@ public class NodeManager extends CompositeService implements ContainerExecutor exec = ReflectionUtils.newInstance( conf.getClass(YarnConfiguration.NM_CONTAINER_EXECUTOR, DefaultContainerExecutor.class, ContainerExecutor.class), conf); + try { + exec.init(); + } catch (IOException e) { + throw new YarnException("Failed to initialize container executor", e); + } DeletionService del = new DeletionService(exec); addService(del); diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/launcher/ContainerLaunch.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/launcher/ContainerLaunch.java index 37a7966d156..f7fd522f811 100644 --- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/launcher/ContainerLaunch.java +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/launcher/ContainerLaunch.java @@ -302,10 +302,12 @@ public class ContainerLaunch implements Callable { // by this time, it will never be launched exec.deactivateContainer(containerId); - LOG.debug("Getting pid for container " + containerIdStr + " to kill" - + " from pid file " - + (pidFilePath != null ? pidFilePath.toString() : "null")); - + if (LOG.isDebugEnabled()) { + LOG.debug("Getting pid for container " + containerIdStr + " to kill" + + " from pid file " + + (pidFilePath != null ? pidFilePath.toString() : "null")); + } + // however the container process may have already started try { diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c index 6e62ef9100f..40fbad83653 100644 --- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c @@ -38,12 +38,15 @@ #endif void display_usage(FILE *stream) { + fprintf(stream, + "Usage: container-executor --checksetup\n"); fprintf(stream, "Usage: container-executor user command command-args\n"); fprintf(stream, "Commands:\n"); fprintf(stream, " initialize container: %2d appid tokens cmd app...\n", INITIALIZE_CONTAINER); - fprintf(stream, " launch container: %2d appid containerid workdir container-script tokens\n", + fprintf(stream, + " launch container: %2d appid containerid workdir container-script tokens pidfile\n", LAUNCH_CONTAINER); fprintf(stream, " signal container: %2d container-pid signal\n", SIGNAL_CONTAINER); @@ -52,14 +55,31 @@ void display_usage(FILE *stream) { } int main(int argc, char **argv) { - //Minimum number of arguments required to run the container-executor + int invalid_args = 0; + int do_check_setup = 0; + + LOGFILE = stdout; + ERRORFILE = stderr; + + // Minimum number of arguments required to run + // the std. container-executor commands is 4 + // 4 args not needed for checksetup option if (argc < 4) { + invalid_args = 1; + if (argc == 2) { + const char *arg1 = argv[1]; + if (strcmp("--checksetup", arg1) == 0) { + invalid_args = 0; + do_check_setup = 1; + } + } + } + + if (invalid_args != 0) { display_usage(stdout); return INVALID_ARGUMENT_NUMBER; } - LOGFILE = stdout; - ERRORFILE = stderr; int command; const char * app_id = NULL; const char * container_id = NULL; @@ -111,11 +131,19 @@ int main(int argc, char **argv) { return INVALID_CONTAINER_EXEC_PERMISSIONS; } + if (do_check_setup != 0) { + // basic setup checks done + // verified configs available and valid + // verified executor permissions + return 0; + } + //checks done for user name if (argv[optind] == NULL) { fprintf(ERRORFILE, "Invalid user name.\n"); return INVALID_USER_NAME; } + int ret = set_user(argv[optind]); if (ret != 0) { return ret; @@ -143,7 +171,7 @@ int main(int argc, char **argv) { break; case LAUNCH_CONTAINER: if (argc < 9) { - fprintf(ERRORFILE, "Too few arguments (%d vs 8) for launch container\n", + fprintf(ERRORFILE, "Too few arguments (%d vs 9) for launch container\n", argc); fflush(ERRORFILE); return INVALID_ARGUMENT_NUMBER; diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestNodeManager.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestNodeManager.java new file mode 100644 index 00000000000..98fabe1c5d0 --- /dev/null +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestNodeManager.java @@ -0,0 +1,55 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package org.apache.hadoop.yarn.server.nodemanager; + +import static org.junit.Assert.fail; + +import java.io.IOException; + +import org.apache.hadoop.yarn.YarnException; +import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.junit.Test; + +public class TestNodeManager { + + public static final class InvalidContainerExecutor extends + DefaultContainerExecutor { + @Override + public void init() throws IOException { + throw new IOException("dummy executor init called"); + } + } + + @Test + public void testContainerExecutorInitCall() { + NodeManager nm = new NodeManager(); + YarnConfiguration conf = new YarnConfiguration(); + conf.setClass(YarnConfiguration.NM_CONTAINER_EXECUTOR, + InvalidContainerExecutor.class, + ContainerExecutor.class); + try { + nm.init(conf); + fail("Init should fail"); + } catch (YarnException e) { + //PASS + assert(e.getCause().getMessage().contains("dummy executor init called")); + } + } + +}