YARN-11641. Fix getCapacityConfigurationTypeForQueues for absolute mode with zero resource. (#6435)

This commit is contained in:
Tamas Domok 2024-01-25 13:58:00 +01:00 committed by GitHub
parent 38f10c657e
commit 7272a3d960
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 8397 additions and 13 deletions

View File

@ -229,8 +229,7 @@ public QueueCapacityType getCapacityConfigurationTypeForQueues(
"{Queue=" + queue.getQueuePath() + ", label=" + nodeLabel "{Queue=" + queue.getQueuePath() + ", label=" + nodeLabel
+ " uses weight mode}. "); + " uses weight mode}. ");
} }
if (!queue.getQueueResourceQuotas().getConfiguredMinResource(nodeLabel) if (checkConfigTypeIsAbsoluteResource(queue.getQueuePath(), nodeLabel)) {
.equals(Resources.none())) {
absoluteMinResSet = true; absoluteMinResSet = true;
// There's a special handling: when absolute resource is configured, // There's a special handling: when absolute resource is configured,
// capacity will be calculated (and set) for UI/metrics purposes, so // capacity will be calculated (and set) for UI/metrics purposes, so

View File

@ -95,7 +95,7 @@ public void testPercentageMode() throws Exception {
conf.put("yarn.scheduler.capacity.root.test1.test1_1.capacity", "12.5"); conf.put("yarn.scheduler.capacity.root.test1.test1_1.capacity", "12.5");
conf.put("yarn.scheduler.capacity.root.test1.test1_2.capacity", "12.5"); conf.put("yarn.scheduler.capacity.root.test1.test1_2.capacity", "12.5");
conf.put("yarn.scheduler.capacity.root.test1.test1_3.capacity", "75"); conf.put("yarn.scheduler.capacity.root.test1.test1_3.capacity", "75");
try (MockRM rm = createMutableRM(createConfiguration(conf))) { try (MockRM rm = createMutableRM(createConfiguration(conf), false)) {
runTest(EXPECTED_FILE_TMPL, "testPercentageMode", rm, resource()); runTest(EXPECTED_FILE_TMPL, "testPercentageMode", rm, resource());
} }
} }
@ -111,7 +111,7 @@ public void testAbsoluteMode() throws Exception {
conf.put("yarn.scheduler.capacity.root.test1.test1_1.capacity", "[memory=2048,vcores=2]"); conf.put("yarn.scheduler.capacity.root.test1.test1_1.capacity", "[memory=2048,vcores=2]");
conf.put("yarn.scheduler.capacity.root.test1.test1_2.capacity", "[memory=2048,vcores=2]"); conf.put("yarn.scheduler.capacity.root.test1.test1_2.capacity", "[memory=2048,vcores=2]");
conf.put("yarn.scheduler.capacity.root.test1.test1_3.capacity", "[memory=12288,vcores=12]"); conf.put("yarn.scheduler.capacity.root.test1.test1_3.capacity", "[memory=12288,vcores=12]");
try (MockRM rm = createMutableRM(createConfiguration(conf))) { try (MockRM rm = createMutableRM(createConfiguration(conf), false)) {
runTest(EXPECTED_FILE_TMPL, "testAbsoluteMode", rm, resource()); runTest(EXPECTED_FILE_TMPL, "testAbsoluteMode", rm, resource());
} }
} }
@ -128,7 +128,7 @@ public void testWeightMode() throws Exception {
conf.put("yarn.scheduler.capacity.root.test1.test1_1.capacity", "2w"); conf.put("yarn.scheduler.capacity.root.test1.test1_1.capacity", "2w");
conf.put("yarn.scheduler.capacity.root.test1.test1_2.capacity", "2w"); conf.put("yarn.scheduler.capacity.root.test1.test1_2.capacity", "2w");
conf.put("yarn.scheduler.capacity.root.test1.test1_3.capacity", "12w"); conf.put("yarn.scheduler.capacity.root.test1.test1_3.capacity", "12w");
try (MockRM rm = createMutableRM(createConfiguration(conf))) { try (MockRM rm = createMutableRM(createConfiguration(conf), false)) {
// capacity and normalizedWeight are set differently between legacy/non-legacy queue mode // capacity and normalizedWeight are set differently between legacy/non-legacy queue mode
runTest(EXPECTED_FILE_TMPL, "testWeightMode", rm, resource()); runTest(EXPECTED_FILE_TMPL, "testWeightMode", rm, resource());
} }
@ -149,7 +149,7 @@ public void testWeightModeFlexibleAQC() throws Exception {
Configuration config = createConfiguration(conf); Configuration config = createConfiguration(conf);
setupAQC(config, "yarn.scheduler.capacity.root.test2."); setupAQC(config, "yarn.scheduler.capacity.root.test2.");
try (MockRM rm = createMutableRM(config)) { try (MockRM rm = createMutableRM(config, false)) {
// capacity and normalizedWeight are set differently between legacy/non-legacy queue mode // capacity and normalizedWeight are set differently between legacy/non-legacy queue mode
rm.registerNode("h1:1234", 32 * GB, 32); rm.registerNode("h1:1234", 32 * GB, 32);
assertJsonResponse(sendRequest(resource()), assertJsonResponse(sendRequest(resource()),

View File

@ -77,7 +77,7 @@ public void testSchedulerResponsePercentageModeLegacyAutoCreation()
conf.put("yarn.scheduler.capacity.root.managed.capacity", "75"); conf.put("yarn.scheduler.capacity.root.managed.capacity", "75");
conf.put("yarn.scheduler.capacity.root.managed." + conf.put("yarn.scheduler.capacity.root.managed." +
"auto-create-child-queue.enabled", "true"); "auto-create-child-queue.enabled", "true");
try (MockRM rm = createMutableRM(createConfiguration(conf))) { try (MockRM rm = createMutableRM(createConfiguration(conf), false)) {
rm.registerNode("h1:1234", 32 * GB, 32); rm.registerNode("h1:1234", 32 * GB, 32);
assertJsonResponse(sendRequest(), assertJsonResponse(sendRequest(),
"webapp/scheduler-response-PercentageModeLegacyAutoCreation.json"); "webapp/scheduler-response-PercentageModeLegacyAutoCreation.json");
@ -100,7 +100,7 @@ public void testSchedulerResponseAbsoluteModeLegacyAutoCreation()
"user"); "user");
conf.put("yarn.scheduler.capacity.root.managed.leaf-queue-template.acl_administer_queue", conf.put("yarn.scheduler.capacity.root.managed.leaf-queue-template.acl_administer_queue",
"admin"); "admin");
try (MockRM rm = createMutableRM(createConfiguration(conf))) { try (MockRM rm = createMutableRM(createConfiguration(conf), false)) {
rm.registerNode("h1:1234", 32 * GB, 32); rm.registerNode("h1:1234", 32 * GB, 32);
CapacityScheduler cs = (CapacityScheduler) rm.getResourceScheduler(); CapacityScheduler cs = (CapacityScheduler) rm.getResourceScheduler();
CapacitySchedulerQueueManager autoQueueHandler = cs.getCapacitySchedulerQueueManager(); CapacitySchedulerQueueManager autoQueueHandler = cs.getCapacitySchedulerQueueManager();

View File

@ -0,0 +1,145 @@
/**
* 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.webapp;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.sun.jersey.api.client.ClientResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerConfiguration;
import org.apache.hadoop.yarn.webapp.dao.QueueConfigInfo;
import org.apache.hadoop.yarn.webapp.dao.SchedConfUpdateInfo;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.yarn.server.resourcemanager.MockRM;
import org.apache.hadoop.yarn.webapp.JerseyTestBase;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import static org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerTestUtilities.GB;
import static org.apache.hadoop.yarn.server.resourcemanager.webapp.TestWebServiceUtil.assertJsonResponse;
import static org.apache.hadoop.yarn.server.resourcemanager.webapp.TestWebServiceUtil.createMutableRM;
import static org.apache.hadoop.yarn.server.resourcemanager.webapp.TestWebServiceUtil.createWebAppDescriptor;
import static org.apache.hadoop.yarn.server.resourcemanager.webapp.TestWebServiceUtil.backupSchedulerConfigFileInTarget;
import static org.apache.hadoop.yarn.server.resourcemanager.webapp.TestWebServiceUtil.getCapacitySchedulerConfigFileInTarget;
import static org.apache.hadoop.yarn.server.resourcemanager.webapp.TestWebServiceUtil.getExpectedResourceFile;
import static org.apache.hadoop.yarn.server.resourcemanager.webapp.TestWebServiceUtil.restoreSchedulerConfigFileInTarget;
import static org.apache.hadoop.yarn.webapp.util.YarnWebServiceUtils.toJson;
import static org.junit.Assert.assertEquals;
@RunWith(Parameterized.class)
public class TestRMWebServicesCapacitySchedulerConfigMutation extends JerseyTestBase {
private static final String EXPECTED_FILE_TMPL = "webapp/configmutation-%s-%s.json";
private final boolean legacyQueueMode;
private final String userName;
@Parameterized.Parameters(name = "{index}: legacy-queue-mode={0}")
public static Collection<Boolean> getParameters() {
return Arrays.asList(true, false);
}
@BeforeClass
public static void beforeClass() {
backupSchedulerConfigFileInTarget();
}
@AfterClass
public static void afterClass() {
restoreSchedulerConfigFileInTarget();
}
public TestRMWebServicesCapacitySchedulerConfigMutation(boolean legacyQueueMode)
throws IOException {
super(createWebAppDescriptor());
this.legacyQueueMode = legacyQueueMode;
userName = UserGroupInformation.getCurrentUser().getShortUserName();
}
@Test
public void testUpdateAbsoluteHierarchyWithZeroCapacities() throws Exception {
Configuration absoluteConfig = createAbsoluteConfig();
FileOutputStream out = new FileOutputStream(getCapacitySchedulerConfigFileInTarget());
absoluteConfig.writeXml(out);
out.close();
try (MockRM rm = createMutableRM(absoluteConfig, true)){
rm.registerNode("h1:1234", 32 * GB, 32);
assertJsonResponse(resource().path("ws/v1/cluster/scheduler")
.queryParam("user.name", userName)
.accept(MediaType.APPLICATION_JSON).get(ClientResponse.class),
getExpectedResourceFile(EXPECTED_FILE_TMPL, "absolute-hierarchy", "before-update",
legacyQueueMode));
SchedConfUpdateInfo updateInfo = new SchedConfUpdateInfo();
Map<String, String> capacityChange = new HashMap<>();
capacityChange.put(CapacitySchedulerConfiguration.CAPACITY,
"[memory=4096, vcores=4]");
capacityChange.put(CapacitySchedulerConfiguration.MAXIMUM_CAPACITY,
"[memory=32768, vcores=32]");
QueueConfigInfo b = new QueueConfigInfo("root.a", capacityChange);
updateInfo.getUpdateQueueInfo().add(b);
ClientResponse response = resource().path("ws/v1/cluster/scheduler-conf")
.queryParam("user.name", userName)
.accept(MediaType.APPLICATION_JSON)
.entity(toJson(updateInfo, SchedConfUpdateInfo.class), MediaType.APPLICATION_JSON)
.put(ClientResponse.class);
// HTTP 400 - Bad Request is encountered, check the logs for the failure
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
assertJsonResponse(resource().path("ws/v1/cluster/scheduler")
.queryParam("user.name", userName)
.accept(MediaType.APPLICATION_JSON).get(ClientResponse.class),
getExpectedResourceFile(EXPECTED_FILE_TMPL, "absolute-hierarchy", "after-update",
legacyQueueMode));
}
}
private Configuration createAbsoluteConfig() {
Configuration conf = new Configuration(false);
conf.set(YarnConfiguration.YARN_ADMIN_ACL, userName);
conf.set("yarn.scheduler.capacity.legacy-queue-mode.enabled", String.valueOf(legacyQueueMode));
conf.set("yarn.scheduler.capacity.root.capacity", "[memory=32768, vcores=32]");
conf.set("yarn.scheduler.capacity.root.queues", "default, a");
conf.set("yarn.scheduler.capacity.root.default.capacity", "[memory=1024, vcores=1]");
conf.set("yarn.scheduler.capacity.root.a.capacity", "[memory=0, vcores=0]");
conf.set("yarn.scheduler.capacity.root.a.max-capacity", "[memory=32768, vcores=32]");
conf.set("yarn.scheduler.capacity.root.a.queues", "b, c");
conf.set("yarn.scheduler.capacity.root.a.b.capacity", "[memory=0, vcores=0]");
conf.set("yarn.scheduler.capacity.root.a.b.max-capacity", "[memory=32768, vcores=32]");
conf.set("yarn.scheduler.capacity.root.a.c.capacity", "[memory=0, vcores=0]");
conf.set("yarn.scheduler.capacity.root.a.c.max-capacity", "[memory=32768, vcores=32]");
return conf;
}
}

View File

@ -115,7 +115,7 @@ public void setUp() throws Exception {
createConfig(new CapacitySchedulerConfiguration(new Configuration(false))); createConfig(new CapacitySchedulerConfiguration(new Configuration(false)));
rm = createMockRM(config); rm = createMockRM(config);
GuiceServletConfig.setInjector( GuiceServletConfig.setInjector(
Guice.createInjector(new TestWebServiceUtil.WebServletModule(rm))); Guice.createInjector(new TestWebServiceUtil.WebServletModule(rm, false)));
} }
public static MockRM createMockRM(CapacitySchedulerConfiguration csConf) { public static MockRM createMockRM(CapacitySchedulerConfiguration csConf) {

View File

@ -87,9 +87,11 @@ private TestWebServiceUtil(){
public static class WebServletModule extends ServletModule { public static class WebServletModule extends ServletModule {
private final MockRM rm; private final MockRM rm;
private final boolean setCustomAuthFilter;
WebServletModule(MockRM rm) { WebServletModule(MockRM rm, boolean setCustomAuthFilter) {
this.rm = rm; this.rm = rm;
this.setCustomAuthFilter = setCustomAuthFilter;
} }
@Override @Override
@ -99,6 +101,11 @@ protected void configureServlets() {
bind(GenericExceptionHandler.class); bind(GenericExceptionHandler.class);
bind(ResourceManager.class).toInstance(rm); bind(ResourceManager.class).toInstance(rm);
serve("/*").with(GuiceContainer.class); serve("/*").with(GuiceContainer.class);
if (setCustomAuthFilter) {
filter("/*").through(TestRMWebServicesAppsModification
.TestRMCustomAuthFilter.class);
}
} }
} }
@ -321,20 +328,25 @@ public static WebAppDescriptor createWebAppDescriptor() {
} }
public static MockRM createRM(Configuration config) { public static MockRM createRM(Configuration config) {
return createRM(config, false);
}
public static MockRM createRM(Configuration config, boolean setCustomAuthFilter) {
config.setClass(YarnConfiguration.RM_SCHEDULER, config.setClass(YarnConfiguration.RM_SCHEDULER,
CapacityScheduler.class, ResourceScheduler.class); CapacityScheduler.class, ResourceScheduler.class);
config.set(YarnConfiguration.RM_PLACEMENT_CONSTRAINTS_HANDLER, config.set(YarnConfiguration.RM_PLACEMENT_CONSTRAINTS_HANDLER,
YarnConfiguration.SCHEDULER_RM_PLACEMENT_CONSTRAINTS_HANDLER); YarnConfiguration.SCHEDULER_RM_PLACEMENT_CONSTRAINTS_HANDLER);
MockRM rm = new MockRM(config); MockRM rm = new MockRM(config);
GuiceServletConfig.setInjector(Guice.createInjector(new WebServletModule(rm))); GuiceServletConfig.setInjector(Guice.createInjector(
new WebServletModule(rm, setCustomAuthFilter)));
rm.start(); rm.start();
return rm; return rm;
} }
public static MockRM createMutableRM(Configuration conf) { public static MockRM createMutableRM(Configuration conf, boolean setCustomAuthFilter) {
conf.set(YarnConfiguration.SCHEDULER_CONFIGURATION_STORE_CLASS, conf.set(YarnConfiguration.SCHEDULER_CONFIGURATION_STORE_CLASS,
YarnConfiguration.MEMORY_CONFIGURATION_STORE); YarnConfiguration.MEMORY_CONFIGURATION_STORE);
return createRM(new CapacitySchedulerConfiguration(conf)); return createRM(new CapacitySchedulerConfiguration(conf), setCustomAuthFilter);
} }
public static void reinitialize(MockRM rm, Configuration conf) throws IOException { public static void reinitialize(MockRM rm, Configuration conf) throws IOException {