diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/cli/ApplicationCLI.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/cli/ApplicationCLI.java index 535e6ce56f5..6ec484876b2 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/cli/ApplicationCLI.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/cli/ApplicationCLI.java @@ -143,6 +143,9 @@ public class ApplicationCLI extends YarnCLI { @Override public int run(String[] args) throws Exception { + int exitCode = -1; + + // Prepare the command's title and options Options opts = new Options(); String title = null; if (firstArg != null) { @@ -150,622 +153,71 @@ public class ApplicationCLI extends YarnCLI { } else if (args.length > 0) { title = args[0]; } - if (title != null && (title.equalsIgnoreCase(APPLICATION) || title - .equalsIgnoreCase(APP))) { + if (APPLICATION.equalsIgnoreCase(title) || APP.equalsIgnoreCase(title)) { title = APPLICATION; - opts.addOption(STATUS_CMD, true, - "Prints the status of the application. If app ID is" - + " provided, it prints the generic YARN application status." - + " If name is provided, it prints the application specific" - + " status based on app's own implementation, and -appTypes" - + " option must be specified unless it is the default" - + " yarn-service type."); - opts.addOption(LIST_CMD, false, "List applications. " - + "Supports optional use of -appTypes to filter applications " - + "based on application type, -appStates to filter applications " - + "based on application state and -appTags to filter applications " - + "based on application tag."); - opts.addOption(MOVE_TO_QUEUE_CMD, true, "Moves the application to a " - + "different queue. Deprecated command. Use 'changeQueue' instead."); - opts.addOption(QUEUE_CMD, true, "Works with the movetoqueue command to" - + " specify which queue to move an application to."); - opts.addOption(HELP_CMD, false, "Displays help for all commands."); - Option appTypeOpt = new Option(APP_TYPE_CMD, true, "Works with -list to " - + "filter applications based on " - + "input comma-separated list of application types."); - appTypeOpt.setValueSeparator(','); - appTypeOpt.setArgs(Option.UNLIMITED_VALUES); - appTypeOpt.setArgName("Types"); - opts.addOption(appTypeOpt); - Option appStateOpt = new Option(APP_STATE_CMD, true, "Works with -list " - + "to filter applications based on input comma-separated list of " - + "application states. " + getAllValidApplicationStates()); - appStateOpt.setValueSeparator(','); - appStateOpt.setArgs(Option.UNLIMITED_VALUES); - appStateOpt.setArgName("States"); - opts.addOption(appStateOpt); - Option appTagOpt = new Option(APP_TAG_CMD, true, "Works with -list to " - + "filter applications based on input comma-separated list of " - + "application tags."); - appTagOpt.setValueSeparator(','); - appTagOpt.setArgs(Option.UNLIMITED_VALUES); - appTagOpt.setArgName("Tags"); - opts.addOption(appTagOpt); - opts.addOption(APP_ID, true, "Specify Application Id to be operated"); - opts.addOption(UPDATE_PRIORITY, true, - "update priority of an application. ApplicationId can be" - + " passed using 'appId' option."); - opts.addOption(UPDATE_LIFETIME, true, - "update timeout of an application from NOW. ApplicationId can be" - + " passed using 'appId' option. Timeout value is in seconds."); - opts.addOption(CHANGE_APPLICATION_QUEUE, true, - "Moves application to a new queue. ApplicationId can be" - + " passed using 'appId' option. 'movetoqueue' command is" - + " deprecated, this new command 'changeQueue' performs same" - + " functionality."); - Option killOpt = new Option(KILL_CMD, true, "Kills the application. " - + "Set of applications can be provided separated with space"); - killOpt.setValueSeparator(' '); - killOpt.setArgs(Option.UNLIMITED_VALUES); - killOpt.setArgName("Application ID"); - opts.addOption(killOpt); - opts.getOption(MOVE_TO_QUEUE_CMD).setArgName("Application ID"); - opts.getOption(QUEUE_CMD).setArgName("Queue Name"); - opts.getOption(STATUS_CMD).setArgName("Application Name or ID"); - opts.getOption(APP_ID).setArgName("Application ID"); - opts.getOption(UPDATE_PRIORITY).setArgName("Priority"); - opts.getOption(UPDATE_LIFETIME).setArgName("Timeout"); - opts.getOption(CHANGE_APPLICATION_QUEUE).setArgName("Queue Name"); - opts.addOption(LAUNCH_CMD, true, "Launches application from " + - "specification file (saves specification and starts application). " + - "Options -updateLifetime and -changeQueue can be specified to alter" + - " the values provided in the file. Supports -appTypes option to " + - "specify which client implementation to use."); - opts.addOption(STOP_CMD, true, "Stops application gracefully (may be " + - "started again later). If name is provided, appType must be " + - "provided unless it is the default yarn-service. If ID is provided," + - " the appType will be looked up. Supports -appTypes option to " + - "specify which client implementation to use."); - opts.addOption(START_CMD, true, "Starts a previously saved " + - "application. Supports -appTypes option to specify which client " + - "implementation to use."); - opts.addOption(SAVE_CMD, true, "Saves specification file for " + - "an application. Options -updateLifetime and -changeQueue can be " + - "specified to alter the values provided in the file. Supports " + - "-appTypes option to specify which client implementation to use."); - opts.addOption(DESTROY_CMD, true, "Destroys a saved application " + - "specification and removes all application data permanently. " + - "Supports -appTypes option to specify which client implementation " + - "to use."); - opts.addOption(FLEX_CMD, true, "Changes number of " + - "running containers for a component of an application / " + - "long-running service. Requires -component option. If name is " + - "provided, appType must be provided unless it is the default " + - "yarn-service. If ID is provided, the appType will be looked up. " + - "Supports -appTypes option to specify which client implementation " + - "to use."); - opts.addOption(DECOMMISSION, true, "Decommissions component " + - "instances for an application / long-running service. Requires " + - "-instances option. Supports -appTypes option to specify which " + - "client implementation to use."); - opts.addOption(COMPONENT, true, "Works with -flex option to change " + - "the number of components/containers running for an application / " + - "long-running service. Supports absolute or relative changes, such " + - "as +1, 2, or -3."); - opts.addOption(ENABLE_FAST_LAUNCH, true, "Uploads AM dependencies " + - "to HDFS to make future launches faster. Supports -appTypes option " + - "to specify which client implementation to use. Optionally a " + - "destination folder for the tarball can be specified."); - opts.addOption(UPGRADE_CMD, true, "Upgrades an application/long-" + - "running service. It requires either -initiate, -instances, or " + - "-finalize options."); - opts.addOption(UPGRADE_EXPRESS, true, "Works with -upgrade option to " + - "perform express upgrade. It requires the upgraded application " + - "specification file."); - opts.addOption(UPGRADE_INITIATE, true, "Works with -upgrade option to " + - "initiate the application upgrade. It requires the upgraded " + - "application specification file."); - opts.addOption(COMPONENT_INSTS, true, "Works with -upgrade option to " + - "trigger the upgrade of specified component instances of the " + - "application. Also works with -decommission option to decommission " + - "specified component instances. Multiple instances should be " + - "separated by commas."); - opts.addOption(COMPONENTS, true, "Works with -upgrade option to " + - "trigger the upgrade of specified components of the application. " + - "Multiple components should be separated by commas."); - opts.addOption(UPGRADE_FINALIZE, false, "Works with -upgrade option to " + - "finalize the upgrade."); - opts.addOption(UPGRADE_AUTO_FINALIZE, false, "Works with -upgrade and " + - "-initiate options to initiate the upgrade of the application with " + - "the ability to finalize the upgrade automatically."); - opts.addOption(UPGRADE_CANCEL, false, "Works with -upgrade option to " + - "cancel current upgrade."); - opts.addOption(CLUSTER_ID_OPTION, true, "ClusterId. " - + "By default, it will take default cluster id from the RM"); - opts.getOption(LAUNCH_CMD).setArgName("Application Name> appTypes = new HashSet(); - if (cliParser.hasOption(APP_TYPE_CMD)) { - String[] types = cliParser.getOptionValues(APP_TYPE_CMD); - if (types != null) { - for (String type : types) { - if (!type.trim().isEmpty()) { - appTypes.add(StringUtils.toUpperCase(type).trim()); - } - } - } - } - - EnumSet appStates = EnumSet - .noneOf(YarnApplicationState.class); - if (cliParser.hasOption(APP_STATE_CMD)) { - String[] states = cliParser.getOptionValues(APP_STATE_CMD); - if (states != null) { - for (String state : states) { - if (!state.trim().isEmpty()) { - if (state.trim().equalsIgnoreCase(ALLSTATES_OPTION)) { - allAppStates = true; - break; - } - try { - appStates.add(YarnApplicationState.valueOf( - StringUtils.toUpperCase(state).trim())); - } catch (IllegalArgumentException ex) { - sysout.println("The application state " + state - + " is invalid."); - sysout.println(getAllValidApplicationStates()); - return exitCode; - } - } - } - } - } - - Set appTags = new HashSet(); - if (cliParser.hasOption(APP_TAG_CMD)) { - String[] tags = cliParser.getOptionValues(APP_TAG_CMD); - if (tags != null) { - for (String tag : tags) { - if (!tag.trim().isEmpty()) { - appTags.add(tag.trim()); - } - } - } - } - listApplications(appTypes, appStates, appTags); - } else if (title.equalsIgnoreCase(APPLICATION_ATTEMPT)) { - if (hasAnyOtherCLIOptions(cliParser, opts, LIST_CMD)) { - printUsage(title, opts); - return exitCode; - } - listApplicationAttempts(cliParser.getOptionValue(LIST_CMD)); - } else if (title.equalsIgnoreCase(CONTAINER)) { - if (hasAnyOtherCLIOptions(cliParser, opts, LIST_CMD, APP_TYPE_CMD, - VERSION, COMPONENTS, STATES)) { - printUsage(title, opts); - return exitCode; - } - String appAttemptIdOrName = cliParser.getOptionValue(LIST_CMD); - try { - // try parsing attempt id, if it succeeds, it means it's appId - ApplicationAttemptId.fromString(appAttemptIdOrName); - listContainers(appAttemptIdOrName); - } catch (IllegalArgumentException e) { - // not appAttemptId format, it could be appName. If app-type is not - // provided, assume it is yarn-service type. - AppAdminClient client = AppAdminClient - .createAppAdminClient(getSingleAppTypeFromCLI(cliParser), - getConf()); - String version = cliParser.getOptionValue(VERSION); - String[] components = cliParser.getOptionValues(COMPONENTS); - String[] instanceStates = cliParser.getOptionValues(STATES); - try { - sysout.println(client.getInstances(appAttemptIdOrName, - components == null ? null : Arrays.asList(components), - version, instanceStates == null ? null : - Arrays.asList(instanceStates))); - return 0; - } catch (ApplicationNotFoundException exception) { - System.err.println("Application with name '" + appAttemptIdOrName - + "' doesn't exist in RM or Timeline Server."); - return -1; - } catch (Exception ex) { - System.err.println(ex.getMessage()); - return -1; - } - } - } + return executeListCommand(cliParser, title, opts); } else if (cliParser.hasOption(KILL_CMD)) { - if (hasAnyOtherCLIOptions(cliParser, opts, KILL_CMD)) { - printUsage(title, opts); - return exitCode; - } - return killApplication(cliParser.getOptionValues(KILL_CMD)); + return executeKillCommand(cliParser, title, opts); } else if (cliParser.hasOption(MOVE_TO_QUEUE_CMD)) { - if (!cliParser.hasOption(QUEUE_CMD)) { - printUsage(title, opts); - return exitCode; - } - moveApplicationAcrossQueues(cliParser.getOptionValue(MOVE_TO_QUEUE_CMD), - cliParser.getOptionValue(QUEUE_CMD)); + return executeMoveToQueueCommand(cliParser, title, opts); } else if (cliParser.hasOption(FAIL_CMD)) { - if (!title.equalsIgnoreCase(APPLICATION_ATTEMPT)) { - printUsage(title, opts); - return exitCode; - } - failApplicationAttempt(cliParser.getOptionValue(FAIL_CMD)); + return executeFailCommand(cliParser, title, opts); + } else if (cliParser.hasOption(UPDATE_PRIORITY)) { + return executeUpdatePriorityCommand(cliParser, title, opts); + } else if (cliParser.hasOption(SIGNAL_CMD)) { + return executeSignalCommand(cliParser, title, opts); + } else if (cliParser.hasOption(SHELL_CMD)) { + return executeShellCommand(cliParser, title, opts); + } else if (cliParser.hasOption(LAUNCH_CMD)) { + return executeLaunchCommand(cliParser, title, opts); + } else if (cliParser.hasOption(STOP_CMD)) { + return executeStopCommand(cliParser, title, opts); + } else if (cliParser.hasOption(START_CMD)) { + return executeStartCommand(cliParser, title, opts); + } else if (cliParser.hasOption(SAVE_CMD)) { + return executeSaveCommand(cliParser, title, opts); + } else if (cliParser.hasOption(DESTROY_CMD)) { + return executeDestroyCommand(cliParser, title, opts); + } else if (cliParser.hasOption(FLEX_CMD)) { + return executeFlexCommand(cliParser, title, opts); + } else if (cliParser.hasOption(ENABLE_FAST_LAUNCH)) { + return executeEnableFastLaunchCommand(cliParser, title, opts); + } else if (cliParser.hasOption(UPDATE_LIFETIME)) { + return executeUpdateLifeTimeCommand(cliParser, title, opts); + } else if (cliParser.hasOption(CHANGE_APPLICATION_QUEUE)) { + return executeChangeApplicationQueueCommand(cliParser, title, opts); + } else if (cliParser.hasOption(UPGRADE_CMD)) { + return executeUpgradeCommand(cliParser, title, opts); + } else if (cliParser.hasOption(DECOMMISSION)) { + return executeDecommissionCommand(cliParser, title, opts); } else if (cliParser.hasOption(HELP_CMD)) { printUsage(title, opts); return 0; - } else if (cliParser.hasOption(UPDATE_PRIORITY)) { - if (!cliParser.hasOption(APP_ID)) { - printUsage(title, opts); - return exitCode; - } - updateApplicationPriority(cliParser.getOptionValue(APP_ID), - cliParser.getOptionValue(UPDATE_PRIORITY)); - } else if (cliParser.hasOption(SIGNAL_CMD)) { - if (hasAnyOtherCLIOptions(cliParser, opts, SIGNAL_CMD)) { - printUsage(title, opts); - return exitCode; - } - final String[] signalArgs = cliParser.getOptionValues(SIGNAL_CMD); - final String containerId = signalArgs[0]; - SignalContainerCommand command = - SignalContainerCommand.OUTPUT_THREAD_DUMP; - if (signalArgs.length == 2) { - command = SignalContainerCommand.valueOf(signalArgs[1]); - } - signalToContainer(containerId, command); - } else if (cliParser.hasOption(SHELL_CMD)) { - if (hasAnyOtherCLIOptions(cliParser, opts, SHELL_CMD)) { - printUsage(title, opts); - return exitCode; - } - final String[] shellArgs = cliParser.getOptionValues(SHELL_CMD); - final String containerId = shellArgs[0]; - ShellContainerCommand command = - ShellContainerCommand.BASH; - if (shellArgs.length == 2) { - command = ShellContainerCommand.valueOf(shellArgs[1].toUpperCase()); - } - shellToContainer(containerId, command); - } else if (cliParser.hasOption(LAUNCH_CMD)) { - if (hasAnyOtherCLIOptions(cliParser, opts, LAUNCH_CMD, APP_TYPE_CMD, - UPDATE_LIFETIME, CHANGE_APPLICATION_QUEUE)) { - printUsage(title, opts); - return exitCode; - } - String appType = getSingleAppTypeFromCLI(cliParser); - Long lifetime = null; - if (cliParser.hasOption(UPDATE_LIFETIME)) { - lifetime = Long.parseLong(cliParser.getOptionValue(UPDATE_LIFETIME)); - } - String queue = null; - if (cliParser.hasOption(CHANGE_APPLICATION_QUEUE)) { - queue = cliParser.getOptionValue(CHANGE_APPLICATION_QUEUE); - } - String[] nameAndFile = cliParser.getOptionValues(LAUNCH_CMD); - return AppAdminClient.createAppAdminClient(appType, getConf()) - .actionLaunch(nameAndFile[1], nameAndFile[0], lifetime, queue); - } else if (cliParser.hasOption(STOP_CMD)) { - if (hasAnyOtherCLIOptions(cliParser, opts, STOP_CMD, APP_TYPE_CMD)) { - printUsage(title, opts); - return exitCode; - } - String[] appNameAndType = getAppNameAndType(cliParser, STOP_CMD); - return AppAdminClient.createAppAdminClient(appNameAndType[1], getConf()) - .actionStop(appNameAndType[0]); - } else if (cliParser.hasOption(START_CMD)) { - if (hasAnyOtherCLIOptions(cliParser, opts, START_CMD, APP_TYPE_CMD)) { - printUsage(title, opts); - return exitCode; - } - String appType = getSingleAppTypeFromCLI(cliParser); - return AppAdminClient.createAppAdminClient(appType, getConf()) - .actionStart(cliParser.getOptionValue(START_CMD)); - } else if (cliParser.hasOption(SAVE_CMD)) { - if (hasAnyOtherCLIOptions(cliParser, opts, SAVE_CMD, APP_TYPE_CMD, - UPDATE_LIFETIME, CHANGE_APPLICATION_QUEUE)) { - printUsage(title, opts); - return exitCode; - } - String appType = getSingleAppTypeFromCLI(cliParser); - Long lifetime = null; - if (cliParser.hasOption(UPDATE_LIFETIME)) { - lifetime = Long.parseLong(cliParser.getOptionValue(UPDATE_LIFETIME)); - } - String queue = null; - if (cliParser.hasOption(CHANGE_APPLICATION_QUEUE)) { - queue = cliParser.getOptionValue(CHANGE_APPLICATION_QUEUE); - } - String[] nameAndFile = cliParser.getOptionValues(SAVE_CMD); - return AppAdminClient.createAppAdminClient(appType, getConf()) - .actionSave(nameAndFile[1], nameAndFile[0], lifetime, queue); - } else if (cliParser.hasOption(DESTROY_CMD)) { - if (hasAnyOtherCLIOptions(cliParser, opts, DESTROY_CMD, APP_TYPE_CMD)) { - printUsage(title, opts); - return exitCode; - } - String appType = getSingleAppTypeFromCLI(cliParser); - return AppAdminClient.createAppAdminClient(appType, getConf()) - .actionDestroy(cliParser.getOptionValue(DESTROY_CMD)); - } else if (cliParser.hasOption(FLEX_CMD)) { - if (!cliParser.hasOption(COMPONENT) || - hasAnyOtherCLIOptions(cliParser, opts, FLEX_CMD, COMPONENT, - APP_TYPE_CMD)) { - printUsage(title, opts); - return exitCode; - } - String[] rawCounts = cliParser.getOptionValues(COMPONENT); - Map counts = new HashMap<>(rawCounts.length/2); - for (int i = 0; i < rawCounts.length - 1; i+=2) { - counts.put(rawCounts[i], rawCounts[i+1]); - } - String[] appNameAndType = getAppNameAndType(cliParser, FLEX_CMD); - return AppAdminClient.createAppAdminClient(appNameAndType[1], getConf()) - .actionFlex(appNameAndType[0], counts); - } else if (cliParser.hasOption(ENABLE_FAST_LAUNCH)) { - String appType = getSingleAppTypeFromCLI(cliParser); - String uploadDestinationFolder = cliParser - .getOptionValue(ENABLE_FAST_LAUNCH); - if (hasAnyOtherCLIOptions(cliParser, opts, ENABLE_FAST_LAUNCH, - APP_TYPE_CMD)) { - printUsage(title, opts); - return exitCode; - } - return AppAdminClient.createAppAdminClient(appType, getConf()) - .enableFastLaunch(uploadDestinationFolder); - } else if (cliParser.hasOption(UPDATE_LIFETIME)) { - if (!cliParser.hasOption(APP_ID)) { - printUsage(title, opts); - return exitCode; - } - - long timeoutInSec = - Long.parseLong(cliParser.getOptionValue(UPDATE_LIFETIME)); - - updateApplicationTimeout(cliParser.getOptionValue(APP_ID), - ApplicationTimeoutType.LIFETIME, timeoutInSec); - } else if (cliParser.hasOption(CHANGE_APPLICATION_QUEUE)) { - if (!cliParser.hasOption(APP_ID)) { - printUsage(title, opts); - return exitCode; - } - moveApplicationAcrossQueues(cliParser.getOptionValue(APP_ID), - cliParser.getOptionValue(CHANGE_APPLICATION_QUEUE)); - } else if (cliParser.hasOption(UPGRADE_CMD)) { - if (hasAnyOtherCLIOptions(cliParser, opts, UPGRADE_CMD, UPGRADE_EXPRESS, - UPGRADE_INITIATE, UPGRADE_AUTO_FINALIZE, UPGRADE_FINALIZE, - UPGRADE_CANCEL, COMPONENT_INSTS, COMPONENTS, APP_TYPE_CMD)) { - printUsage(title, opts); - return exitCode; - } - String appType = getSingleAppTypeFromCLI(cliParser); - AppAdminClient client = AppAdminClient.createAppAdminClient(appType, - getConf()); - String appName = cliParser.getOptionValue(UPGRADE_CMD); - if (cliParser.hasOption(UPGRADE_EXPRESS)) { - File file = new File(cliParser.getOptionValue(UPGRADE_EXPRESS)); - if (!file.exists()) { - System.err.println(file.getAbsolutePath() + " does not exist."); - return exitCode; - } - return client.actionUpgradeExpress(appName, file); - } else if (cliParser.hasOption(UPGRADE_INITIATE)) { - if (hasAnyOtherCLIOptions(cliParser, opts, UPGRADE_CMD, - UPGRADE_INITIATE, UPGRADE_AUTO_FINALIZE, APP_TYPE_CMD)) { - printUsage(title, opts); - return exitCode; - } - String fileName = cliParser.getOptionValue(UPGRADE_INITIATE); - if (cliParser.hasOption(UPGRADE_AUTO_FINALIZE)) { - return client.initiateUpgrade(appName, fileName, true); - } else { - return client.initiateUpgrade(appName, fileName, false); - } - } else if (cliParser.hasOption(COMPONENT_INSTS)) { - if (hasAnyOtherCLIOptions(cliParser, opts, UPGRADE_CMD, - COMPONENT_INSTS, APP_TYPE_CMD)) { - printUsage(title, opts); - return exitCode; - } - String[] instances = cliParser.getOptionValues(COMPONENT_INSTS); - return client.actionUpgradeInstances(appName, Arrays.asList(instances)); - } else if (cliParser.hasOption(COMPONENTS)) { - if (hasAnyOtherCLIOptions(cliParser, opts, UPGRADE_CMD, - COMPONENTS, APP_TYPE_CMD)) { - printUsage(title, opts); - return exitCode; - } - String[] components = cliParser.getOptionValues(COMPONENTS); - return client.actionUpgradeComponents(appName, - Arrays.asList(components)); - } else if (cliParser.hasOption(UPGRADE_FINALIZE)) { - if (hasAnyOtherCLIOptions(cliParser, opts, UPGRADE_CMD, - UPGRADE_FINALIZE, APP_TYPE_CMD)) { - printUsage(title, opts); - return exitCode; - } - return client.actionStart(appName); - } else if (cliParser.hasOption(UPGRADE_CANCEL)) { - if (hasAnyOtherCLIOptions(cliParser, opts, UPGRADE_CMD, - UPGRADE_CANCEL, APP_TYPE_CMD)) { - printUsage(title, opts); - return exitCode; - } - return client.actionCancelUpgrade(appName); - } - } else if (cliParser.hasOption(DECOMMISSION)) { - if (!cliParser.hasOption(COMPONENT_INSTS) || - hasAnyOtherCLIOptions(cliParser, opts, DECOMMISSION, COMPONENT_INSTS, - APP_TYPE_CMD)) { - printUsage(title, opts); - return exitCode; - } - String[] instances = cliParser.getOptionValues(COMPONENT_INSTS); - String[] appNameAndType = getAppNameAndType(cliParser, DECOMMISSION); - return AppAdminClient.createAppAdminClient(appNameAndType[1], getConf()) - .actionDecommissionInstances(appNameAndType[0], - Arrays.asList(instances)); } else { syserr.println("Invalid Command Usage : "); printUsage(title, opts); @@ -881,7 +333,7 @@ public class ApplicationCLI extends YarnCLI { /** * Prints the application attempt report for an application attempt id. - * + * * @param applicationAttemptId * @return exitCode * @throws YarnException @@ -938,7 +390,7 @@ public class ApplicationCLI extends YarnCLI { /** * Prints the container report for an container id. - * + * * @param containerId * @return exitCode * @throws YarnException @@ -1142,7 +594,7 @@ public class ApplicationCLI extends YarnCLI { /** * Prints the application report for an application id. - * + * * @param applicationId * @return ApplicationReport * @throws YarnException @@ -1335,6 +787,688 @@ public class ApplicationCLI extends YarnCLI { } } + private void addApplicationOptions(Options opts) { + opts.addOption(STATUS_CMD, true, "Prints the status of the application. " + + "If app ID is provided, it prints the generic YARN application " + + "status. If name is provided, it prints the application specific " + + "status based on app's own implementation, and -appTypes option " + + "must be specified unless it is the default yarn-service type."); + opts.addOption(LIST_CMD, false, "List applications. Supports optional use " + + "of -appTypes to filter applications based on application type, " + + "-appStates to filter applications based on application state and " + + "-appTags to filter applications based on application tag."); + opts.addOption(MOVE_TO_QUEUE_CMD, true, "Moves the application to a " + + "different queue. Deprecated command. Use 'changeQueue' instead."); + opts.addOption(QUEUE_CMD, true, "Works with the movetoqueue command to" + + " specify which queue to move an application to."); + opts.addOption(HELP_CMD, false, "Displays help for all commands."); + Option appTypeOpt = new Option(APP_TYPE_CMD, true, "Works with -list to " + + "filter applications based on input comma-separated list of " + + "application types."); + appTypeOpt.setValueSeparator(','); + appTypeOpt.setArgs(Option.UNLIMITED_VALUES); + appTypeOpt.setArgName("Types"); + opts.addOption(appTypeOpt); + Option appStateOpt = new Option(APP_STATE_CMD, true, "Works with -list to " + + "filter applications based on input comma-separated list of " + + "application states. " + getAllValidApplicationStates()); + appStateOpt.setValueSeparator(','); + appStateOpt.setArgs(Option.UNLIMITED_VALUES); + appStateOpt.setArgName("States"); + opts.addOption(appStateOpt); + Option appTagOpt = new Option(APP_TAG_CMD, true, "Works with -list to " + + "filter applications based on input comma-separated list of " + + "application tags."); + appTagOpt.setValueSeparator(','); + appTagOpt.setArgs(Option.UNLIMITED_VALUES); + appTagOpt.setArgName("Tags"); + opts.addOption(appTagOpt); + opts.addOption(APP_ID, true, "Specify Application Id to be operated"); + opts.addOption(UPDATE_PRIORITY, true, "update priority of an application. " + + "ApplicationId can be passed using 'appId' option."); + opts.addOption(UPDATE_LIFETIME, true, "update timeout of an application " + + "from NOW. ApplicationId can be passed using 'appId' option. Timeout " + + "value is in seconds."); + opts.addOption(CHANGE_APPLICATION_QUEUE, true, "Moves application to a new " + + "queue. ApplicationId can be passed using 'appId' option. " + + "'movetoqueue' command is deprecated, this new command " + + "'changeQueue' performs same functionality."); + Option killOpt = new Option(KILL_CMD, true, "Kills the application. Set of " + + "applications can be provided separated with space"); + killOpt.setValueSeparator(' '); + killOpt.setArgs(Option.UNLIMITED_VALUES); + killOpt.setArgName("Application ID"); + opts.addOption(killOpt); + opts.getOption(MOVE_TO_QUEUE_CMD).setArgName("Application ID"); + opts.getOption(QUEUE_CMD).setArgName("Queue Name"); + opts.getOption(STATUS_CMD).setArgName("Application Name or ID"); + opts.getOption(APP_ID).setArgName("Application ID"); + opts.getOption(UPDATE_PRIORITY).setArgName("Priority"); + opts.getOption(UPDATE_LIFETIME).setArgName("Timeout"); + opts.getOption(CHANGE_APPLICATION_QUEUE).setArgName("Queue Name"); + opts.addOption(LAUNCH_CMD, true, "Launches application from specification " + + "file (saves specification and starts application). Options " + + "-updateLifetime and -changeQueue can be specified to alter the " + + "values provided in the file. Supports -appTypes option to specify " + + "which client implementation to use."); + opts.addOption(STOP_CMD, true, "Stops application gracefully (may be " + + "started again later). If name is provided, appType must be " + + "provided unless it is the default yarn-service. If ID is provided, " + + "the appType will be looked up. Supports -appTypes option to specify " + + "which client implementation to use."); + opts.addOption(START_CMD, true, "Starts a previously saved application. " + + "Supports -appTypes option to specify which client implementation " + + "to use."); + opts.addOption(SAVE_CMD, true, "Saves specification file for an " + + "application. Options -updateLifetime and -changeQueue can be " + + "specified to alter the values provided in the file. Supports " + + "-appTypes option to specify which client implementation to use."); + opts.addOption(DESTROY_CMD, true, "Destroys a saved application " + + "specification and removes all application data permanently. " + + "Supports -appTypes option to specify which client implementation " + + "to use."); + opts.addOption(FLEX_CMD, true, "Changes number of running containers for a " + + "component of an application / long-running service. Requires " + + "-component option. If name is provided, appType must be provided " + + "unless it is the default yarn-service. If ID is provided, the " + + "appType will be looked up. Supports -appTypes option to specify " + + "which client implementation to use."); + opts.addOption(DECOMMISSION, true, "Decommissions component instances for " + + "an application / long-running service. Requires -instances option. " + + "Supports -appTypes option to specify which client implementation to " + + "use."); + opts.addOption(COMPONENT, true, "Works with -flex option to change the " + + "number of components/containers running for an application / " + + "long-running service. Supports absolute or relative changes, such " + + "as +1, 2, or -3."); + opts.addOption(ENABLE_FAST_LAUNCH, true, "Uploads AM dependencies to HDFS " + + "to make future launches faster. Supports -appTypes option to " + + "specify which client implementation to use. Optionally a " + + "destination folder for the tarball can be specified."); + opts.addOption(UPGRADE_CMD, true, "Upgrades an application/long-running " + + "service. It requires either -initiate, -instances, or -finalize " + + "options."); + opts.addOption(UPGRADE_EXPRESS, true, "Works with -upgrade option to " + + "perform express upgrade. It requires the upgraded application " + + "specification file."); + opts.addOption(UPGRADE_INITIATE, true, "Works with -upgrade option to " + + "initiate the application upgrade. It requires the upgraded " + + "application specification file."); + opts.addOption(COMPONENT_INSTS, true, "Works with -upgrade option to " + + "trigger the upgrade of specified component instances of the " + + "application. Also works with -decommission option to decommission " + + "specified component instances. Multiple instances should be " + + "separated by commas."); + opts.addOption(COMPONENTS, true, "Works with -upgrade option to trigger " + + "the upgrade of specified components of the application. Multiple " + + "components should be separated by commas."); + opts.addOption(UPGRADE_FINALIZE, false, "Works with -upgrade option to " + + "finalize the upgrade."); + opts.addOption(UPGRADE_AUTO_FINALIZE, false, "Works with -upgrade and " + + "-initiate options to initiate the upgrade of the application with " + + "the ability to finalize the upgrade automatically."); + opts.addOption(UPGRADE_CANCEL, false, "Works with -upgrade option to " + + "cancel current upgrade."); + opts.addOption(CLUSTER_ID_OPTION, true, "ClusterId. By default, it will " + + "take default cluster id from the RM"); + opts.getOption(LAUNCH_CMD).setArgName("Application Name> appTypes = new HashSet<>(); + if (cliParser.hasOption(APP_TYPE_CMD)) { + String[] types = cliParser.getOptionValues(APP_TYPE_CMD); + if (types != null) { + for (String type : types) { + if (!type.trim().isEmpty()) { + appTypes.add(StringUtils.toUpperCase(type).trim()); + } + } + } + } + + EnumSet appStates = EnumSet.noneOf( + YarnApplicationState.class); + if (cliParser.hasOption(APP_STATE_CMD)) { + String[] states = cliParser.getOptionValues(APP_STATE_CMD); + if (states != null) { + for (String state : states) { + if (!state.trim().isEmpty()) { + if (state.trim().equalsIgnoreCase(ALLSTATES_OPTION)) { + allAppStates = true; + break; + } + try { + appStates.add(YarnApplicationState.valueOf( + StringUtils.toUpperCase(state).trim())); + } catch (IllegalArgumentException ex) { + sysout.println("The application state " + state + + " is invalid."); + sysout.println(getAllValidApplicationStates()); + return exitCode; + } + } + } + } + } + + Set appTags = new HashSet<>(); + if (cliParser.hasOption(APP_TAG_CMD)) { + String[] tags = cliParser.getOptionValues(APP_TAG_CMD); + if (tags != null) { + for (String tag : tags) { + if (!tag.trim().isEmpty()) { + appTags.add(tag.trim()); + } + } + } + } + listApplications(appTypes, appStates, appTags); + } else if (APPLICATION_ATTEMPT.equalsIgnoreCase(title)) { + if (hasAnyOtherCLIOptions(cliParser, opts, LIST_CMD)) { + printUsage(title, opts); + return exitCode; + } + listApplicationAttempts(cliParser.getOptionValue(LIST_CMD)); + } else if (CONTAINER.equalsIgnoreCase(title)) { + if (hasAnyOtherCLIOptions(cliParser, opts, LIST_CMD, APP_TYPE_CMD, + VERSION, COMPONENTS, STATES)) { + printUsage(title, opts); + return exitCode; + } + String appAttemptIdOrName = cliParser.getOptionValue(LIST_CMD); + try { + // try parsing attempt id, if it succeeds, it means it's appId + ApplicationAttemptId.fromString(appAttemptIdOrName); + listContainers(appAttemptIdOrName); + } catch (IllegalArgumentException e) { + // not appAttemptId format, it could be appName. If app-type is not + // provided, assume it is yarn-service type. + AppAdminClient client = AppAdminClient.createAppAdminClient( + getSingleAppTypeFromCLI(cliParser), getConf()); + String version = cliParser.getOptionValue(VERSION); + String[] components = cliParser.getOptionValues(COMPONENTS); + String[] instanceStates = cliParser.getOptionValues(STATES); + try { + sysout.println(client.getInstances(appAttemptIdOrName, + components == null ? null : Arrays.asList(components), + version, instanceStates == null ? null : + Arrays.asList(instanceStates))); + return 0; + } catch (ApplicationNotFoundException exception) { + System.err.println("Application with name '" + appAttemptIdOrName + + "' doesn't exist in RM or Timeline Server."); + return -1; + } catch (Exception ex) { + System.err.println(ex.getMessage()); + return -1; + } + } + } + return 0; + } + + private int executeKillCommand(CommandLine cliParser, String title, + Options opts) throws Exception { + int exitCode = -1; + if (hasAnyOtherCLIOptions(cliParser, opts, KILL_CMD)) { + printUsage(title, opts); + return exitCode; + } + return killApplication(cliParser.getOptionValues(KILL_CMD)); + } + + private int executeMoveToQueueCommand(CommandLine cliParser, String title, + Options opts) throws Exception { + int exitCode = -1; + if (!cliParser.hasOption(QUEUE_CMD)) { + printUsage(title, opts); + return exitCode; + } + moveApplicationAcrossQueues(cliParser.getOptionValue(MOVE_TO_QUEUE_CMD), + cliParser.getOptionValue(QUEUE_CMD)); + return 0; + } + + private int executeFailCommand(CommandLine cliParser, String title, + Options opts) throws Exception { + int exitCode = -1; + if (!title.equalsIgnoreCase(APPLICATION_ATTEMPT)) { + printUsage(title, opts); + return exitCode; + } + failApplicationAttempt(cliParser.getOptionValue(FAIL_CMD)); + return 0; + } + + private int executeUpdatePriorityCommand(CommandLine cliParser, String title, + Options opts) throws Exception { + int exitCode = -1; + if (!cliParser.hasOption(APP_ID)) { + printUsage(title, opts); + return exitCode; + } + updateApplicationPriority(cliParser.getOptionValue(APP_ID), + cliParser.getOptionValue(UPDATE_PRIORITY)); + return 0; + } + + private int executeSignalCommand(CommandLine cliParser, String title, + Options opts) throws Exception { + int exitCode = -1; + if (hasAnyOtherCLIOptions(cliParser, opts, SIGNAL_CMD)) { + printUsage(title, opts); + return exitCode; + } + final String[] signalArgs = cliParser.getOptionValues(SIGNAL_CMD); + final String containerId = signalArgs[0]; + SignalContainerCommand command = + SignalContainerCommand.OUTPUT_THREAD_DUMP; + if (signalArgs.length == 2) { + command = SignalContainerCommand.valueOf(signalArgs[1]); + } + signalToContainer(containerId, command); + return 0; + } + + private int executeShellCommand(CommandLine cliParser, String title, + Options opts) throws Exception { + int exitCode = -1; + if (hasAnyOtherCLIOptions(cliParser, opts, SHELL_CMD)) { + printUsage(title, opts); + return exitCode; + } + final String[] shellArgs = cliParser.getOptionValues(SHELL_CMD); + final String containerId = shellArgs[0]; + ShellContainerCommand command = + ShellContainerCommand.BASH; + if (shellArgs.length == 2) { + command = ShellContainerCommand.valueOf(shellArgs[1].toUpperCase()); + } + shellToContainer(containerId, command); + return 0; + } + + private int executeLaunchCommand(CommandLine cliParser, String title, + Options opts) throws Exception { + int exitCode = -1; + if (hasAnyOtherCLIOptions(cliParser, opts, LAUNCH_CMD, APP_TYPE_CMD, + UPDATE_LIFETIME, CHANGE_APPLICATION_QUEUE)) { + printUsage(title, opts); + return exitCode; + } + String appType = getSingleAppTypeFromCLI(cliParser); + Long lifetime = null; + if (cliParser.hasOption(UPDATE_LIFETIME)) { + lifetime = Long.parseLong(cliParser.getOptionValue(UPDATE_LIFETIME)); + } + String queue = null; + if (cliParser.hasOption(CHANGE_APPLICATION_QUEUE)) { + queue = cliParser.getOptionValue(CHANGE_APPLICATION_QUEUE); + } + String[] nameAndFile = cliParser.getOptionValues(LAUNCH_CMD); + return AppAdminClient.createAppAdminClient(appType, getConf()) + .actionLaunch(nameAndFile[1], nameAndFile[0], lifetime, queue); + } + + private int executeStopCommand(CommandLine cliParser, String title, + Options opts) throws Exception { + int exitCode = -1; + if (hasAnyOtherCLIOptions(cliParser, opts, STOP_CMD, APP_TYPE_CMD)) { + printUsage(title, opts); + return exitCode; + } + String[] appNameAndType = getAppNameAndType(cliParser, STOP_CMD); + return AppAdminClient.createAppAdminClient(appNameAndType[1], getConf()) + .actionStop(appNameAndType[0]); + } + + private int executeStartCommand(CommandLine cliParser, String title, + Options opts) throws Exception { + int exitCode = -1; + if (hasAnyOtherCLIOptions(cliParser, opts, START_CMD, APP_TYPE_CMD)) { + printUsage(title, opts); + return exitCode; + } + String appType = getSingleAppTypeFromCLI(cliParser); + return AppAdminClient.createAppAdminClient(appType, getConf()) + .actionStart(cliParser.getOptionValue(START_CMD)); + } + + private int executeSaveCommand(CommandLine cliParser, String title, + Options opts) throws Exception { + int exitCode = -1; + if (hasAnyOtherCLIOptions(cliParser, opts, SAVE_CMD, APP_TYPE_CMD, + UPDATE_LIFETIME, CHANGE_APPLICATION_QUEUE)) { + printUsage(title, opts); + return exitCode; + } + String appType = getSingleAppTypeFromCLI(cliParser); + Long lifetime = null; + if (cliParser.hasOption(UPDATE_LIFETIME)) { + lifetime = Long.parseLong(cliParser.getOptionValue(UPDATE_LIFETIME)); + } + String queue = null; + if (cliParser.hasOption(CHANGE_APPLICATION_QUEUE)) { + queue = cliParser.getOptionValue(CHANGE_APPLICATION_QUEUE); + } + String[] nameAndFile = cliParser.getOptionValues(SAVE_CMD); + return AppAdminClient.createAppAdminClient(appType, getConf()) + .actionSave(nameAndFile[1], nameAndFile[0], lifetime, queue); + } + + private int executeDestroyCommand(CommandLine cliParser, String title, + Options opts) throws Exception { + int exitCode = -1; + if (hasAnyOtherCLIOptions(cliParser, opts, DESTROY_CMD, APP_TYPE_CMD)) { + printUsage(title, opts); + return exitCode; + } + String appType = getSingleAppTypeFromCLI(cliParser); + return AppAdminClient.createAppAdminClient(appType, getConf()) + .actionDestroy(cliParser.getOptionValue(DESTROY_CMD)); + } + + private int executeFlexCommand(CommandLine cliParser, String title, + Options opts) throws Exception { + int exitCode = -1; + if (!cliParser.hasOption(COMPONENT) || + hasAnyOtherCLIOptions(cliParser, opts, FLEX_CMD, COMPONENT, + APP_TYPE_CMD)) { + printUsage(title, opts); + return exitCode; + } + String[] rawCounts = cliParser.getOptionValues(COMPONENT); + Map counts = new HashMap<>(rawCounts.length/2); + for (int i = 0; i < rawCounts.length - 1; i+=2) { + counts.put(rawCounts[i], rawCounts[i+1]); + } + String[] appNameAndType = getAppNameAndType(cliParser, FLEX_CMD); + return AppAdminClient.createAppAdminClient(appNameAndType[1], getConf()) + .actionFlex(appNameAndType[0], counts); + } + + private int executeEnableFastLaunchCommand(CommandLine cliParser, + String title, Options opts) throws Exception { + int exitCode = -1; + String appType = getSingleAppTypeFromCLI(cliParser); + String uploadDestinationFolder = cliParser + .getOptionValue(ENABLE_FAST_LAUNCH); + if (hasAnyOtherCLIOptions(cliParser, opts, ENABLE_FAST_LAUNCH, + APP_TYPE_CMD)) { + printUsage(title, opts); + return exitCode; + } + return AppAdminClient.createAppAdminClient(appType, getConf()) + .enableFastLaunch(uploadDestinationFolder); + } + + private int executeUpdateLifeTimeCommand(CommandLine cliParser, String title, + Options opts) throws Exception { + int exitCode = -1; + if (!cliParser.hasOption(APP_ID)) { + printUsage(title, opts); + return exitCode; + } + long timeoutInSec = Long.parseLong( + cliParser.getOptionValue(UPDATE_LIFETIME)); + updateApplicationTimeout(cliParser.getOptionValue(APP_ID), + ApplicationTimeoutType.LIFETIME, timeoutInSec); + return 0; + } + + private int executeChangeApplicationQueueCommand(CommandLine cliParser, + String title, Options opts) throws Exception { + int exitCode = -1; + if (!cliParser.hasOption(APP_ID)) { + printUsage(title, opts); + return exitCode; + } + moveApplicationAcrossQueues(cliParser.getOptionValue(APP_ID), + cliParser.getOptionValue(CHANGE_APPLICATION_QUEUE)); + return 0; + } + + private int executeUpgradeCommand(CommandLine cliParser, String title, + Options opts) throws Exception { + int exitCode = -1; + if (hasAnyOtherCLIOptions(cliParser, opts, UPGRADE_CMD, UPGRADE_EXPRESS, + UPGRADE_INITIATE, UPGRADE_AUTO_FINALIZE, UPGRADE_FINALIZE, + UPGRADE_CANCEL, COMPONENT_INSTS, COMPONENTS, APP_TYPE_CMD)) { + printUsage(title, opts); + return exitCode; + } + String appType = getSingleAppTypeFromCLI(cliParser); + AppAdminClient client = AppAdminClient.createAppAdminClient(appType, + getConf()); + String appName = cliParser.getOptionValue(UPGRADE_CMD); + if (cliParser.hasOption(UPGRADE_EXPRESS)) { + File file = new File(cliParser.getOptionValue(UPGRADE_EXPRESS)); + if (!file.exists()) { + System.err.println(file.getAbsolutePath() + " does not exist."); + return exitCode; + } + return client.actionUpgradeExpress(appName, file); + } else if (cliParser.hasOption(UPGRADE_INITIATE)) { + if (hasAnyOtherCLIOptions(cliParser, opts, UPGRADE_CMD, + UPGRADE_INITIATE, UPGRADE_AUTO_FINALIZE, APP_TYPE_CMD)) { + printUsage(title, opts); + return exitCode; + } + String fileName = cliParser.getOptionValue(UPGRADE_INITIATE); + if (cliParser.hasOption(UPGRADE_AUTO_FINALIZE)) { + return client.initiateUpgrade(appName, fileName, true); + } else { + return client.initiateUpgrade(appName, fileName, false); + } + } else if (cliParser.hasOption(COMPONENT_INSTS)) { + if (hasAnyOtherCLIOptions(cliParser, opts, UPGRADE_CMD, + COMPONENT_INSTS, APP_TYPE_CMD)) { + printUsage(title, opts); + return exitCode; + } + String[] instances = cliParser.getOptionValues(COMPONENT_INSTS); + return client.actionUpgradeInstances(appName, Arrays.asList(instances)); + } else if (cliParser.hasOption(COMPONENTS)) { + if (hasAnyOtherCLIOptions(cliParser, opts, UPGRADE_CMD, + COMPONENTS, APP_TYPE_CMD)) { + printUsage(title, opts); + return exitCode; + } + String[] components = cliParser.getOptionValues(COMPONENTS); + return client.actionUpgradeComponents(appName, + Arrays.asList(components)); + } else if (cliParser.hasOption(UPGRADE_FINALIZE)) { + if (hasAnyOtherCLIOptions(cliParser, opts, UPGRADE_CMD, + UPGRADE_FINALIZE, APP_TYPE_CMD)) { + printUsage(title, opts); + return exitCode; + } + return client.actionStart(appName); + } else if (cliParser.hasOption(UPGRADE_CANCEL)) { + if (hasAnyOtherCLIOptions(cliParser, opts, UPGRADE_CMD, + UPGRADE_CANCEL, APP_TYPE_CMD)) { + printUsage(title, opts); + return exitCode; + } + return client.actionCancelUpgrade(appName); + } + return 0; + } + + private int executeDecommissionCommand(CommandLine cliParser, String title, + Options opts) throws Exception { + int exitCode = -1; + if (!cliParser.hasOption(COMPONENT_INSTS) || + hasAnyOtherCLIOptions(cliParser, opts, DECOMMISSION, COMPONENT_INSTS, + APP_TYPE_CMD)) { + printUsage(title, opts); + return exitCode; + } + String[] instances = cliParser.getOptionValues(COMPONENT_INSTS); + String[] appNameAndType = getAppNameAndType(cliParser, DECOMMISSION); + return AppAdminClient.createAppAdminClient(appNameAndType[1], getConf()) + .actionDecommissionInstances(appNameAndType[0], + Arrays.asList(instances)); + } + @SuppressWarnings("unchecked") private boolean hasAnyOtherCLIOptions(CommandLine cliParser, Options opts, String... excludeOptions) { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/cli/TestYarnCLI.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/cli/TestYarnCLI.java index 939ae461713..9ee5b871df2 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/cli/TestYarnCLI.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/cli/TestYarnCLI.java @@ -2027,9 +2027,8 @@ public class TestYarnCLI { @Test public void testFailApplicationAttempt() throws Exception { ApplicationCLI cli = createAndGetAppCLI(); - int exitCode = - cli.run(new String[] { "applicationattempt", "-fail", - "appattempt_1444199730803_0003_000001" }); + int exitCode = cli.run(new String[] {"applicationattempt", "-fail", + "appattempt_1444199730803_0003_000001"}); Assert.assertEquals(0, exitCode); verify(client).failApplicationAttempt(any(ApplicationAttemptId.class));