YARN-8776. Implement Container Exec feature in LinuxContainerExecutor. Contributed by Eric Yang
Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/1f9c4f32 Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/1f9c4f32 Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/1f9c4f32 Branch: refs/heads/YARN-7402 Commit: 1f9c4f32e842529be5980e395587f135452372bb Parents: 18fe65d Author: Billie Rinaldi <bil...@apache.org> Authored: Mon Nov 12 10:41:45 2018 -0800 Committer: Billie Rinaldi <bil...@apache.org> Committed: Mon Nov 12 10:42:30 2018 -0800 ---------------------------------------------------------------------- .../server/nodemanager/ContainerExecutor.java | 2 +- .../nodemanager/LinuxContainerExecutor.java | 31 +++++----- .../linux/privileged/PrivilegedOperation.java | 1 + .../privileged/PrivilegedOperationExecutor.java | 57 +++++++++++++++++- .../runtime/DefaultLinuxContainerRuntime.java | 8 +++ .../DelegatingLinuxContainerRuntime.java | 10 ++++ .../runtime/DockerLinuxContainerRuntime.java | 45 ++++++++++++++ .../linux/runtime/docker/DockerExecCommand.java | 62 ++++++++++++++++++++ .../runtime/ContainerRuntime.java | 14 ++++- .../executor/ContainerExecContext.java | 11 ++-- .../webapp/ContainerShellWebSocket.java | 49 ++++++++++++---- .../server/nodemanager/webapp/WebServer.java | 1 + .../impl/container-executor.c | 9 ++- .../nodemanager/TestContainerExecutor.java | 3 +- .../nodemanager/TestLinuxContainerExecutor.java | 4 +- .../runtime/MockLinuxContainerRuntime.java | 9 +++ .../TestContainersMonitorResourceChange.java | 2 + 17 files changed, 275 insertions(+), 43 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java index 6024dbf..77b7859 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java @@ -38,7 +38,6 @@ import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import org.apache.hadoop.hdfs.protocol.datatransfer.IOStreamPair; -import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerExecContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,6 +58,7 @@ import org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.Conta import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerExecutionException; import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerPrepareContext; import org.apache.hadoop.yarn.server.nodemanager.util.NodeManagerHardwareUtils; +import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerExecContext; import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerLivenessContext; import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerReacquisitionContext; import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerReapContext; http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java index 0282f58..db2fed9 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java @@ -62,15 +62,10 @@ import org.apache.hadoop.yarn.server.nodemanager.executor.LocalizerStartContext; import org.apache.hadoop.yarn.server.nodemanager.util.CgroupsLCEResourcesHandler; import org.apache.hadoop.yarn.server.nodemanager.util.DefaultLCEResourcesHandler; import org.apache.hadoop.yarn.server.nodemanager.util.LCEResourcesHandler; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.io.OutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.InetSocketAddress; -import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -801,20 +796,22 @@ public class LinuxContainerExecutor extends ContainerExecutor { @Override public IOStreamPair execContainer(ContainerExecContext ctx) throws ContainerExecutionException { - // TODO: calls PrivilegedOperationExecutor and return IOStream pairs - InputStream in = null; - OutputStream out = null; - int byteSize = 4000; + IOStreamPair res; try { - in = new ByteArrayInputStream( - "This is input command".getBytes(Charset.forName("UTF-8"))); - out = new ByteArrayOutputStream(byteSize); - } catch (IllegalArgumentException e) { - LOG.error("Failed to execute command to container runtime", e); + res = linuxContainerRuntime.execContainer(ctx); + } catch (ContainerExecutionException e) { + int retCode = e.getExitCode(); + if (retCode != 0) { + return new IOStreamPair(null, null); + } + LOG.warn("Error in executing container interactive shell" + + ctx + " exit = " + retCode, e); + logOutput(e.getOutput()); + throw new ContainerExecutionException( + "Error in executing container interactive shel" + ctx.getContainer() + .getContainerId().toString() + " exit = " + retCode); } - IOStreamPair pair = new IOStreamPair(in, out); - System.out.println(pair); - return new IOStreamPair(in, out); + return res; } @Override http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/privileged/PrivilegedOperation.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/privileged/PrivilegedOperation.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/privileged/PrivilegedOperation.java index f199662..b4c8fb8 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/privileged/PrivilegedOperation.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/privileged/PrivilegedOperation.java @@ -44,6 +44,7 @@ public class PrivilegedOperation { INITIALIZE_CONTAINER(""), //no CLI switch supported yet LAUNCH_CONTAINER(""), //no CLI switch supported yet SIGNAL_CONTAINER(""), //no CLI switch supported yet + EXEC_CONTAINER("--run-docker"), //no CLI switch supported yet DELETE_AS_USER(""), //no CLI switch supported yet LAUNCH_DOCKER_CONTAINER(""), //no CLI switch supported yet TC_MODIFY_STATE("--tc-modify-state"), http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/privileged/PrivilegedOperationExecutor.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/privileged/PrivilegedOperationExecutor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/privileged/PrivilegedOperationExecutor.java index 76949ff..d3e96d8 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/privileged/PrivilegedOperationExecutor.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/privileged/PrivilegedOperationExecutor.java @@ -20,8 +20,8 @@ package org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged; -import com.google.common.annotations.VisibleForTesting; import org.apache.commons.lang3.StringUtils; +import org.apache.hadoop.hdfs.protocol.datatransfer.IOStreamPair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.hadoop.classification.InterfaceAudience; @@ -34,6 +34,8 @@ import org.apache.hadoop.yarn.conf.YarnConfiguration; import java.io.File; import java.io.IOException; +import java.io.OutputStream; +import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -207,6 +209,59 @@ public class PrivilegedOperationExecutor { false); } + /** + * + * @param prefixCommands + * @param operation + * @return stdin and stdout of container exec + * @throws PrivilegedOperationException + */ + public IOStreamPair executePrivilegedInteractiveOperation( + List<String> prefixCommands, PrivilegedOperation operation) + throws PrivilegedOperationException, InterruptedException { + String[] fullCommandArray = getPrivilegedOperationExecutionCommand( + prefixCommands, operation); + ProcessBuilder pb = new ProcessBuilder(fullCommandArray); + OutputStream stdin; + InputStream stdout; + try { + pb.redirectErrorStream(true); + Process p = pb.start(); + stdin = p.getOutputStream(); + stdout = p.getInputStream(); + + if (LOG.isDebugEnabled()) { + LOG.debug("command array:"); + LOG.debug(Arrays.toString(fullCommandArray)); + } + } catch (ExitCodeException e) { + if (operation.isFailureLoggingEnabled()) { + StringBuilder logBuilder = new StringBuilder( + "Interactive Shell execution returned exit code: ") + .append(e.getExitCode()) + .append(". Privileged Interactive Operation Stderr: ") + .append(System.lineSeparator()) + .append(e.getMessage()) + .append(System.lineSeparator()); + logBuilder.append("Full command array for failed execution: ") + .append(System.lineSeparator()); + logBuilder.append(Arrays.toString(fullCommandArray)); + + LOG.warn(logBuilder.toString()); + } + + //stderr from shell executor seems to be stuffed into the exception + //'message' - so, we have to extract it and set it as the error out + throw new PrivilegedOperationException(e, e.getExitCode(), + pb.redirectError().toString(), e.getMessage()); + } catch (IOException e) { + LOG.warn("IOException executing command: ", e); + throw new PrivilegedOperationException(e); + } + + return new IOStreamPair(stdout, stdin); + } + //Utility functions for squashing together operations in supported ways //At some point, we need to create a generalized mechanism that uses a set //of squashing 'rules' to squash an set of PrivilegedOperations of varying http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DefaultLinuxContainerRuntime.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DefaultLinuxContainerRuntime.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DefaultLinuxContainerRuntime.java index b4cead2..837db62 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DefaultLinuxContainerRuntime.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DefaultLinuxContainerRuntime.java @@ -24,6 +24,7 @@ import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hdfs.protocol.datatransfer.IOStreamPair; import org.apache.hadoop.util.StringUtils; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.server.nodemanager.ContainerExecutor; @@ -36,6 +37,7 @@ import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.Contai import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerRuntime; import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerRuntimeConstants; import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerRuntimeContext; +import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerExecContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -194,4 +196,10 @@ public class DefaultLinuxContainerRuntime implements LinuxContainerRuntime { public String[] getIpAndHost(Container container) { return ContainerExecutor.getLocalIpAndHost(container); } + + @Override + public IOStreamPair execContainer(ContainerExecContext containerExecContext) + throws ContainerExecutionException { + throw new ContainerExecutionException("Unsupported operation."); + } } http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DelegatingLinuxContainerRuntime.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DelegatingLinuxContainerRuntime.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DelegatingLinuxContainerRuntime.java index 7199b54..28b2039 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DelegatingLinuxContainerRuntime.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DelegatingLinuxContainerRuntime.java @@ -24,6 +24,7 @@ import com.google.common.annotations.VisibleForTesting; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hdfs.protocol.datatransfer.IOStreamPair; import org.apache.hadoop.util.ReflectionUtils; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.server.nodemanager.Context; @@ -32,6 +33,7 @@ import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileg import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerExecutionException; import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerRuntime; import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerRuntimeContext; +import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerExecContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -229,4 +231,12 @@ public class DelegatingLinuxContainerRuntime implements LinuxContainerRuntime { return runtimeType != null && allowedRuntimes.contains( runtimeType.toUpperCase()); } + + @Override + public IOStreamPair execContainer(ContainerExecContext ctx) + throws ContainerExecutionException { + Container container = ctx.getContainer(); + LinuxContainerRuntime runtime = pickContainerRuntime(container); + return runtime.execContainer(ctx); + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java index 2cfa9c5..83460fc 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java @@ -21,12 +21,14 @@ package org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime; import com.google.common.annotations.VisibleForTesting; +import org.apache.hadoop.hdfs.protocol.datatransfer.IOStreamPair; import org.apache.hadoop.security.Credentials; import org.apache.hadoop.yarn.api.ApplicationConstants.Environment; import org.apache.hadoop.yarn.api.records.ContainerId; import org.apache.hadoop.yarn.server.nodemanager.Context; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerCommand; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerCommandExecutor; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerExecCommand; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerKillCommand; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerRmCommand; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerStartCommand; @@ -62,6 +64,7 @@ import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.Contai import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerRuntime; import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerRuntimeConstants; import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerRuntimeContext; +import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerExecContext; import java.io.File; import java.io.IOException; @@ -1144,6 +1147,48 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime { } } + /** + * Perform docker exec command into running container + * + * @param ctx container exec context + * @return IOStreams of docker exec + * @throws ContainerExecutionException + */ + @Override + public IOStreamPair execContainer(ContainerExecContext ctx) + throws ContainerExecutionException { + String containerId = ctx.getContainer().getContainerId().toString(); + DockerExecCommand dockerExecCommand = new DockerExecCommand(containerId); + dockerExecCommand.setInteractive(); + dockerExecCommand.setTTY(); + List<String> command = new ArrayList<String>(); + command.add("bash"); + dockerExecCommand.setOverrideCommandWithArgs(command); + String commandFile = dockerClient.writeCommandToTempFile(dockerExecCommand, + ContainerId.fromString(containerId), nmContext); + PrivilegedOperation privOp = new PrivilegedOperation( + PrivilegedOperation.OperationType.EXEC_CONTAINER); + privOp.appendArgs(commandFile); + privOp.disableFailureLogging(); + + IOStreamPair output; + try { + output = + privilegedOperationExecutor.executePrivilegedInteractiveOperation( + null, privOp); + LOG.info("ContainerId=" + containerId + ", docker exec output for " + + dockerExecCommand + ": " + output); + } catch (PrivilegedOperationException e) { + throw new ContainerExecutionException( + "Execute container interactive shell failed", e.getExitCode(), + e.getOutput(), e.getErrorOutput()); + } catch (InterruptedException ie) { + LOG.warn("InterruptedException executing command: ", ie); + throw new ContainerExecutionException(ie.getMessage()); + } + return output; + } + // ipAndHost[0] contains comma separated list of IPs // ipAndHost[1] contains the hostname. http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerExecCommand.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerExecCommand.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerExecCommand.java new file mode 100644 index 0000000..7ab6f4d --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerExecCommand.java @@ -0,0 +1,62 @@ +/* + * 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.containermanager.linux.runtime.docker; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Encapsulates the docker exec command and its command + * line arguments. + */ +public class DockerExecCommand extends DockerCommand { + private static final String EXEC_COMMAND = "exec"; + private final Map<String, String> userEnv; + + public DockerExecCommand(String containerId) { + super(EXEC_COMMAND); + super.addCommandArguments("name", containerId); + this.userEnv = new LinkedHashMap<String, String>(); + } + + public DockerExecCommand setInteractive() { + super.addCommandArguments("interactive", "true"); + return this; + } + + public DockerExecCommand setTTY() { + super.addCommandArguments("tty", "true"); + return this; + } + + public DockerExecCommand setOverrideCommandWithArgs( + List<String> overrideCommandWithArgs) { + for(String override: overrideCommandWithArgs) { + super.addCommandArguments("launch-command", override); + } + return this; + } + + @Override + public Map<String, List<String>> getDockerCommandWithArguments() { + return super.getDockerCommandWithArguments(); + } + +} http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/runtime/ContainerRuntime.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/runtime/ContainerRuntime.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/runtime/ContainerRuntime.java index 01995d9..91f9aa4 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/runtime/ContainerRuntime.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/runtime/ContainerRuntime.java @@ -22,7 +22,9 @@ package org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; +import org.apache.hadoop.hdfs.protocol.datatransfer.IOStreamPair; import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container; +import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerExecContext; /** * An abstraction for various container runtime implementations. Examples @@ -86,7 +88,17 @@ public interface ContainerRuntime { throws ContainerExecutionException; /** - * Return the host and ip of the container + * Run a program in container. + * + * @param ctx the {@link ContainerExecContext} + * @return stdin and stdout of container exec + * @throws ContainerExecutionException + */ + IOStreamPair execContainer(ContainerExecContext ctx) + throws ContainerExecutionException; + + /** + * Return the host and ip of the container. * * @param container the {@link Container} * @throws ContainerExecutionException if an error occurs while getting the ip http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/executor/ContainerExecContext.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/executor/ContainerExecContext.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/executor/ContainerExecContext.java index 4e6c6ec..dbc1a2d 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/executor/ContainerExecContext.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/executor/ContainerExecContext.java @@ -22,6 +22,7 @@ package org.apache.hadoop.yarn.server.nodemanager.executor; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container; /** * Encapsulates information required for starting/launching containers. @@ -32,7 +33,7 @@ import org.apache.hadoop.classification.InterfaceStability; public final class ContainerExecContext { private final String user; private final String appId; - private final String container; + private final Container container; /** * Builder for ContainerExecContext. @@ -40,13 +41,13 @@ public final class ContainerExecContext { public static final class Builder { private String user; private String appId; - private String container; + private Container container; public Builder() { } - public Builder setContainer(String container) { - this.container = container; + public Builder setContainer(Container c) { + this.container = c; return this; } @@ -79,7 +80,7 @@ public final class ContainerExecContext { return this.appId; } - public String getContainerId() { + public Container getContainer() { return this.container; } } http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/ContainerShellWebSocket.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/ContainerShellWebSocket.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/ContainerShellWebSocket.java index ea61b57..4d74a14 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/ContainerShellWebSocket.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/ContainerShellWebSocket.java @@ -24,8 +24,10 @@ import java.nio.charset.Charset; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; +import org.apache.hadoop.yarn.api.records.ContainerId; +import org.apache.hadoop.yarn.server.nodemanager.Context; import org.apache.hadoop.yarn.server.nodemanager.ContainerExecutor; -import org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container; import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerExecContext; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; @@ -47,31 +49,43 @@ import org.slf4j.LoggerFactory; public class ContainerShellWebSocket { private static final Logger LOG = LoggerFactory.getLogger(ContainerShellWebSocket.class); + private static Context nmContext; - private final ContainerExecutor exec = new LinuxContainerExecutor(); - + private final ContainerExecutor exec; private IOStreamPair pair; + public ContainerShellWebSocket() { + exec = nmContext.getContainerExecutor(); + } + + public static void init(Context nm) { + ContainerShellWebSocket.nmContext = nm; + } + @OnWebSocketMessage public void onText(Session session, String message) throws IOException { - LOG.info("Message received: " + message); try { byte[] buffer = new byte[4000]; if (session.isOpen()) { - int ni = message.length(); - if (ni > 0) { - pair.out.write(message.getBytes(Charset.forName("UTF-8"))); - pair.out.flush(); + if (!message.equals("1{}")) { + // Send keystroke to process input + byte[] payload; + payload = message.getBytes(Charset.forName("UTF-8")); + if (payload != null) { + pair.out.write(payload); + pair.out.flush(); + } } + // Render process output int no = pair.in.available(); pair.in.read(buffer, 0, Math.min(no, buffer.length)); String formatted = new String(buffer, Charset.forName("UTF-8")) .replaceAll("\n", "\r\n"); session.getRemote().sendString(formatted); } - } catch (Exception e) { - LOG.error("Failed to parse WebSocket message from Client", e); + } catch (IOException e) { + onClose(session, 1001, "Shutdown"); } } @@ -84,12 +98,14 @@ public class ContainerShellWebSocket { URI containerURI = session.getUpgradeRequest().getRequestURI(); String[] containerPath = containerURI.getPath().split("/"); String cId = containerPath[2]; + Container container = nmContext.getContainers().get(ContainerId + .fromString(cId)); LOG.info( "Making interactive connection to running docker container with ID: " + cId); ContainerExecContext execContext = new ContainerExecContext .Builder() - .setContainer(cId) + .setContainer(container) .build(); pair = exec.execContainer(execContext); } catch (Exception e) { @@ -100,7 +116,14 @@ public class ContainerShellWebSocket { @OnWebSocketClose public void onClose(Session session, int status, String reason) { - LOG.info(session.getRemoteAddress().getHostString() + " closed!"); + try { + LOG.info(session.getRemoteAddress().getHostString() + " closed!"); + pair.in.close(); + pair.out.close(); + } catch (IOException e) { + } finally { + session.close(); + } } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/WebServer.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/WebServer.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/WebServer.java index 3476aeb..84c5d08 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/WebServer.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/WebServer.java @@ -99,6 +99,7 @@ public class WebServer extends AbstractService { targets.add(AuthenticationFilterInitializer.class.getName()); conf.set(filterInitializerConfKey, StringUtils.join(",", targets)); } + ContainerShellWebSocket.init(nmContext); LOG.info("Instantiating NMWebApp at " + bindAddress); try { this.webApp = http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c index e2130ab..a22b9fa 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c @@ -1485,8 +1485,13 @@ int run_docker_with_pty(const char *command_file) { } } else { if (rc < 0) { - fprintf(stderr, "Error %d on read master PTY\n", errno); - exit(DOCKER_EXEC_FAILED); + if (errno==5) { + fprintf(stderr, "Remote Connection Closed.\n"); + exit(0); + } else { + fprintf(stderr, "Error %d on read master PTY\n", errno); + exit(DOCKER_EXEC_FAILED); + } } } } http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestContainerExecutor.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestContainerExecutor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestContainerExecutor.java index aafdc31..c9f35c6 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestContainerExecutor.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestContainerExecutor.java @@ -181,9 +181,10 @@ public class TestContainerExecutor { @Test public void testExecContainer() throws Exception { + Container container = mock(Container.class); try { ContainerExecContext.Builder builder = new ContainerExecContext.Builder(); - builder.setUser("foo").setAppId("app1").setContainer("container1"); + builder.setUser("foo").setAppId("app1").setContainer(container); ContainerExecContext ctx = builder.build(); containerExecutor.execContainer(ctx); } catch (Exception e) { http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java index c34fb20..f7fc7ad 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java @@ -44,7 +44,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.net.InetSocketAddress; import java.util.ArrayList; -import java.util.Arrays; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; @@ -697,10 +696,11 @@ public class TestLinuxContainerExecutor { @Test public void testExecContainer() throws Exception { + Container container = mock(Container.class); LinuxContainerExecutor lce = mock(LinuxContainerExecutor.class); ContainerExecContext.Builder builder = new ContainerExecContext.Builder(); - builder.setUser("foo").setAppId("app1").setContainer("container1"); + builder.setUser("foo").setAppId("app1").setContainer(container); ContainerExecContext ctx = builder.build(); lce.execContainer(ctx); verify(lce, times(1)).execContainer(ctx); http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/MockLinuxContainerRuntime.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/MockLinuxContainerRuntime.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/MockLinuxContainerRuntime.java index 6bfaed1..37c6eea 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/MockLinuxContainerRuntime.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/MockLinuxContainerRuntime.java @@ -17,10 +17,13 @@ package org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hdfs.protocol.datatransfer.IOStreamPair; import org.apache.hadoop.yarn.server.nodemanager.Context; import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerExecutionException; import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerRuntimeConstants; import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerRuntimeContext; +import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerExecContext; import java.util.Map; @@ -58,4 +61,10 @@ public class MockLinuxContainerRuntime implements LinuxContainerRuntime { public String[] getIpAndHost(Container container) { return new String[0]; } + + @Override + public IOStreamPair execContainer(ContainerExecContext ctx) + throws ContainerExecutionException { + return null; + } } http://git-wip-us.apache.org/repos/asf/hadoop/blob/1f9c4f32/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/TestContainersMonitorResourceChange.java ---------------------------------------------------------------------- diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/TestContainersMonitorResourceChange.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/TestContainersMonitorResourceChange.java index d00c93b..cc8e180 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/TestContainersMonitorResourceChange.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/TestContainersMonitorResourceChange.java @@ -103,11 +103,13 @@ public class TestContainersMonitorResourceChange { throws IOException { return true; } + @Override public IOStreamPair execContainer(ContainerExecContext ctx) throws ContainerExecutionException { return new IOStreamPair(null, null); } + @Override public void deleteAsUser(DeletionAsUserContext ctx) throws IOException, InterruptedException { --------------------------------------------------------------------- To unsubscribe, e-mail: common-commits-unsubscr...@hadoop.apache.org For additional commands, e-mail: common-commits-h...@hadoop.apache.org