diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/cli/ApplicationCLI.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/cli/ApplicationCLI.java index b486074..a35f10d 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/cli/ApplicationCLI.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/cli/ApplicationCLI.java @@ -79,6 +79,8 @@ public static final String CONTAINER = "container"; public static final String APP_ID = "appId"; public static final String UPDATE_PRIORITY = "updatePriority"; + public static final String APP_KILL_BY_APPSTATES_CMD = "killByAppStates"; + public static final String APP_KILL_BY_USER_CMD = "killByUser"; private boolean allAppStates; @@ -109,6 +111,8 @@ public int run(String[] args) throws Exception { 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."); + opts.addOption(APP_KILL_BY_USER_CMD, true, + "Kill running-state applications of specific user."); Option appTypeOpt = new Option(APP_TYPE_CMD, true, "Works with -list to " + "filter applications based on " + "input comma-separated list of application types."); @@ -127,12 +131,20 @@ public int run(String[] args) throws Exception { opts.addOption(UPDATE_PRIORITY, true, "update priority of an application. ApplicationId can be" + " passed using 'appId' option."); + Option killAppStateOpt = + new Option(APP_KILL_BY_APPSTATES_CMD, true, + "The states of application that will be killed."); + killAppStateOpt.setValueSeparator(','); + killAppStateOpt.setArgs(Option.UNLIMITED_VALUES); + killAppStateOpt.setArgName("States"); + opts.addOption(killAppStateOpt); opts.getOption(KILL_CMD).setArgName("Application ID"); opts.getOption(MOVE_TO_QUEUE_CMD).setArgName("Application ID"); opts.getOption(QUEUE_CMD).setArgName("Queue Name"); opts.getOption(STATUS_CMD).setArgName("Application ID"); opts.getOption(APP_ID).setArgName("Application ID"); opts.getOption(UPDATE_PRIORITY).setArgName("Priority"); + opts.getOption(APP_KILL_BY_USER_CMD).setArgName("User name"); } else if (args.length > 0 && args[0].equalsIgnoreCase(APPLICATION_ATTEMPT)) { title = APPLICATION_ATTEMPT; opts.addOption(STATUS_CMD, true, @@ -284,6 +296,47 @@ public int run(String[] args) throws Exception { command = SignalContainerCommand.valueOf(signalArgs[1]); } signalContainer(containerId, command); + } else if (cliParser.hasOption(APP_KILL_BY_APPSTATES_CMD)) { + if (args.length != 3) { + printUsage(title, opts); + return exitCode; + } + + EnumSet appStates = + EnumSet.noneOf(YarnApplicationState.class); + String[] states = cliParser.getOptionValues(APP_KILL_BY_APPSTATES_CMD); + if (states != null) { + for (String state : states) { + if (!state.trim().isEmpty()) { + 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; + } + } + } + } + + try { + killApplicationsByAppStates(appStates); + } catch (ApplicationNotFoundException e) { + return exitCode; + } + } else if (cliParser.hasOption(APP_KILL_BY_USER_CMD)) { + if (args.length != 3) { + printUsage(title, opts); + return exitCode; + } + + try { + killRunningApplicationsOfUser(cliParser + .getOptionValue(APP_KILL_BY_USER_CMD)); + } catch (ApplicationNotFoundException e) { + return exitCode; + } } else { syserr.println("Invalid Command Usage : "); printUsage(title, opts); @@ -511,6 +564,67 @@ private void killApplication(String applicationId) throws YarnException, } /** + * Kill the applications by appStates + * + * @param appStates + * @throws IOException + */ + private void killApplicationsByAppStates( + EnumSet appStates) throws YarnException, + IOException { + if (appStates.contains(YarnApplicationState.FAILED) + || appStates.contains(YarnApplicationState.KILLED) + || appStates.contains(YarnApplicationState.FINISHED)) { + sysout + .println("The appState should not contain state failed, killed, finished"); + return; + } + + ApplicationId appId; + List appsReport = client.getApplications(appStates); + + if (appsReport.isEmpty()) { + sysout.println("There are no running applications."); + } else { + for (ApplicationReport report : appsReport) { + appId = report.getApplicationId(); + sysout.println("Killing application " + appId); + client.killApplication(appId); + } + } + } + + /** + * Kill the running applications of specific user + * + * @param user + * @throws IOException + */ + private void killRunningApplicationsOfUser(String user) throws YarnException, + IOException { + EnumSet appStates = + EnumSet.noneOf(YarnApplicationState.class); + appStates.add(YarnApplicationState.RUNNING); + + ApplicationId appId; + List appsReport = client.getApplications(appStates); + + if (appsReport.isEmpty()) { + sysout.println("There are no running applications of " + user); + } else { + for (ApplicationReport report : appsReport) { + if (!report.getUser().equals(user)) { + continue; + } + + appId = report.getApplicationId(); + sysout.println("Killing application " + appId); + client.killApplication(appId); + } + } + } + + /** * Moves the application with the given ID to the given queue. */ private void moveApplicationAcrossQueues(String applicationId, String queue) diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/cli/TestYarnCLI.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/cli/TestYarnCLI.java index 9ee7001..fac2b94 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/cli/TestYarnCLI.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/cli/TestYarnCLI.java @@ -870,6 +870,67 @@ public void testKillApplication() throws Exception { Assert.fail("Unexpected exception: " + e); } } + + @Test + public void testKillApplicationByAppStates() throws Exception { + EnumSet appStates = + EnumSet.noneOf(YarnApplicationState.class); + appStates.add(YarnApplicationState.RUNNING); + appStates.add(YarnApplicationState.SUBMITTED); + List appsReport = new ArrayList(); + ApplicationCLI cli = createAndGetAppCLI(); + ApplicationId applicationId = ApplicationId.newInstance(1234, 5); + + ApplicationReport newApplicationReport = + ApplicationReport.newInstance(applicationId, + ApplicationAttemptId.newInstance(applicationId, 1), "user", + "queue", "appname", "host", 124, null, + YarnApplicationState.RUNNING, "diagnostics", "url", 0, 0, + FinalApplicationStatus.SUCCEEDED, null, "N/A", 0.53789f, "YARN", + null); + + ApplicationReport newApplicationReport2 = + ApplicationReport.newInstance(applicationId, + ApplicationAttemptId.newInstance(applicationId, 1), "user", + "queue", "appname", "host", 124, null, + YarnApplicationState.SUBMITTED, "diagnostics", "url", 0, 0, + FinalApplicationStatus.SUCCEEDED, null, "N/A", 0.53789f, "YARN", + null); + appsReport.add(newApplicationReport); + appsReport.add(newApplicationReport2); + + when(client.getApplications(appStates)).thenReturn(appsReport); + int result = + cli.run(new String[] { "application", "-killByAppStates", + "RUNNING,SUBMITTED" }); + assertEquals(0, result); + verify(client, times(2)).killApplication(any(ApplicationId.class)); + } + + @Test + public void testKillApplicationByUser() throws Exception { + String user = "user"; + EnumSet appStates = + EnumSet.noneOf(YarnApplicationState.class); + appStates.add(YarnApplicationState.RUNNING); + List appsReport = new ArrayList(); + ApplicationCLI cli = createAndGetAppCLI(); + ApplicationId applicationId = ApplicationId.newInstance(1234, 5); + + ApplicationReport newApplicationReport = + ApplicationReport.newInstance(applicationId, + ApplicationAttemptId.newInstance(applicationId, 1), user, "queue", + "appname", "host", 124, null, YarnApplicationState.RUNNING, + "diagnostics", "url", 0, 0, FinalApplicationStatus.SUCCEEDED, null, + "N/A", 0.53789f, "YARN", null); + appsReport.add(newApplicationReport); + + when(client.getApplications(appStates)).thenReturn(appsReport); + int result = cli.run(new String[] { "application", "-killByUser", user }); + assertEquals(0, result); + verify(client).killApplication(any(ApplicationId.class)); + verify(sysOut).println("Killing application " + applicationId); + } @Test public void testMoveApplicationAcrossQueues() throws Exception { @@ -1517,6 +1578,10 @@ private String createApplicationCLIHelpMessage() throws IOException { pw.println(" application types."); pw.println(" -help Displays help for all commands."); pw.println(" -kill Kills the application."); + pw.println(" -killByAppStates The states of application that will be"); + pw.println(" killed."); + pw.println(" -killByUser Kill running-state applications of"); + pw.println(" specific user."); pw.println(" -list List applications. Supports optional use"); pw.println(" of -appTypes to filter applications based"); pw.println(" on application type, and -appStates to");