Author: tucu
Date: Fri Oct  4 21:59:43 2013
New Revision: 1529325

URL: http://svn.apache.org/r1529325
Log:
YARN-1253. Changes to LinuxContainerExecutor to run containers as a single 
dedicated user in non-secure mode. (rvs via tucu)

Modified:
    hadoop/common/trunk/hadoop-yarn-project/CHANGES.txt
    
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
    
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml
    
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java
    
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c
    
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c
    
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/test-container-executor.c
    
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java
    
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutorWithMocks.java

Modified: hadoop/common/trunk/hadoop-yarn-project/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-yarn-project/CHANGES.txt?rev=1529325&r1=1529324&r2=1529325&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-yarn-project/CHANGES.txt (original)
+++ hadoop/common/trunk/hadoop-yarn-project/CHANGES.txt Fri Oct  4 21:59:43 2013
@@ -29,6 +29,9 @@ Release 2.3.0 - UNRELEASED
     YARN-1010. FairScheduler: decouple container scheduling from nodemanager
     heartbeats. (Wei Yan via Sandy Ryza)
 
+    YARN-1253. Changes to LinuxContainerExecutor to run containers as a single 
+    dedicated user in non-secure mode. (rvs via tucu)
+
   IMPROVEMENTS
 
     YARN-905. Add state filters to nodes CLI (Wei Yan via Sandy Ryza)

Modified: 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java?rev=1529325&r1=1529324&r2=1529325&view=diff
==============================================================================
--- 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
 (original)
+++ 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
 Fri Oct  4 21:59:43 2013
@@ -635,7 +635,27 @@ public class YarnConfiguration extends C
    */
   public static final String NM_LINUX_CONTAINER_GROUP =
     NM_PREFIX + "linux-container-executor.group";
-  
+
+  /**
+   * The UNIX user that containers will run as when Linux-container-executor
+   * is used in nonsecure mode (a use case for this is using cgroups).
+   */
+  public static final String NM_NONSECURE_MODE_LOCAL_USER_KEY = NM_PREFIX +
+      "linux-container-executor.nonsecure-mode.local-user";
+
+  public static final String DEFAULT_NM_NONSECURE_MODE_LOCAL_USER = "nobody";
+
+  /**
+   * The allowed pattern for UNIX user names enforced by 
+   * Linux-container-executor when used in nonsecure mode (use case for this 
+   * is using cgroups). The default value is taken from /usr/sbin/adduser
+   */
+  public static final String NM_NONSECURE_MODE_USER_PATTERN_KEY = NM_PREFIX +
+      "linux-container-executor.nonsecure-mode.user-pattern";
+
+  public static final String DEFAULT_NM_NONSECURE_MODE_USER_PATTERN = 
+      "^[_.A-Za-z0-9][-@_.A-Za-z0-9]{0,255}?[$]?$";
+
   /** The type of resource enforcement to use with the
    *  linux container executor.
    */

Modified: 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml?rev=1529325&r1=1529324&r2=1529325&view=diff
==============================================================================
--- 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml
 (original)
+++ 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml
 Fri Oct  4 21:59:43 2013
@@ -728,6 +728,21 @@
   </property>
 
   <property>
+    <description>The UNIX user that containers will run as when 
Linux-container-executor
+    is used in nonsecure mode (a use case for this is using 
cgroups).</description>
+    
<name>yarn.nodemanager.linux-container-executor.nonsecure-mode.local-user</name>
+    <value>nobody</value>
+  </property>
+
+  <property>
+    <description>The allowed pattern for UNIX user names enforced by
+    Linux-container-executor when used in nonsecure mode (use case for this
+    is using cgroups). The default value is taken from 
/usr/sbin/adduser</description>
+    
<name>yarn.nodemanager.linux-container-executor.nonsecure-mode.user-pattern</name>
+    <value>^[_.A-Za-z0-9][-@_.A-Za-z0-9]{0,255}?[$]?$</value>
+  </property>
+
+  <property>
     <description>T-file compression types used to compress aggregated 
logs.</description>
     <name>yarn.nodemanager.log-aggregation.compression-type</name>
     <value>none</value>

Modified: 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java?rev=1529325&r1=1529324&r2=1529325&view=diff
==============================================================================
--- 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java
 (original)
+++ 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java
 Fri Oct  4 21:59:43 2013
@@ -24,11 +24,13 @@ import java.net.InetSocketAddress;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.regex.Pattern;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.util.ReflectionUtils;
 import org.apache.hadoop.util.Shell.ExitCodeException;
 import org.apache.hadoop.util.Shell.ShellCommandExecutor;
@@ -48,6 +50,8 @@ public class LinuxContainerExecutor exte
   private static final Log LOG = LogFactory
       .getLog(LinuxContainerExecutor.class);
 
+  private String nonsecureLocalUser;
+  private Pattern nonsecureLocalUserPattern;
   private String containerExecutorExe;
   private LCEResourcesHandler resourcesHandler;
   private boolean containerSchedPriorityIsSet = false;
@@ -70,6 +74,24 @@ public class LinuxContainerExecutor exte
           .getInt(YarnConfiguration.NM_CONTAINER_EXECUTOR_SCHED_PRIORITY, 
           YarnConfiguration.DEFAULT_NM_CONTAINER_EXECUTOR_SCHED_PRIORITY);
     }
+    nonsecureLocalUser = conf.get(
+        YarnConfiguration.NM_NONSECURE_MODE_LOCAL_USER_KEY,
+        YarnConfiguration.DEFAULT_NM_NONSECURE_MODE_LOCAL_USER);
+    nonsecureLocalUserPattern = Pattern.compile(
+        conf.get(YarnConfiguration.NM_NONSECURE_MODE_USER_PATTERN_KEY,
+            YarnConfiguration.DEFAULT_NM_NONSECURE_MODE_USER_PATTERN));        
+  }
+
+  void verifyUsernamePattern(String user) {
+    if (!UserGroupInformation.isSecurityEnabled() &&
+        !nonsecureLocalUserPattern.matcher(user).matches()) {
+        throw new IllegalArgumentException("Invalid user name '" + user + "'," 
+
+            " it must match '" + nonsecureLocalUserPattern.pattern() + "'");
+      }
+  }
+
+  String getRunAsUser(String user) {
+    return UserGroupInformation.isSecurityEnabled() ? user : 
nonsecureLocalUser;
   }
 
   /**
@@ -162,9 +184,12 @@ public class LinuxContainerExecutor exte
       List<String> localDirs, List<String> logDirs)
       throws IOException, InterruptedException {
 
+    verifyUsernamePattern(user);
+    String runAsUser = getRunAsUser(user);
     List<String> command = new ArrayList<String>();
     addSchedPriorityCommand(command);
     command.addAll(Arrays.asList(containerExecutorExe,
+                   runAsUser,
                    user, 
                    Integer.toString(Commands.INITIALIZE_CONTAINER.getValue()),
                    appId,
@@ -218,6 +243,9 @@ public class LinuxContainerExecutor exte
       String user, String appId, Path containerWorkDir,
       List<String> localDirs, List<String> logDirs) throws IOException {
 
+    verifyUsernamePattern(user);
+    String runAsUser = getRunAsUser(user);
+
     ContainerId containerId = container.getContainerId();
     String containerIdStr = ConverterUtils.toString(containerId);
     
@@ -234,7 +262,7 @@ public class LinuxContainerExecutor exte
         List<String> command = new ArrayList<String>();
         addSchedPriorityCommand(command);
         command.addAll(Arrays.asList(
-            containerExecutorExe, user, Integer
+            containerExecutorExe, runAsUser, user, Integer
                 .toString(Commands.LAUNCH_CONTAINER.getValue()), appId,
             containerIdStr, containerWorkDir.toString(),
             nmPrivateCotainerScriptPath.toUri().getPath().toString(),
@@ -293,8 +321,12 @@ public class LinuxContainerExecutor exte
   public boolean signalContainer(String user, String pid, Signal signal)
       throws IOException {
 
+    verifyUsernamePattern(user);
+    String runAsUser = getRunAsUser(user);
+
     String[] command =
         new String[] { containerExecutorExe,
+                   runAsUser,
                    user,
                    Integer.toString(Commands.SIGNAL_CONTAINER.getValue()),
                    pid,
@@ -322,8 +354,12 @@ public class LinuxContainerExecutor exte
 
   @Override
   public void deleteAsUser(String user, Path dir, Path... baseDirs) {
+    verifyUsernamePattern(user);
+    String runAsUser = getRunAsUser(user);
+
     List<String> command = new ArrayList<String>(
         Arrays.asList(containerExecutorExe,
+                    runAsUser,
                     user,
                     Integer.toString(Commands.DELETE_AS_USER.getValue()),
                     dir == null ? "" : dir.toUri().getPath()));

Modified: 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c?rev=1529325&r1=1529324&r2=1529325&view=diff
==============================================================================
--- 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c
 (original)
+++ 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c
 Fri Oct  4 21:59:43 2013
@@ -407,7 +407,7 @@ static int create_container_directories(
     const char *container_id, char* const* local_dir, char* const* log_dir, 
const char *work_dir) {
   // create dirs as 0750
   const mode_t perms = S_IRWXU | S_IRGRP | S_IXGRP;
-  if (app_id == NULL || container_id == NULL || user == NULL) {
+  if (app_id == NULL || container_id == NULL || user == NULL || user_detail == 
NULL || user_detail->pw_name == NULL) {
     fprintf(LOGFILE, 
             "Either app_id, container_id or the user passed is null.\n");
     return -1;
@@ -758,7 +758,7 @@ int initialize_app(const char *user, con
                    const char* nmPrivate_credentials_file,
                    char* const* local_dirs, char* const* log_roots,
                    char* const* args) {
-  if (app_id == NULL || user == NULL) {
+  if (app_id == NULL || user == NULL || user_detail == NULL || 
user_detail->pw_name == NULL) {
     fprintf(LOGFILE, "Either app_id is null or the user passed is null.\n");
     return INVALID_ARGUMENT_NUMBER;
   }

Modified: 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c?rev=1529325&r1=1529324&r2=1529325&view=diff
==============================================================================
--- 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c
 (original)
+++ 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c
 Fri Oct  4 21:59:43 2013
@@ -49,7 +49,7 @@ void display_usage(FILE *stream) {
           "Usage: container-executor --mount-cgroups "\
           "hierarchy controller=path...\n");
   fprintf(stream,
-      "Usage: container-executor user command command-args\n");
+      "Usage: container-executor user yarn-user command command-args\n");
   fprintf(stream, "Commands:\n");
   fprintf(stream, "   initialize container: %2d appid tokens " \
    "nm-local-dirs nm-log-dirs cmd app...\n", INITIALIZE_CONTAINER);
@@ -178,18 +178,29 @@ int main(int argc, char **argv) {
   if (ret != 0) {
     return ret;
   }
+
+  // this string is used for building pathnames, the
+  // process management is done based on the 'user_detail'
+  // global, which was set by 'set_user()' above
+  optind = optind + 1;
+  char *yarn_user_name = argv[optind];
+  if (yarn_user_name == NULL) {
+    fprintf(ERRORFILE, "Invalid yarn user name.\n");
+    return INVALID_USER_NAME;
+  }
  
   optind = optind + 1;
   command = atoi(argv[optind++]);
 
   fprintf(LOGFILE, "main : command provided %d\n",command);
   fprintf(LOGFILE, "main : user is %s\n", user_detail->pw_name);
+  fprintf(LOGFILE, "main : requested yarn user is %s\n", yarn_user_name);
   fflush(LOGFILE);
 
   switch (command) {
   case INITIALIZE_CONTAINER:
-    if (argc < 8) {
-      fprintf(ERRORFILE, "Too few arguments (%d vs 8) for initialize 
container\n",
+    if (argc < 9) {
+      fprintf(ERRORFILE, "Too few arguments (%d vs 9) for initialize 
container\n",
              argc);
       fflush(ERRORFILE);
       return INVALID_ARGUMENT_NUMBER;
@@ -198,13 +209,13 @@ int main(int argc, char **argv) {
     cred_file = argv[optind++];
     local_dirs = argv[optind++];// good local dirs as a comma separated list
     log_dirs = argv[optind++];// good log dirs as a comma separated list
-    exit_code = initialize_app(user_detail->pw_name, app_id, cred_file,
+    exit_code = initialize_app(yarn_user_name, app_id, cred_file,
                                extract_values(local_dirs),
                                extract_values(log_dirs), argv + optind);
     break;
   case LAUNCH_CONTAINER:
-    if (argc != 12) {
-      fprintf(ERRORFILE, "Wrong number of arguments (%d vs 12) for launch 
container\n",
+    if (argc != 13) {
+      fprintf(ERRORFILE, "Wrong number of arguments (%d vs 13) for launch 
container\n",
              argc);
       fflush(ERRORFILE);
       return INVALID_ARGUMENT_NUMBER;
@@ -230,7 +241,7 @@ int main(int argc, char **argv) {
         return INVALID_ARGUMENT_NUMBER;
     }
     char** resources_values = extract_values(resources_value);
-    exit_code = launch_container_as_user(user_detail->pw_name, app_id,
+    exit_code = launch_container_as_user(yarn_user_name, app_id,
                     container_id, current_dir, script_file, cred_file,
                     pid_file, extract_values(local_dirs),
                     extract_values(log_dirs), resources_key,
@@ -239,8 +250,8 @@ int main(int argc, char **argv) {
     free(resources_value);
     break;
   case SIGNAL_CONTAINER:
-    if (argc != 5) {
-      fprintf(ERRORFILE, "Wrong number of arguments (%d vs 5) for " \
+    if (argc != 6) {
+      fprintf(ERRORFILE, "Wrong number of arguments (%d vs 6) for " \
           "signal container\n", argc);
       fflush(ERRORFILE);
       return INVALID_ARGUMENT_NUMBER;
@@ -260,12 +271,12 @@ int main(int argc, char **argv) {
         fflush(ERRORFILE);
         return INVALID_ARGUMENT_NUMBER;
       }
-      exit_code = signal_container_as_user(user_detail->pw_name, 
container_pid, signal);
+      exit_code = signal_container_as_user(yarn_user_name, container_pid, 
signal);
     }
     break;
   case DELETE_AS_USER:
     dir_to_be_deleted = argv[optind++];
-    exit_code= delete_as_user(user_detail->pw_name, dir_to_be_deleted,
+    exit_code= delete_as_user(yarn_user_name, dir_to_be_deleted,
                               argv + optind);
     break;
   default:

Modified: 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/test-container-executor.c
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/test-container-executor.c?rev=1529325&r1=1529324&r2=1529325&view=diff
==============================================================================
--- 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/test-container-executor.c
 (original)
+++ 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/test-container-executor.c
 Fri Oct  4 21:59:43 2013
@@ -36,6 +36,7 @@
 #define ARRAY_SIZE 1000
 
 static char* username = NULL;
+static char* yarn_username = NULL;
 static char** local_dirs = NULL;
 static char** log_dirs = NULL;
 
@@ -252,15 +253,15 @@ void test_check_configuration_permission
 }
 
 void test_delete_container() {
-  if (initialize_user(username, local_dirs)) {
-    printf("FAIL: failed to initialize user %s\n", username);
+  if (initialize_user(yarn_username, local_dirs)) {
+    printf("FAIL: failed to initialize user %s\n", yarn_username);
     exit(1);
   }
-  char* app_dir = get_app_directory(TEST_ROOT "/local-2", username, "app_1");
-  char* dont_touch = get_app_directory(TEST_ROOT "/local-2", username, 
+  char* app_dir = get_app_directory(TEST_ROOT "/local-2", yarn_username, 
"app_1");
+  char* dont_touch = get_app_directory(TEST_ROOT "/local-2", yarn_username, 
                                        DONT_TOUCH_FILE);
   char* container_dir = get_container_work_directory(TEST_ROOT "/local-2", 
-                                             username, "app_1", "container_1");
+                                             yarn_username, "app_1", 
"container_1");
   char buffer[100000];
   sprintf(buffer, "mkdir -p %s/who/let/the/dogs/out/who/who", container_dir);
   run(buffer);
@@ -287,7 +288,7 @@ void test_delete_container() {
 
   // delete container directory
   char * dirs[] = {app_dir, 0};
-  int ret = delete_as_user(username, "container_1" , dirs);
+  int ret = delete_as_user(yarn_username, "container_1" , dirs);
   if (ret != 0) {
     printf("FAIL: return code from delete_as_user is %d\n", ret);
     exit(1);
@@ -318,11 +319,11 @@ void test_delete_container() {
 }
 
 void test_delete_app() {
-  char* app_dir = get_app_directory(TEST_ROOT "/local-2", username, "app_2");
-  char* dont_touch = get_app_directory(TEST_ROOT "/local-2", username, 
+  char* app_dir = get_app_directory(TEST_ROOT "/local-2", yarn_username, 
"app_2");
+  char* dont_touch = get_app_directory(TEST_ROOT "/local-2", yarn_username, 
                                        DONT_TOUCH_FILE);
   char* container_dir = get_container_work_directory(TEST_ROOT "/local-2", 
-                                             username, "app_2", "container_1");
+                                             yarn_username, "app_2", 
"container_1");
   char buffer[100000];
   sprintf(buffer, "mkdir -p %s/who/let/the/dogs/out/who/who", container_dir);
   run(buffer);
@@ -348,7 +349,7 @@ void test_delete_app() {
   run(buffer);
 
   // delete container directory
-  int ret = delete_as_user(username, app_dir, NULL);
+  int ret = delete_as_user(yarn_username, app_dir, NULL);
   if (ret != 0) {
     printf("FAIL: return code from delete_as_user is %d\n", ret);
     exit(1);
@@ -377,17 +378,17 @@ void test_delete_app() {
 
 void test_delete_user() {
   printf("\nTesting delete_user\n");
-  char* app_dir = get_app_directory(TEST_ROOT "/local-1", username, "app_3");
+  char* app_dir = get_app_directory(TEST_ROOT "/local-1", yarn_username, 
"app_3");
   if (mkdirs(app_dir, 0700) != 0) {
     exit(1);
   }
   char buffer[100000];
-  sprintf(buffer, "%s/local-1/usercache/%s", TEST_ROOT, username);
+  sprintf(buffer, "%s/local-1/usercache/%s", TEST_ROOT, yarn_username);
   if (access(buffer, R_OK) != 0) {
     printf("FAIL: directory missing before test\n");
     exit(1);
   }
-  if (delete_as_user(username, buffer, NULL) != 0) {
+  if (delete_as_user(yarn_username, buffer, NULL) != 0) {
     exit(1);
   }
   if (access(buffer, R_OK) == 0) {
@@ -446,7 +447,7 @@ void test_signal_container() {
     exit(0);
   } else {
     printf("Child container launched as %d\n", child);
-    if (signal_container_as_user(username, child, SIGQUIT) != 0) {
+    if (signal_container_as_user(yarn_username, child, SIGQUIT) != 0) {
       exit(1);
     }
     int status = 0;
@@ -486,7 +487,7 @@ void test_signal_container_group() {
   // there's a race condition for child calling change_user and us 
   // calling signal_container_as_user, hence sleeping
   sleep(3);
-  if (signal_container_as_user(username, child, SIGKILL) != 0) {
+  if (signal_container_as_user(yarn_username, child, SIGKILL) != 0) {
     exit(1);
   }
   int status = 0;
@@ -550,7 +551,7 @@ void test_init_app() {
     exit(1);
   } else if (child == 0) {
     char *final_pgm[] = {"touch", "my-touch-file", 0};
-    if (initialize_app(username, "app_4", TEST_ROOT "/creds.txt",
+    if (initialize_app(yarn_username, "app_4", TEST_ROOT "/creds.txt",
                        local_dirs, log_dirs, final_pgm) != 0) {
       printf("FAIL: failed in child\n");
       exit(42);
@@ -568,7 +569,7 @@ void test_init_app() {
     printf("FAIL: failed to create app log directory\n");
     exit(1);
   }
-  char* app_dir = get_app_directory(TEST_ROOT "/local-1", username, "app_4");
+  char* app_dir = get_app_directory(TEST_ROOT "/local-1", yarn_username, 
"app_4");
   if (access(app_dir, R_OK) != 0) {
     printf("FAIL: failed to create app directory %s\n", app_dir);
     exit(1);
@@ -640,7 +641,7 @@ void test_run_container() {
   fflush(stdout);
   fflush(stderr);
   char* container_dir = get_container_work_directory(TEST_ROOT "/local-1", 
-                                             username, "app_4", "container_1");
+                                             yarn_username, "app_4", 
"container_1");
   const char * pid_file = TEST_ROOT "/pid.txt";
 
   pid_t child = fork();
@@ -649,7 +650,7 @@ void test_run_container() {
           strerror(errno));
     exit(1);
   } else if (child == 0) {
-    if (launch_container_as_user(username, "app_4", "container_1", 
+    if (launch_container_as_user(yarn_username, "app_4", "container_1", 
           container_dir, script_name, TEST_ROOT "/creds.txt", pid_file,
           local_dirs, log_dirs,
           "cgroups", cgroups_pids) != 0) {
@@ -697,10 +698,22 @@ void test_run_container() {
   check_pid_file(cgroups_pids[1], child);
 }
 
+// This test is expected to be executed either by a regular
+// user or by root. If executed by a regular user it doesn't
+// test all the functions that would depend on changing the
+// effective user id. If executed by a super-user everything
+// gets tested. Here are different ways of execing the test binary:
+// 1. regular user assuming user == yarn user
+//    $ test-container-executor     
+// 2. regular user with a given yarn user
+//    $ test-container-executor yarn_user
+// 3. super user with a given user and assuming user == yarn user
+//    # test-container-executor user
+// 4. super user with a given user and a given yarn user
+//    # test-container-executor user yarn_user
 int main(int argc, char **argv) {
   LOGFILE = stdout;
   ERRORFILE = stderr;
-  int my_username = 0;
 
   // clean up any junk from previous run
   if (system("chmod -R u=rwx " TEST_ROOT "; rm -fr " TEST_ROOT)) {
@@ -721,11 +734,15 @@ int main(int argc, char **argv) {
 
   create_nm_roots(local_dirs);
 
-  if (getuid() == 0 && argc == 2) {
+  // See the description above of various ways this test
+  // can be executed in order to understand the following logic
+  char* current_username = strdup(getpwuid(getuid())->pw_name);
+  if (getuid() == 0 && (argc == 2 || argc == 3)) {
     username = argv[1];
+    yarn_username = (argc == 3) ? argv[2] : argv[1];
   } else {
-    username = strdup(getpwuid(getuid())->pw_name);
-    my_username = 1;
+    username = current_username;
+    yarn_username = (argc == 2) ? argv[1] : current_username;
   }
   set_nm_uid(geteuid(), getegid());
 
@@ -783,9 +800,7 @@ int main(int argc, char **argv) {
   run("rm -fr " TEST_ROOT);
   printf("\nFinished tests\n");
 
-  if (my_username) {
-    free(username);
-  }
+  free(current_username);
   free_configurations();
   return 0;
 }

Modified: 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java?rev=1529325&r1=1529324&r2=1529325&view=diff
==============================================================================
--- 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java
 (original)
+++ 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java
 Fri Oct  4 21:59:43 2013
@@ -31,14 +31,17 @@ import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.HashMap;
 
+import junit.framework.Assert;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
 import org.apache.hadoop.fs.FileContext;
 import org.apache.hadoop.fs.FileStatus;
 import org.apache.hadoop.fs.FileUtil;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.fs.permission.FsPermission;
+import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.yarn.api.records.ContainerId;
 import org.apache.hadoop.yarn.api.records.ContainerLaunchContext;
 import org.apache.hadoop.yarn.conf.YarnConfiguration;
@@ -256,4 +259,91 @@ public class TestLinuxContainerExecutor 
     
     assertFalse(t.isAlive());
   }
+
+  @Test
+  public void testLocalUser() throws Exception {
+    try {
+      //nonsecure default
+      Configuration conf = new YarnConfiguration();
+      conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
+          "simple");
+      UserGroupInformation.setConfiguration(conf);
+      LinuxContainerExecutor lce = new LinuxContainerExecutor();
+      lce.setConf(conf);
+      
Assert.assertEquals(YarnConfiguration.DEFAULT_NM_NONSECURE_MODE_LOCAL_USER,
+          lce.getRunAsUser("foo"));
+
+      //nonsecure custom setting
+      conf.set(YarnConfiguration.NM_NONSECURE_MODE_LOCAL_USER_KEY, "bar");
+      lce = new LinuxContainerExecutor();
+      lce.setConf(conf);
+      Assert.assertEquals("bar", lce.getRunAsUser("foo"));
+
+      //secure
+      conf = new YarnConfiguration();
+      conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
+          "kerberos");
+      UserGroupInformation.setConfiguration(conf);
+      lce = new LinuxContainerExecutor();
+      lce.setConf(conf);
+      Assert.assertEquals("foo", lce.getRunAsUser("foo"));
+    } finally {
+      Configuration conf = new YarnConfiguration();
+      conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
+          "simple");
+      UserGroupInformation.setConfiguration(conf);
+    }
+  }
+
+  @Test
+  public void testNonsecureUsernamePattern() throws Exception {
+    try {
+      //nonsecure default
+      Configuration conf = new YarnConfiguration();
+      conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
+          "simple");
+      UserGroupInformation.setConfiguration(conf);
+      LinuxContainerExecutor lce = new LinuxContainerExecutor();
+      lce.setConf(conf);
+      lce.verifyUsernamePattern("foo");
+      try {
+        lce.verifyUsernamePattern("foo/x");
+        Assert.fail();
+      } catch (IllegalArgumentException ex) {
+        //NOP        
+      } catch (Throwable ex) {
+        Assert.fail(ex.toString());
+      }
+      
+      //nonsecure custom setting
+      conf.set(YarnConfiguration.NM_NONSECURE_MODE_USER_PATTERN_KEY, "foo");
+      lce = new LinuxContainerExecutor();
+      lce.setConf(conf);
+      lce.verifyUsernamePattern("foo");
+      try {
+        lce.verifyUsernamePattern("bar");
+        Assert.fail();
+      } catch (IllegalArgumentException ex) {
+        //NOP        
+      } catch (Throwable ex) {
+        Assert.fail(ex.toString());
+      }
+
+      //secure, pattern matching does not kick in.
+      conf = new YarnConfiguration();
+      conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
+          "kerberos");
+      UserGroupInformation.setConfiguration(conf);
+      lce = new LinuxContainerExecutor();
+      lce.setConf(conf);
+      lce.verifyUsernamePattern("foo");
+      lce.verifyUsernamePattern("foo/w");
+    } finally {
+      Configuration conf = new YarnConfiguration();
+      conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
+          "simple");
+      UserGroupInformation.setConfiguration(conf);
+    }
+  }
+
 }

Modified: 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutorWithMocks.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutorWithMocks.java?rev=1529325&r1=1529324&r2=1529325&view=diff
==============================================================================
--- 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutorWithMocks.java
 (original)
+++ 
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutorWithMocks.java
 Fri Oct  4 21:59:43 2013
@@ -128,7 +128,8 @@ public class TestLinuxContainerExecutorW
         appSubmitter, appId, workDir, dirsHandler.getLocalDirs(),
         dirsHandler.getLogDirs());
     assertEquals(0, ret);
-    assertEquals(Arrays.asList(appSubmitter, cmd, appId, containerId,
+    
assertEquals(Arrays.asList(YarnConfiguration.DEFAULT_NM_NONSECURE_MODE_LOCAL_USER,
+        appSubmitter, cmd, appId, containerId,
         workDir.toString(), "/bin/echo", "/dev/null", pidFile.toString(),
         StringUtils.join(",", dirsHandler.getLocalDirs()),
         StringUtils.join(",", dirsHandler.getLogDirs()), "cgroups=none"),
@@ -180,18 +181,19 @@ public class TestLinuxContainerExecutorW
     try {
       mockExec.startLocalizer(nmPrivateCTokensPath, address, "test", 
"application_0", "12345", dirsHandler.getLocalDirs(), dirsHandler.getLogDirs());
       List<String> result=readMockParams();
-      Assert.assertEquals(result.size(), 16);
-      Assert.assertEquals(result.get(0), "test");
-      Assert.assertEquals(result.get(1), "0" );
-      Assert.assertEquals(result.get(2),"application_0" );
-      Assert.assertEquals(result.get(3), "/bin/nmPrivateCTokensPath");
-      Assert.assertEquals(result.get(7), "-classpath" );
-      
Assert.assertEquals(result.get(10),"org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.ContainerLocalizer"
 );
-      Assert.assertEquals(result.get(11), "test");
-      Assert.assertEquals(result.get(12), "application_0");
-      Assert.assertEquals(result.get(13),"12345" );
-      Assert.assertEquals(result.get(14),"localhost" );
-      Assert.assertEquals(result.get(15),"8040" );
+      Assert.assertEquals(result.size(), 17);
+      Assert.assertEquals(result.get(0), 
YarnConfiguration.DEFAULT_NM_NONSECURE_MODE_LOCAL_USER);
+      Assert.assertEquals(result.get(1), "test");
+      Assert.assertEquals(result.get(2), "0" );
+      Assert.assertEquals(result.get(3),"application_0" );
+      Assert.assertEquals(result.get(4), "/bin/nmPrivateCTokensPath");
+      Assert.assertEquals(result.get(8), "-classpath" );
+      
Assert.assertEquals(result.get(11),"org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.ContainerLocalizer"
 );
+      Assert.assertEquals(result.get(12), "test");
+      Assert.assertEquals(result.get(13), "application_0");
+      Assert.assertEquals(result.get(14),"12345" );
+      Assert.assertEquals(result.get(15),"localhost" );
+      Assert.assertEquals(result.get(16),"8040" );
 
     } catch (InterruptedException e) {
       LOG.error("Error:"+e.getMessage(),e);
@@ -246,7 +248,8 @@ public class TestLinuxContainerExecutorW
         appSubmitter, appId, workDir, dirsHandler.getLocalDirs(),
         dirsHandler.getLogDirs());
     Assert.assertNotSame(0, ret);
-    assertEquals(Arrays.asList(appSubmitter, cmd, appId, containerId,
+    
assertEquals(Arrays.asList(YarnConfiguration.DEFAULT_NM_NONSECURE_MODE_LOCAL_USER,
+        appSubmitter, cmd, appId, containerId,
         workDir.toString(), "/bin/echo", "/dev/null", pidFile.toString(),
         StringUtils.join(",", dirsHandler.getLocalDirs()),
         StringUtils.join(",", dirsHandler.getLogDirs()),
@@ -272,7 +275,8 @@ public class TestLinuxContainerExecutorW
     String sigVal = String.valueOf(signal.getValue());
     
     mockExec.signalContainer(appSubmitter, "1000", signal);
-    assertEquals(Arrays.asList(appSubmitter, cmd, "1000", sigVal),
+    
assertEquals(Arrays.asList(YarnConfiguration.DEFAULT_NM_NONSECURE_MODE_LOCAL_USER,
+        appSubmitter, cmd, "1000", sigVal),
         readMockParams());
   }
   
@@ -284,7 +288,8 @@ public class TestLinuxContainerExecutorW
     Path dir = new Path("/tmp/testdir");
     
     mockExec.deleteAsUser(appSubmitter, dir);
-    assertEquals(Arrays.asList(appSubmitter, cmd, "/tmp/testdir"),
+    
assertEquals(Arrays.asList(YarnConfiguration.DEFAULT_NM_NONSECURE_MODE_LOCAL_USER,
+        appSubmitter, cmd, "/tmp/testdir"),
         readMockParams());
   }
 }


Reply via email to