Skip to content

Commit 9cd69c2

Browse files
YARN-10714. Remove dangling dynamic queues on reinitialization. Contributed by Andras Gyori
1 parent dac60b8 commit 9cd69c2

2 files changed

Lines changed: 97 additions & 7 deletions

File tree

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CapacitySchedulerQueueManager.java

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
import java.util.Map;
2828
import java.util.Set;
2929

30-
import org.apache.hadoop.yarn.util.resource.ResourceUtils;
31-
import org.apache.hadoop.yarn.util.resource.Resources;
3230
import org.slf4j.Logger;
3331
import org.slf4j.LoggerFactory;
3432
import org.apache.hadoop.classification.InterfaceAudience.Private;
@@ -340,11 +338,14 @@ private void updateQueues(CSQueueStore existingQueues,
340338
}
341339

342340
for (CSQueue queue : existingQueues.getQueues()) {
343-
if (!((AbstractCSQueue) queue).isDynamicQueue() && newQueues.get(
344-
queue.getQueuePath()) == null && !(
345-
queue instanceof AutoCreatedLeafQueue && conf
346-
.isAutoCreateChildQueueEnabled(
347-
queue.getParent().getQueuePath()))) {
341+
boolean isDanglingDynamicQueue = isDanglingDynamicQueue(
342+
newQueues, existingQueues, queue);
343+
boolean isRemovable = isDanglingDynamicQueue || !isDynamicQueue(queue)
344+
&& newQueues.get(queue.getQueuePath()) == null
345+
&& !(queue instanceof AutoCreatedLeafQueue &&
346+
conf.isAutoCreateChildQueueEnabled(queue.getParent().getQueuePath()));
347+
348+
if (isRemovable) {
348349
existingQueues.remove(queue);
349350
}
350351
}
@@ -435,4 +436,32 @@ private Map<String, Set<String>> getQueueToLabels() {
435436
getQueueStateManager() {
436437
return this.queueStateManager;
437438
}
439+
440+
private boolean isDynamicQueue(CSQueue queue) {
441+
return (queue instanceof AbstractCSQueue) &&
442+
((AbstractCSQueue) queue).isDynamicQueue();
443+
}
444+
445+
private boolean isDanglingDynamicQueue(
446+
CSQueueStore newQueues, CSQueueStore existingQueues,
447+
CSQueue queue) {
448+
if (!isDynamicQueue(queue)) {
449+
return false;
450+
}
451+
if (queue.getParent() == null) {
452+
return true;
453+
}
454+
if (newQueues.get(queue.getParent().getQueuePath()) != null) {
455+
return false;
456+
}
457+
CSQueue parent = existingQueues.get(queue.getParent().getQueuePath());
458+
if (parent == null) {
459+
return true;
460+
}
461+
// A dynamic queue is dangling, if its parent is not parsed in newQueues
462+
// or if its parent is not a dynamic queue. Dynamic queues are not parsed in
463+
// newQueues but they are deleted automatically, so it is safe to assume
464+
// that existingQueues contain valid dynamic queues.
465+
return !isDynamicQueue(parent);
466+
}
438467
}

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/TestCapacitySchedulerNewQueueAutoCreation.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.hadoop.util.Time;
2323
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
2424
import org.apache.hadoop.yarn.api.records.ApplicationId;
25+
import org.apache.hadoop.yarn.api.records.QueueState;
2526
import org.apache.hadoop.yarn.conf.YarnConfiguration;
2627
import org.apache.hadoop.yarn.exceptions.YarnException;
2728
import org.apache.hadoop.yarn.server.resourcemanager.MockNM;
@@ -968,6 +969,66 @@ public void testQueueInfoIfAmbiguousQueueNames() throws Exception {
968969
bAutoLeafQueue.getQueueInfo().getQueueName());
969970
}
970971

972+
@Test
973+
public void testRemoveDanglingAutoCreatedQueuesOnReinit() throws Exception {
974+
startScheduler();
975+
976+
// Validate static parent deletion
977+
createQueue("root.a.a-auto");
978+
AbstractCSQueue aAuto = (AbstractCSQueue) cs.
979+
getQueue("root.a.a-auto");
980+
Assert.assertTrue(aAuto.isDynamicQueue());
981+
982+
csConf.setState("root.a", QueueState.STOPPED);
983+
cs.reinitialize(csConf, mockRM.getRMContext());
984+
aAuto = (AbstractCSQueue) cs.
985+
getQueue("root.a.a-auto");
986+
Assert.assertEquals("root.a.a-auto is not in STOPPED state", QueueState.STOPPED, aAuto.getState());
987+
csConf.setQueues("root", new String[]{"b"});
988+
cs.reinitialize(csConf, mockRM.getRMContext());
989+
CSQueue aAutoNew = cs.getQueue("root.a.a-auto");
990+
Assert.assertNull(aAutoNew);
991+
992+
submitApp(cs, USER0, "a-auto", "root.a");
993+
aAutoNew = cs.getQueue("root.a.a-auto");
994+
Assert.assertNotNull(aAutoNew);
995+
996+
// Validate static grandparent deletion
997+
csConf.setQueues("root", new String[]{"a", "b"});
998+
csConf.setQueues("root.a", new String[]{"a1"});
999+
csConf.setAutoQueueCreationV2Enabled("root.a.a1", true);
1000+
cs.reinitialize(csConf, mockRM.getRMContext());
1001+
1002+
createQueue("root.a.a1.a1-auto");
1003+
CSQueue a1Auto = cs.getQueue("root.a.a1.a1-auto");
1004+
Assert.assertNotNull("a1-auto should exist", a1Auto);
1005+
1006+
csConf.setQueues("root", new String[]{"b"});
1007+
cs.reinitialize(csConf, mockRM.getRMContext());
1008+
a1Auto = cs.getQueue("root.a.a1.a1-auto");
1009+
Assert.assertNull("a1-auto has no parent and should not exist", a1Auto);
1010+
1011+
// Validate dynamic parent deletion
1012+
csConf.setState("root.b", QueueState.STOPPED);
1013+
cs.reinitialize(csConf, mockRM.getRMContext());
1014+
csConf.setAutoQueueCreationV2Enabled("root.b", true);
1015+
cs.reinitialize(csConf, mockRM.getRMContext());
1016+
1017+
createQueue("root.b.b-auto-parent.b-auto-leaf");
1018+
CSQueue bAutoParent = cs.getQueue("root.b.b-auto-parent");
1019+
Assert.assertNotNull("b-auto-parent should exist", bAutoParent);
1020+
ParentQueue b = (ParentQueue) cs.getQueue("root.b");
1021+
b.removeChildQueue(bAutoParent);
1022+
1023+
cs.reinitialize(csConf, mockRM.getRMContext());
1024+
1025+
bAutoParent = cs.getQueue("root.b.b-auto-parent");
1026+
Assert.assertNull("b-auto-parent should not exist ", bAutoParent);
1027+
CSQueue bAutoLeaf = cs.getQueue("root.b.b-auto-parent.b-auto-leaf");
1028+
Assert.assertNull("b-auto-leaf should not exist " +
1029+
"when its dynamic parent is removed", bAutoLeaf);
1030+
}
1031+
9711032
protected LeafQueue createQueue(String queuePath) throws YarnException {
9721033
return autoQueueHandler.autoCreateQueue(
9731034
CSQueueUtils.extractQueuePath(queuePath));

0 commit comments

Comments
 (0)