YARN-5740. Add a new field in Slider status output - lifetime (remaining). Contributed by Jian He
This commit is contained in:
parent
2cea59dc54
commit
2e1fa61253
|
@ -52,6 +52,8 @@ import org.apache.commons.lang.SerializationUtils;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.hadoop.security.UserGroupInformation;
|
import org.apache.hadoop.security.UserGroupInformation;
|
||||||
import org.apache.hadoop.yarn.api.records.ApplicationId;
|
import org.apache.hadoop.yarn.api.records.ApplicationId;
|
||||||
|
import org.apache.hadoop.yarn.api.records.ApplicationReport;
|
||||||
|
import org.apache.hadoop.yarn.api.records.ApplicationTimeoutType;
|
||||||
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
||||||
import org.apache.hadoop.yarn.exceptions.YarnException;
|
import org.apache.hadoop.yarn.exceptions.YarnException;
|
||||||
import org.apache.hadoop.yarn.services.api.ApplicationApi;
|
import org.apache.hadoop.yarn.services.api.ApplicationApi;
|
||||||
|
@ -771,7 +773,7 @@ public class ApplicationApiService implements ApplicationApi {
|
||||||
|
|
||||||
// Get all applications in a specific state - lighter projection. For full
|
// Get all applications in a specific state - lighter projection. For full
|
||||||
// detail, call getApplication on a specific app.
|
// detail, call getApplication on a specific app.
|
||||||
Set<String> applications;
|
Set<ApplicationReport> applications;
|
||||||
try {
|
try {
|
||||||
if (StringUtils.isNotEmpty(state)) {
|
if (StringUtils.isNotEmpty(state)) {
|
||||||
ApplicationStatus appStatus = new ApplicationStatus();
|
ApplicationStatus appStatus = new ApplicationStatus();
|
||||||
|
@ -793,13 +795,12 @@ public class ApplicationApiService implements ApplicationApi {
|
||||||
Set<Application> apps = new HashSet<Application>();
|
Set<Application> apps = new HashSet<Application>();
|
||||||
if (applications.size() > 0) {
|
if (applications.size() > 0) {
|
||||||
try {
|
try {
|
||||||
for (String app : applications) {
|
for (ApplicationReport app : applications) {
|
||||||
Application application = new Application();
|
Application application = new Application();
|
||||||
// TODO: Need to get lifetime, launch-time and privileged container
|
application.setLifetime(app.getApplicationTimeouts().get(
|
||||||
// status from YARN
|
ApplicationTimeoutType.LIFETIME).getRemainingTime());
|
||||||
application.setLifetime(null);
|
application.setLaunchTime(new Date(app.getStartTime()));
|
||||||
application.setLaunchTime(new Date());
|
application.setName(app.getName());
|
||||||
application.setName(app);
|
|
||||||
// Containers not required, setting to null to avoid empty list
|
// Containers not required, setting to null to avoid empty list
|
||||||
application.setContainers(null);
|
application.setContainers(null);
|
||||||
apps.add(application);
|
apps.add(application);
|
||||||
|
@ -930,9 +931,7 @@ public class ApplicationApiService implements ApplicationApi {
|
||||||
app.setLaunchTime(appStatus.get("createTime") == null ? null
|
app.setLaunchTime(appStatus.get("createTime") == null ? null
|
||||||
: new Date(appStatus.get("createTime").getAsLong()));
|
: new Date(appStatus.get("createTime").getAsLong()));
|
||||||
|
|
||||||
// lifetime - set it to unlimited for now
|
app.setLifetime(queryLifetime(appName));
|
||||||
// TODO: Once YARN-3813 and YARN-4205 are available - get it from YARN
|
|
||||||
app.setLifetime(DEFAULT_UNLIMITED_LIFETIME);
|
|
||||||
|
|
||||||
// Quicklinks
|
// Quicklinks
|
||||||
Map<String, String> appQuicklinks = new HashMap<>();
|
Map<String, String> appQuicklinks = new HashMap<>();
|
||||||
|
@ -1062,6 +1061,24 @@ public class ApplicationApiService implements ApplicationApi {
|
||||||
return object.get(key) == null ? null : object.get(key).getAsJsonObject();
|
return object.get(key) == null ? null : object.get(key).getAsJsonObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private long queryLifetime(String appName) {
|
||||||
|
try {
|
||||||
|
return invokeSliderClientRunnable(
|
||||||
|
new SliderClientContextRunnable<Long>() {
|
||||||
|
@Override
|
||||||
|
public Long run(SliderClient sliderClient)
|
||||||
|
throws YarnException, IOException, InterruptedException {
|
||||||
|
ApplicationReport report = sliderClient.findInstance(appName);
|
||||||
|
return report.getApplicationTimeouts()
|
||||||
|
.get(ApplicationTimeoutType.LIFETIME).getRemainingTime();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error when querying lifetime for " + appName, e);
|
||||||
|
return DEFAULT_UNLIMITED_LIFETIME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private JsonObject getSliderApplicationStatus(final String appName)
|
private JsonObject getSliderApplicationStatus(final String appName)
|
||||||
throws IOException, YarnException, InterruptedException {
|
throws IOException, YarnException, InterruptedException {
|
||||||
|
|
||||||
|
@ -1142,24 +1159,25 @@ public class ApplicationApiService implements ApplicationApi {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<String> getSliderApplications(final String state)
|
private Set<ApplicationReport> getSliderApplications(final String state)
|
||||||
throws IOException, YarnException, InterruptedException {
|
throws IOException, YarnException, InterruptedException {
|
||||||
return getSliderApplications(false, state);
|
return getSliderApplications(false, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<String> getSliderApplications(final boolean liveOnly)
|
private Set<ApplicationReport> getSliderApplications(final boolean liveOnly)
|
||||||
throws IOException, YarnException, InterruptedException {
|
throws IOException, YarnException, InterruptedException {
|
||||||
return getSliderApplications(liveOnly, null);
|
return getSliderApplications(liveOnly, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<String> getSliderApplications(final boolean liveOnly,
|
private Set<ApplicationReport> getSliderApplications(final boolean liveOnly,
|
||||||
final String state) throws IOException, YarnException,
|
final String state)
|
||||||
InterruptedException {
|
throws IOException, YarnException, InterruptedException {
|
||||||
return invokeSliderClientRunnable(new SliderClientContextRunnable<Set<String>>() {
|
return invokeSliderClientRunnable(
|
||||||
|
new SliderClientContextRunnable<Set<ApplicationReport>>() {
|
||||||
@Override
|
@Override
|
||||||
public Set<String> run(SliderClient sliderClient) throws YarnException,
|
public Set<ApplicationReport> run(SliderClient sliderClient)
|
||||||
IOException, InterruptedException {
|
throws YarnException, IOException, InterruptedException {
|
||||||
Set<String> apps;
|
Set<ApplicationReport> apps;
|
||||||
ActionListArgs listArgs = new ActionListArgs();
|
ActionListArgs listArgs = new ActionListArgs();
|
||||||
if (liveOnly) {
|
if (liveOnly) {
|
||||||
apps = sliderClient.getApplicationList(null);
|
apps = sliderClient.getApplicationList(null);
|
||||||
|
|
|
@ -55,6 +55,7 @@ import org.apache.hadoop.yarn.api.ApplicationConstants;
|
||||||
import org.apache.hadoop.yarn.api.protocolrecords.UpdateApplicationTimeoutsRequest;
|
import org.apache.hadoop.yarn.api.protocolrecords.UpdateApplicationTimeoutsRequest;
|
||||||
import org.apache.hadoop.yarn.api.records.ApplicationId;
|
import org.apache.hadoop.yarn.api.records.ApplicationId;
|
||||||
import org.apache.hadoop.yarn.api.records.ApplicationReport;
|
import org.apache.hadoop.yarn.api.records.ApplicationReport;
|
||||||
|
import org.apache.hadoop.yarn.api.records.ApplicationTimeout;
|
||||||
import org.apache.hadoop.yarn.api.records.ApplicationTimeoutType;
|
import org.apache.hadoop.yarn.api.records.ApplicationTimeoutType;
|
||||||
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
|
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
|
||||||
import org.apache.hadoop.yarn.api.records.LocalResource;
|
import org.apache.hadoop.yarn.api.records.LocalResource;
|
||||||
|
@ -178,6 +179,7 @@ import org.codehaus.jettison.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.Console;
|
import java.io.Console;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
@ -185,6 +187,7 @@ import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InterruptedIOException;
|
import java.io.InterruptedIOException;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
@ -2706,11 +2709,12 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
|
||||||
@Override
|
@Override
|
||||||
public int actionList(String clustername, ActionListArgs args)
|
public int actionList(String clustername, ActionListArgs args)
|
||||||
throws IOException, YarnException {
|
throws IOException, YarnException {
|
||||||
Set<String> appInstances = getApplicationList(clustername, args);
|
Set<ApplicationReport> appInstances = getApplicationList(clustername, args);
|
||||||
// getApplicationList never returns null
|
if (!appInstances.isEmpty()) {
|
||||||
return !appInstances.isEmpty() ? EXIT_SUCCESS
|
return EXIT_SUCCESS;
|
||||||
: ((appInstances.isEmpty() && isUnset(clustername)) ? EXIT_SUCCESS
|
} else {
|
||||||
: EXIT_FALSE);
|
return EXIT_FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2723,8 +2727,8 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws YarnException
|
* @throws YarnException
|
||||||
*/
|
*/
|
||||||
public Set<String> getApplicationList(String clustername) throws IOException,
|
public Set<ApplicationReport> getApplicationList(String clustername)
|
||||||
YarnException {
|
throws IOException, YarnException {
|
||||||
ActionListArgs args = new ActionListArgs();
|
ActionListArgs args = new ActionListArgs();
|
||||||
args.live = true;
|
args.live = true;
|
||||||
return getApplicationList(clustername, args);
|
return getApplicationList(clustername, args);
|
||||||
|
@ -2743,8 +2747,8 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
|
||||||
* @throws UnknownApplicationInstanceException
|
* @throws UnknownApplicationInstanceException
|
||||||
* if a specific instance was named but it was not found
|
* if a specific instance was named but it was not found
|
||||||
*/
|
*/
|
||||||
public Set<String> getApplicationList(String clustername, ActionListArgs args)
|
public Set<ApplicationReport> getApplicationList(String clustername,
|
||||||
throws IOException, YarnException {
|
ActionListArgs args) throws IOException, YarnException {
|
||||||
if (args.help) {
|
if (args.help) {
|
||||||
actionHelp(ACTION_LIST);
|
actionHelp(ACTION_LIST);
|
||||||
// the above call throws an exception so the return is not really required
|
// the above call throws an exception so the return is not really required
|
||||||
|
@ -2830,13 +2834,13 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
|
||||||
}
|
}
|
||||||
|
|
||||||
// at this point there is either the entire list or a stripped down instance
|
// at this point there is either the entire list or a stripped down instance
|
||||||
Set<String> listedInstances = new HashSet<String>();
|
Set<ApplicationReport> listedInstances = new HashSet<ApplicationReport>();
|
||||||
for (String name : persistentInstances.keySet()) {
|
for (String name : persistentInstances.keySet()) {
|
||||||
ApplicationReport report = reportMap.get(name);
|
ApplicationReport report = reportMap.get(name);
|
||||||
if (!listOnlyInState || report != null) {
|
if (!listOnlyInState || report != null) {
|
||||||
// list the details if all were requested, or the filtering contained
|
// list the details if all were requested, or the filtering contained
|
||||||
// a report
|
// a report
|
||||||
listedInstances.add(name);
|
listedInstances.add(report);
|
||||||
// containers will be non-null when only one instance is requested
|
// containers will be non-null when only one instance is requested
|
||||||
String details = instanceDetailsToString(name, report,
|
String details = instanceDetailsToString(name, report,
|
||||||
containers, version, components, verbose);
|
containers, version, components, verbose);
|
||||||
|
@ -3055,7 +3059,7 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
|
||||||
* @throws YarnException YARN issues
|
* @throws YarnException YARN issues
|
||||||
* @throws IOException IO problems
|
* @throws IOException IO problems
|
||||||
*/
|
*/
|
||||||
private ApplicationReport findInstance(String appname)
|
public ApplicationReport findInstance(String appname)
|
||||||
throws YarnException, IOException {
|
throws YarnException, IOException {
|
||||||
return yarnAppListClient.findInstance(appname);
|
return yarnAppListClient.findInstance(appname);
|
||||||
}
|
}
|
||||||
|
@ -3106,6 +3110,11 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public int actionStatus(String clustername, ActionStatusArgs statusArgs)
|
public int actionStatus(String clustername, ActionStatusArgs statusArgs)
|
||||||
throws YarnException, IOException {
|
throws YarnException, IOException {
|
||||||
|
if (statusArgs.lifetime) {
|
||||||
|
queryAndPrintLifetime(clustername);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
ClusterDescription status = verifyAndGetClusterDescription(clustername);
|
ClusterDescription status = verifyAndGetClusterDescription(clustername);
|
||||||
String outfile = statusArgs.getOutput();
|
String outfile = statusArgs.getOutput();
|
||||||
if (outfile == null) {
|
if (outfile == null) {
|
||||||
|
@ -3122,6 +3131,32 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
|
||||||
return verifyAndGetClusterDescription(clustername).toJsonString();
|
return verifyAndGetClusterDescription(clustername).toJsonString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void queryAndPrintLifetime(String appName)
|
||||||
|
throws YarnException, IOException {
|
||||||
|
ApplicationReport appReport = findInstance(appName);
|
||||||
|
if (appReport == null) {
|
||||||
|
throw new YarnException("No application found for " + appName);
|
||||||
|
}
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
PrintWriter timeoutStr =
|
||||||
|
new PrintWriter(new OutputStreamWriter(baos, Charset.forName("UTF-8")));
|
||||||
|
try {
|
||||||
|
ApplicationTimeout lifetime = appReport.getApplicationTimeouts()
|
||||||
|
.get(ApplicationTimeoutType.LIFETIME);
|
||||||
|
if (lifetime.getRemainingTime() == -1L) {
|
||||||
|
timeoutStr.append(appName + " has no lifetime configured.");
|
||||||
|
} else {
|
||||||
|
timeoutStr.append("\t" + ApplicationTimeoutType.LIFETIME);
|
||||||
|
timeoutStr.print(" expires at : " + lifetime.getExpiryTime());
|
||||||
|
timeoutStr.println(
|
||||||
|
".\tRemaining Time : " + lifetime.getRemainingTime() + " seconds");
|
||||||
|
}
|
||||||
|
System.out.println(baos.toString("UTF-8"));
|
||||||
|
} finally {
|
||||||
|
timeoutStr.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private ClusterDescription verifyAndGetClusterDescription(String clustername)
|
private ClusterDescription verifyAndGetClusterDescription(String clustername)
|
||||||
throws YarnException, IOException {
|
throws YarnException, IOException {
|
||||||
verifyBindingsDefined();
|
verifyBindingsDefined();
|
||||||
|
@ -3547,7 +3582,8 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public List<ApplicationReport> getApplications() throws YarnException, IOException {
|
public List<ApplicationReport> getApplications()
|
||||||
|
throws YarnException, IOException {
|
||||||
return yarnClient.getApplications();
|
return yarnClient.getApplications();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,10 @@ public class ActionStatusArgs extends AbstractActionArgs {
|
||||||
description = "Output file for the status information")
|
description = "Output file for the status information")
|
||||||
public String output;
|
public String output;
|
||||||
|
|
||||||
|
@Parameter(names = {ARG_LIFETIME},
|
||||||
|
description = "Lifetime of the application from the time of request")
|
||||||
|
public boolean lifetime;
|
||||||
|
|
||||||
public String getOutput() {
|
public String getOutput() {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue