diff --git a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-jobclient/src/main/java/org/apache/hadoop/mapred/ResourceMgrDelegate.java b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-jobclient/src/main/java/org/apache/hadoop/mapred/ResourceMgrDelegate.java
index e65744b..507fc80 100644
--- a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-jobclient/src/main/java/org/apache/hadoop/mapred/ResourceMgrDelegate.java
+++ b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-jobclient/src/main/java/org/apache/hadoop/mapred/ResourceMgrDelegate.java
@@ -283,9 +283,15 @@ public YarnClientApplication createApplication() throws
}
@Override
+ public void killApplication(ApplicationId applicationId, String reason)
+ throws YarnException, IOException {
+ client.killApplication(applicationId, reason);
+ }
+
+ @Override
public void killApplication(ApplicationId applicationId)
throws YarnException, IOException {
- client.killApplication(applicationId);
+ killApplication(applicationId, null);
}
@Override
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/KillApplicationRequest.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/KillApplicationRequest.java
index 606cf4e..26a5a9d 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/KillApplicationRequest.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/KillApplicationRequest.java
@@ -20,6 +20,7 @@
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.classification.InterfaceStability.Stable;
+import org.apache.hadoop.classification.InterfaceStability.Evolving;
import org.apache.hadoop.yarn.api.ApplicationClientProtocol;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.util.Records;
@@ -53,8 +54,26 @@ public static KillApplicationRequest newInstance(ApplicationId applicationId) {
@Public
@Stable
public abstract ApplicationId getApplicationId();
-
+
+ /**
+ * Set the ApplicationId of the application to be aborted.
+ */
@Public
@Stable
public abstract void setApplicationId(ApplicationId applicationId);
+
+ /**
+ * Get the diagnostic Reason for the application abort.
+ * @return Reason for the application abort.
+ */
+ @Public
+ @Evolving
+ public abstract String getReason();
+
+ /**
+ * Set the diagnostic Reason for the application abort.
+ */
+ @Public
+ @Evolving
+ public abstract void setReason(String reason);
}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
index 8c8ad16..0487629 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
@@ -58,6 +58,9 @@
@Evolving
public static final int APPLICATION_MAX_TAG_LENGTH = 100;
+ @Evolving
+ public static final int MAX_KILL_REASON_LENGTH = 128;
+
private static final String YARN_DEFAULT_XML_FILE = "yarn-default.xml";
static {
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/proto/yarn_service_protos.proto b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/proto/yarn_service_protos.proto
index eff5cd7..faf5d66 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/proto/yarn_service_protos.proto
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/proto/yarn_service_protos.proto
@@ -115,6 +115,7 @@ message SubmitApplicationResponseProto {
message KillApplicationRequestProto {
optional ApplicationIdProto application_id = 1;
+ optional string reason = 2;
}
message KillApplicationResponseProto {
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/YarnClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/YarnClient.java
index c6db3ab..9a7333a 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/YarnClient.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/YarnClient.java
@@ -106,6 +106,25 @@ public abstract ApplicationId submitApplication(ApplicationSubmissionContext app
*
* @param applicationId
* {@link ApplicationId} of the application that needs to be killed
+ * @param reason justification for application kill. Callers are expected to
+ * use the same reason for repeated invocation attempts with the same
+ * application id.
+ * @throws YarnException
+ * in case of errors or if YARN rejects the request due to
+ * access-control restrictions.
+ * @throws IOException
+ * @see #getQueueAclsInfo()
+ */
+ public abstract void killApplication(ApplicationId applicationId,
+ String reason) throws YarnException, IOException;
+
+ /**
+ *
+ * Kill an application identified by given ID.
+ *
+ *
+ * @param applicationId
+ * {@link ApplicationId} of the application that needs to be killed
* @throws YarnException
* in case of errors or if YARN rejects the request due to
* access-control restrictions.
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/YarnClientImpl.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/YarnClientImpl.java
index feb3bb7..3c10d74 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/YarnClientImpl.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/YarnClientImpl.java
@@ -218,9 +218,16 @@ public YarnClientApplication createApplication()
@Override
public void killApplication(ApplicationId applicationId)
throws YarnException, IOException {
+ killApplication(applicationId, null);
+ }
+
+ @Override
+ public void killApplication(ApplicationId applicationId, String reason)
+ throws YarnException, IOException {
KillApplicationRequest request =
Records.newRecord(KillApplicationRequest.class);
request.setApplicationId(applicationId);
+ request.setReason(reason);
try {
int pollCount = 0;
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 4332f5b..96ee706 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
@@ -96,7 +96,10 @@ public int run(String[] args) throws Exception {
+ "based on application type, "
+ "and -appStates to filter applications based on application state");
}
- opts.addOption(KILL_CMD, true, "Kills the application.");
+ Option killOption = new Option(KILL_CMD, true, "Kills the application.");
+ killOption.setArgs(2);
+ killOption.setArgName("Application ID [reason]");
+ opts.addOption(killOption);
opts.addOption(MOVE_TO_QUEUE_CMD, true, "Moves the application to a "
+ "different queue.");
opts.addOption(QUEUE_CMD, true, "Works with the movetoqueue command to"
@@ -116,7 +119,6 @@ public int run(String[] args) throws Exception {
appStateOpt.setArgs(Option.UNLIMITED_VALUES);
appStateOpt.setArgName("States");
opts.addOption(appStateOpt);
- 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");
@@ -204,11 +206,12 @@ public int run(String[] args) throws Exception {
listApplications(appTypes, appStates);
}
} else if (cliParser.hasOption(KILL_CMD)) {
- if (args.length != 3) {
+ if (args.length < 3 || args.length > 4) {
printUsage(opts);
return exitCode;
}
- killApplication(cliParser.getOptionValue(KILL_CMD));
+ final String[] killArgs = cliParser.getOptionValues(KILL_CMD);
+ killApplication(killArgs[0], killArgs.length == 2 ? killArgs[1] : null);
} else if (cliParser.hasOption(MOVE_TO_QUEUE_CMD)) {
if (!cliParser.hasOption(QUEUE_CMD)) {
printUsage(opts);
@@ -364,11 +367,12 @@ private void listApplications(Set appTypes,
* Kills the application with the application id as appId
*
* @param applicationId
+ * @param reason
* @throws YarnException
* @throws IOException
*/
- private void killApplication(String applicationId) throws YarnException,
- IOException {
+ private void killApplication(String applicationId, String reason)
+ throws YarnException, IOException {
ApplicationId appId = ConverterUtils.toApplicationId(applicationId);
ApplicationReport appReport = client.getApplicationReport(appId);
if (appReport.getYarnApplicationState() == YarnApplicationState.FINISHED
@@ -377,7 +381,7 @@ private void killApplication(String applicationId) throws YarnException,
sysout.println("Application " + applicationId + " has already finished ");
} else {
sysout.println("Killing application " + applicationId);
- client.killApplication(appId);
+ client.killApplication(appId, reason);
}
}
@@ -455,18 +459,17 @@ private void printApplicationReport(String applicationId)
private String getAllValidApplicationStates() {
StringBuilder sb = new StringBuilder();
sb.append("The valid application state can be" + " one of the following: ");
- sb.append(ALLSTATES_OPTION + ",");
+ sb.append(ALLSTATES_OPTION);
for (YarnApplicationState appState : YarnApplicationState.values()) {
- sb.append(appState + ",");
+ sb.append(", " + appState);
}
- String output = sb.toString();
- return output.substring(0, output.length() - 1);
+ return sb.toString();
}
/**
* Lists the application attempts matching the given applicationid
*
- * @param applicationId
+ * @param appId
* @throws YarnException
* @throws IOException
*/
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestYarnClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestYarnClient.java
index 7c34966..bd1c93d 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestYarnClient.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestYarnClient.java
@@ -18,8 +18,8 @@
package org.apache.hadoop.yarn.client.api.impl;
-import static org.junit.Assert.assertFalse;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -68,6 +68,8 @@
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
import org.junit.Test;
public class TestYarnClient {
@@ -133,6 +135,12 @@ public void testSubmitApplication() {
@Test
public void testKillApplication() throws Exception {
+ testKillApplicationInternal(null);
+ testKillApplicationInternal("TestKillAppReason");
+ }
+
+ private void testKillApplicationInternal(final String reason)
+ throws Exception {
MockRM rm = new MockRM();
rm.start();
RMApp app = rm.submitApp(2000);
@@ -142,10 +150,25 @@ public void testKillApplication() throws Exception {
final YarnClient client = new MockYarnClient();
client.init(conf);
client.start();
+ client.killApplication(app.getApplicationId(), reason);
+
+ BaseMatcher bm =
+ new BaseMatcher() {
+
+ @Override
+ public void describeTo(Description decs) {}
+
+ @Override
+ public boolean matches(Object o) {
+ KillApplicationRequest req = (KillApplicationRequest)o;
+ final String reqReason = req.getReason();
+ return reason == reqReason
+ || reason != null && reason.contains(reqReason);
+ }
+ };
- client.killApplication(app.getApplicationId());
verify(((MockYarnClient) client).getRMClient(), times(2))
- .forceKillApplication(any(KillApplicationRequest.class));
+ .forceKillApplication((argThat(bm)));
}
@Test(timeout = 30000)
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 9772186..c6996c0 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
@@ -20,6 +20,8 @@
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -29,15 +31,16 @@
import static org.mockito.Mockito.doThrow;
import java.io.ByteArrayOutputStream;
-import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.regex.Pattern;
import junit.framework.Assert;
@@ -67,6 +70,10 @@
import org.apache.commons.cli.Options;
public class TestYarnCLI {
+ private static final Pattern SPACES_PATTERN =
+ Pattern.compile("\\s+|\\n+|\\t+");
+ private static final String APP_HELP = createApplicationCLIHelpMessage();
+ private static final String NODE_HELP = createNodeCLIHelpMessage();
private YarnClient client = mock(YarnClient.class);
ByteArrayOutputStream sysOutStream;
@@ -534,12 +541,11 @@ public void testGetApplications() throws Exception {
pw.println("The application state INVALID is invalid.");
pw.print("The valid application state can be one of the following: ");
StringBuilder sb = new StringBuilder();
- sb.append("ALL,");
+ sb.append("ALL");
for(YarnApplicationState state : YarnApplicationState.values()) {
- sb.append(state+",");
+ sb.append(", " + state);
}
- String output = sb.toString();
- pw.println(output.substring(0, output.length()-1));
+ pw.println(sb.toString());
pw.close();
appsReportStr = baos.toString("UTF-8");
Assert.assertEquals(appsReportStr, sysOutStream.toString());
@@ -675,23 +681,25 @@ public void testAppsHelpCommand() throws Exception {
int result = spyCli.run(new String[] { "-help" });
Assert.assertTrue(result == 0);
verify(spyCli).printUsage(any(Options.class));
- Assert.assertEquals(createApplicationCLIHelpMessage(),
- sysOutStream.toString());
+ Assert.assertEquals(APP_HELP, normalize(sysOutStream.toString()));
+ // too many args for kill
+ //
sysOutStream.reset();
ApplicationId applicationId = ApplicationId.newInstance(1234, 5);
result =
- cli.run(new String[] {"application", "-kill", applicationId.toString(), "args" });
+ cli.run(new String[] {"application", "-kill", applicationId.toString(),
+ "args2", "args3" });
+ Assert.assertSame("Exit code", -1, result);
verify(spyCli).printUsage(any(Options.class));
- Assert.assertEquals(createApplicationCLIHelpMessage(),
- sysOutStream.toString());
+ Assert.assertEquals(APP_HELP, normalize(sysOutStream.toString()));
sysOutStream.reset();
NodeId nodeId = NodeId.newInstance("host0", 0);
result = cli.run(new String[] { "-status", nodeId.toString(), "args" });
+ Assert.assertSame("Exit code", -1, result);
verify(spyCli).printUsage(any(Options.class));
- Assert.assertEquals(createApplicationCLIHelpMessage(),
- sysOutStream.toString());
+ Assert.assertEquals(APP_HELP, normalize(sysOutStream.toString()));
}
@Test (timeout = 5000)
@@ -701,8 +709,7 @@ public void testNodesHelpCommand() throws Exception {
nodeCLI.setSysOutPrintStream(sysOut);
nodeCLI.setSysErrPrintStream(sysErr);
nodeCLI.run(new String[] {});
- Assert.assertEquals(createNodeCLIHelpMessage(),
- sysOutStream.toString());
+ Assert.assertEquals(NODE_HELP, normalize(sysOutStream.toString()));
}
@Test
@@ -710,31 +717,46 @@ public void testKillApplication() throws Exception {
ApplicationCLI cli = createAndGetAppCLI();
ApplicationId applicationId = ApplicationId.newInstance(1234, 5);
- ApplicationReport newApplicationReport2 = ApplicationReport.newInstance(
+ ApplicationReport newApplicationReport1 = ApplicationReport.newInstance(
applicationId, ApplicationAttemptId.newInstance(applicationId, 1),
"user", "queue", "appname", "host", 124, null,
YarnApplicationState.FINISHED, "diagnostics", "url", 0, 0,
FinalApplicationStatus.SUCCEEDED, null, "N/A", 0.53789f, "YARN", null);
when(client.getApplicationReport(any(ApplicationId.class))).thenReturn(
- newApplicationReport2);
+ newApplicationReport1);
int result = cli.run(new String[] { "application","-kill", applicationId.toString() });
assertEquals(0, result);
verify(client, times(0)).killApplication(any(ApplicationId.class));
verify(sysOut).println(
"Application " + applicationId + " has already finished ");
- ApplicationReport newApplicationReport = ApplicationReport.newInstance(
- applicationId, ApplicationAttemptId.newInstance(applicationId, 1),
+ ApplicationReport newApplicationReport2 = ApplicationReport.newInstance(
+ applicationId, ApplicationAttemptId.newInstance(applicationId, 2),
"user", "queue", "appname", "host", 124, null,
YarnApplicationState.RUNNING, "diagnostics", "url", 0, 0,
FinalApplicationStatus.SUCCEEDED, null, "N/A", 0.53789f, "YARN", null);
when(client.getApplicationReport(any(ApplicationId.class))).thenReturn(
- newApplicationReport);
+ newApplicationReport2);
result = cli.run(new String[] { "application","-kill", applicationId.toString() });
assertEquals(0, result);
- verify(client).killApplication(any(ApplicationId.class));
+ verify(client).killApplication(any(ApplicationId.class), anyString());
verify(sysOut).println("Killing application application_1234_0005");
+ ApplicationReport newApplicationReport3 = ApplicationReport.newInstance(
+ applicationId, ApplicationAttemptId.newInstance(applicationId, 3),
+ "user", "queue", "appname", "host", 124, null,
+ YarnApplicationState.RUNNING, "diagnostics", "url", 0, 0,
+ FinalApplicationStatus.SUCCEEDED, null, "N/A", 0.53789f, "YARN", null);
+ when(client.getApplicationReport(any(ApplicationId.class))).thenReturn(
+ newApplicationReport3);
+ final String reason = "TestKillAppReason";
+ result = cli.run(new String[] { "application", "-kill",
+ applicationId.toString(), reason});
+ assertEquals(0, result);
+ verify(client).killApplication(any(ApplicationId.class), eq(reason));
+ verify(sysOut, times(2))
+ .println("Killing application application_1234_0005");
+
doThrow(new ApplicationNotFoundException("Application with id '"
+ applicationId + "' doesn't exist in RM.")).when(client)
.getApplicationReport(applicationId);
@@ -1093,8 +1115,8 @@ public void testMissingArguments() throws Exception {
ApplicationCLI cli = createAndGetAppCLI();
int result = cli.run(new String[] { "-status" });
Assert.assertEquals(result, -1);
- Assert.assertEquals(String.format("Missing argument for options%n%1s",
- createApplicationCLIHelpMessage()), sysOutStream.toString());
+ Assert.assertEquals("Missing argument for options " + APP_HELP,
+ normalize(sysOutStream.toString()));
sysOutStream.reset();
NodeCLI nodeCLI = new NodeCLI();
@@ -1103,8 +1125,8 @@ public void testMissingArguments() throws Exception {
nodeCLI.setSysErrPrintStream(sysErr);
result = nodeCLI.run(new String[] { "-status" });
Assert.assertEquals(result, -1);
- Assert.assertEquals(String.format("Missing argument for options%n%1s",
- createNodeCLIHelpMessage()), sysOutStream.toString());
+ Assert.assertEquals("Missing argument for options " + NODE_HELP,
+ normalize(sysOutStream.toString()));
}
private void verifyUsageInfo(YarnCLI cli) throws Exception {
@@ -1133,7 +1155,7 @@ private ApplicationCLI createAndGetAppCLI() {
return cli;
}
- private String createApplicationCLIHelpMessage() throws IOException {
+ private static String createApplicationCLIHelpMessage() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintWriter pw = new PrintWriter(baos);
pw.println("usage: application");
@@ -1141,13 +1163,13 @@ private String createApplicationCLIHelpMessage() throws IOException {
pw.println(" based on input comma-separated list of");
pw.println(" application states. The valid application");
pw.println(" state can be one of the following:");
- pw.println(" ALL,NEW,NEW_SAVING,SUBMITTED,ACCEPTED,RUN");
- pw.println(" NING,FINISHED,FAILED,KILLED");
+ pw.println(" ALL, NEW, NEW_SAVING, SUBMITTED, ACCEPTED, RUNNING,");
+ pw.println(" FINISHED, FAILED, KILLED");
pw.println(" -appTypes Works with -list to filter applications");
pw.println(" based on input comma-separated list of");
pw.println(" application types.");
pw.println(" -help Displays help for all commands.");
- pw.println(" -kill Kills the application.");
+ pw.println(" -kill Kills the application.");
pw.println(" -list List applications from the RM. Supports");
pw.println(" optional use of -appTypes to filter");
pw.println(" applications based on application type,");
@@ -1160,11 +1182,15 @@ private String createApplicationCLIHelpMessage() throws IOException {
pw.println(" application to.");
pw.println(" -status Prints the status of the application.");
pw.close();
- String appsHelpStr = baos.toString("UTF-8");
- return appsHelpStr;
+
+ try {
+ return normalize(baos.toString("UTF-8"));
+ } catch (UnsupportedEncodingException infeasible) {
+ return infeasible.toString();
+ }
}
- private String createNodeCLIHelpMessage() throws IOException {
+ private static String createNodeCLIHelpMessage() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintWriter pw = new PrintWriter(baos);
pw.println("usage: node");
@@ -1176,7 +1202,15 @@ private String createNodeCLIHelpMessage() throws IOException {
pw.println(" comma-separated list of node states.");
pw.println(" -status Prints the status report of the node.");
pw.close();
- String nodesHelpStr = baos.toString("UTF-8");
- return nodesHelpStr;
+
+ try {
+ return normalize(baos.toString("UTF-8"));
+ } catch (UnsupportedEncodingException infeasible) {
+ return infeasible.toString();
+ }
+ }
+
+ private static String normalize(String s) {
+ return SPACES_PATTERN.matcher(s).replaceAll(" "); // single space
}
}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/impl/pb/KillApplicationRequestPBImpl.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/impl/pb/KillApplicationRequestPBImpl.java
index db97367..99ca603 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/impl/pb/KillApplicationRequestPBImpl.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/impl/pb/KillApplicationRequestPBImpl.java
@@ -38,8 +38,8 @@
boolean viaProto = false;
private ApplicationId applicationId = null;
-
-
+ private String reason;
+
public KillApplicationRequestPBImpl() {
builder = KillApplicationRequestProto.newBuilder();
}
@@ -80,6 +80,9 @@ private void mergeLocalToBuilder() {
if (this.applicationId != null) {
builder.setApplicationId(convertToProtoFormat(this.applicationId));
}
+ if (reason != null) {
+ builder.setReason(reason);
+ }
}
private void mergeLocalToProto() {
@@ -119,6 +122,27 @@ public void setApplicationId(ApplicationId applicationId) {
this.applicationId = applicationId;
}
+ @Override
+ public String getReason() {
+ if (reason != null) {
+ return reason;
+ }
+ final KillApplicationRequestProtoOrBuilder p = viaProto ? proto : builder;
+ if (p.hasReason()) {
+ reason = p.getReason();
+ }
+ return reason;
+ }
+
+ @Override
+ public void setReason(String reason) {
+ maybeInitBuilder();
+ if (reason == null) {
+ builder.clearReason();
+ }
+ this.reason = reason;
+ }
+
private ApplicationIdPBImpl convertFromProtoFormat(ApplicationIdProto p) {
return new ApplicationIdPBImpl(p);
}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java
index 43e94ed..4a484c4 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java
@@ -94,8 +94,7 @@
import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
import org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger.AuditConstants;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
-import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppEvent;
-import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppEventType;
+import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppKillEvent;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppMoveEvent;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppState;
import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNode;
@@ -360,6 +359,13 @@ public KillApplicationResponse forceKillApplication(
KillApplicationRequest request) throws YarnException {
ApplicationId applicationId = request.getApplicationId();
+ String reason = request.getReason();
+ if (reason != null) {
+ if (reason.length() > YarnConfiguration.MAX_KILL_REASON_LENGTH) {
+ reason = reason.substring(0, YarnConfiguration.MAX_KILL_REASON_LENGTH);
+ request.setReason(reason);
+ }
+ }
UserGroupInformation callerUGI;
try {
@@ -399,7 +405,7 @@ public KillApplicationResponse forceKillApplication(
return KillApplicationResponse.newInstance(true);
} else {
this.rmContext.getDispatcher().getEventHandler()
- .handle(new RMAppEvent(applicationId, RMAppEventType.KILL));
+ .handle(new RMAppKillEvent(applicationId, reason));
return KillApplicationResponse.newInstance(false);
}
}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/RMAppImpl.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/RMAppImpl.java
index 196e89d..daf6c58 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/RMAppImpl.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/RMAppImpl.java
@@ -112,6 +112,7 @@
private long storedFinishTime = 0;
private RMAppAttempt currentAttempt;
private String queue;
+ private boolean killDiagsAdded;
@SuppressWarnings("rawtypes")
private EventHandler handler;
private static final FinalTransition FINAL_TRANSITION = new FinalTransition();
@@ -893,7 +894,12 @@ private void rememberTargetTransitionsAndStoreState(RMAppEvent event,
diags = getAppAttemptFailedDiagnostics(failedEvent);
break;
case ATTEMPT_KILLED:
- diags = getAppKilledDiagnostics();
+ if (killDiagsAdded) {
+ diags = getDiagnostics().toString();
+ } else {
+ killDiagsAdded = true;
+ diags = getDiagnostics().append(getAppKilledDiagnostics()).toString();
+ }
break;
default:
break;
@@ -982,7 +988,11 @@ public void transition(RMAppImpl app, RMAppEvent event) {
private static class AppKilledTransition extends FinalTransition {
@Override
public void transition(RMAppImpl app, RMAppEvent event) {
- app.diagnostics.append(getAppKilledDiagnostics());
+ app.addUserReason(event);
+ if (!app.killDiagsAdded) {
+ app.killDiagsAdded = true;
+ app.diagnostics.append(getAppKilledDiagnostics());
+ }
super.transition(app, event);
};
}
@@ -994,6 +1004,7 @@ private static String getAppKilledDiagnostics() {
private static class KillAttemptTransition extends RMAppTransition {
@Override
public void transition(RMAppImpl app, RMAppEvent event) {
+ app.addUserReason(event);
app.stateBeforeKilling = app.getState();
app.handler.handle(new RMAppAttemptEvent(app.currentAttempt
.getAppAttemptId(), RMAppAttemptEventType.KILL));
@@ -1080,6 +1091,16 @@ public RMAppState transition(RMAppImpl app, RMAppEvent event) {
}
}
+ private void addUserReason(RMAppEvent event) {
+ if (event.getType() == RMAppEventType.KILL) {
+ final RMAppKillEvent killEvent = (RMAppKillEvent)event;
+ final String reason = killEvent.getReason();
+ if (reason != null) {
+ diagnostics.append("user diagnostics: \"" + reason + "\"; ");
+ }
+ }
+ }
+
@Override
public String getApplicationType() {
return this.applicationType;
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/RMAppKillEvent.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/RMAppKillEvent.java
new file mode 100644
index 0000000..98abea6
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/RMAppKillEvent.java
@@ -0,0 +1,37 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.yarn.server.resourcemanager.rmapp;
+
+import org.apache.hadoop.yarn.api.records.ApplicationId;
+
+public class RMAppKillEvent extends RMAppEvent {
+ private final String reason;
+
+ public RMAppKillEvent(ApplicationId applicationId, String reason) {
+ super(applicationId, RMAppEventType.KILL);
+ this.reason = reason;
+ }
+
+ public RMAppKillEvent(ApplicationId applicationId) {
+ this(applicationId, null);
+ }
+
+ public String getReason() {
+ return reason;
+ }
+}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java
index 7c49681..28c4055 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java
@@ -44,7 +44,6 @@
import com.google.common.collect.Sets;
import junit.framework.Assert;
-import org.apache.commons.lang.math.LongRange;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
@@ -75,7 +74,6 @@
import org.apache.hadoop.yarn.api.records.QueueACL;
import org.apache.hadoop.yarn.api.records.QueueInfo;
import org.apache.hadoop.yarn.api.records.Resource;
-import org.apache.hadoop.yarn.api.records.YarnApplicationState;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.event.Dispatcher;
import org.apache.hadoop.yarn.event.Event;
@@ -228,6 +226,7 @@ public void testForceKillApplication() throws YarnException {
BuilderUtils.newApplicationId(System.currentTimeMillis(), 0);
KillApplicationRequest request =
KillApplicationRequest.newInstance(applicationId);
+ request.setReason("ForceKillReason");
try {
rmService.forceKillApplication(request);
Assert.fail();
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java
index 58482ee..e489b1e 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java
@@ -19,6 +19,7 @@
package org.apache.hadoop.yarn.server.resourcemanager.rmapp;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
@@ -57,7 +58,6 @@
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttempt;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptEvent;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptEventType;
-import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptState;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.event.RMAppAttemptUpdateSavedEvent;
import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.ContainerAllocationExpirer;
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.YarnScheduler;
@@ -291,31 +291,25 @@ private void assertTimesAtFinish(RMApp application) {
(application.getFinishTime() >= application.getStartTime()));
}
- private void assertAppFinalStateSaved(RMApp application){
+ private void assertAppFinalStateSaved(){
verify(store, times(1)).updateApplicationState(any(ApplicationState.class));
}
- private void assertAppFinalStateNotSaved(RMApp application){
+ private void assertAppFinalStateNotSaved(){
verify(store, times(0)).updateApplicationState(any(ApplicationState.class));
}
- private void assertKilled(RMApp application) {
+ private void assertKilled(RMApp application, String reason) {
assertTimesAtFinish(application);
assertAppState(RMAppState.KILLED, application);
assertFinalAppStatus(FinalApplicationStatus.KILLED, application);
- StringBuilder diag = application.getDiagnostics();
- Assert.assertEquals("application diagnostics is not correct",
- "Application killed by user.", diag.toString());
- }
-
- private void assertAppAndAttemptKilled(RMApp application)
- throws InterruptedException {
- sendAttemptUpdateSavedEvent(application);
- sendAppUpdateSavedEvent(application);
- assertKilled(application);
- Assert.assertEquals(RMAppAttemptState.KILLED, application
- .getCurrentAppAttempt().getAppAttemptState());
- assertAppFinalStateSaved(application);
+ final String diag = application.getDiagnostics().toString();
+ Assert.assertTrue("application diagnostics is not correct",
+ diag.contains("Application killed by user."));
+ if (reason != null) {
+ Assert.assertTrue("application diagnostics is not correct",
+ diag.contains(reason));
+ }
}
private void assertFailed(RMApp application, String regex) {
@@ -342,8 +336,8 @@ private void sendAttemptUpdateSavedEvent(RMApp application) {
protected RMApp testCreateAppNewSaving(
ApplicationSubmissionContext submissionContext) throws IOException {
- RMApp application = createNewTestApp(submissionContext);
- verify(writer).applicationStarted(any(RMApp.class));
+ RMApp application = createNewTestApp(submissionContext);
+ verify(writer).applicationStarted(eq(application));
// NEW => NEW_SAVING event RMAppEventType.START
RMAppEvent event =
new RMAppEvent(application.getApplicationId(), RMAppEventType.START);
@@ -412,7 +406,7 @@ protected RMApp testCreateAppFinalSaving(
RMAppEventType.ATTEMPT_UNREGISTERED);
application.handle(finishingEvent);
assertAppState(RMAppState.FINAL_SAVING, application);
- assertAppFinalStateSaved(application);
+ assertAppFinalStateSaved();
return application;
}
@@ -466,7 +460,7 @@ public void testUnmanagedApp() throws IOException {
application.getDiagnostics().indexOf(diagMsg) != -1);
// reset the counter of Mockito.verify
- reset(writer);
+ reset(writer, store);
// test app fails after 1 app attempt failure
LOG.info("--- START: testUnmanagedAppFailPath ---");
@@ -480,7 +474,7 @@ public void testUnmanagedApp() throws IOException {
sendAppUpdateSavedEvent(application);
assertFailed(application,
".*Unmanaged application.*Failing the application.*");
- assertAppFinalStateSaved(application);
+ assertAppFinalStateSaved();
}
@Test
@@ -500,18 +494,24 @@ public void testAppRecoverPath() throws IOException {
@Test (timeout = 30000)
public void testAppNewKill() throws IOException {
- LOG.info("--- START: testAppNewKill ---");
+ testAppNewKillInternal("TestAppKillReason");
+ reset(writer, store);
+ testAppNewKillInternal(null);
+ }
+
+ private void testAppNewKillInternal(String reason) {
+ LOG.info("--- START: testAppNewKill " + reason + " ---");
RMApp application = createNewTestApp(null);
// NEW => KILLED event RMAppEventType.KILL
- RMAppEvent event =
- new RMAppEvent(application.getApplicationId(), RMAppEventType.KILL);
+ RMAppEvent event =
+ new RMAppKillEvent(application.getApplicationId(), reason);
application.handle(event);
rmDispatcher.await();
sendAppUpdateSavedEvent(application);
- assertKilled(application);
- assertAppFinalStateNotSaved(application);
- verify(writer).applicationFinished(any(RMApp.class));
+ assertKilled(application, reason);
+ assertAppFinalStateNotSaved();
+ verify(writer).applicationFinished(eq(application));
}
@Test
@@ -527,23 +527,29 @@ public void testAppNewReject() throws IOException {
rmDispatcher.await();
sendAppUpdateSavedEvent(application);
assertFailed(application, rejectedText);
- assertAppFinalStateNotSaved(application);
- verify(writer).applicationFinished(any(RMApp.class));
+ assertAppFinalStateNotSaved();
+ verify(writer).applicationFinished(eq(application));
}
@Test (timeout = 30000)
public void testAppNewSavingKill() throws IOException {
- LOG.info("--- START: testAppNewSavingKill ---");
+ testAppNewSavingKillInternal("TestAppKillReason");
+ reset(writer, store);
+ testAppNewSavingKillInternal(null);
+ }
+
+ private void testAppNewSavingKillInternal(String reason) throws IOException {
+ LOG.info("--- START: testAppNewSavingKill " + reason + " ---");
RMApp application = testCreateAppNewSaving(null);
// NEW_SAVING => KILLED event RMAppEventType.KILL
RMAppEvent event =
- new RMAppEvent(application.getApplicationId(), RMAppEventType.KILL);
+ new RMAppKillEvent(application.getApplicationId(), reason);
application.handle(event);
rmDispatcher.await();
sendAppUpdateSavedEvent(application);
- assertKilled(application);
- verify(writer).applicationFinished(any(RMApp.class));
+ assertKilled(application, reason);
+ verify(writer).applicationFinished(eq(application));
}
@Test (timeout = 30000)
@@ -559,8 +565,8 @@ public void testAppNewSavingReject() throws IOException {
rmDispatcher.await();
sendAppUpdateSavedEvent(application);
assertFailed(application, rejectedText);
- assertAppFinalStateSaved(application);
- verify(writer).applicationFinished(any(RMApp.class));
+ assertAppFinalStateSaved();
+ verify(writer).applicationFinished(eq(application));
}
@Test (timeout = 30000)
@@ -576,23 +582,29 @@ public void testAppSubmittedRejected() throws IOException {
rmDispatcher.await();
sendAppUpdateSavedEvent(application);
assertFailed(application, rejectedText);
- assertAppFinalStateSaved(application);
- verify(writer).applicationFinished(any(RMApp.class));
+ assertAppFinalStateSaved();
+ verify(writer).applicationFinished(eq(application));
}
@Test
public void testAppSubmittedKill() throws IOException, InterruptedException {
- LOG.info("--- START: testAppSubmittedKill---");
+ testAppSubmittedKillInternal("TestAppKillReason");
+ reset(writer, store);
+ testAppSubmittedKillInternal(null);
+ }
+
+ private void testAppSubmittedKillInternal(String reason) throws IOException {
+ LOG.info("--- START: testAppSubmittedKill " + reason + " ---");
RMApp application = testCreateAppSubmittedNoRecovery(null);
// SUBMITTED => KILLED event RMAppEventType.KILL
- RMAppEvent event = new RMAppEvent(application.getApplicationId(),
- RMAppEventType.KILL);
+ RMAppEvent event =
+ new RMAppKillEvent(application.getApplicationId(), reason);
application.handle(event);
rmDispatcher.await();
sendAppUpdateSavedEvent(application);
- assertKilled(application);
- assertAppFinalStateSaved(application);
- verify(writer).applicationFinished(any(RMApp.class));
+ assertKilled(application, reason);
+ assertAppFinalStateSaved();
+ verify(writer).applicationFinished(eq(application));
}
@Test
@@ -626,17 +638,23 @@ public void testAppAcceptedFailed() throws IOException {
rmDispatcher.await();
sendAppUpdateSavedEvent(application);
assertFailed(application, ".*" + message + ".*Failing the application.*");
- assertAppFinalStateSaved(application);
- verify(writer).applicationFinished(any(RMApp.class));
+ assertAppFinalStateSaved();
+ verify(writer).applicationFinished(eq(application));
}
@Test
public void testAppAcceptedKill() throws IOException, InterruptedException {
- LOG.info("--- START: testAppAcceptedKill ---");
+ testAppAcceptedKillInternal("TestAppKillReason");
+ reset(writer, store);
+ testAppAcceptedKillInternal(null);
+ }
+
+ private void testAppAcceptedKillInternal(String reason) throws IOException {
+ LOG.info("--- START: testAppAcceptedKill " + reason + " ---");
RMApp application = testCreateAppAccepted(null);
// ACCEPTED => KILLED event RMAppEventType.KILL
- RMAppEvent event = new RMAppEvent(application.getApplicationId(),
- RMAppEventType.KILL);
+ RMAppEvent event =
+ new RMAppKillEvent(application.getApplicationId(), reason);
application.handle(event);
rmDispatcher.await();
@@ -647,19 +665,24 @@ public void testAppAcceptedKill() throws IOException, InterruptedException {
application.handle(appAttemptKilled);
assertAppState(RMAppState.FINAL_SAVING, application);
sendAppUpdateSavedEvent(application);
- assertKilled(application);
- assertAppFinalStateSaved(application);
- verify(writer).applicationFinished(any(RMApp.class));
+ assertKilled(application, reason);
+ assertAppFinalStateSaved();
+ verify(writer).applicationFinished(eq(application));
}
@Test
public void testAppRunningKill() throws IOException {
- LOG.info("--- START: testAppRunningKill ---");
+ testAppRunningKillInternal("TestKillAppReason");
+ reset(writer, store);
+ testAppRunningKillInternal(null);
+ }
+ private void testAppRunningKillInternal(String reason) throws IOException {
+ LOG.info("--- START: testAppRunningKill " + reason + " ---");
RMApp application = testCreateAppRunning(null);
// RUNNING => KILLED event RMAppEventType.KILL
- RMAppEvent event =
- new RMAppEvent(application.getApplicationId(), RMAppEventType.KILL);
+ RMAppEvent event =
+ new RMAppKillEvent(application.getApplicationId(), reason);
application.handle(event);
rmDispatcher.await();
@@ -671,8 +694,8 @@ public void testAppRunningKill() throws IOException {
assertAppState(RMAppState.KILLING, application);
sendAttemptUpdateSavedEvent(application);
sendAppUpdateSavedEvent(application);
- assertKilled(application);
- verify(writer).applicationFinished(any(RMApp.class));
+ assertKilled(application, reason);
+ verify(writer).applicationFinished(eq(application));
}
@Test
@@ -719,15 +742,15 @@ public void testAppRunningFailed() throws IOException {
rmDispatcher.await();
sendAppUpdateSavedEvent(application);
assertFailed(application, ".*Failing the application.*");
- assertAppFinalStateSaved(application);
+ assertAppFinalStateSaved();
// FAILED => FAILED event RMAppEventType.KILL
- event = new RMAppEvent(application.getApplicationId(), RMAppEventType.KILL);
+ event = new RMAppKillEvent(application.getApplicationId());
application.handle(event);
rmDispatcher.await();
assertFailed(application, ".*Failing the application.*");
- assertAppFinalStateSaved(application);
- verify(writer).applicationFinished(any(RMApp.class));
+ assertAppFinalStateSaved();
+ verify(writer).applicationFinished(eq(application));
}
@Test
@@ -736,8 +759,7 @@ public void testAppAtFinishingIgnoreKill() throws IOException {
RMApp application = testCreateAppFinishing(null);
// FINISHING => FINISHED event RMAppEventType.KILL
- RMAppEvent event =
- new RMAppEvent(application.getApplicationId(), RMAppEventType.KILL);
+ RMAppEvent event = new RMAppKillEvent(application.getApplicationId());
application.handle(event);
rmDispatcher.await();
assertAppState(RMAppState.FINISHING, application);
@@ -776,8 +798,8 @@ public void testAppFinishedFinished() throws IOException {
RMApp application = testCreateAppFinished(null, "");
// FINISHED => FINISHED event RMAppEventType.KILL
- RMAppEvent event =
- new RMAppEvent(application.getApplicationId(), RMAppEventType.KILL);
+ RMAppEvent event = new RMAppKillEvent(application.getApplicationId(),
+ "TestAppKillReason");
application.handle(event);
rmDispatcher.await();
assertTimesAtFinish(application);
@@ -785,7 +807,7 @@ public void testAppFinishedFinished() throws IOException {
StringBuilder diag = application.getDiagnostics();
Assert.assertEquals("application diagnostics is not correct",
"", diag.toString());
- verify(writer).applicationFinished(any(RMApp.class));
+ verify(writer).applicationFinished(eq(application));
}
@Test (timeout = 30000)
@@ -804,8 +826,7 @@ public void testAppFailedFailed() throws IOException {
assertAppState(RMAppState.FAILED, application);
// FAILED => FAILED event RMAppEventType.KILL
- event =
- new RMAppEvent(application.getApplicationId(), RMAppEventType.KILL);
+ event = new RMAppKillEvent(application.getApplicationId());
application.handle(event);
rmDispatcher.await();
assertTimesAtFinish(application);
@@ -813,7 +834,7 @@ public void testAppFailedFailed() throws IOException {
assertTimesAtFinish(application);
assertAppState(RMAppState.FAILED, application);
- verify(writer).applicationFinished(any(RMApp.class));
+ verify(writer).applicationFinished(eq(application));
}
@Test (timeout = 30000)
@@ -823,8 +844,7 @@ public void testAppKilledKilled() throws IOException {
RMApp application = testCreateAppRunning(null);
// RUNNING => KILLED event RMAppEventType.KILL
- RMAppEvent event =
- new RMAppEvent(application.getApplicationId(), RMAppEventType.KILL);
+ RMAppEvent event = new RMAppKillEvent(application.getApplicationId());
application.handle(event);
rmDispatcher.await();
sendAttemptUpdateSavedEvent(application);
@@ -851,7 +871,7 @@ public void testAppKilledKilled() throws IOException {
// KILLED => KILLED event RMAppEventType.KILL
- event = new RMAppEvent(application.getApplicationId(), RMAppEventType.KILL);
+ event = new RMAppKillEvent(application.getApplicationId());
application.handle(event);
rmDispatcher.await();
assertTimesAtFinish(application);
@@ -859,7 +879,7 @@ public void testAppKilledKilled() throws IOException {
assertTimesAtFinish(application);
assertAppState(RMAppState.KILLED, application);
- verify(writer).applicationFinished(any(RMApp.class));
+ verify(writer).applicationFinished(eq(application));
}
@Test