diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/SchedulerUtils.java 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 c999e26..de7c9ac 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/SchedulerUtils.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/SchedulerUtils.java @@ -245,7 +245,8 @@ public static void normalizeAndValidateRequest(ResourceRequest resReq, } SchedulerUtils.normalizeNodeLabelExpressionInRequest(resReq, queueInfo); if (!isRecovery) { - validateResourceRequest(resReq, maximumResource, queueInfo, rmContext); + validateResourceRequest(resReq, maximumResource, queueInfo, rmContext, + scheduler); } } @@ -269,28 +270,24 @@ public static void normalizeAndvalidateRequest(ResourceRequest resReq, * Utility method to validate a resource request, by insuring that the * requested memory/vcore is non-negative and not greater than max * + * * @throws InvalidResourceRequestException when there is invalid request */ private static void validateResourceRequest(ResourceRequest resReq, - Resource maximumResource, QueueInfo queueInfo, RMContext rmContext) + Resource maximumResource, QueueInfo queueInfo, RMContext rmContext, + YarnScheduler scheduler) throws InvalidResourceRequestException { - if (resReq.getCapability().getMemorySize() < 0 || - resReq.getCapability().getMemorySize() > maximumResource.getMemorySize()) { - throw new InvalidResourceRequestException("Invalid resource request" - + ", requested memory < 0" - + ", or requested memory > max configured" - + ", requestedMemory=" + resReq.getCapability().getMemorySize() - + ", maxMemory=" + maximumResource.getMemorySize()); - } - if (resReq.getCapability().getVirtualCores() < 0 || - resReq.getCapability().getVirtualCores() > - maximumResource.getVirtualCores()) { - throw new InvalidResourceRequestException("Invalid resource request" - + ", requested virtual cores < 0" - + ", or requested virtual cores > max configured" - + ", requestedVirtualCores=" - + resReq.getCapability().getVirtualCores() - + ", maxVirtualCores=" + maximumResource.getVirtualCores()); + ResourceCalculator resourceCalculator = scheduler.getResourceCalculator(); + Resource clusterResource = scheduler.getClusterResource(); + if (!Resources.fitsIn(resourceCalculator, clusterResource, Resources.none(), + resReq.getCapability()) + || !Resources.fitsIn(resourceCalculator, clusterResource, + resReq.getCapability(), maximumResource)) { + throw new InvalidResourceRequestException( + "Invalid resource request" + ", requested memory/vcore < 0" + + ", or requested memory/vcore > max configured" + + ", requested Resource=" + resReq.getCapability() + + ", maxResource=" + maximumResource); } String labelExp = resReq.getNodeLabelExpression(); // we don't allow specify label expression other than resourceName=ANY now diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/TestSchedulerUtils.java 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 63f97c5..a6f95e8 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/TestSchedulerUtils.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/TestSchedulerUtils.java @@ -200,17 +200,20 @@ public void testValidateResourceRequestWithErrorLabelsPermission() throws IOException { // mock queue and scheduler YarnScheduler scheduler = mock(YarnScheduler.class); + ResourceCalculator resourceCalculator = new DefaultResourceCalculator(); Set queueAccessibleNodeLabels = Sets.newHashSet(); QueueInfo queueInfo = mock(QueueInfo.class); when(queueInfo.getQueueName()).thenReturn("queue"); when(queueInfo.getAccessibleNodeLabels()).thenReturn(queueAccessibleNodeLabels); when(scheduler.getQueueInfo(any(String.class), anyBoolean(), anyBoolean())) .thenReturn(queueInfo); - + when(scheduler.getResourceCalculator()).thenReturn(resourceCalculator); + Resource maxResource = Resources.createResource( YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB, YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES); + when(scheduler.getClusterResource()).thenReturn(maxResource); // queue has labels, success cases try { // set queue accessible node labesl to [x, y] @@ -497,15 +500,21 @@ public void testValidateResourceRequestWithErrorLabelsPermission() } } - @Test (timeout = 30000) + @Test(timeout = 30000) public void testValidateResourceRequest() { YarnScheduler mockScheduler = mock(YarnScheduler.class); + ResourceCalculator resourceCalculator = new DefaultResourceCalculator(); + when(mockScheduler.getResourceCalculator()).thenReturn(resourceCalculator); + + YarnScheduler mockScheduler2 = mock(YarnScheduler.class); + ResourceCalculator drf = new DominantResourceCalculator(); + when(mockScheduler2.getResourceCalculator()).thenReturn(drf); Resource maxResource = Resources.createResource( YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB, YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES); - + when(mockScheduler2.getClusterResource()).thenReturn(maxResource); // zero memory try { Resource resource = @@ -579,7 +588,7 @@ public void testValidateResourceRequest() { // expected } - // negative vcores + // negative vcores for Dominant resource Calculator try { Resource resource = Resources.createResource( @@ -588,12 +597,25 @@ public void testValidateResourceRequest() { BuilderUtils.newResourceRequest(mock(Priority.class), ResourceRequest.ANY, resource, 1); SchedulerUtils.normalizeAndvalidateRequest(resReq, maxResource, null, - mockScheduler, rmContext); + mockScheduler2, rmContext); fail("Negative vcores should not be accepted"); } catch (InvalidResourceRequestException e) { // expected } + // negative vcores for Default resource allocator + try { + Resource resource = Resources.createResource( + YarnConfiguration.DEFAULT_RM_SCHEDULER_MINIMUM_ALLOCATION_MB, -1); + ResourceRequest resReq = BuilderUtils.newResourceRequest( + mock(Priority.class), ResourceRequest.ANY, resource, 1); + SchedulerUtils.normalizeAndvalidateRequest(resReq, maxResource, null, + mockScheduler, rmContext); + } catch (InvalidResourceRequestException e) { + fail( + "Negative vcores should be accepted for default resource calculator"); + } + // more than max memory try { Resource resource = @@ -610,6 +632,20 @@ public void testValidateResourceRequest() { // expected } + // more than max vcores dominant + try { + Resource resource = Resources.createResource( + YarnConfiguration.DEFAULT_RM_SCHEDULER_MINIMUM_ALLOCATION_MB, + YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES + 1); + ResourceRequest resReq = BuilderUtils.newResourceRequest( + mock(Priority.class), ResourceRequest.ANY, resource, 1); + SchedulerUtils.normalizeAndvalidateRequest(resReq, maxResource, null, + mockScheduler2, rmContext); + fail("More than max vcores should not be accepted"); + } catch (InvalidResourceRequestException e) { + // expected + } + // more than max vcores try { Resource resource = @@ -622,9 +658,8 @@ public void testValidateResourceRequest() { ResourceRequest.ANY, resource, 1); SchedulerUtils.normalizeAndvalidateRequest(resReq, maxResource, null, mockScheduler, rmContext); - fail("More than max vcores should not be accepted"); } catch (InvalidResourceRequestException e) { - // expected + fail("More than max vcores should be accepted for default"); } } @@ -733,6 +768,7 @@ public void testCreatePreemptedContainerStatus() { @Test (timeout = 30000) public void testNormalizeNodeLabelExpression() throws IOException { + ResourceCalculator resourceCalculator = new DefaultResourceCalculator(); // mock queue and scheduler YarnScheduler scheduler = mock(YarnScheduler.class); Set queueAccessibleNodeLabels = Sets.newHashSet(); @@ -742,6 +778,7 @@ public void testNormalizeNodeLabelExpression() when(queueInfo.getDefaultNodeLabelExpression()).thenReturn(" x "); when(scheduler.getQueueInfo(any(String.class), anyBoolean(), anyBoolean())) .thenReturn(queueInfo); + when(scheduler.getResourceCalculator()).thenReturn(resourceCalculator); Resource maxResource = Resources.createResource( YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB,