Преглед изворни кода

YARN-9032. Support sh shell for interactive container shell at command line. Contributed by Eric Yang

Billie Rinaldi пре 6 година
родитељ
комит
ca90b2480e

+ 3 - 2
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/YarnClientImpl.java

@@ -1104,10 +1104,11 @@ public class YarnClientImpl extends YarnClient {
       }
       WebSocketClient client = new WebSocketClient();
       URI uri = URI.create(protocol + host + ":" + port + "/container/" +
-          containerId);
+          containerId + "/" + command);
       if (!UserGroupInformation.isSecurityEnabled()) {
         uri = URI.create(protocol + host + ":" + port + "/container/" +
-            containerId + "?user.name=" + System.getProperty("user.name"));
+            containerId + "/" + command + "?user.name=" +
+            System.getProperty("user.name"));
       }
       try {
         client.start();

+ 3 - 2
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/cli/ApplicationCLI.java

@@ -335,7 +335,8 @@ public class ApplicationCLI extends YarnCLI {
           "app version, -components to filter instances based on component " +
           "names, -states to filter instances based on instance state.");
       opts.addOption(HELP_CMD, false, "Displays help for all commands.");
-      opts.getOption(SHELL_CMD).setArgName("Container ID");
+      opts.getOption(SHELL_CMD).setArgName("Container ID [bash|sh]");
+      opts.getOption(SHELL_CMD).setArgs(3);
       opts.getOption(STATUS_CMD).setArgName("Container ID");
       opts.getOption(LIST_CMD).setArgName("Application Name or Attempt ID");
       opts.addOption(APP_TYPE_CMD, true, "Works with -list to " +
@@ -584,7 +585,7 @@ public class ApplicationCLI extends YarnCLI {
       ShellContainerCommand command =
           ShellContainerCommand.BASH;
       if (shellArgs.length == 2) {
-        command = ShellContainerCommand.valueOf(shellArgs[1]);
+        command = ShellContainerCommand.valueOf(shellArgs[1].toUpperCase());
       }
       shellToContainer(containerId, command);
     } else if (cliParser.hasOption(LAUNCH_CMD)) {

+ 1 - 1
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/cli/TestYarnCLI.java

@@ -2314,7 +2314,7 @@ public class TestYarnCLI {
     pw.println(" -components <arg>                Works with -list to filter instances based on input comma-separated list of component names.");
     pw.println(" -help                            Displays help for all commands.");
     pw.println(" -list <Application Name or Attempt ID>   List containers for application attempt  when application attempt ID is provided. When application name is provided, then it finds the instances of the application based on app's own implementation, and -appTypes option must be specified unless it is the default yarn-service type. With app name, it supports optional use of -version to filter instances based on app version, -components to filter instances based on component names, -states to filter instances based on instance state.");
-    pw.println(" -shell <Container ID> Run a shell in the container.");
+    pw.println(" -shell <Container ID [bash|sh]> Run a shell in the container.");
     pw.println(" -signal <container ID [signal command]> Signal the container.");
     pw.println("The available signal commands are ");
     pw.println(java.util.Arrays.asList(SignalContainerCommand.values()));

+ 4 - 1
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

@@ -267,7 +267,10 @@ public class DefaultLinuxContainerRuntime implements LinuxContainerRuntime {
         cmd.put("user", user);
         // launch-command = bash,-i
         List<String> commands = new ArrayList<String>();
-        commands.add("/bin/bash");
+        StringBuilder sb = new StringBuilder();
+        sb.append("/bin/");
+        sb.append(ctx.getShell());
+        commands.add(sb.toString());
         commands.add("-ir");
         cmd.put("launch-command", commands);
         // workdir = ../nm-local-dir/usercache/appcache/appid/containerid

+ 5 - 1
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

@@ -1178,7 +1178,11 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime {
     dockerExecCommand.setInteractive();
     dockerExecCommand.setTTY();
     List<String> command = new ArrayList<String>();
-    command.add("bash");
+    StringBuilder sb = new StringBuilder();
+    sb.append("/bin/");
+    sb.append(ctx.getShell());
+    command.add(sb.toString());
+    command.add("-i");
     dockerExecCommand.setOverrideCommandWithArgs(command);
     String commandFile = dockerClient.writeCommandToTempFile(dockerExecCommand,
         ContainerId.fromString(containerId), nmContext);

+ 13 - 1
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/executor/ContainerExecContext.java

@@ -35,6 +35,7 @@ public final class ContainerExecContext {
   private final String user;
   private final String appId;
   private final Container container;
+  private String command;
   private final LocalDirsHandlerService localDirsHandler;
 
   /**
@@ -44,6 +45,7 @@ public final class ContainerExecContext {
     private String user;
     private String appId;
     private Container container;
+    private String command;
     private LocalDirsHandlerService localDirsHandler;
 
     public Builder() {
@@ -73,12 +75,18 @@ public final class ContainerExecContext {
       this.localDirsHandler = ldhs;
       return this;
     }
+
+    public Builder setShell(String command) {
+      this.command = command;
+      return this;
+    }
   }
 
   private ContainerExecContext(Builder builder) {
-    this.container = builder.container;
     this.user = builder.user;
     this.appId = builder.appId;
+    this.container = builder.container;
+    this.command = builder.command;
     this.localDirsHandler = builder.localDirsHandler;
   }
 
@@ -94,6 +102,10 @@ public final class ContainerExecContext {
     return this.container;
   }
 
+  public String getShell() {
+    return this.command;
+  }
+
   public LocalDirsHandlerService getLocalDirsHandlerService() {
     return this.localDirsHandler;
   }

+ 10 - 0
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/ContainerShellWebSocket.java

@@ -27,6 +27,7 @@ import java.util.Map;
 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.api.records.ShellContainerCommand;
 import org.apache.hadoop.yarn.server.nodemanager.Context;
 import org.apache.hadoop.yarn.server.nodemanager.ContainerExecutor;
 import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container;
@@ -98,8 +99,16 @@ public class ContainerShellWebSocket {
   public void onConnect(Session session) {
     try {
       URI containerURI = session.getUpgradeRequest().getRequestURI();
+      String command = "bash";
       String[] containerPath = containerURI.getPath().split("/");
       String cId = containerPath[2];
+      if (containerPath.length==4) {
+        for (ShellContainerCommand c : ShellContainerCommand.values()) {
+          if (c.name().equalsIgnoreCase(containerPath[3])) {
+            command = containerPath[3].toLowerCase();
+          }
+        }
+      }
       Container container = nmContext.getContainers().get(ContainerId
           .fromString(cId));
       if (!checkAuthorization(session, container)) {
@@ -113,6 +122,7 @@ public class ContainerShellWebSocket {
           .Builder()
           .setContainer(container)
           .setNMLocalPath(nmContext.getLocalDirsHandler())
+          .setShell(command)
           .build();
       pair = exec.execContainer(execContext);
     } catch (Exception e) {