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/AbstractCSQueue.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/AbstractCSQueue.java index 12ce05f2791..b0912215a29 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/AbstractCSQueue.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/AbstractCSQueue.java @@ -1614,6 +1614,12 @@ void updateEffectiveResources(Resource clusterResource) { } } + public CapacitySchedulerConfiguration getTemplateConfiguration() { + return isDynamicQueue() ? new AutoCreatedQueueTemplateConfig( + csContext.getConfiguration(), getQueuePath()) : + csContext.getConfiguration(); + } + public boolean isDynamicQueue() { readLock.lock(); 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/AutoCreatedQueueTemplateConfig.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/AutoCreatedQueueTemplateConfig.java new file mode 100644 index 00000000000..ef88b9c8027 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/AutoCreatedQueueTemplateConfig.java @@ -0,0 +1,114 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *
+ * http://www.apache.org/licenses/LICENSE-2.0 + *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.thirdparty.com.google.common.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Represents a configuration that handles template entries based on
+ * template settings.
+ */
+public class AutoCreatedQueueTemplateConfig
+ extends CapacitySchedulerConfiguration {
+ public static final String AUTO_QUEUE_TEMPLATE_PREFIX =
+ AUTO_QUEUE_CREATION_V2_PREFIX + "template.";
+ private static final String WILDCARD_QUEUE = "*";
+ private static final int MAX_WILDCARD_LEVEL = 1;
+
+ private final String queuePath;
+
+ public AutoCreatedQueueTemplateConfig(Configuration configuration,
+ String queuePath) {
+ super(configuration);
+ this.queuePath = queuePath;
+ setTemplateConfigEntries();
+ }
+
+ /**
+ * Set the template configuration entries. Explicit templates always take
+ * precedence over wildcard values. An example template precedence
+ * hierarchy for root.a.b LeafQueue from highest to lowest:
+ * yarn.scheduler.capacity.root.a.auto-queue-creation-v2.template.capacity
+ * yarn.scheduler.capacity.root.*.auto-queue-creation-v2.template.capacity
+ */
+ private void setTemplateConfigEntries() {
+ HashMap
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Map;
+
+public class TestAutoCreatedQueueTemplateConfig {
+ private static final String TEST_QUEUE_ABC = "root.a.b.c";
+ private static final String TEST_QUEUE_AB = "root.a.b";
+ private static final String TEST_QUEUE_A = "root.a";
+ private static final String ROOT = "root";
+ private CapacitySchedulerConfiguration conf;
+
+ @Before
+ public void setUp() throws Exception {
+ conf = new CapacitySchedulerConfiguration();
+ conf.setQueues("root", new String[]{"a"});
+ conf.setQueues("a", new String[]{"b"});
+ conf.setQueues("b", new String[]{"c"});
+ }
+
+ @Test
+ public void testNonWildCardTemplate() {
+ conf.set(getTemplateKey(TEST_QUEUE_AB, "capacity"), "6w");
+ AutoCreatedQueueTemplateConfig templateConfig =
+ new AutoCreatedQueueTemplateConfig(conf, TEST_QUEUE_ABC);
+
+ Assert.assertEquals("weight is not set", 6f,
+ templateConfig.getNonLabeledQueueWeight(TEST_QUEUE_ABC), 10e-6);
+
+ }
+
+ @Test
+ public void testOneLevelWildcardTemplate() {
+ conf.set(getTemplateKey("root.a.*", "capacity"), "6w");
+ AutoCreatedQueueTemplateConfig templateConfig =
+ new AutoCreatedQueueTemplateConfig(conf, TEST_QUEUE_ABC);
+
+ Assert.assertEquals("weight is not set", 6f,
+ templateConfig.getNonLabeledQueueWeight(TEST_QUEUE_ABC), 10e-6);
+
+ }
+
+ @Test
+ public void testIgnoredWhenRootWildcarded() {
+ conf.set(getTemplateKey("*", "capacity"), "6w");
+ AutoCreatedQueueTemplateConfig templateConfig =
+ new AutoCreatedQueueTemplateConfig(conf, TEST_QUEUE_A);
+
+ Assert.assertEquals("weight is set", -1f,
+ templateConfig.getNonLabeledQueueWeight(TEST_QUEUE_A), 10e-6);
+ }
+
+ @Test
+ public void testIgnoredWhenNoParent() {
+ conf.set(getTemplateKey("root", "capacity"), "6w");
+ AutoCreatedQueueTemplateConfig templateConfig =
+ new AutoCreatedQueueTemplateConfig(conf, ROOT);
+
+ Assert.assertEquals("weight is set", -1f,
+ templateConfig.getNonLabeledQueueWeight(ROOT), 10e-6);
+ }
+
+ @Test
+ public void testTemplatePrecedence() {
+ conf.set(getTemplateKey("root.a.b", "capacity"), "6w");
+ conf.set(getTemplateKey("root.a.*", "capacity"), "4w");
+ conf.set(getTemplateKey("root.*.*", "capacity"), "2w");
+
+ AutoCreatedQueueTemplateConfig templateConfig =
+ new AutoCreatedQueueTemplateConfig(conf, TEST_QUEUE_ABC);
+
+ Assert.assertEquals(
+ "explicit template does not have the highest precedence", 6f,
+ templateConfig.getNonLabeledQueueWeight(TEST_QUEUE_ABC), 10e-6);
+
+ CapacitySchedulerConfiguration newConf =
+ new CapacitySchedulerConfiguration();
+ newConf.set(getTemplateKey("root.a.*", "capacity"), "4w");
+
+ AutoCreatedQueueTemplateConfig newTemplateConfig =
+ new AutoCreatedQueueTemplateConfig(newConf, TEST_QUEUE_ABC);
+
+ Assert.assertEquals("precedence is invalid", 4f,
+ newTemplateConfig.getNonLabeledQueueWeight(TEST_QUEUE_ABC), 10e-6);
+ }
+
+ private String getTemplateKey(String queuePath, String entryKey) {
+ return CapacitySchedulerConfiguration.getQueuePrefix(queuePath)
+ + AutoCreatedQueueTemplateConfig.AUTO_QUEUE_TEMPLATE_PREFIX + entryKey;
+ }
+}
\ No newline at end of file
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/TestCapacitySchedulerNewQueueAutoCreation.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/TestCapacitySchedulerNewQueueAutoCreation.java
index 4facf943b6e..0d9f18902d7 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/TestCapacitySchedulerNewQueueAutoCreation.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/TestCapacitySchedulerNewQueueAutoCreation.java
@@ -18,6 +18,7 @@
package org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity;
+import org.apache.hadoop.yarn.api.records.QueueState;
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
@@ -565,6 +566,85 @@ public void testAutoCreateQueueMaxQueuesLimit() throws Exception {
}
}
+ @Test
+ public void testAutoCreatedQueueTemplateConfig() throws Exception {
+ startScheduler();
+ csConf.set(AutoCreatedQueueTemplateConfig.getAutoQueueTemplatePrefix(
+ "root.a.*") + "capacity", "6w");
+ cs.reinitialize(csConf, mockRM.getRMContext());
+
+ LeafQueue a2 = createQueue("root.a.a-auto.a2");
+ Assert.assertEquals("weight is not set by template", 6f,
+ a2.getQueueCapacities().getWeight(), 1e-6);
+
+ cs.reinitialize(csConf, mockRM.getRMContext());
+ a2 = (LeafQueue) cs.getQueue("root.a.a-auto.a2");
+ Assert.assertEquals("weight is overridden", 6f,
+ a2.getQueueCapacities().getWeight(), 1e-6);
+
+ csConf.setNonLabeledQueueWeight("root.a.a-auto.a2", 4f);
+ cs.reinitialize(csConf, mockRM.getRMContext());
+ Assert.assertEquals("weight is not explicitly set", 4f,
+ a2.getQueueCapacities().getWeight(), 1e-6);
+ }
+
+ @Test
+ public void testAutoCreatedQueueConfigChange() throws Exception {
+ startScheduler();
+ LeafQueue a2 = createQueue("root.a.a-auto.a2");
+ csConf.setNonLabeledQueueWeight("root.a.a-auto.a2", 4f);
+ cs.reinitialize(csConf, mockRM.getRMContext());
+
+ Assert.assertEquals("weight is not explicitly set", 4f,
+ a2.getQueueCapacities().getWeight(), 1e-6);
+
+ a2 = (LeafQueue) cs.getQueue("root.a.a-auto.a2");
+ csConf.setState("root.a.a-auto.a2", QueueState.STOPPED);
+ cs.reinitialize(csConf, mockRM.getRMContext());
+ Assert.assertEquals("root.a.a-auto.a2 has not been stopped",
+ QueueState.STOPPED, a2.getState());
+
+ csConf.setState("root.a.a-auto.a2", QueueState.RUNNING);
+ cs.reinitialize(csConf, mockRM.getRMContext());
+ Assert.assertEquals("root.a.a-auto.a2 is not running",
+ QueueState.RUNNING, a2.getState());
+ }
+
+ @Test
+ public void testAutoCreateQueueState() throws Exception {
+ startScheduler();
+
+ createQueue("root.e.e1");
+ csConf.setState("root.e", QueueState.STOPPED);
+ csConf.setState("root.e.e1", QueueState.STOPPED);
+ csConf.setState("root.a", QueueState.STOPPED);
+ cs.reinitialize(csConf, mockRM.getRMContext());
+
+ // Make sure the static queue is stopped
+ Assert.assertEquals(cs.getQueue("root.a").getState(),
+ QueueState.STOPPED);
+ // If not set, default is the queue state of parent
+ Assert.assertEquals(cs.getQueue("root.a.a1").getState(),
+ QueueState.STOPPED);
+
+ Assert.assertEquals(cs.getQueue("root.e").getState(),
+ QueueState.STOPPED);
+ Assert.assertEquals(cs.getQueue("root.e.e1").getState(),
+ QueueState.STOPPED);
+
+ // Make root.e state to RUNNING
+ csConf.setState("root.e", QueueState.RUNNING);
+ cs.reinitialize(csConf, mockRM.getRMContext());
+ Assert.assertEquals(cs.getQueue("root.e.e1").getState(),
+ QueueState.STOPPED);
+
+ // Make root.e.e1 state to RUNNING
+ csConf.setState("root.e.e1", QueueState.RUNNING);
+ cs.reinitialize(csConf, mockRM.getRMContext());
+ Assert.assertEquals(cs.getQueue("root.e.e1").getState(),
+ QueueState.RUNNING);
+ }
+
private LeafQueue createQueue(String queuePath) throws YarnException {
return autoQueueHandler.autoCreateQueue(
CSQueueUtils.extractQueuePath(queuePath));