YARN-593. container launch on Windows does not correctly populate classpath with new process's environment variables and localized resources (Chris Nauroth via bikas)
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1469998 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7c66645417
commit
edcfd4527c
|
@ -37,6 +37,10 @@ Trunk - Unreleased
|
||||||
YARN-493. Fixed some shell related flaws in YARN on Windows. (Chris Nauroth
|
YARN-493. Fixed some shell related flaws in YARN on Windows. (Chris Nauroth
|
||||||
via vinodkv)
|
via vinodkv)
|
||||||
|
|
||||||
|
YARN-593. container launch on Windows does not correctly populate
|
||||||
|
classpath with new process's environment variables and localized resources
|
||||||
|
(Chris Nauroth via bikas)
|
||||||
|
|
||||||
BREAKDOWN OF HADOOP-8562 SUBTASKS
|
BREAKDOWN OF HADOOP-8562 SUBTASKS
|
||||||
|
|
||||||
YARN-158. Yarn creating package-info.java must not depend on sh.
|
YARN-158. Yarn creating package-info.java must not depend on sh.
|
||||||
|
|
|
@ -28,6 +28,7 @@ import java.io.OutputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
@ -211,7 +212,7 @@ public class ContainerLaunch implements Callable<Integer> {
|
||||||
FINAL_CONTAINER_TOKENS_FILE).toUri().getPath());
|
FINAL_CONTAINER_TOKENS_FILE).toUri().getPath());
|
||||||
|
|
||||||
// Sanitize the container's environment
|
// Sanitize the container's environment
|
||||||
sanitizeEnv(environment, containerWorkDir, appDirs);
|
sanitizeEnv(environment, containerWorkDir, appDirs, localResources);
|
||||||
|
|
||||||
// Write out the environment
|
// Write out the environment
|
||||||
writeLaunchEnv(containerScriptOutStream, environment, localResources,
|
writeLaunchEnv(containerScriptOutStream, environment, localResources,
|
||||||
|
@ -506,9 +507,17 @@ public class ContainerLaunch implements Callable<Integer> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void link(Path src, Path dst) throws IOException {
|
protected void link(Path src, Path dst) throws IOException {
|
||||||
line(String.format("@%s symlink \"%s\" \"%s\"", Shell.WINUTILS,
|
File srcFile = new File(src.toUri().getPath());
|
||||||
new File(dst.toString()).getPath(),
|
String srcFileStr = srcFile.getPath();
|
||||||
new File(src.toUri().getPath()).getPath()));
|
String dstFileStr = new File(dst.toString()).getPath();
|
||||||
|
// If not on Java7+ on Windows, then copy file instead of symlinking.
|
||||||
|
// See also FileUtil#symLink for full explanation.
|
||||||
|
if (!Shell.isJava7OrAbove() && srcFile.isFile()) {
|
||||||
|
line(String.format("@copy \"%s\" \"%s\"", srcFileStr, dstFileStr));
|
||||||
|
} else {
|
||||||
|
line(String.format("@%s symlink \"%s\" \"%s\"", Shell.WINUTILS,
|
||||||
|
dstFileStr, srcFileStr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -532,7 +541,8 @@ public class ContainerLaunch implements Callable<Integer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sanitizeEnv(Map<String, String> environment,
|
public void sanitizeEnv(Map<String, String> environment,
|
||||||
Path pwd, List<Path> appDirs) throws IOException {
|
Path pwd, List<Path> appDirs, Map<Path, List<String>> resources)
|
||||||
|
throws IOException {
|
||||||
/**
|
/**
|
||||||
* Non-modifiable environment variables
|
* Non-modifiable environment variables
|
||||||
*/
|
*/
|
||||||
|
@ -566,16 +576,6 @@ public class ContainerLaunch implements Callable<Integer> {
|
||||||
environment.put("JVM_PID", "$$");
|
environment.put("JVM_PID", "$$");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove Windows check and use this approach on all platforms after
|
|
||||||
// additional testing. See YARN-358.
|
|
||||||
if (Shell.WINDOWS) {
|
|
||||||
String inputClassPath = environment.get(Environment.CLASSPATH.name());
|
|
||||||
if (inputClassPath != null && !inputClassPath.isEmpty()) {
|
|
||||||
environment.put(Environment.CLASSPATH.name(),
|
|
||||||
FileUtil.createJarWithClassPath(inputClassPath, pwd));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modifiable environment variables
|
* Modifiable environment variables
|
||||||
*/
|
*/
|
||||||
|
@ -594,6 +594,57 @@ public class ContainerLaunch implements Callable<Integer> {
|
||||||
YarnConfiguration.NM_ADMIN_USER_ENV,
|
YarnConfiguration.NM_ADMIN_USER_ENV,
|
||||||
YarnConfiguration.DEFAULT_NM_ADMIN_USER_ENV)
|
YarnConfiguration.DEFAULT_NM_ADMIN_USER_ENV)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TODO: Remove Windows check and use this approach on all platforms after
|
||||||
|
// additional testing. See YARN-358.
|
||||||
|
if (Shell.WINDOWS) {
|
||||||
|
String inputClassPath = environment.get(Environment.CLASSPATH.name());
|
||||||
|
if (inputClassPath != null && !inputClassPath.isEmpty()) {
|
||||||
|
StringBuilder newClassPath = new StringBuilder(inputClassPath);
|
||||||
|
|
||||||
|
// Localized resources do not exist at the desired paths yet, because the
|
||||||
|
// container launch script has not run to create symlinks yet. This
|
||||||
|
// means that FileUtil.createJarWithClassPath can't automatically expand
|
||||||
|
// wildcards to separate classpath entries for each file in the manifest.
|
||||||
|
// To resolve this, append classpath entries explicitly for each
|
||||||
|
// resource.
|
||||||
|
for (Map.Entry<Path,List<String>> entry : resources.entrySet()) {
|
||||||
|
boolean targetIsDirectory = new File(entry.getKey().toUri().getPath())
|
||||||
|
.isDirectory();
|
||||||
|
|
||||||
|
for (String linkName : entry.getValue()) {
|
||||||
|
// Append resource.
|
||||||
|
newClassPath.append(File.pathSeparator).append(pwd.toString())
|
||||||
|
.append(Path.SEPARATOR).append(linkName);
|
||||||
|
|
||||||
|
// FileUtil.createJarWithClassPath must use File.toURI to convert
|
||||||
|
// each file to a URI to write into the manifest's classpath. For
|
||||||
|
// directories, the classpath must have a trailing '/', but
|
||||||
|
// File.toURI only appends the trailing '/' if it is a directory that
|
||||||
|
// already exists. To resolve this, add the classpath entries with
|
||||||
|
// explicit trailing '/' here for any localized resource that targets
|
||||||
|
// a directory. Then, FileUtil.createJarWithClassPath will guarantee
|
||||||
|
// that the resulting entry in the manifest's classpath will have a
|
||||||
|
// trailing '/', and thus refer to a directory instead of a file.
|
||||||
|
if (targetIsDirectory) {
|
||||||
|
newClassPath.append(Path.SEPARATOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the container launches, it takes the parent process's environment
|
||||||
|
// and then adds/overwrites with the entries from the container launch
|
||||||
|
// context. Do the same thing here for correct substitution of
|
||||||
|
// environment variables in the classpath jar manifest.
|
||||||
|
Map<String, String> mergedEnv = new HashMap<String, String>(
|
||||||
|
System.getenv());
|
||||||
|
mergedEnv.putAll(environment);
|
||||||
|
|
||||||
|
String classPathJar = FileUtil.createJarWithClassPath(
|
||||||
|
newClassPath.toString(), pwd, mergedEnv);
|
||||||
|
environment.put(Environment.CLASSPATH.name(), classPathJar);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeLaunchEnv(OutputStream out,
|
static void writeLaunchEnv(OutputStream out,
|
||||||
|
|
Loading…
Reference in New Issue