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/LeafQueue.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/LeafQueue.java index ffe862fc618..3c673883eda 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/LeafQueue.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/LeafQueue.java @@ -1463,7 +1463,9 @@ Resource computeUserLimitAndSetHeadroom(FiCaSchedulerApp application, userLimit = getResourceLimitForActiveUsers(application.getUser(), clusterResource, nodePartition, schedulingMode); } - setQueueResourceLimitsInfo(clusterResource); + if (RMNodeLabelsManager.NO_LABEL.equals(nodePartition)) { + setQueueResourceLimitsInfo(clusterResource); + } Resource headroom = metrics.getUserMetrics(user) == null ? Resources.none() : 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/TestNodeLabelContainerAllocation.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/TestNodeLabelContainerAllocation.java index 1836919d404..d9eefe56d21 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/TestNodeLabelContainerAllocation.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/TestNodeLabelContainerAllocation.java @@ -2246,4 +2246,70 @@ public RMNodeLabelsManager createNodeLabelManager() { rm1.close(); } + + @Test + public void testAppHeadroom() throws Exception { + /** + * Test case: app headroom in default label should not be affected by + * allocation of other apps in non-default label and in the same queue. + * + * Queue a can access default partition or partition "x". + * Launch app1 in default partition and its headroom should be + * (default partition limit - app used), then launch app2 in partition "x", + * after that app1's headroom should not be updated. + * + * app1's headroom was updated to (partition "x" limit - app used) + * before YARN-8728. + */ + CapacitySchedulerConfiguration csConf = + new CapacitySchedulerConfiguration(this.conf); + + // Define top-level queues + csConf.setQueues(CapacitySchedulerConfiguration.ROOT, new String[] { "a" }); + csConf.setCapacityByLabel(CapacitySchedulerConfiguration.ROOT, "x", 100); + csConf.setCapacityByLabel(CapacitySchedulerConfiguration.ROOT, "", 100); + + final String queueA = CapacitySchedulerConfiguration.ROOT + ".a"; + csConf.setCapacity(queueA, 100); + csConf.setAccessibleNodeLabels(queueA, toSet("", "x")); + csConf.setCapacityByLabel(queueA, "x", 100); + csConf.setMaximumCapacityByLabel(queueA, "x", 100); + + // set node -> label + mgr.addToCluserNodeLabels( + ImmutableSet.of(NodeLabel.newInstance("x", false))); + mgr.addLabelsToNode( + ImmutableMap.of(NodeId.newInstance("h1", 0), toSet("x"))); + + // inject node label manager + MockRM rm1 = new MockRM(csConf) { + @Override public RMNodeLabelsManager createNodeLabelManager() { + return mgr; + } + }; + + rm1.getRMContext().setNodeLabelManager(mgr); + rm1.start(); + MockNM nm1 = rm1.registerNode("h1:1234", 10 * GB); // label = "x" + MockNM nm2 = rm1.registerNode("h2:1234", 10 * GB); // label = "" + MockNM nm3 = rm1.registerNode("h3:1234", 10 * GB); // label = "" + CapacityScheduler cs = (CapacityScheduler) rm1.getResourceScheduler(); + + // app1 -> a (partition="") + RMApp app1 = rm1.submitApp(1 * GB, "app", "user", null, "a", ""); + MockRM.launchAndRegisterAM(app1, rm1, nm2); + FiCaSchedulerApp schedulerApp1 = + cs.getApplicationAttempt(app1.getCurrentAppAttempt().getAppAttemptId()); + // Verify app1 headroom, memory-size should be 19 GB + Assert.assertEquals(19 * GB, schedulerApp1.getHeadroom().getMemorySize()); + + // app2 -> a (partition="x") + RMApp app2 = rm1.submitApp(1 * GB, "app2", "user", null, "a", "x"); + MockRM.launchAndRegisterAM(app2, rm1, nm1); + + // Verify allocation for partition "x" can't affect app1's headroom + Assert.assertEquals(19 * GB, schedulerApp1.getHeadroom().getMemorySize()); + + rm1.close(); + } }