diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java index ead9977..c1024ea 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java @@ -1675,6 +1675,12 @@ public static boolean isAclEnabled(Configuration conf) { public static final String NM_CONTAINER_LOCALIZER_JAVA_OPTS_DEFAULT = "-Xmx256m"; + /** The log level of container localizer process. */ + public static final String NM_CONTAINER_LOCALIZER_LOG_LEVEL= + NM_PREFIX + "container-localizer.log.level"; + public static final String NM_CONTAINER_LOCALIZER_LOG_LEVEL_DEFAULT = + "INFO"; + /** Prefix for runtime configuration constants. */ public static final String LINUX_CONTAINER_RUNTIME_PREFIX = NM_PREFIX + "runtime.linux."; diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java index e8c46a2..5e98cb3 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java @@ -33,6 +33,7 @@ import org.apache.hadoop.yarn.exceptions.ConfigurationException; import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container; import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.ContainerDiagnosticsUpdateEvent; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperation; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperationException; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperationExecutor; @@ -382,6 +383,10 @@ public void startLocalizer(LocalizerStartContext ctx) List localizerArgs = new ArrayList<>(); buildMainArgs(localizerArgs, user, appId, locId, nmAddr, localDirs); + + Path containerLogDir = getContaierLogDir(dirsHandler, appId, locId); + localizerArgs = replaceWithContainerLogDir(localizerArgs, containerLogDir); + initializeContainerOp.appendArgs(localizerArgs); try { @@ -402,6 +407,27 @@ public void startLocalizer(LocalizerStartContext ctx) } } + private List replaceWithContainerLogDir(List commands, + Path containerLogDir) { + List newCmds = new ArrayList<>(commands.size()); + + for (String item : commands) { + newCmds.add(item.replace(ApplicationConstants.LOG_DIR_EXPANSION_VAR, + containerLogDir.toString())); + } + + return newCmds; + } + + private Path getContaierLogDir(LocalDirsHandlerService dirsHandler, + String appId, String containerId) throws IOException { + String relativeContainerLogDir = ContainerLaunch + .getRelativeContainerLogDir(appId, containerId); + + return dirsHandler.getLogPathForWrite(relativeContainerLogDir, + false); + } + /** * Set up the {@link ContainerLocalizer}. * @@ -417,7 +443,7 @@ public void startLocalizer(LocalizerStartContext ctx) public void buildMainArgs(List command, String user, String appId, String locId, InetSocketAddress nmAddr, List localDirs) { ContainerLocalizer.buildMainArgs(command, user, appId, locId, nmAddr, - localDirs); + localDirs, super.getConf()); } @Override diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/WindowsSecureContainerExecutor.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/WindowsSecureContainerExecutor.java index 7c124c3..e934472 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/WindowsSecureContainerExecutor.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/WindowsSecureContainerExecutor.java @@ -702,7 +702,7 @@ public void startLocalizer(LocalizerStartContext ctx) throws IOException, command.addAll(ContainerLocalizer.getJavaOpts(getConf())); ContainerLocalizer.buildMainArgs(command, user, appId, locId, nmAddr, - localDirs); + localDirs, super.getConf()); String cmdLine = StringUtils.join(command, " "); diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/localizer/ContainerLocalizer.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/localizer/ContainerLocalizer.java index 2378c45..541911a 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/localizer/ContainerLocalizer.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/localizer/ContainerLocalizer.java @@ -63,6 +63,8 @@ import org.apache.hadoop.util.Shell; import org.apache.hadoop.util.concurrent.HadoopExecutors; import org.apache.hadoop.yarn.YarnUncaughtExceptionHandler; +import org.apache.hadoop.yarn.exceptions.YarnRuntimeException; +import org.apache.hadoop.yarn.api.ApplicationConstants; import org.apache.hadoop.yarn.api.records.LocalResource; import org.apache.hadoop.yarn.api.records.LocalResourceVisibility; import org.apache.hadoop.yarn.api.records.SerializedException; @@ -408,8 +410,12 @@ private LocalizerStatus createStatus() throws InterruptedException { */ public static void buildMainArgs(List command, String user, String appId, String locId, - InetSocketAddress nmAddr, List localDirs) { - + InetSocketAddress nmAddr, List localDirs, Configuration conf) { + + String logLevel = conf.get(YarnConfiguration. + NM_CONTAINER_LOCALIZER_LOG_LEVEL, + YarnConfiguration.NM_CONTAINER_LOCALIZER_LOG_LEVEL_DEFAULT); + addLog4jSystemProperties(logLevel, command); command.add(ContainerLocalizer.class.getName()); command.add(user); command.add(appId); @@ -421,6 +427,16 @@ public static void buildMainArgs(List command, } } + private static void addLog4jSystemProperties( + String logLevel, List command) { + command.add("-Dlog4j.configuration=container-log4j.properties"); + command.add("-D" + YarnConfiguration.YARN_APP_CONTAINER_LOG_DIR + "=" + + ApplicationConstants.LOG_DIR_EXPANSION_VAR); + command.add("-D" + YarnConfiguration.YARN_APP_CONTAINER_LOG_SIZE + "=0"); + command.add("-Dhadoop.root.logger=" + logLevel + ",CLA"); + command.add("-Dhadoop.root.logfile=container-localizer-syslog"); + } + public static void main(String[] argv) throws Throwable { Thread.setDefaultUncaughtExceptionHandler(new YarnUncaughtExceptionHandler()); int nRet = 0; @@ -431,6 +447,7 @@ public static void main(String[] argv) throws Throwable { // MKDIR $x/$user/appcache/$appid/filecache // LOAD $x/$user/appcache/$appid/appTokens try { + createLogDir(); String user = argv[0]; String appId = argv[1]; String locId = argv[2]; @@ -466,6 +483,31 @@ public static void main(String[] argv) throws Throwable { } } + /** + * Create the log directory, if the directory exists, make sure its permission + * is 750. + */ + private static void createLogDir() { + FileContext localFs; + try { + localFs = FileContext.getLocalFSFileContext(new Configuration()); + + String logDir = System.getProperty( + YarnConfiguration.YARN_APP_CONTAINER_LOG_DIR); + + if (logDir != null && !logDir.trim().isEmpty()) { + Path containerLogPath = new Path(logDir); + FsPermission containerLogDirPerm= new FsPermission((short)0750); + localFs.mkdir(containerLogPath, containerLogDirPerm, true); + // set permission again to make sure the permission is correct + // in case the directory is already there. + localFs.setPermission(containerLogPath, containerLogDirPerm); + } + } catch (IOException e) { + throw new YarnRuntimeException("Unable to create the log dir", e); + } + } + private static void initDirs(Configuration conf, String user, String appId, FileContext lfs, List localDirs) throws IOException { if (null == localDirs || 0 == localDirs.size()) { diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutorWithMocks.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutorWithMocks.java index e1d9c69..d1ab267 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutorWithMocks.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutorWithMocks.java @@ -269,7 +269,7 @@ public void testStartLocalizer() throws IOException { .build()); List result=readMockParams(); - Assert.assertEquals(result.size(), 19); + Assert.assertEquals(result.size(), 24); Assert.assertEquals(result.get(0), YarnConfiguration.DEFAULT_NM_NONSECURE_MODE_LOCAL_USER); Assert.assertEquals(result.get(1), "test"); Assert.assertEquals(result.get(2), "0" ); diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/localizer/TestContainerLocalizer.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/localizer/TestContainerLocalizer.java index 17eee82..7b66658 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/localizer/TestContainerLocalizer.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/localizer/TestContainerLocalizer.java @@ -18,6 +18,7 @@ package org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer; import static junit.framework.TestCase.assertFalse; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; @@ -675,4 +676,23 @@ public void testUserCacheDirPermission() throws Exception { lfs.getFileStatus(destDirPath.getParent().getParent()).getPermission()); } + @Test + public void testBuildMainArg() { + List command = new ArrayList<>(); + List dirs = new ArrayList<>(); + dirs.add("/yarn/nm"); + ContainerLocalizer.buildMainArgs(command, appUser, appId, containerId, + nmAddr, dirs, new Configuration()); + assertEquals("[-Dlog4j.configuration=container-log4j.properties," + + " -Dyarn.app.container.log.dir=," + + " -Dyarn.app.container.log.filesize=0," + + " -Dhadoop.root.logger=INFO,CLA," + + " -Dhadoop.root.logfile=container-localizer-syslog," + + " org.apache.hadoop.yarn.server.nodemanager.containermanager." + + "localizer.ContainerLocalizer" + + ", " + appUser + ", " + appId + ", " + containerId + ", " + + nmAddr.getHostName() + ", " + nmAddr.getPort() + ", /yarn/nm]", + command.toString()); + } + }