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/fair/AllocationConfiguration.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/AllocationConfiguration.java index f984fef..ac8688a 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/AllocationConfiguration.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/AllocationConfiguration.java @@ -43,9 +43,13 @@ new DefaultResourceCalculator(); // Minimum resource allocation for each queue private final Map minQueueResources; + // Minimum resource allocation for each queue's ad hoc children + private final Map minChildQueueResources; // Maximum amount of resources per queue @VisibleForTesting final Map maxQueueResources; + // Maximum amount of resources for each queue's ad hoc children + private final Map maxChildQueueResources; // Sharing weights for each queue private final Map queueWeights; @@ -106,7 +110,9 @@ private final Set nonPreemptableQueues; public AllocationConfiguration(Map minQueueResources, + Map minChildQueueResources, Map maxQueueResources, + Map maxChildQueueResources, Map queueMaxApps, Map userMaxApps, Map queueWeights, Map queueMaxAMShares, int userMaxAppsDefault, @@ -125,7 +131,9 @@ public AllocationConfiguration(Map minQueueResources, Set reservableQueues, Set nonPreemptableQueues) { this.minQueueResources = minQueueResources; + this.minChildQueueResources = minChildQueueResources; this.maxQueueResources = maxQueueResources; + this.maxChildQueueResources = maxChildQueueResources; this.queueMaxApps = queueMaxApps; this.userMaxApps = userMaxApps; this.queueMaxAMShares = queueMaxAMShares; @@ -149,31 +157,33 @@ public AllocationConfiguration(Map minQueueResources, } public AllocationConfiguration(Configuration conf) { - minQueueResources = new HashMap(); - maxQueueResources = new HashMap(); - queueWeights = new HashMap(); - queueMaxApps = new HashMap(); - userMaxApps = new HashMap(); - queueMaxAMShares = new HashMap(); + minQueueResources = new HashMap<>(); + minChildQueueResources = new HashMap<>(); + maxChildQueueResources = new HashMap<>(); + maxQueueResources = new HashMap<>(); + queueWeights = new HashMap<>(); + queueMaxApps = new HashMap<>(); + userMaxApps = new HashMap<>(); + queueMaxAMShares = new HashMap<>(); userMaxAppsDefault = Integer.MAX_VALUE; queueMaxAppsDefault = Integer.MAX_VALUE; queueMaxResourcesDefault = Resources.unbounded(); queueMaxAMShareDefault = 0.5f; - queueAcls = new HashMap>(); - resAcls = new HashMap>(); - minSharePreemptionTimeouts = new HashMap(); - fairSharePreemptionTimeouts = new HashMap(); - fairSharePreemptionThresholds = new HashMap(); - schedulingPolicies = new HashMap(); + queueAcls = new HashMap<>(); + resAcls = new HashMap<>(); + minSharePreemptionTimeouts = new HashMap<>(); + fairSharePreemptionTimeouts = new HashMap<>(); + fairSharePreemptionThresholds = new HashMap<>(); + schedulingPolicies = new HashMap<>(); defaultSchedulingPolicy = SchedulingPolicy.DEFAULT_POLICY; reservableQueues = new HashSet<>(); - configuredQueues = new HashMap>(); + configuredQueues = new HashMap<>(); for (FSQueueType queueType : FSQueueType.values()) { - configuredQueues.put(queueType, new HashSet()); + configuredQueues.put(queueType, new HashSet<>()); } - placementPolicy = QueuePlacementPolicy.fromConfiguration(conf, - configuredQueues); - nonPreemptableQueues = new HashSet(); + placementPolicy = + QueuePlacementPolicy.fromConfiguration(conf, configuredQueues); + nonPreemptableQueues = new HashSet<>(); } /** @@ -263,6 +273,8 @@ public float getQueueMaxAMShare(String queue) { /** * Get the minimum resource allocation for the given queue. + * + * @param queue the target queue's name * @return the cap set on this queue, or 0 if not set. */ public Resource getMinResources(String queue) { @@ -271,14 +283,67 @@ public Resource getMinResources(String queue) { } /** - * Get the maximum resource allocation for the given queue. - * @return the cap set on this queue, or Integer.MAX_VALUE if not set. + * Set the minimum resource allocation for the given queue if it's not already + * set. If the queue already has a minimum resource allocation set, this + * call has no effect. + * + * @param queue the target queue + * @param minResource the minimum resource allocation + */ + public void addMinResources(String queue, Resource minResource) { + minQueueResources.putIfAbsent(queue, minResource); + } + + /** + * Get the minimum resource allocation for children of the given queue. + * + * @param queue the target queue's name + * @return the minimum allocation on this queue, or 0 if not set. */ + public Resource getMinChildResources(String queue) { + Resource minChildResource = minChildQueueResources.get(queue); - public Resource getMaxResources(String queueName) { - Resource maxQueueResource = maxQueueResources.get(queueName); + if (minChildResource == null) { + minChildResource = Resources.none(); + } + + return minChildResource; + } + + /** + * Set the minimum resource allocation for the children of the given queue if + * it's not already set. If the queue already has a minimum resource + * allocation set, this call has no effect. + * + * @param queue the target queue + * @param minResource the minimum resource allocation + */ + public void addMinChildResources(String queue, Resource minResource) { + minChildQueueResources.putIfAbsent(queue, minResource); + } + + /** + * Set the maximum resource allocation for the given queue if it's not already + * set. If the queue already has a maximum child resource allocation set, this + * call has no effect. + * + * @param queue the target queue + * @param maxResource the maximum resource allocation + */ + public void addMaxResources(String queue, Resource maxResource) { + maxQueueResources.putIfAbsent(queue, maxResource); + } + + /** + * Get the maximum resource allocation for the given queue. + * + * @param queue the target queue's name + * @return the max allocation on this queue, or Integer.MAX_VALUE if not set. + */ + public Resource getMaxResources(String queue) { + Resource maxQueueResource = maxQueueResources.get(queue); if (maxQueueResource == null) { - Resource minQueueResource = minQueueResources.get(queueName); + Resource minQueueResource = minQueueResources.get(queue); if (minQueueResource != null && Resources.greaterThan(RESOURCE_CALCULATOR, Resources.unbounded(), minQueueResource, queueMaxResourcesDefault)) { @@ -291,6 +356,42 @@ public Resource getMaxResources(String queueName) { } } + /** + * Get the maximum resource allocation for children of the given queue. + * + * @param queue the target queue's name + * @return the max allocation on this queue, or Integer.MAX_VALUE if not set. + */ + public Resource getMaxChildResources(String queue) { + Resource maxQueueResource = maxChildQueueResources.get(queue); + + if (maxQueueResource == null) { + Resource minQueueResource = minChildQueueResources.get(queue); + + if (minQueueResource != null && + Resources.greaterThan(RESOURCE_CALCULATOR, Resources.unbounded(), + minQueueResource, queueMaxResourcesDefault)) { + maxQueueResource = minQueueResource; + } else { + maxQueueResource = queueMaxResourcesDefault; + } + } + + return maxQueueResource; + } + + /** + * Set the maximum resource allocation for the children of the given queue if + * it's not already set. If the queue already has a maximum child resource + * allocation set, this call has no effect. + * + * @param queue the target queue + * @param maxResource the maximum resource allocation + */ + public void addMaxChildResources(String queue, Resource maxResource) { + maxChildQueueResources.putIfAbsent(queue, maxResource); + } + public boolean hasAccess(String queueName, QueueACL acl, UserGroupInformation user) { int lastPeriodIndex = queueName.length(); 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/fair/AllocationFileLoaderService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/AllocationFileLoaderService.java index fab536d..b64501f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/AllocationFileLoaderService.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/AllocationFileLoaderService.java @@ -213,23 +213,23 @@ public synchronized void reloadAllocations() throws IOException, LOG.info("Loading allocation file " + allocFile); // Create some temporary hashmaps to hold the new allocs, and we only save // them in our fields if we have parsed the entire allocs file successfully. - Map minQueueResources = new HashMap(); - Map maxQueueResources = new HashMap(); - Map queueMaxApps = new HashMap(); - Map userMaxApps = new HashMap(); - Map queueMaxAMShares = new HashMap(); - Map queueWeights = new HashMap(); - Map queuePolicies = new HashMap(); - Map minSharePreemptionTimeouts = new HashMap(); - Map fairSharePreemptionTimeouts = new HashMap(); - Map fairSharePreemptionThresholds = - new HashMap(); - Map> queueAcls = - new HashMap>(); + Map minQueueResources = new HashMap<>(); + Map minChildQueueResources = new HashMap<>(); + Map maxQueueResources = new HashMap<>(); + Map maxChildQueueResources = new HashMap<>(); + Map queueMaxApps = new HashMap<>(); + Map userMaxApps = new HashMap<>(); + Map queueMaxAMShares = new HashMap<>(); + Map queueWeights = new HashMap<>(); + Map queuePolicies = new HashMap<>(); + Map minSharePreemptionTimeouts = new HashMap<>(); + Map fairSharePreemptionTimeouts = new HashMap<>(); + Map fairSharePreemptionThresholds = new HashMap<>(); + Map> queueAcls = new HashMap<>(); Map> reservationAcls = - new HashMap>(); - Set reservableQueues = new HashSet(); - Set nonPreemptableQueues = new HashSet(); + new HashMap<>(); + Set reservableQueues = new HashSet<>(); + Set nonPreemptableQueues = new HashSet<>(); int userMaxAppsDefault = Integer.MAX_VALUE; int queueMaxAppsDefault = Integer.MAX_VALUE; Resource queueMaxResourcesDefault = Resources.unbounded(); @@ -250,8 +250,8 @@ public synchronized void reloadAllocations() throws IOException, // configuredQueues is segregated based on whether it is a leaf queue // or a parent queue. This information is used for creating queues // and also for making queue placement decisions(QueuePlacementRule.java). - Map> configuredQueues = - new HashMap>(); + Map> configuredQueues = new HashMap<>(); + for (FSQueueType queueType : FSQueueType.values()) { configuredQueues.put(queueType, new HashSet()); } @@ -367,9 +367,10 @@ public synchronized void reloadAllocations() throws IOException, } parent = null; } - loadQueue(parent, element, minQueueResources, maxQueueResources, - queueMaxApps, userMaxApps, queueMaxAMShares, queueWeights, - queuePolicies, minSharePreemptionTimeouts, fairSharePreemptionTimeouts, + loadQueue(parent, element, minQueueResources, minChildQueueResources, + maxQueueResources, maxChildQueueResources, queueMaxApps, userMaxApps, + queueMaxAMShares, queueWeights, queuePolicies, + minSharePreemptionTimeouts, fairSharePreemptionTimeouts, fairSharePreemptionThresholds, queueAcls, reservationAcls, configuredQueues, reservableQueues, nonPreemptableQueues); } @@ -413,14 +414,15 @@ public synchronized void reloadAllocations() throws IOException, globalReservationQueueConfig.setReservationAgent(reservationAgent); } - AllocationConfiguration info = new AllocationConfiguration(minQueueResources, - maxQueueResources, queueMaxApps, userMaxApps, queueWeights, - queueMaxAMShares, userMaxAppsDefault, queueMaxAppsDefault, - queueMaxResourcesDefault, queueMaxAMShareDefault, queuePolicies, - defaultSchedPolicy, minSharePreemptionTimeouts, - fairSharePreemptionTimeouts, fairSharePreemptionThresholds, queueAcls, - reservationAcls, newPlacementPolicy, configuredQueues, - globalReservationQueueConfig, reservableQueues, nonPreemptableQueues); + AllocationConfiguration info = + new AllocationConfiguration(minQueueResources, minChildQueueResources, + maxQueueResources, maxChildQueueResources, queueMaxApps, userMaxApps, + queueWeights, queueMaxAMShares, userMaxAppsDefault, + queueMaxAppsDefault, queueMaxResourcesDefault, queueMaxAMShareDefault, + queuePolicies, defaultSchedPolicy, minSharePreemptionTimeouts, + fairSharePreemptionTimeouts, fairSharePreemptionThresholds, queueAcls, + reservationAcls, newPlacementPolicy, configuredQueues, + globalReservationQueueConfig, reservableQueues, nonPreemptableQueues); lastSuccessfulReload = clock.getTime(); lastReloadAttemptFailed = false; @@ -433,8 +435,12 @@ public synchronized void reloadAllocations() throws IOException, */ private void loadQueue(String parentName, Element element, Map minQueueResources, - Map maxQueueResources, Map queueMaxApps, - Map userMaxApps, Map queueMaxAMShares, + Map minChildQueueResources, + Map maxQueueResources, + Map maxChildQueueResources, + Map queueMaxApps, + Map userMaxApps, + Map queueMaxAMShares, Map queueWeights, Map queuePolicies, Map minSharePreemptionTimeouts, @@ -463,8 +469,8 @@ private void loadQueue(String parentName, Element element, if (parentName != null) { queueName = parentName + "." + queueName; } - Map acls = - new HashMap(); + + Map acls = new HashMap<>(); Map racls = new HashMap<>(); NodeList fields = element.getChildNodes(); boolean isLeaf = true; @@ -478,10 +484,18 @@ private void loadQueue(String parentName, Element element, String text = ((Text)field.getFirstChild()).getData().trim(); Resource val = FairSchedulerConfiguration.parseResourceConfigValue(text); minQueueResources.put(queueName, val); + } else if ("minChildResources".equals(field.getTagName())) { + String text = ((Text)field.getFirstChild()).getData().trim(); + Resource val = FairSchedulerConfiguration.parseResourceConfigValue(text); + minChildQueueResources.put(queueName, val); } else if ("maxResources".equals(field.getTagName())) { String text = ((Text)field.getFirstChild()).getData().trim(); Resource val = FairSchedulerConfiguration.parseResourceConfigValue(text); maxQueueResources.put(queueName, val); + } else if ("maxChildResources".equals(field.getTagName())) { + String text = ((Text)field.getFirstChild()).getData().trim(); + Resource val = FairSchedulerConfiguration.parseResourceConfigValue(text); + maxChildQueueResources.put(queueName, val); } else if ("maxRunningApps".equals(field.getTagName())) { String text = ((Text)field.getFirstChild()).getData().trim(); int val = Integer.parseInt(text); @@ -542,8 +556,9 @@ private void loadQueue(String parentName, Element element, } } else if ("queue".endsWith(field.getTagName()) || "pool".equals(field.getTagName())) { - loadQueue(queueName, field, minQueueResources, maxQueueResources, - queueMaxApps, userMaxApps, queueMaxAMShares, queueWeights, + loadQueue(queueName, field, minQueueResources, minChildQueueResources, + maxQueueResources, maxChildQueueResources, queueMaxApps, + userMaxApps, queueMaxAMShares, queueWeights, queuePolicies, minSharePreemptionTimeouts, fairSharePreemptionTimeouts, fairSharePreemptionThresholds, queueAcls, resAcls, configuredQueues, reservableQueues, @@ -574,11 +589,20 @@ private void loadQueue(String parentName, Element element, && !Resources.fitsIn(minQueueResources.get(queueName), maxQueueResources.get(queueName))) { LOG.warn( - String.format( - "Queue %s has max resources %s less than min resources %s", - queueName, maxQueueResources.get(queueName), + String.format("Queue %s has max resources %s less than " + + "min resources %s", queueName, maxQueueResources.get(queueName), minQueueResources.get(queueName))); } + + if (maxChildQueueResources.containsKey(queueName) && + minChildQueueResources.containsKey(queueName) && + !Resources.fitsIn(minChildQueueResources.get(queueName), + maxChildQueueResources.get(queueName))) { + LOG.warn(String.format("Queue %s has child max resources %s less than " + + "child min resources %s", queueName, + maxChildQueueResources.get(queueName), + minChildQueueResources.get(queueName))); + } } public interface Listener { 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/fair/QueueManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/QueueManager.java index 8d308dc..a73afeb 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/QueueManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/QueueManager.java @@ -39,6 +39,8 @@ import com.google.common.base.CharMatcher; import com.google.common.annotations.VisibleForTesting; +import java.util.Iterator; +import org.apache.hadoop.yarn.api.records.Resource; /** * Maintains a list of queues as well as scheduling parameters for each queue, * such as guaranteed share allocations, from the fair scheduler config file. @@ -173,15 +175,42 @@ private FSQueue getQueue( } /** - * Creates a leaf or parent queue based on what is specified in 'queueType' - * and places it in the tree. Creates any parents that don't already exist. + * Create a leaf or parent queue based on what is specified in + * {@code queueType} and place it in the tree. Create any parents that don't + * already exist. * - * @return - * the created queue, if successful. null if not allowed (one of the parent - * queues in the queue name is already a leaf queue) + * @return the created queue, if successful or null if not allowed (one of the + * parent queues in the queue name is already a leaf queue) */ - private FSQueue createQueue(String name, FSQueueType queueType) { - List newQueueNames = new ArrayList(); + @VisibleForTesting + FSQueue createQueue(String name, FSQueueType queueType) { + List newQueueNames = new ArrayList<>(); + FSParentQueue parent = buildNewQueueList(name, newQueueNames); + FSQueue queue = null; + + if (parent != null) { + // Now that we know everything worked out, make all the queues + // and add them to the map. + queue = createNewQueues(queueType, parent, newQueueNames); + } + + return queue; + } + + /** + * Compile a list of all parent queues of the given queue name that do not + * already exist. The queue names will be added to the {@code newQueueNames} + * list. The list will be in order of increasing queue depth. The first + * element of the list will be the parent closest to the root. The last + * element added will be the queue to be created. This method returns the + * deepest parent that does exist. + * + * @param name the fully qualified name of the queue to create + * @param newQueueNames the list to which to add non-existent queues + * @return the deepest existing parent queue + */ + private FSParentQueue buildNewQueueList(String name, + List newQueueNames) { newQueueNames.add(name); int sepIndex = name.length(); FSParentQueue parent = null; @@ -195,60 +224,115 @@ private FSQueue createQueue(String name, FSQueueType queueType) { throw new InvalidQueueNameException("Illegal node name at offset " + (sepIndex+1) + " for queue name " + name); } - FSQueue queue; - String curName = null; - curName = name.substring(0, sepIndex); - queue = queues.get(curName); + + String curName = name.substring(0, sepIndex); + FSQueue queue = queues.get(curName); if (queue == null) { - newQueueNames.add(curName); + newQueueNames.add(0, curName); } else { if (queue instanceof FSParentQueue) { parent = (FSParentQueue)queue; - break; - } else { - return null; } + + // If the queue isn't a parent queue, parent will still be null when + // we break + + break; } } - - // At this point, parent refers to the deepest existing parent of the - // queue to create. - // Now that we know everything worked out, make all the queues - // and add them to the map. + + return parent; + } + + /** + * Create all queues in the {@code newQueueNames} list. The list must be in + * order of increasing depth. All but the last element in the list will be + * created as parent queues. The last element will be created as the type + * specified by the {@code queueType} parameter. The first queue will be + * created as a child of the {@code topParent} queue. All subsequent queues + * will be created as a child of the previously created queue. + * + * @param queueType the type of the last queue to create + * @param topParent the parent of the first queue to create + * @param newQueueNames the list of queues to create + * @return the last queue created + */ + private FSQueue createNewQueues(FSQueueType queueType, + FSParentQueue topParent, List newQueueNames) { AllocationConfiguration queueConf = scheduler.getAllocationConfiguration(); - FSLeafQueue leafQueue = null; - for (int i = newQueueNames.size()-1; i >= 0; i--) { - String queueName = newQueueNames.get(i); - if (i == 0 && queueType != FSQueueType.PARENT) { - leafQueue = new FSLeafQueue(name, scheduler, parent); + Iterator i = newQueueNames.iterator(); + FSParentQueue parent = topParent; + FSQueue queue = null; + + while (i.hasNext()) { + String queueName = i.next(); + + // Only create a leaf queue at the very end + if (!i.hasNext() && (queueType != FSQueueType.PARENT)) { + FSLeafQueue leafQueue = new FSLeafQueue(queueName, scheduler, parent); + try { leafQueue.setPolicy(queueConf.getDefaultSchedulingPolicy()); } catch (AllocationConfigurationException ex) { LOG.warn("Failed to set default scheduling policy " - + queueConf.getDefaultSchedulingPolicy() + " on new leaf queue.", ex); + + queueConf.getDefaultSchedulingPolicy() + + " on new leaf queue.", ex); } + parent.addChildQueue(leafQueue); - queues.put(leafQueue.getName(), leafQueue); + setChildResourceLimits(parent, leafQueue, queueConf); leafQueues.add(leafQueue); - leafQueue.updatePreemptionVariables(); - return leafQueue; + queue = leafQueue; } else { - FSParentQueue newParent = new FSParentQueue(queueName, scheduler, parent); + FSParentQueue newParent = + new FSParentQueue(queueName, scheduler, parent); + try { newParent.setPolicy(queueConf.getDefaultSchedulingPolicy()); } catch (AllocationConfigurationException ex) { LOG.warn("Failed to set default scheduling policy " - + queueConf.getDefaultSchedulingPolicy() + " on new parent queue.", ex); + + queueConf.getDefaultSchedulingPolicy() + + " on new parent queue.", ex); } + parent.addChildQueue(newParent); - queues.put(newParent.getName(), newParent); - newParent.updatePreemptionVariables(); parent = newParent; + queue = parent; } + + queues.put(queue.getName(), queue); + queue.updatePreemptionVariables(); } - return parent; + return queue; + } + + /** + * For the given child queue, set the min and max resources based on the + * parent queue's default child resource settings. This method assumes that + * the child queue is ad hoc and hence does not do any safety checks around + * overwriting existing min and max resource settings. + * + * @param parent the parent queue + * @param child the child queue + * @param queueConf the {@link AllocationConfiguration} + */ + private void setChildResourceLimits(FSParentQueue parent, FSLeafQueue child, + AllocationConfiguration queueConf) { + // For ad hoc queues, set their min and max reource allocations based on + // their parents' default child settings. + Resource minChild = queueConf.getMinChildResources(parent.getName()); + + if (minChild != null) { + queueConf.addMinResources(child.getName(), minChild); + } + + Resource maxChild = queueConf.getMaxChildResources(parent.getName()); + + if (maxChild != null) { + queueConf.addMaxResources(child.getName(), maxChild); + } } /** 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/fair/TestAllocationFileLoaderService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestAllocationFileLoaderService.java index 11d4981..4f98e27 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestAllocationFileLoaderService.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestAllocationFileLoaderService.java @@ -178,13 +178,19 @@ public void testAllocationFileParsing() throws Exception { // Give queue E a preemption timeout of one minute out.println(""); out.println("60"); + out.println("8192mb,200vcores"); out.println(""); - //Make queue F a parent queue without configured leaf queues using the 'type' attribute + // Make queue F a parent queue without configured leaf queues using the + // 'type' attribute out.println(""); + out.println("1024mb,16vcores"); + out.println("2048mb,64vcores"); out.println(""); // Create hierarchical queues G,H, with different min/fair share preemption - // timeouts and preemption thresholds + // timeouts and preemption thresholds. Also add a child default to make sure + // it doesn't impact queue H. out.println(""); + out.println("2048mb,64vcores"); out.println("120"); out.println("50"); out.println("0.6"); @@ -240,6 +246,12 @@ public void testAllocationFileParsing() throws Exception { queueConf.getMaxResources("root.queueD")); assertEquals(Resources.createResource(4096, 100), queueConf.getMaxResources("root.queueE")); + assertEquals(Resources.createResource(4096, 100), + queueConf.getMaxResources("root.queueF")); + assertEquals(Resources.createResource(4096, 100), + queueConf.getMaxResources("root.queueG")); + assertEquals(Resources.createResource(4096, 100), + queueConf.getMaxResources("root.queueG.queueH")); assertEquals(Resources.createResource(1024, 0), queueConf.getMinResources("root.queueA")); @@ -251,6 +263,46 @@ public void testAllocationFileParsing() throws Exception { queueConf.getMinResources("root.queueD")); assertEquals(Resources.createResource(0), queueConf.getMinResources("root.queueE")); + assertEquals(Resources.createResource(0), + queueConf.getMinResources("root.queueF")); + assertEquals(Resources.createResource(0), + queueConf.getMinResources("root.queueG")); + assertEquals(Resources.createResource(0), + queueConf.getMinResources("root.queueG.queueH")); + + assertEquals(Resources.createResource(4096, 100), + queueConf.getMaxChildResources("root.queueA")); + assertEquals(Resources.createResource(4096, 100), + queueConf.getMaxChildResources("root.queueB")); + assertEquals(Resources.createResource(4096, 100), + queueConf.getMaxChildResources("root.queueC")); + assertEquals(Resources.createResource(4096, 100), + queueConf.getMaxChildResources("root.queueD")); + assertEquals(Resources.createResource(8192, 200), + queueConf.getMaxChildResources("root.queueE")); + assertEquals(Resources.createResource(2048, 64), + queueConf.getMaxChildResources("root.queueF")); + assertEquals(Resources.createResource(2048, 64), + queueConf.getMaxChildResources("root.queueG")); + assertEquals(Resources.createResource(4096, 100), + queueConf.getMaxChildResources("root.queueG.queueH")); + + assertEquals(Resources.createResource(0), + queueConf.getMinChildResources("root.queueA")); + assertEquals(Resources.createResource(0), + queueConf.getMinChildResources("root.queueB")); + assertEquals(Resources.createResource(0), + queueConf.getMinChildResources("root.queueC")); + assertEquals(Resources.createResource(0), + queueConf.getMinChildResources("root.queueD")); + assertEquals(Resources.createResource(8192, 200), + queueConf.getMinChildResources("root.queueE")); + assertEquals(Resources.createResource(1024, 16), + queueConf.getMinChildResources("root.queueF")); + assertEquals(Resources.createResource(0), + queueConf.getMinChildResources("root.queueG")); + assertEquals(Resources.createResource(0), + queueConf.getMinChildResources("root.queueG.queueH")); assertEquals(15, queueConf.getQueueMaxApps("root." + YarnConfiguration.DEFAULT_QUEUE_NAME)); assertEquals(15, queueConf.getQueueMaxApps("root.queueA")); 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/fair/TestQueueManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestQueueManager.java index 33d4419..495194d 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestQueueManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestQueueManager.java @@ -24,6 +24,7 @@ import java.util.Set; import org.apache.hadoop.yarn.util.SystemClock; +import org.apache.hadoop.yarn.util.resource.Resources; import org.junit.Before; import org.junit.Test; @@ -33,11 +34,12 @@ private FairSchedulerConfiguration conf; private QueueManager queueManager; private Set notEmptyQueues; + private FairScheduler scheduler; @Before public void setUp() throws Exception { conf = new FairSchedulerConfiguration(); - FairScheduler scheduler = mock(FairScheduler.class); + scheduler = mock(FairScheduler.class); AllocationConfiguration allocConf = new AllocationConfiguration(conf); when(scheduler.getAllocationConfiguration()).thenReturn(allocConf); when(scheduler.getConf()).thenReturn(conf); @@ -53,7 +55,7 @@ public boolean isEmpty(FSQueue queue) { FSQueueMetrics.forQueue("root", null, true, conf); queueManager.initialize(conf); } - + @Test public void testReloadTurnsLeafQueueIntoParent() throws Exception { updateConfiguredLeafQueues(queueManager, "queue1"); @@ -143,4 +145,141 @@ private void updateConfiguredLeafQueues(QueueManager queueMgr, String... confLea allocConf.configuredQueues.get(FSQueueType.LEAF).addAll(Sets.newHashSet(confLeafQueues)); queueMgr.updateAllocationConfiguration(allocConf); } + + /** + * Test simple leaf queue creation. + */ + @Test + public void testCreateLeafQueue() { + AllocationConfiguration allocConf = scheduler.getAllocationConfiguration(); + + queueManager.updateAllocationConfiguration(allocConf); + + FSQueue q1 = queueManager.createQueue("root.queue1", FSQueueType.LEAF); + + assertNotNull("Leaf queue root.queue1 was not created", + queueManager.getLeafQueue("root.queue1", false)); + assertEquals("createQueue() returned wrong queue", + "root.queue1", q1.getName()); + } + + /** + * Test creation of a leaf queue and its parent. + */ + @Test + public void testCreateLeafQueueAndParent() { + AllocationConfiguration allocConf = scheduler.getAllocationConfiguration(); + + queueManager.updateAllocationConfiguration(allocConf); + + FSQueue q2 = queueManager.createQueue("root.queue1.queue2", + FSQueueType.LEAF); + + assertNotNull("Parent queue root.queue1 was not created", + queueManager.getParentQueue("root.queue1", false)); + assertNotNull("Leaf queue root.queue1.queue2 was not created", + queueManager.getLeafQueue("root.queue1.queue2", false)); + assertEquals("createQueue() returned wrong queue", + "root.queue1.queue2", q2.getName()); + } + + /** + * Test creation on leaf and parent child queues when the parent queue has + * child defaults set. + */ + @Test + public void testCreateQueueWithChildDefaults() { + AllocationConfiguration allocConf = scheduler.getAllocationConfiguration(); + + allocConf.addMinChildResources("root", Resources.createResource(2048, 16)); + allocConf.addMaxChildResources("root", Resources.createResource(8192, 64)); + queueManager.updateAllocationConfiguration(allocConf); + + FSQueue q1 = queueManager.createQueue("root.queue1", FSQueueType.LEAF); + + assertNotNull("Leaf queue root.queue1 was not created", + queueManager.getLeafQueue("root.queue1", false)); + assertEquals("createQueue() returned wrong queue", + "root.queue1", q1.getName()); + assertEquals("Min resources for root.queue1 were not inherited from " + + "parent's min child resources", Resources.createResource(2048, 16), + allocConf.getMinResources("root.queue1")); + assertEquals("Max resources for root.queue1 were not inherited from " + + "parent's max child resources", Resources.createResource(8192, 64), + allocConf.getMaxResources("root.queue1")); + + FSQueue q2 = queueManager.createQueue("root.queue2", FSQueueType.PARENT); + + assertNotNull("Leaf queue root.queue1 was not created", + queueManager.getLeafQueue("root.queue1", false)); + assertEquals("createQueue() returned wrong queue", + "root.queue2", q2.getName()); + assertEquals("Min resources for root.queue2 were not inherited from " + + "parent's min child resources", Resources.createResource(2048, 16), + allocConf.getMinResources("root.queue1")); + assertEquals("Max resources for root.queue2 were not inherited from " + + "parent's max child resources", Resources.createResource(8192, 64), + allocConf.getMaxResources("root.queue1")); + } + + /** + * Test creation of a leaf queue with no resource limits. + */ + @Test + public void testCreateLeafQueueWithDefaults() { + AllocationConfiguration allocConf = scheduler.getAllocationConfiguration(); + FSQueue q1 = queueManager.createQueue("root.queue1", FSQueueType.LEAF); + + assertNotNull("Leaf queue root.queue1 was not created", + queueManager.getLeafQueue("root.queue1", false)); + assertEquals("createQueue() returned wrong queue", + "root.queue1", q1.getName()); + + // Min default is 0,0 + assertEquals("Min resources were not inherited from parent's min child " + + "resources", Resources.createResource(0, 0), + allocConf.getMinResources("root.queue1")); + + // Max default is unbounded + assertEquals("Max resources were not inherited from parent's max child " + + "resources", Resources.unbounded(), + allocConf.getMaxResources("root.queue1")); + } + + /** + * Test creation of a simple parent queue. + */ + @Test + public void testCreateParentQueue() { + AllocationConfiguration allocConf = scheduler.getAllocationConfiguration(); + + queueManager.updateAllocationConfiguration(allocConf); + + FSQueue q1 = queueManager.createQueue("root.queue1", FSQueueType.PARENT); + + assertNotNull("Parent queue root.queue1 was not created", + queueManager.getParentQueue("root.queue1", false)); + assertEquals("createQueue() returned wrong queue", + "root.queue1", q1.getName()); + } + + /** + * Test creation of a parent queue and its parent. + */ + @Test + public void testCreateParentQueueAndParent() { + AllocationConfiguration allocConf = scheduler.getAllocationConfiguration(); + + queueManager.updateAllocationConfiguration(allocConf); + + FSQueue q2 = queueManager.createQueue("root.queue1.queue2", + FSQueueType.PARENT); + + assertNotNull("Parent queue root.queue1 was not created", + queueManager.getParentQueue("root.queue1", false)); + assertNotNull("Leaf queue root.queue1.queue2 was not created", + queueManager.getParentQueue("root.queue1.queue2", false)); + assertEquals("createQueue() returned wrong queue", + "root.queue1.queue2", q2.getName()); + } }