YARN-10655. Limit queue creation depth relative to its first static parent. Contributed by Andras Gyori.

This commit is contained in:
Peter Bacsko 2021-03-03 17:44:30 +01:00
parent cdba06e380
commit 7e8040e6ad
2 changed files with 47 additions and 13 deletions

View File

@ -55,34 +55,43 @@ public class CapacitySchedulerAutoQueueHandler {
List<ApplicationPlacementContext> parentsToCreate = new ArrayList<>(); List<ApplicationPlacementContext> parentsToCreate = new ArrayList<>();
ApplicationPlacementContext queueCandidateContext = parentContext; ApplicationPlacementContext queueCandidateContext = parentContext;
CSQueue existingQueueCandidate = getQueue( CSQueue firstExistingQueue = getQueue(
queueCandidateContext.getFullQueuePath()); queueCandidateContext.getFullQueuePath());
while (existingQueueCandidate == null) { while (firstExistingQueue == null) {
parentsToCreate.add(queueCandidateContext); parentsToCreate.add(queueCandidateContext);
queueCandidateContext = CSQueueUtils.extractQueuePath( queueCandidateContext = CSQueueUtils.extractQueuePath(
queueCandidateContext.getParentQueue()); queueCandidateContext.getParentQueue());
existingQueueCandidate = getQueue( firstExistingQueue = getQueue(
queueCandidateContext.getFullQueuePath()); queueCandidateContext.getFullQueuePath());
} }
CSQueue firstExistingStaticQueue = firstExistingQueue;
// Include the LeafQueue in the distance
int firstStaticParentDistance = parentsToCreate.size() + 1;
while(isNonStaticParent(firstExistingStaticQueue)) {
queueCandidateContext = CSQueueUtils.extractQueuePath(
queueCandidateContext.getParentQueue());
firstExistingStaticQueue = getQueue(
queueCandidateContext.getFullQueuePath());
++firstStaticParentDistance;
}
// Reverse the collection to to represent the hierarchy to be created // Reverse the collection to to represent the hierarchy to be created
// from highest to lowest level // from highest to lowest level
Collections.reverse(parentsToCreate); Collections.reverse(parentsToCreate);
if (!(existingQueueCandidate instanceof ParentQueue)) { if (!(firstExistingQueue instanceof ParentQueue)) {
throw new SchedulerDynamicEditException( throw new SchedulerDynamicEditException(
"Could not auto create hierarchy of " "Could not auto create hierarchy of "
+ queue.getFullQueuePath() + ". Queue " + queue.getFullQueuePath() + ". Queue "
+ existingQueueCandidate.getQueuePath() + + firstExistingQueue.getQueuePath() +
" is not a ParentQueue." " is not a ParentQueue."
); );
} }
ParentQueue existingParentQueue = (ParentQueue) existingQueueCandidate; ParentQueue existingParentQueue = (ParentQueue) firstExistingQueue;
int depthLimit = extractDepthLimit(existingParentQueue); int depthLimit = extractDepthLimit(existingParentQueue);
// The number of levels to be created including the LeafQueue
// (which is last)
int levelsToCreate = parentsToCreate.size() + 1;
if (depthLimit == 0) { if (depthLimit == 0) {
throw new SchedulerDynamicEditException("Auto creation of queue " + throw new SchedulerDynamicEditException("Auto creation of queue " +
@ -90,12 +99,12 @@ public class CapacitySchedulerAutoQueueHandler {
+ existingParentQueue.getQueuePath()); + existingParentQueue.getQueuePath());
} }
if (levelsToCreate > depthLimit) { if (firstStaticParentDistance > depthLimit) {
throw new SchedulerDynamicEditException( throw new SchedulerDynamicEditException(
"Could not auto create queue " + queue.getFullQueuePath() "Could not auto create queue " + queue.getFullQueuePath()
+ ". In order to create the desired queue hierarchy, " + + ". The distance of the LeafQueue from the first static " +
levelsToCreate + " levels of queues would need " + "ParentQueue is" + firstStaticParentDistance + ", which is " +
"to be created, which is above the limit."); "above the limit.");
} }
for (ApplicationPlacementContext current : parentsToCreate) { for (ApplicationPlacementContext current : parentsToCreate) {
@ -123,4 +132,9 @@ public class CapacitySchedulerAutoQueueHandler {
private CSQueue getQueue(String queue) { private CSQueue getQueue(String queue) {
return queue != null ? queueManager.getQueue(queue) : null; return queue != null ? queueManager.getQueue(queue) : null;
} }
private boolean isNonStaticParent(CSQueue queue) {
return (!(queue instanceof AbstractCSQueue)
|| ((AbstractCSQueue) queue).isDynamicQueue());
}
} }

View File

@ -565,6 +565,26 @@ public class TestCapacitySchedulerNewQueueAutoCreation
} }
} }
@Test
public void testAutoQueueCreationDepthLimitFromStaticParent()
throws Exception {
startScheduler();
// a is the first existing queue here and it is static, therefore
// the distance is 2
createQueue("root.a.a-auto.a1-auto");
Assert.assertNotNull(cs.getQueue("root.a.a-auto.a1-auto"));
try {
createQueue("root.a.a-auto.a2-auto.a3-auto");
Assert.fail("Queue creation should not succeed because the distance " +
"from the first static parent is above limit");
} catch (SchedulerDynamicEditException ignored) {
}
}
private LeafQueue createQueue(String queuePath) throws YarnException { private LeafQueue createQueue(String queuePath) throws YarnException {
return autoQueueHandler.autoCreateQueue( return autoQueueHandler.autoCreateQueue(
CSQueueUtils.extractQueuePath(queuePath)); CSQueueUtils.extractQueuePath(queuePath));