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/capacity/allocator/RegularContainerAllocator.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/allocator/RegularContainerAllocator.java index 2643fd0b7a1..413b391b1bf 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/allocator/RegularContainerAllocator.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/allocator/RegularContainerAllocator.java @@ -86,9 +86,8 @@ private boolean checkHeadroom(Resource clusterResource, // allocation. resourceCouldBeUnReserved = Resources.none(); } - return Resources.greaterThanOrEqual(rc, clusterResource, Resources.add( - currentResourceLimits.getHeadroom(), resourceCouldBeUnReserved), - required); + return Resources.fitsIn(rc, required, Resources.add( + currentResourceLimits.getHeadroom(), resourceCouldBeUnReserved)); } /* 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/capacity/TestContainerAllocation.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestContainerAllocation.java index 22b311db4dd..dcd8f23f068 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestContainerAllocation.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestContainerAllocation.java @@ -22,6 +22,8 @@ import java.util.List; import java.util.Set; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.hadoop.conf.Configuration; @@ -1187,4 +1189,52 @@ public void testContainerRejectionWhenAskBeyondDynamicMax() rm1.close(); } + + @Test(timeout = 30000) + public void testReachedQueueHeadroomWithDRF() throws Exception { + CapacitySchedulerConfiguration newConf = + (CapacitySchedulerConfiguration) TestUtils + .getConfigurationWithMultipleQueues(conf); + newConf.setClass(CapacitySchedulerConfiguration.RESOURCE_CALCULATOR_CLASS, + DominantResourceCalculator.class, ResourceCalculator.class); + newConf + .setBoolean(CapacitySchedulerConfiguration.RESERVE_CONT_LOOK_ALL_NODES, + false); + // set max-capacity of queue a to 50% + newConf.setMaximumCapacity(CapacitySchedulerConfiguration.ROOT + ".a", 50); + MockRM rm1 = new MockRM(newConf); + rm1.start(); + + // add nm1 with resource <10GB, 10> + // Now headroom of queue a is <5GB, 5> + MockNM nm1 = rm1.registerNode("h1:1234", 10 * GB, 10); + + // launch app1 with AM resource <3GB, 1> + RMApp app1 = rm1.submitApp(3 * GB, "app", "user", null, "a"); + MockAM am1 = MockRM.launchAndRegisterAM(app1, rm1, nm1); + + // Now headroom of queue a is <2GB, 4> + // Ask 1 container with <3GB, 1> + am1.allocate("*", Resource.newInstance(3 * GB, 1), 1, null, null); + + // Check there should be no allocation proposal + // spy CapacityScheduler and hook its submitResourceCommitRequest method + final CapacityScheduler spyCs = + Mockito.spy((CapacityScheduler) rm1.getResourceScheduler()); + Mockito.doAnswer((InvocationOnMock invocation) -> { + CSAssignment assignment = invocation.getArgument(1); + // check no proposal in actual submit, will reach here before YARN-9687 + if (assignment.getAssignmentInformation().getNumAllocations() > 0) { + Assert.fail("Unacceptable allocation should not be generated!"); + } + return false; + }).when(spyCs).submitResourceCommitRequest(Mockito.any(Resource.class), + Mockito.any(CSAssignment.class)); + + // Do nm1 heartbeats 1 times, will allocate a container on nm1 for app2 + spyCs.handle(new NodeUpdateSchedulerEvent( + rm1.getRMContext().getRMNodes().get(nm1.getNodeId()))); + + rm1.close(); + } }