diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/exceptions/InvalidResourceRequestException.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/exceptions/InvalidResourceRequestException.java index f4fd2fa38a1..07680e3fe81 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/exceptions/InvalidResourceRequestException.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/exceptions/InvalidResourceRequestException.java @@ -30,19 +30,34 @@ * */ public class InvalidResourceRequestException extends YarnException { + public enum InvalidResourceType { + LESS_THAN_ZERO, GREATER_THEN_MAX_ALLOCATION, UNKNOWN; + } private static final long serialVersionUID = 13498237L; + private final InvalidResourceType invalidResourceType; public InvalidResourceRequestException(Throwable cause) { super(cause); + this.invalidResourceType = InvalidResourceType.UNKNOWN; } public InvalidResourceRequestException(String message) { + this(message, InvalidResourceType.UNKNOWN); + } + + public InvalidResourceRequestException(String message, + InvalidResourceType invalidResourceType) { super(message); + this.invalidResourceType = invalidResourceType; } public InvalidResourceRequestException(String message, Throwable cause) { super(message, cause); + this.invalidResourceType = InvalidResourceType.UNKNOWN; } + public InvalidResourceType getInvalidResourceType() { + return invalidResourceType; + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/DefaultAMSProcessor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/DefaultAMSProcessor.java index 71558a76be9..294a4d87db5 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/DefaultAMSProcessor.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/DefaultAMSProcessor.java @@ -53,6 +53,8 @@ import org.apache.hadoop.yarn.exceptions.InvalidContainerReleaseException; import org.apache.hadoop.yarn.exceptions.InvalidResourceBlacklistRequestException; import org.apache.hadoop.yarn.exceptions.InvalidResourceRequestException; +import org.apache.hadoop.yarn.exceptions.InvalidResourceRequestException + .InvalidResourceType; import org.apache.hadoop.yarn.exceptions.SchedulerInvalidResoureRequestException; import org.apache.hadoop.yarn.exceptions.YarnException; import org.apache.hadoop.yarn.factories.RecordFactory; @@ -231,6 +233,18 @@ public void allocate(ApplicationAttemptId appAttemptId, maximumCapacity, app.getQueue(), getScheduler(), getRmContext()); } catch (InvalidResourceRequestException e) { + if (e.getInvalidResourceType() == + InvalidResourceType.GREATER_THEN_MAX_ALLOCATION) { + app.getRMAppAttempt(appAttemptId).updateAMLaunchDiagnostics( + "Cannot allocate containers as resource request is " + + "greater than the maximum allowed allocation!"); + } else if (e.getInvalidResourceType() == + InvalidResourceType.LESS_THAN_ZERO) { + app.getRMAppAttempt(appAttemptId).updateAMLaunchDiagnostics( + "Cannot allocate containers as resource request is " + + "less than zero!"); + } + LOG.warn("Invalid resource ask by application " + appAttemptId, e); throw e; } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/SchedulerUtils.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/SchedulerUtils.java index 844057ea142..df6fe7d9cd4 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/SchedulerUtils.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/SchedulerUtils.java @@ -45,6 +45,8 @@ import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.exceptions.InvalidLabelResourceRequestException; import org.apache.hadoop.yarn.exceptions.InvalidResourceRequestException; +import org.apache.hadoop.yarn.exceptions.InvalidResourceRequestException + .InvalidResourceType; import org.apache.hadoop.yarn.exceptions .SchedulerInvalidResoureRequestException; import org.apache.hadoop.yarn.factories.RecordFactory; @@ -257,9 +259,9 @@ public static void normalizeAndValidateRequest(ResourceRequest resReq, } - public static void normalizeAndValidateRequest(ResourceRequest resReq, - Resource maximumResource, String queueName, YarnScheduler scheduler, - boolean isRecovery, RMContext rmContext, QueueInfo queueInfo) + private static void normalizeAndValidateRequest(ResourceRequest resReq, + Resource maximumResource, String queueName, YarnScheduler scheduler, + boolean isRecovery, RMContext rmContext, QueueInfo queueInfo) throws InvalidResourceRequestException { Configuration conf = rmContext.getYarnConfiguration(); // If Node label is not enabled throw exception @@ -384,13 +386,13 @@ static void checkResourceRequestAgainstAvailableResource(Resource reqResource, if (requestedRI.getValue() < 0) { throwInvalidResourceException(reqResource, availableResource, - reqResourceName); + reqResourceName, InvalidResourceType.LESS_THAN_ZERO); } boolean valid = checkResource(requestedRI, availableResource); if (!valid) { throwInvalidResourceException(reqResource, availableResource, - reqResourceName); + reqResourceName, InvalidResourceType.GREATER_THEN_MAX_ALLOCATION); } } } @@ -470,7 +472,8 @@ private static boolean checkResource( } private static void throwInvalidResourceException(Resource reqResource, - Resource availableResource, String reqResourceName) + Resource availableResource, String reqResourceName, + InvalidResourceType invalidResourceType) throws InvalidResourceRequestException { throw new InvalidResourceRequestException( "Invalid resource request, requested resource type=[" + reqResourceName @@ -481,7 +484,8 @@ private static void throwInvalidResourceException(Resource reqResource, + "by scheduler based on maximum resource of registered " + "NodeManagers, which might be less than configured " + "maximum allocation=" - + ResourceUtils.getResourceTypesMaximumAllocation()); + + ResourceUtils.getResourceTypesMaximumAllocation(), + invalidResourceType); } private static void checkQueueLabelInLabelManager(String labelExpression, diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/TestSchedulerUtils.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/TestSchedulerUtils.java index 15cfdb01e7b..36838832a4d 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/TestSchedulerUtils.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/TestSchedulerUtils.java @@ -67,6 +67,8 @@ import org.apache.hadoop.yarn.exceptions.InvalidLabelResourceRequestException; import org.apache.hadoop.yarn.exceptions.InvalidResourceBlacklistRequestException; import org.apache.hadoop.yarn.exceptions.InvalidResourceRequestException; +import org.apache.hadoop.yarn.exceptions.InvalidResourceRequestException + .InvalidResourceType; import org.apache.hadoop.yarn.exceptions.YarnException; import org.apache.hadoop.yarn.ipc.YarnRPC; import org.apache.hadoop.yarn.nodelabels.CommonNodeLabelsManager; @@ -642,7 +644,8 @@ public void testValidateResourceRequest() { mockScheduler, rmContext); fail("Negative memory should not be accepted"); } catch (InvalidResourceRequestException e) { - // expected + assertEquals(InvalidResourceType.LESS_THAN_ZERO, + e.getInvalidResourceType()); } // negative vcores @@ -657,7 +660,8 @@ public void testValidateResourceRequest() { mockScheduler, rmContext); fail("Negative vcores should not be accepted"); } catch (InvalidResourceRequestException e) { - // expected + assertEquals(InvalidResourceType.LESS_THAN_ZERO, + e.getInvalidResourceType()); } // more than max memory @@ -673,7 +677,8 @@ public void testValidateResourceRequest() { mockScheduler, rmContext); fail("More than max memory should not be accepted"); } catch (InvalidResourceRequestException e) { - // expected + assertEquals(InvalidResourceType.GREATER_THEN_MAX_ALLOCATION, + e.getInvalidResourceType()); } // more than max vcores @@ -688,7 +693,8 @@ public void testValidateResourceRequest() { mockScheduler, rmContext); fail("More than max vcores should not be accepted"); } catch (InvalidResourceRequestException e) { - // expected + assertEquals(InvalidResourceType.GREATER_THEN_MAX_ALLOCATION, + e.getInvalidResourceType()); } }