|
@@ -24,11 +24,9 @@ import java.nio.ByteBuffer;
|
|
|
import java.security.AccessControlException;
|
|
|
import java.security.Principal;
|
|
|
import java.security.PrivilegedExceptionAction;
|
|
|
-import java.text.ParseException;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
import java.util.Collection;
|
|
|
-import java.util.Collections;
|
|
|
import java.util.EnumSet;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.HashSet;
|
|
@@ -97,12 +95,10 @@ import org.apache.hadoop.yarn.api.protocolrecords.ReservationUpdateRequest;
|
|
|
import org.apache.hadoop.yarn.api.protocolrecords.SubmitApplicationRequest;
|
|
|
import org.apache.hadoop.yarn.api.protocolrecords.SubmitApplicationResponse;
|
|
|
import org.apache.hadoop.yarn.api.protocolrecords.UpdateApplicationPriorityRequest;
|
|
|
-import org.apache.hadoop.yarn.api.protocolrecords.UpdateApplicationTimeoutsRequest;
|
|
|
import org.apache.hadoop.yarn.api.records.ApplicationAccessType;
|
|
|
import org.apache.hadoop.yarn.api.records.ApplicationId;
|
|
|
import org.apache.hadoop.yarn.api.records.ApplicationReport;
|
|
|
import org.apache.hadoop.yarn.api.records.ApplicationSubmissionContext;
|
|
|
-import org.apache.hadoop.yarn.api.records.ApplicationTimeoutType;
|
|
|
import org.apache.hadoop.yarn.api.records.ContainerLaunchContext;
|
|
|
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
|
|
|
import org.apache.hadoop.yarn.api.records.LocalResource;
|
|
@@ -193,7 +189,6 @@ import org.apache.hadoop.yarn.server.webapp.dao.ContainerInfo;
|
|
|
import org.apache.hadoop.yarn.server.webapp.dao.ContainersInfo;
|
|
|
import org.apache.hadoop.yarn.util.AdHocLogDumper;
|
|
|
import org.apache.hadoop.yarn.util.ConverterUtils;
|
|
|
-import org.apache.hadoop.yarn.util.Times;
|
|
|
import org.apache.hadoop.yarn.webapp.BadRequestException;
|
|
|
import org.apache.hadoop.yarn.webapp.ForbiddenException;
|
|
|
import org.apache.hadoop.yarn.webapp.NotFoundException;
|
|
@@ -2393,185 +2388,4 @@ public class RMWebServices extends WebServices {
|
|
|
return Response.status(Status.OK).entity(resResponse).build();
|
|
|
}
|
|
|
|
|
|
- @GET
|
|
|
- @Path("/apps/{appid}/timeout/{type}")
|
|
|
- @Produces({ MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
|
|
|
- MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8 })
|
|
|
- public AppTimeoutInfo getAppTimeout(@Context HttpServletRequest hsr,
|
|
|
- @PathParam("appid") String appId, @PathParam("type") String type)
|
|
|
- throws AuthorizationException {
|
|
|
- init();
|
|
|
- RMApp app = validateAppTimeoutRequest(hsr, appId);
|
|
|
-
|
|
|
- ApplicationTimeoutType appTimeoutType = parseTimeoutType(type);
|
|
|
- Long timeoutValue = app.getApplicationTimeouts().get(appTimeoutType);
|
|
|
- AppTimeoutInfo timeout =
|
|
|
- constructAppTimeoutDao(appTimeoutType, timeoutValue);
|
|
|
- return timeout;
|
|
|
- }
|
|
|
-
|
|
|
- private RMApp validateAppTimeoutRequest(HttpServletRequest hsr,
|
|
|
- String appId) {
|
|
|
- UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true);
|
|
|
- String userName = "UNKNOWN-USER";
|
|
|
- if (callerUGI != null) {
|
|
|
- userName = callerUGI.getUserName();
|
|
|
- }
|
|
|
-
|
|
|
- if (UserGroupInformation.isSecurityEnabled() && isStaticUser(callerUGI)) {
|
|
|
- String msg = "The default static user cannot carry out this operation.";
|
|
|
- RMAuditLogger.logFailure(userName, AuditConstants.GET_APP_TIMEOUTS,
|
|
|
- "UNKNOWN", "RMWebService", msg);
|
|
|
- throw new ForbiddenException(msg);
|
|
|
- }
|
|
|
-
|
|
|
- RMApp app = null;
|
|
|
- try {
|
|
|
- app = getRMAppForAppId(appId);
|
|
|
- } catch (NotFoundException e) {
|
|
|
- RMAuditLogger.logFailure(userName, AuditConstants.GET_APP_TIMEOUTS,
|
|
|
- "UNKNOWN", "RMWebService",
|
|
|
- "Trying to get timeouts of an absent application " + appId);
|
|
|
- throw e;
|
|
|
- }
|
|
|
- return app;
|
|
|
- }
|
|
|
-
|
|
|
- @GET
|
|
|
- @Path("/apps/{appid}/timeouts")
|
|
|
- @Produces({ MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
|
|
|
- MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8 })
|
|
|
- public AppTimeoutsInfo getAppTimeouts(@Context HttpServletRequest hsr,
|
|
|
- @PathParam("appid") String appId) throws AuthorizationException {
|
|
|
- init();
|
|
|
-
|
|
|
- RMApp app = validateAppTimeoutRequest(hsr, appId);
|
|
|
-
|
|
|
- AppTimeoutsInfo timeouts = new AppTimeoutsInfo();
|
|
|
- Map<ApplicationTimeoutType, Long> applicationTimeouts =
|
|
|
- app.getApplicationTimeouts();
|
|
|
- if (applicationTimeouts.isEmpty()) {
|
|
|
- // If application is not set timeout, lifetime should be sent as default
|
|
|
- // with expiryTime=UNLIMITED and remainingTime=-1
|
|
|
- timeouts
|
|
|
- .add(constructAppTimeoutDao(ApplicationTimeoutType.LIFETIME, null));
|
|
|
- } else {
|
|
|
- for (Entry<ApplicationTimeoutType, Long> timeout : app
|
|
|
- .getApplicationTimeouts().entrySet()) {
|
|
|
- AppTimeoutInfo timeoutInfo =
|
|
|
- constructAppTimeoutDao(timeout.getKey(), timeout.getValue());
|
|
|
- timeouts.add(timeoutInfo);
|
|
|
- }
|
|
|
- }
|
|
|
- return timeouts;
|
|
|
- }
|
|
|
-
|
|
|
- private ApplicationTimeoutType parseTimeoutType(String type) {
|
|
|
- try {
|
|
|
- // enum string is in the uppercase
|
|
|
- return ApplicationTimeoutType
|
|
|
- .valueOf(StringUtils.toUpperCase(type.trim()));
|
|
|
- } catch (RuntimeException e) {
|
|
|
- ApplicationTimeoutType[] typeArray = ApplicationTimeoutType.values();
|
|
|
- String allAppTimeoutTypes = Arrays.toString(typeArray);
|
|
|
- throw new BadRequestException("Invalid application-state " + type.trim()
|
|
|
- + " specified. It should be one of " + allAppTimeoutTypes);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private AppTimeoutInfo constructAppTimeoutDao(ApplicationTimeoutType type,
|
|
|
- Long timeoutInMillis) {
|
|
|
- AppTimeoutInfo timeout = new AppTimeoutInfo();
|
|
|
- timeout.setTimeoutType(type);
|
|
|
- if (timeoutInMillis != null) {
|
|
|
- timeout.setExpiryTime(Times.formatISO8601(timeoutInMillis.longValue()));
|
|
|
- timeout.setRemainingTime(
|
|
|
- Math.max((timeoutInMillis - System.currentTimeMillis()) / 1000, 0));
|
|
|
- }
|
|
|
- return timeout;
|
|
|
- }
|
|
|
-
|
|
|
- @PUT
|
|
|
- @Path("/apps/{appid}/timeout")
|
|
|
- @Produces({ MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8,
|
|
|
- MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8 })
|
|
|
- @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
|
|
- public Response updateApplicationTimeout(AppTimeoutInfo appTimeout,
|
|
|
- @Context HttpServletRequest hsr, @PathParam("appid") String appId)
|
|
|
- throws AuthorizationException, YarnException, InterruptedException,
|
|
|
- IOException {
|
|
|
- init();
|
|
|
-
|
|
|
- UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true);
|
|
|
- if (callerUGI == null) {
|
|
|
- throw new AuthorizationException(
|
|
|
- "Unable to obtain user name, user not authenticated");
|
|
|
- }
|
|
|
-
|
|
|
- if (UserGroupInformation.isSecurityEnabled() && isStaticUser(callerUGI)) {
|
|
|
- return Response.status(Status.FORBIDDEN)
|
|
|
- .entity("The default static user cannot carry out this operation.")
|
|
|
- .build();
|
|
|
- }
|
|
|
-
|
|
|
- String userName = callerUGI.getUserName();
|
|
|
- RMApp app = null;
|
|
|
- try {
|
|
|
- app = getRMAppForAppId(appId);
|
|
|
- } catch (NotFoundException e) {
|
|
|
- RMAuditLogger.logFailure(userName, AuditConstants.UPDATE_APP_TIMEOUTS,
|
|
|
- "UNKNOWN", "RMWebService",
|
|
|
- "Trying to update timeout of an absent application " + appId);
|
|
|
- throw e;
|
|
|
- }
|
|
|
-
|
|
|
- return updateApplicationTimeouts(app, callerUGI, appTimeout);
|
|
|
- }
|
|
|
-
|
|
|
- private Response updateApplicationTimeouts(final RMApp app,
|
|
|
- UserGroupInformation callerUGI, final AppTimeoutInfo appTimeout)
|
|
|
- throws IOException, InterruptedException {
|
|
|
-
|
|
|
- if (appTimeout.getTimeoutType() == null) {
|
|
|
- return Response.status(Status.BAD_REQUEST).entity("Timeout type is null.")
|
|
|
- .build();
|
|
|
- }
|
|
|
-
|
|
|
- String userName = callerUGI.getUserName();
|
|
|
- try {
|
|
|
- callerUGI.doAs(new PrivilegedExceptionAction<Void>() {
|
|
|
- @Override
|
|
|
- public Void run() throws IOException, YarnException {
|
|
|
- UpdateApplicationTimeoutsRequest request =
|
|
|
- UpdateApplicationTimeoutsRequest
|
|
|
- .newInstance(app.getApplicationId(), Collections.singletonMap(
|
|
|
- appTimeout.getTimeoutType(), appTimeout.getExpireTime()));
|
|
|
- rm.getClientRMService().updateApplicationTimeouts(request);
|
|
|
- return null;
|
|
|
- }
|
|
|
- });
|
|
|
- } catch (UndeclaredThrowableException ue) {
|
|
|
- // if the root cause is a permissions issue
|
|
|
- // bubble that up to the user
|
|
|
- if (ue.getCause() instanceof YarnException) {
|
|
|
- YarnException ye = (YarnException) ue.getCause();
|
|
|
- if (ye.getCause() instanceof AccessControlException) {
|
|
|
- String appId = app.getApplicationId().toString();
|
|
|
- String msg = "Unauthorized attempt to change timeout of app " + appId
|
|
|
- + " by remote user " + userName;
|
|
|
- return Response.status(Status.FORBIDDEN).entity(msg).build();
|
|
|
- } else if (ye.getCause() instanceof ParseException) {
|
|
|
- return Response.status(Status.BAD_REQUEST)
|
|
|
- .entity(ye.getMessage()).build();
|
|
|
- } else {
|
|
|
- throw ue;
|
|
|
- }
|
|
|
- } else {
|
|
|
- throw ue;
|
|
|
- }
|
|
|
- }
|
|
|
- AppTimeoutInfo timeout = constructAppTimeoutDao(appTimeout.getTimeoutType(),
|
|
|
- app.getApplicationTimeouts().get(appTimeout.getTimeoutType()));
|
|
|
- return Response.status(Status.OK).entity(timeout).build();
|
|
|
- }
|
|
|
}
|