Ejemplo n.º 1
0
/**
 * Mount a cgroup controller at the requested mount point and create
 * a hierarchy for the Hadoop NodeManager to manage.
 * pair: a key-value pair of the form "controller=mount-path"
 * hierarchy: the top directory of the hierarchy for the NM
 */
int mount_cgroup(const char *pair, const char *hierarchy) {
#ifndef __linux
  fprintf(LOGFILE, "Failed to mount cgroup controller, not supported\n");
  return -1;
#else
  char *controller = malloc(strlen(pair));
  char *mount_path = malloc(strlen(pair));
  char hier_path[PATH_MAX];
  int result = 0;

  if (get_kv_key(pair, controller, strlen(pair)) < 0 ||
      get_kv_value(pair, mount_path, strlen(pair)) < 0) {
    fprintf(LOGFILE, "Failed to mount cgroup controller; invalid option: %s\n",
              pair);
    result = -1; 
  } else {
    if (mount("none", mount_path, "cgroup", 0, controller) == 0) {
      char *buf = stpncpy(hier_path, mount_path, strlen(mount_path));
      *buf++ = '/';
      snprintf(buf, PATH_MAX - (buf - hier_path), "%s", hierarchy);

      // create hierarchy as 0750 and chown to Hadoop NM user
      const mode_t perms = S_IRWXU | S_IRGRP | S_IXGRP;
      if (mkdirs(hier_path, perms) == 0) {
        change_owner(hier_path, nm_uid, nm_gid);
        chown_dir_contents(hier_path, nm_uid, nm_gid);
      }
    } else {
      fprintf(LOGFILE, "Failed to mount cgroup controller %s at %s - %s\n",
                controller, mount_path, strerror(errno));
      // if controller is already mounted, don't stop trying to mount others
      if (errno != EBUSY) {
        result = -1;
      }
    }
  }

  free(controller);
  free(mount_path);

  return result;
#endif
}
Ejemplo n.º 2
0
/* Parse/validate 'run as user' commands */
static int validate_run_as_user_commands(int argc, char **argv, int *operation) {
  /* We need at least the following arguments in order to proceed further :
    <user>, <yarn-user> <command> - i.e at argc should be at least 4 */

  if (argc < 4) {
    display_usage(stdout);
    return INVALID_ARGUMENT_NUMBER;
  }

  cmd_input.run_as_user_name = argv[optind++];
  cmd_input.yarn_user_name = argv[optind++];
  int command = atoi(argv[optind++]);

  fprintf(LOGFILE, "main : command provided %d\n", command);
  fprintf(LOGFILE, "main : run as user is %s\n", cmd_input.run_as_user_name);
  fprintf(LOGFILE, "main : requested yarn user is %s\n", cmd_input.yarn_user_name);
  fflush(LOGFILE);
  char * resources = NULL;// key,value pair describing resources
  char * resources_key = NULL;
  char * resources_value = NULL;
  switch (command) {
  case INITIALIZE_CONTAINER:
    if (argc < 9) {
      fprintf(ERRORFILE, "Too few arguments (%d vs 9) for initialize container\n",
       argc);
      fflush(ERRORFILE);
      return INVALID_ARGUMENT_NUMBER;
    }
    cmd_input.app_id = argv[optind++];
    cmd_input.cred_file = argv[optind++];
    cmd_input.local_dirs = argv[optind++];// good local dirs as a comma separated list
    cmd_input.log_dirs = argv[optind++];// good log dirs as a comma separated list

    *operation = RUN_AS_USER_INITIALIZE_CONTAINER;
    return 0;
 case LAUNCH_DOCKER_CONTAINER:
    //kill me now.
    if (!(argc == 14 || argc == 15)) {
      fprintf(ERRORFILE, "Wrong number of arguments (%d vs 14 or 15) for launch docker container\n",
       argc);
      fflush(ERRORFILE);
      return INVALID_ARGUMENT_NUMBER;
    }

    cmd_input.app_id = argv[optind++];
    cmd_input.container_id = argv[optind++];
    cmd_input.current_dir = argv[optind++];
    cmd_input.script_file = argv[optind++];
    cmd_input.cred_file = argv[optind++];
    cmd_input.pid_file = argv[optind++];
    cmd_input.local_dirs = argv[optind++];// good local dirs as a comma separated list
    cmd_input.log_dirs = argv[optind++];// good log dirs as a comma separated list
    cmd_input.docker_command_file = argv[optind++];
    resources = argv[optind++];// key,value pair describing resources
    resources_key = malloc(strlen(resources));
    resources_value = malloc(strlen(resources));
    if (get_kv_key(resources, resources_key, strlen(resources)) < 0 ||
      get_kv_value(resources, resources_value, strlen(resources)) < 0) {
      fprintf(ERRORFILE, "Invalid arguments for cgroups resources: %s",
                         resources);
      fflush(ERRORFILE);
      free(resources_key);
      free(resources_value);
      return INVALID_ARGUMENT_NUMBER;
    }
    //network isolation through tc
    if (argc == 15) {
      cmd_input.traffic_control_command_file = argv[optind++];
    }

    cmd_input.resources_key = resources_key;
    cmd_input.resources_value = resources_value;
    cmd_input.resources_values = extract_values(resources_value);
    *operation = RUN_AS_USER_LAUNCH_DOCKER_CONTAINER;
    return 0;

  case LAUNCH_CONTAINER:
    //kill me now.
    if (!(argc == 13 || argc == 14)) {
      fprintf(ERRORFILE, "Wrong number of arguments (%d vs 13 or 14) for launch container\n",
       argc);
      fflush(ERRORFILE);
      return INVALID_ARGUMENT_NUMBER;
    }

    cmd_input.app_id = argv[optind++];
    cmd_input.container_id = argv[optind++];
    cmd_input.current_dir = argv[optind++];
    cmd_input.script_file = argv[optind++];
    cmd_input.cred_file = argv[optind++];
    cmd_input.pid_file = argv[optind++];
    cmd_input.local_dirs = argv[optind++];// good local dirs as a comma separated list
    cmd_input.log_dirs = argv[optind++];// good log dirs as a comma separated list
    resources = argv[optind++];// key,value pair describing resources
    resources_key = malloc(strlen(resources));
    resources_value = malloc(strlen(resources));

    if (get_kv_key(resources, resources_key, strlen(resources)) < 0 ||
        get_kv_value(resources, resources_value, strlen(resources)) < 0) {
        fprintf(ERRORFILE, "Invalid arguments for cgroups resources: %s",
                           resources);
        fflush(ERRORFILE);
        free(resources_key);
        free(resources_value);
        return INVALID_ARGUMENT_NUMBER;
    }

    //network isolation through tc
    if (argc == 14) {
      cmd_input.traffic_control_command_file = argv[optind++];
    }

    cmd_input.resources_key = resources_key;
    cmd_input.resources_value = resources_value;
    cmd_input.resources_values = extract_values(resources_value);
    *operation = RUN_AS_USER_LAUNCH_CONTAINER;
    return 0;

  case SIGNAL_CONTAINER:
    if (argc != 6) {
      fprintf(ERRORFILE, "Wrong number of arguments (%d vs 6) for " \
          "signal container\n", argc);
      fflush(ERRORFILE);
      return INVALID_ARGUMENT_NUMBER;
    }

    char* end_ptr = NULL;
    char* option = argv[optind++];
    cmd_input.container_pid = strtol(option, &end_ptr, 10);
    if (option == end_ptr || *end_ptr != '\0') {
      fprintf(ERRORFILE, "Illegal argument for container pid %s\n", option);
      fflush(ERRORFILE);
      return INVALID_ARGUMENT_NUMBER;
    }
    option = argv[optind++];
    cmd_input.signal = strtol(option, &end_ptr, 10);
    if (option == end_ptr || *end_ptr != '\0') {
      fprintf(ERRORFILE, "Illegal argument for signal %s\n", option);
      fflush(ERRORFILE);
      return INVALID_ARGUMENT_NUMBER;
    }

    *operation = RUN_AS_USER_SIGNAL_CONTAINER;
    return 0;

  case DELETE_AS_USER:
    cmd_input.dir_to_be_deleted = argv[optind++];
    *operation = RUN_AS_USER_DELETE;
    return 0;
  default:
    fprintf(ERRORFILE, "Invalid command %d not supported.",command);
    fflush(ERRORFILE);
    return INVALID_COMMAND_PROVIDED;
  }
}
Ejemplo n.º 3
0
int main(int argc, char **argv) {
  int invalid_args = 0; 
  int do_check_setup = 0;
  int do_mount_cgroups = 0;
  
  LOGFILE = stdout;
  ERRORFILE = stderr;

  if (argc > 1) {
    if (strcmp("--mount-cgroups", argv[1]) == 0) {
      do_mount_cgroups = 1;
    }
  }

  // Minimum number of arguments required to run 
  // the std. container-executor commands is 4
  // 4 args not needed for checksetup option
  if (argc < 4 && !do_mount_cgroups) {
    invalid_args = 1;
    if (argc == 2) {
      const char *arg1 = argv[1];
      if (strcmp("--checksetup", arg1) == 0) {
        invalid_args = 0;
        do_check_setup = 1;        
      }      
    }
  }
  
  if (invalid_args != 0) {
    display_usage(stdout);
    return INVALID_ARGUMENT_NUMBER;
  }

  int command;
  const char * app_id = NULL;
  const char * container_id = NULL;
  const char * cred_file = NULL;
  const char * script_file = NULL;
  const char * current_dir = NULL;
  const char * pid_file = NULL;

  int exit_code = 0;

  char * dir_to_be_deleted = NULL;

  char *executable_file = get_executable();

  char *orig_conf_file = HADOOP_CONF_DIR "/" CONF_FILENAME;
  char *conf_file = resolve_config_path(orig_conf_file, argv[0]);
  char *local_dirs, *log_dirs;
  char *resources, *resources_key, *resources_value;

  if (conf_file == NULL) {
    fprintf(ERRORFILE, "Configuration file %s not found.\n", orig_conf_file);
    exit(INVALID_CONFIG_FILE);
  }
  if (check_configuration_permissions(conf_file) != 0) {
    exit(INVALID_CONFIG_FILE);
  }
  read_config(conf_file);
  free(conf_file);

  // look up the node manager group in the config file
  char *nm_group = get_value(NM_GROUP_KEY);
  if (nm_group == NULL) {
    fprintf(ERRORFILE, "Can't get configured value for %s.\n", NM_GROUP_KEY);
    exit(INVALID_CONFIG_FILE);
  }
  struct group *group_info = getgrnam(nm_group);
  if (group_info == NULL) {
    fprintf(ERRORFILE, "Can't get group information for %s - %s.\n", nm_group,
            strerror(errno));
    fflush(LOGFILE);
    exit(INVALID_CONFIG_FILE);
  }
  set_nm_uid(getuid(), group_info->gr_gid);
  // if we are running from a setuid executable, make the real uid root
  setuid(0);
  // set the real and effective group id to the node manager group
  setgid(group_info->gr_gid);

  if (check_executor_permissions(executable_file) != 0) {
    fprintf(ERRORFILE, "Invalid permissions on container-executor binary.\n");
    return INVALID_CONTAINER_EXEC_PERMISSIONS;
  }

  if (do_check_setup != 0) {
    // basic setup checks done
    // verified configs available and valid
    // verified executor permissions
    return 0;
  }

  if (do_mount_cgroups) {
    optind++;
    char *hierarchy = argv[optind++];
    int result = 0;

    while (optind < argc && result == 0) {
      result = mount_cgroup(argv[optind++], hierarchy);
    }

    return result;
  }

  //checks done for user name
  if (argv[optind] == NULL) {
    fprintf(ERRORFILE, "Invalid user name.\n");
    return INVALID_USER_NAME;
  }

  int ret = set_user(argv[optind]);
  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 < 9) {
      fprintf(ERRORFILE, "Too few arguments (%d vs 9) for initialize container\n",
	      argc);
      fflush(ERRORFILE);
      return INVALID_ARGUMENT_NUMBER;
    }
    app_id = argv[optind++];
    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(yarn_user_name, app_id, cred_file,
                               extract_values(local_dirs),
                               extract_values(log_dirs), argv + optind);
    break;
  case LAUNCH_CONTAINER:
    if (argc != 13) {
      fprintf(ERRORFILE, "Wrong number of arguments (%d vs 13) for launch container\n",
	      argc);
      fflush(ERRORFILE);
      return INVALID_ARGUMENT_NUMBER;
    }
    app_id = argv[optind++];
    container_id = argv[optind++];
    current_dir = argv[optind++];
    script_file = argv[optind++];
    cred_file = argv[optind++];
    pid_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
    resources = argv[optind++];// key,value pair describing resources
    char *resources_key = malloc(strlen(resources));
    char *resources_value = malloc(strlen(resources));
    if (get_kv_key(resources, resources_key, strlen(resources)) < 0 ||
        get_kv_value(resources, resources_value, strlen(resources)) < 0) {
        fprintf(ERRORFILE, "Invalid arguments for cgroups resources: %s",
                           resources);
        fflush(ERRORFILE);
        free(resources_key);
        free(resources_value);
        return INVALID_ARGUMENT_NUMBER;
    }
    char** resources_values = extract_values(resources_value);
    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,
                    resources_values);
    free(resources_key);
    free(resources_value);
    break;
  case SIGNAL_CONTAINER:
    if (argc != 6) {
      fprintf(ERRORFILE, "Wrong number of arguments (%d vs 6) for " \
          "signal container\n", argc);
      fflush(ERRORFILE);
      return INVALID_ARGUMENT_NUMBER;
    } else {
      char* end_ptr = NULL;
      char* option = argv[optind++];
      int container_pid = strtol(option, &end_ptr, 10);
      if (option == end_ptr || *end_ptr != '\0') {
        fprintf(ERRORFILE, "Illegal argument for container pid %s\n", option);
        fflush(ERRORFILE);
        return INVALID_ARGUMENT_NUMBER;
      }
      option = argv[optind++];
      int signal = strtol(option, &end_ptr, 10);
      if (option == end_ptr || *end_ptr != '\0') {
        fprintf(ERRORFILE, "Illegal argument for signal %s\n", option);
        fflush(ERRORFILE);
        return INVALID_ARGUMENT_NUMBER;
      }
      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(yarn_user_name, dir_to_be_deleted,
                              argv + optind);
    break;
  default:
    fprintf(ERRORFILE, "Invalid command %d not supported.",command);
    fflush(ERRORFILE);
    exit_code = INVALID_COMMAND_PROVIDED;
  }
  fclose(LOGFILE);
  fclose(ERRORFILE);
  return exit_code;
}