You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@slider.apache.org by st...@apache.org on 2014/10/31 15:25:11 UTC
[03/13] git commit: SLIDER-570: failure output in failed
tests...making sure most recent runs get reported, even failures
SLIDER-570: failure output in failed tests...making sure most recent runs get reported, even failures
Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/09d16a13
Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/09d16a13
Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/09d16a13
Branch: refs/heads/develop
Commit: 09d16a130c3ccb4f2f0195ca23d2fa53074e138b
Parents: e23e680
Author: Steve Loughran <st...@apache.org>
Authored: Tue Oct 28 15:48:23 2014 +0000
Committer: Steve Loughran <st...@apache.org>
Committed: Fri Oct 31 11:07:49 2014 +0000
----------------------------------------------------------------------
.../org/apache/slider/client/SliderClient.java | 70 +++++-----
.../slider/client/SliderYarnClientImpl.java | 7 +-
.../org/apache/slider/common/Constants.java | 1 -
.../apache/slider/common/tools/SliderUtils.java | 128 ++++++++++++++-----
.../framework/AgentCommandTestBase.groovy | 6 +-
.../funtest/framework/CommandTestBase.groovy | 18 ++-
6 files changed, 159 insertions(+), 71 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/09d16a13/slider-core/src/main/java/org/apache/slider/client/SliderClient.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/client/SliderClient.java b/slider-core/src/main/java/org/apache/slider/client/SliderClient.java
index 06efadf..392280a 100644
--- a/slider-core/src/main/java/org/apache/slider/client/SliderClient.java
+++ b/slider-core/src/main/java/org/apache/slider/client/SliderClient.java
@@ -161,7 +161,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;
@@ -193,8 +192,6 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
private SliderYarnClientImpl yarnClient;
private YarnAppListClient YarnAppListClient;
private AggregateConf launchedInstanceDefinition;
-// private SliderRegistryService registry;
-
/**
* The YARN registry service
@@ -1009,7 +1006,13 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
serviceArgs.isDebug());
applicationId = launchedApplication.getApplicationId();
- return waitForAppAccepted(launchedApplication, launchArgs.getWaittime());
+ int waittime = launchArgs.getWaittime();
+ if (waittime > 0) {
+ return waitForAppRunning(launchedApplication, waittime, waittime);
+ } else {
+ // no waiting
+ return EXIT_SUCCESS;
+ }
}
/**
@@ -1384,34 +1387,38 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
/**
- * Wait for the launched app to be accepted
- * @param waittime time in millis
- * @return exit code
+ * Wait for the launched app to be accepted in the time
+ * and, optionally running.
+ * <p>
+ * If the application
+ *
+ * @param launchedApplication application
+ * @param acceptWaitMillis time in millis to wait for accept
+ * @param runWaitMillis time in millis to wait for the app to be running.
+ * May be null, in which case no wait takes place
+ * @return exit code: success
* @throws YarnException
* @throws IOException
*/
- public int waitForAppAccepted(LaunchedApplication launchedApplication,
- int waittime) throws
- YarnException,
- IOException {
+ public int waitForAppRunning(LaunchedApplication launchedApplication,
+ int acceptWaitMillis, int runWaitMillis) throws YarnException, IOException {
assert launchedApplication != null;
int exitCode;
// wait for the submit state to be reached
ApplicationReport report = launchedApplication.monitorAppToState(
YarnApplicationState.ACCEPTED,
- new Duration(Constants.ACCEPT_TIME));
-
+ new Duration(acceptWaitMillis));
// may have failed, so check that
if (SliderUtils.hasAppFinished(report)) {
exitCode = buildExitCode(report);
} else {
// exit unless there is a wait
- exitCode = EXIT_SUCCESS;
- if (waittime != 0) {
+
+ if (runWaitMillis != 0) {
// waiting for state to change
- Duration duration = new Duration(waittime * 1000);
+ Duration duration = new Duration(runWaitMillis * 1000);
duration.start();
report = launchedApplication.monitorAppToState(
YarnApplicationState.RUNNING, duration);
@@ -1419,10 +1426,10 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
report.getYarnApplicationState() == YarnApplicationState.RUNNING) {
exitCode = EXIT_SUCCESS;
} else {
-
- launchedApplication.kill("");
exitCode = buildExitCode(report);
}
+ } else {
+ exitCode = EXIT_SUCCESS;
}
}
return exitCode;
@@ -1579,16 +1586,17 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
}
/**
- * Build an exit code for an application Id and its report.
- * If the report parameter is null, the app is killed
- * @param report report
+ * Build an exit code for an application from its report.
+ * If the report parameter is null, its interpreted as a timeout
+ * @param report report application report
* @return the exit code
+ * @throws IOException
+ * @throws YarnException
*/
private int buildExitCode(ApplicationReport report) throws
IOException,
YarnException {
if (null == report) {
- forceKillApplication("Reached client specified timeout for application");
return EXIT_TIMED_OUT;
}
@@ -1615,6 +1623,7 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
log.info("Application Failed. YarnState={}, DSFinalStatus={}", state,
dsStatus);
return EXIT_YARN_SERVICE_FAILED;
+
default:
//not in any of these states
return EXIT_SUCCESS;
@@ -1730,7 +1739,7 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
// and those the RM knows about
List<ApplicationReport> instances = listSliderInstances(null);
- SliderUtils.sortApplicationReport(instances);
+ SliderUtils.sortApplicationsByMostRecent(instances);
Map<String, ApplicationReport> reportMap =
SliderUtils.buildApplicationReportMap(instances, min, max);
log.debug("Persisted {} deployed {} filtered[{}-{}] & de-duped to {}",
@@ -1746,6 +1755,8 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
if (persistent == null) {
throw unknownClusterException(clustername);
}
+ // create a new map with only that instance in it.
+ // this restricts the output of results to this instance
persistentInstances = new HashMap<String, Path>();
persistentInstances.put(clustername, persistent);
}
@@ -1767,6 +1778,13 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
return listed > 0 ? EXIT_SUCCESS: EXIT_FALSE;
}
+ /**
+ * Convert the instance details of an application to a string
+ * @param name instance name
+ * @param report the application report
+ * @param verbose verbose output
+ * @return a string
+ */
String instanceDetailsToString(String name,
ApplicationReport report,
boolean verbose) {
@@ -1994,12 +2012,6 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
return YarnAppListClient.findAllLiveInstances(appname);
}
-
- public ApplicationReport findClusterInInstanceList(List<ApplicationReport> instances,
- String appname) {
- return yarnClient.findClusterInInstanceList(instances, appname);
- }
-
/**
* Connect to a Slider AM
* @param app application report providing the details on the application
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/09d16a13/slider-core/src/main/java/org/apache/slider/client/SliderYarnClientImpl.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/client/SliderYarnClientImpl.java b/slider-core/src/main/java/org/apache/slider/client/SliderYarnClientImpl.java
index a00f3b2..2f18b7a 100644
--- a/slider-core/src/main/java/org/apache/slider/client/SliderYarnClientImpl.java
+++ b/slider-core/src/main/java/org/apache/slider/client/SliderYarnClientImpl.java
@@ -252,9 +252,10 @@ public class SliderYarnClientImpl extends YarnClientImpl {
/**
* Find a cluster in the instance list; biased towards live instances
- * @param instances
- * @param appname
- * @return
+ * @param instances list of instances
+ * @param appname application name
+ * @return the first found instance, else a failed/finished instance, or null
+ * if there are none of those
*/
public ApplicationReport findClusterInInstanceList(List<ApplicationReport> instances,
String appname) {
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/09d16a13/slider-core/src/main/java/org/apache/slider/common/Constants.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/common/Constants.java b/slider-core/src/main/java/org/apache/slider/common/Constants.java
index 2fe0250..868ea57 100644
--- a/slider-core/src/main/java/org/apache/slider/common/Constants.java
+++ b/slider-core/src/main/java/org/apache/slider/common/Constants.java
@@ -19,7 +19,6 @@
package org.apache.slider.common;
public class Constants {
- public static final int ACCEPT_TIME = 60000;
public static final int CONNECT_TIMEOUT = 10000;
public static final int RPC_TIMEOUT = 15000;
}
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/09d16a13/slider-core/src/main/java/org/apache/slider/common/tools/SliderUtils.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/common/tools/SliderUtils.java b/slider-core/src/main/java/org/apache/slider/common/tools/SliderUtils.java
index 0f622c9..ee8693f 100644
--- a/slider-core/src/main/java/org/apache/slider/common/tools/SliderUtils.java
+++ b/slider-core/src/main/java/org/apache/slider/common/tools/SliderUtils.java
@@ -76,6 +76,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.PrintWriter;
+import java.io.Serializable;
import java.io.StringWriter;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
@@ -84,6 +85,8 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -97,6 +100,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import java.util.TimeZone;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeMap;
@@ -599,36 +603,55 @@ public final class SliderUtils {
builder.append(tag).append(separator);
}
}
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");
+ dateFormat.setTimeZone(TimeZone.getDefault());
builder.append("state: ").append(r.getYarnApplicationState());
- builder.append(separator).append("URL: ").append(r.getTrackingUrl());
+ String trackingUrl = r.getTrackingUrl();
+ if (isSet(trackingUrl)) {
+ builder.append(separator).append("URL: ").append(trackingUrl);
+ }
builder.append(separator)
- .append("Started ")
- .append(new Date(r.getStartTime()).toGMTString());
+ .append("Started: ")
+ .append(dateFormat.format(new Date(r.getStartTime())));
long finishTime = r.getFinishTime();
if (finishTime > 0) {
builder.append(separator)
- .append("Finished ")
- .append(new Date(finishTime).toGMTString());
+ .append("Finished: ")
+ .append(dateFormat.format(new Date(finishTime)));
+ }
+ String rpcHost = r.getHost();
+ if (!isSet(rpcHost)) {
+ builder.append(separator)
+ .append("RPC :")
+ .append(rpcHost)
+ .append(':')
+ .append(r.getRpcPort());
}
- builder.append(separator)
- .append("RPC :")
- .append(r.getHost())
- .append(':')
- .append(r.getRpcPort());
String diagnostics = r.getDiagnostics();
- if (!diagnostics.isEmpty()) {
+ if (!isSet(diagnostics)) {
builder.append(separator).append("Diagnostics :").append(diagnostics);
}
return builder.toString();
}
+
+ /**
+ * Sorts the given list of application reports, most recently started
+ * or finished instance first.
+ *
+ * @param instances list of instances
+ */
+ public static void sortApplicationsByMostRecent(List<ApplicationReport> instances) {
+ Collections.sort(instances, new MostRecentlyStartedOrFinishedFirst());
+ }
+
/**
* Sorts the given list of application reports
* Finished instances are ordered by finished time and running/accepted instances are
* ordered by start time
* Finally Instance are order by finished instances coming after running instances
*
- * @param instances list of intances
+ * @param instances list of instances
*/
public static void sortApplicationReport(List<ApplicationReport> instances) {
if (instances.size() <= 1) {
@@ -650,28 +673,10 @@ public final class SliderUtils {
}
if (liveInstance.size() > 1) {
- Comparator<ApplicationReport> liveInstanceComparator =
- new Comparator<ApplicationReport>() {
- @Override
- public int compare(ApplicationReport r1, ApplicationReport r2) {
- long x = r1.getStartTime();
- long y = r2.getStartTime();
- return (x < y) ? -1 : ((x == y) ? 0 : 1);
- }
- };
- Collections.sort(liveInstance, liveInstanceComparator);
+ Collections.sort(liveInstance, new MostRecentlyStartedAppFirst());
}
if (nonLiveInstance.size() > 1) {
- Comparator<ApplicationReport> nonLiveInstanceComparator =
- new Comparator<ApplicationReport>() {
- @Override
- public int compare(ApplicationReport r1, ApplicationReport r2) {
- long x = r1.getFinishTime();
- long y = r2.getFinishTime();
- return (x < y) ? -1 : ((x == y) ? 0 : 1);
- }
- };
- Collections.sort(nonLiveInstance, nonLiveInstanceComparator);
+ Collections.sort(nonLiveInstance, new MostRecentAppFinishFirst());
}
instances.clear();
instances.addAll(liveInstance);
@@ -2067,4 +2072,63 @@ public final class SliderUtils {
}
return result;
}
+
+ /**
+ * Compare the times of two applications: most recent app comes first
+ * Specifically: the one whose start time value is greater.
+ */
+ private static class MostRecentlyStartedAppFirst
+ implements Comparator<ApplicationReport>, Serializable {
+ @Override
+ public int compare(ApplicationReport r1, ApplicationReport r2) {
+ long x = r1.getStartTime();
+ long y = r2.getStartTime();
+ return compareTwoLongs(x, y);
+ }
+ }
+
+ /**
+ * Compare the times of two applications: most recent app comes first.
+ * "Recent"== the app whose start time <i>or finish time</i> is the greatest.
+ */
+ private static class MostRecentlyStartedOrFinishedFirst
+ implements Comparator<ApplicationReport>, Serializable {
+ @Override
+ public int compare(ApplicationReport r1, ApplicationReport r2) {
+ long started1 = r1.getStartTime();
+ long started2 = r2.getStartTime();
+ long finished1 = r1.getFinishTime();
+ long finished2 = r2.getFinishTime();
+ long lastEvent1 = Math.max(started1, finished1);
+ long lastEvent2 = Math.max(started2, finished2);
+ return compareTwoLongs(lastEvent1, lastEvent2);
+ }
+ }
+
+ /**
+ * Compare the times of two applications: most recently finished app comes first
+ * Specifically: the one whose finish time value is greater.
+ */
+ private static class MostRecentAppFinishFirst
+ implements Comparator<ApplicationReport>, Serializable {
+ @Override
+ public int compare(ApplicationReport r1, ApplicationReport r2) {
+ long x = r1.getFinishTime();
+ long y = r2.getFinishTime();
+ return compareTwoLongs(x, y);
+ }
+ }
+
+ /**
+ * Compare two long values for sorting. As the return value for
+ * comparators must be int, the simple value of <code>x-y</code>
+ * is inapplicable
+ * @param x x value
+ * @param y y value
+ * @return -ve if x is less than y, +ve if y is greater than x; 0 for equality
+ */
+ public static int compareTwoLongs(long x, long y) {
+ return (x < y) ? -1 : ((x == y) ? 0 : 1);
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/09d16a13/slider-funtest/src/main/groovy/org/apache/slider/funtest/framework/AgentCommandTestBase.groovy
----------------------------------------------------------------------
diff --git a/slider-funtest/src/main/groovy/org/apache/slider/funtest/framework/AgentCommandTestBase.groovy b/slider-funtest/src/main/groovy/org/apache/slider/funtest/framework/AgentCommandTestBase.groovy
index b44ae07..6c99ab6 100644
--- a/slider-funtest/src/main/groovy/org/apache/slider/funtest/framework/AgentCommandTestBase.groovy
+++ b/slider-funtest/src/main/groovy/org/apache/slider/funtest/framework/AgentCommandTestBase.groovy
@@ -111,9 +111,9 @@ implements FuntestProperties, Arguments, SliderExitCodes, SliderActions {
SliderShell shell = slider(EXIT_SUCCESS,
[
ACTION_INSTALL_PACKAGE,
- Arguments.ARG_NAME, TEST_APP_PKG_NAME,
- Arguments.ARG_PACKAGE, zipFileName.absolutePath,
- Arguments.ARG_REPLACE_PKG
+ ARG_NAME, TEST_APP_PKG_NAME,
+ ARG_PACKAGE, zipFileName.absolutePath,
+ ARG_REPLACE_PKG
])
logShell(shell)
log.info "App pkg uploaded at home directory .slider/package/$TEST_APP_PKG_NAME/$TEST_APP_PKG_FILE"
http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/09d16a13/slider-funtest/src/main/groovy/org/apache/slider/funtest/framework/CommandTestBase.groovy
----------------------------------------------------------------------
diff --git a/slider-funtest/src/main/groovy/org/apache/slider/funtest/framework/CommandTestBase.groovy b/slider-funtest/src/main/groovy/org/apache/slider/funtest/framework/CommandTestBase.groovy
index f3d91d3..7b50c60 100644
--- a/slider-funtest/src/main/groovy/org/apache/slider/funtest/framework/CommandTestBase.groovy
+++ b/slider-funtest/src/main/groovy/org/apache/slider/funtest/framework/CommandTestBase.groovy
@@ -30,7 +30,6 @@ import org.apache.hadoop.yarn.api.records.YarnApplicationState
import org.apache.hadoop.yarn.conf.YarnConfiguration
import org.apache.slider.api.StatusKeys
import org.apache.slider.common.tools.ConfigHelper
-import org.apache.slider.core.main.LauncherExitCodes
import org.apache.slider.core.main.ServiceLauncher
import org.apache.slider.common.SliderKeys
import org.apache.slider.common.SliderXmlConfKeys
@@ -615,7 +614,6 @@ abstract class CommandTestBase extends SliderTestUtils {
ARG_TEMPLATE, appTemplate,
ARG_RESOURCES, resourceTemplate,
ARG_WAIT, Integer.toString(THAW_WAIT_TIME)
-
]
maybeAddCommandOption(commands,
@@ -631,7 +629,21 @@ abstract class CommandTestBase extends SliderTestUtils {
[ARG_COMP_OPT, SliderKeys.COMPONENT_AM, SliderXmlConfKeys.KEY_KEYTAB_PRINCIPAL],
SLIDER_CONFIG.getTrimmed(SliderXmlConfKeys.KEY_KEYTAB_PRINCIPAL));
commands.addAll(extraArgs)
- SliderShell shell = slider(LauncherExitCodes.EXIT_SUCCESS, commands)
+ SliderShell shell = new SliderShell(commands)
+ shell.execute()
+ if (!shell.execute()) {
+ // app has failed.
+
+ // grab the app report of the last known instance of this app
+ // which may not be there if it was a config failure; may be out of date
+ // from a previous run
+ log.error("Launch failed with exit code ${shell.ret}.\nLast instance of $name:")
+ slider([ACTION_LIST, name, ARG_VERBOSE]).dumpOutput()
+
+ // trigger the assertion failure
+ shell.assertExitCode(EXIT_SUCCESS)
+ }
+
return shell
}