blob: 0440db321b1b684e7f3269542d065a0bb204d57e [file] [log] [blame]
/**
* 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.monitor.capacity;
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerConfiguration;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
/**
* Test class for IntraQueuePreemption scenarios.
*/
public class TestProportionalCapacityPreemptionPolicyIntraQueueUserLimit
extends
ProportionalCapacityPreemptionPolicyMockFramework {
@Before
public void setup() {
super.setup();
conf.setBoolean(
CapacitySchedulerConfiguration.INTRAQUEUE_PREEMPTION_ENABLED, true);
policy = new ProportionalCapacityPreemptionPolicy(rmContext, cs, mClock);
}
@Test
public void testSimpleIntraQueuePreemptionWithTwoUsers()
throws IOException {
/**
* Queue structure is:
*
* <pre>
* root
* |
* a
* </pre>
*
* Scenario:
* Preconditions:
* Queue total resources: 100
* Minimum user limit percent: 50%
* +--------------+----------+------+---------+
* | APP | USER | PRIORITY | USED | PENDING |
* +--------------+----------+------+---------+
* | app1 | user1 | 1 | 100 | 0 |
* | app2 | user2 | 1 | 0 | 30 |
* +--------------+----------+------+---------+
* Hence in queueA of 100, each user has a quota of 50. app1 of high priority
* has a demand of 0 and its already using 100. app2 from user2 has a demand
* of 30, and UL is 50. 30 would be preempted from app1.
*/
// Set max preemption limit as 50%.
conf.setFloat(CapacitySchedulerConfiguration.
INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
(float) 0.5);
String labelsConfig = "=100,true;";
String nodesConfig = // n1 has no label
"n1= res=100";
String queuesConfig =
// guaranteed,max,used,pending,reserved
"root(=[100 100 100 30 0]);" + // root
"-a(=[100 100 100 30 0])"; // a
String appsConfig =
// queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
"a\t" // app1 in a
+ "(1,1,n1,,100,false,0,user1);" + // app1 a
"a\t" // app2 in a
+ "(1,1,n1,,0,false,30,user2)";
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2 needs more resource and its well under its user-limit. Hence preempt
// resources from app1.
verify(mDisp, times(30)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1))));
}
@Test
public void testNoIntraQueuePreemptionWithSingleUser()
throws IOException {
/**
* Queue structure is:
*
* <pre>
* root
* |
* a
* </pre>
*
* Scenario:
* Queue total resources: 100
* Minimum user limit percent: 50%
* +--------------+----------+------+---------+
* | APP | USER | PRIORITY | USED | PENDING |
* +--------------+----------+------+---------+
* | app1 | user1 | 1 | 100 | 0 |
* | app2 | user1 | 1 | 0 | 30 |
* +--------------+----------+------+---------+
* Given single user, lower priority/late submitted apps has to
* wait.
*/
// Set max preemption limit as 50%.
conf.setFloat(CapacitySchedulerConfiguration.
INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
(float) 0.5);
String labelsConfig = "=100,true;";
String nodesConfig = // n1 has no label
"n1= res=100";
String queuesConfig =
// guaranteed,max,used,pending,reserved
"root(=[100 100 100 30 0]);" + // root
"-a(=[100 100 100 30 0])"; // a
String appsConfig =
// queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
"a\t" // app1 in a
+ "(1,1,n1,,100,false,0,user1);" + // app1 a
"a\t" // app2 in a
+ "(1,1,n1,,0,false,30,user1)";
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2 needs more resource. Since app1,2 are from same user, there wont be
// any preemption.
verify(mDisp, times(0)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1))));
}
@Test
public void testNoIntraQueuePreemptionWithTwoUserUnderUserLimit()
throws IOException {
/**
* Queue structure is:
*
* <pre>
* root
* |
* a
* </pre>
*
* Scenario:
* Queue total resources: 100
* Minimum user limit percent: 50%
* +--------------+----------+------+---------+
* | APP | USER | PRIORITY | USED | PENDING |
* +--------------+----------+------+---------+
* | app1 | user1 | 1 | 50 | 0 |
* | app2 | user2 | 1 | 30 | 30 |
* +--------------+----------+------+---------+
* Hence in queueA of 100, each user has a quota of 50. app1 of high priority
* has a demand of 0 and its already using 50. app2 from user2 has a demand
* of 30, and UL is 50. Since app1 is under UL, there should not be any
* preemption.
*/
// Set max preemption limit as 50%.
conf.setFloat(CapacitySchedulerConfiguration.
INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
(float) 0.5);
String labelsConfig = "=100,true;";
String nodesConfig = // n1 has no label
"n1= res=100";
String queuesConfig =
// guaranteed,max,used,pending,reserved
"root(=[100 100 80 30 0]);" + // root
"-a(=[100 100 80 30 0])"; // a
String appsConfig =
// queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
"a\t" // app1 in a
+ "(1,1,n1,,50,false,0,user1);" + // app1 a
"a\t" // app2 in a
+ "(1,1,n1,,30,false,30,user2)";
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2 needs more resource. Since app1,2 are from same user, there wont be
// any preemption.
verify(mDisp, times(0)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1))));
}
@Test
public void testSimpleIntraQueuePreemptionWithTwoUsersWithAppPriority()
throws IOException {
/**
* Queue structure is:
*
* <pre>
* root
* |
* a
* </pre>
*
* Scenario:
* Queue total resources: 100
* Minimum user limit percent: 50%
* +--------------+----------+------+---------+
* | APP | USER | PRIORITY | USED | PENDING |
* +--------------+----------+------+---------+
* | app1 | user1 | 2 | 100 | 0 |
* | app2 | user2 | 1 | 0 | 30 |
* +--------------+----------+------+---------+
* Hence in queueA of 100, each user has a quota of 50. app1 of high priority
* has a demand of 0 and its already using 100. app2 from user2 has a demand
* of 30, and UL is 50. 30 would be preempted from app1.
*/
// Set max preemption limit as 50%.
conf.setFloat(CapacitySchedulerConfiguration.
INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
(float) 0.5);
String labelsConfig = "=100,true;";
String nodesConfig = // n1 has no label
"n1= res=100";
String queuesConfig =
// guaranteed,max,used,pending,reserved
"root(=[100 100 100 30 0]);" + // root
"-a(=[100 100 100 30 0])"; // a
String appsConfig =
// queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
"a\t" // app1 in a
+ "(2,1,n1,,100,false,0,user1);" + // app1 a
"a\t" // app2 in a
+ "(1,1,n1,,0,false,30,user2)";
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2 needs more resource and its well under its user-limit. Hence preempt
// resources from app1 even though its priority is more than app2.
verify(mDisp, times(30)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1))));
}
@Test
public void testIntraQueuePreemptionOfUserLimitWithMultipleApps()
throws IOException {
/**
* Queue structure is:
*
* <pre>
* root
* |
* a
* </pre>
*
* Scenario:
* Queue total resources: 100
* Minimum user limit percent: 50%
* +--------------+----------+------+---------+
* | APP | USER | PRIORITY | USED | PENDING |
* +--------------+----------+------+---------+
* | app1 | user1 | 1 | 30 | 30 |
* | app2 | user2 | 1 | 20 | 20 |
* | app3 | user1 | 1 | 30 | 30 |
* | app4 | user2 | 1 | 0 | 10 |
* +--------------+----------+------+---------+
* Hence in queueA of 100, each user has a quota of 50. Now have multiple
* apps and check for preemption across apps.
*/
// Set max preemption limit as 50%.
conf.setFloat(CapacitySchedulerConfiguration.
INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
(float) 0.5);
String labelsConfig = "=100,true;";
String nodesConfig = // n1 has no label
"n1= res=100";
String queuesConfig =
// guaranteed,max,used,pending,reserved
"root(=[100 100 80 90 0]);" + // root
"-a(=[100 100 80 90 0])"; // a
String appsConfig =
// queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
"a\t" // app1 in a
+ "(1,1,n1,,30,false,30,user1);" + // app1 a
"a\t" // app2 in a
+ "(1,1,n1,,20,false,20,user2);" +
"a\t" // app3 in a
+ "(1,1,n1,,30,false,30,user1);" +
"a\t" // app4 in a
+ "(1,1,n1,,0,false,10,user2)";
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2/app4 needs more resource and its well under its user-limit. Hence
// preempt resources from app3 (compare to app1, app3 has low priority).
verify(mDisp, times(9)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(3))));
}
@Test
public void testNoPreemptionOfUserLimitWithMultipleAppsAndSameUser()
throws IOException {
/**
* Queue structure is:
*
* <pre>
* root
* |
* a
* </pre>
*
* Scenario:
* Queue total resources: 100
* Minimum user limit percent: 50%
* +--------------+----------+------+---------+
* | APP | USER | PRIORITY | USED | PENDING |
* +--------------+----------+------+---------+
* | app1 | user1 | 1 | 30 | 30 |
* | app2 | user1 | 1 | 20 | 20 |
* | app3 | user1 | 1 | 30 | 30 |
* | app4 | user1 | 1 | 0 | 10 |
* +--------------+----------+------+---------+
* Hence in queueA of 100, each user has a quota of 50. Now have multiple
* apps and check for preemption across apps.
*/
// Set max preemption limit as 50%.
conf.setFloat(CapacitySchedulerConfiguration.
INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
(float) 0.5);
String labelsConfig = "=100,true;";
String nodesConfig = // n1 has no label
"n1= res=100";
String queuesConfig =
// guaranteed,max,used,pending,reserved
"root(=[100 100 80 90 0]);" + // root
"-a(=[100 100 80 90 0])"; // a
String appsConfig =
// queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
"a\t" // app1 in a
+ "(1,1,n1,,30,false,20,user1);" + // app1 a
"a\t" // app2 in a
+ "(1,1,n1,,20,false,20,user1);" +
"a\t" // app3 in a
+ "(1,1,n1,,30,false,30,user1);" +
"a\t" // app4 in a
+ "(1,1,n1,,0,false,10,user1)";
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2/app4 needs more resource and its well under its user-limit. Hence
// preempt resources from app3 (compare to app1, app3 has low priority).
verify(mDisp, times(0)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1))));
verify(mDisp, times(0)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(2))));
verify(mDisp, times(0)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(3))));
verify(mDisp, times(0)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(4))));
}
@Test
public void testIntraQueuePreemptionOfUserLimitWitAppsOfDifferentPriority()
throws IOException {
/**
* Queue structure is:
* <pre>
* root
* |
* a
* </pre>
*
* Scenario:
* Queue total resources: 100
* Minimum user limit percent: 50%
* +--------------+----------+------+---------+
* | APP | USER | PRIORITY | USED | PENDING |
* +--------------+----------+------+---------+
* | app1 | user1 | 3 | 30 | 30 |
* | app2 | user2 | 1 | 20 | 20 |
* | app3 | user1 | 4 | 30 | 0 |
* | app4 | user2 | 1 | 0 | 10 |
* +--------------+----------+------+---------+
* Hence in queueA of 100, each user has a quota of 50. Now have multiple
* apps and check for preemption across apps.
*/
// Set max preemption limit as 50%.
conf.setFloat(
CapacitySchedulerConfiguration.INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
(float) 0.5);
String labelsConfig = "=100,true;";
String nodesConfig = // n1 has no label
"n1= res=100";
String queuesConfig =
// guaranteed,max,used,pending,reserved
"root(=[100 100 80 60 0]);" + // root
"-a(=[100 100 80 60 0])"; // b
String appsConfig =
// queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
"a\t" // app1 in a
+ "(3,1,n1,,30,false,30,user1);" + // app1 a
"a\t" // app2 in a
+ "(1,1,n1,,20,false,20,user2);" + "a\t" // app3 in a
+ "(4,1,n1,,30,false,0,user1);" + "a\t" // app4 in a
+ "(1,1,n1,,0,false,10,user2)";
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2/app4 needs more resource and its well under its user-limit. Hence
// preempt resources from app1 (compare to app3, app1 has low priority).
verify(mDisp, times(9)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1))));
}
@Test
public void testIntraQueuePreemptionOfUserLimitInTwoQueues()
throws IOException {
/**
* Queue structure is:
*
* <pre>
* root
* / \
* a b
* </pre>
*
* Guaranteed resource of a/b are 40:60 Total cluster resource = 100
* maxIntraQueuePreemptableLimit by default is 50%. This test is to verify
* that intra-queue preemption could occur in two queues when user-limit
* irreuglarity is present in queue.
*/
// Set max preemption limit as 50%.
conf.setFloat(CapacitySchedulerConfiguration.
INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
(float) 0.5);
String labelsConfig = "=100,true;";
String nodesConfig = // n1 has no label
"n1= res=100";
String queuesConfig =
// guaranteed,max,used,pending,reserved
"root(=[100 100 90 80 0]);" + // root
"-a(=[60 100 55 60 0]);" + // a
"-b(=[40 100 35 20 0])"; // b
String appsConfig =
// queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
"a\t" // app1 in a
+ "(3,1,n1,,20,false,30,user1);" + // app1 a
"a\t" // app2 in a
+ "(1,1,n1,,20,false,20,user2);" +
"a\t" // app3 in a
+ "(4,1,n1,,15,false,0,user1);" +
"a\t" // app4 in a
+ "(1,1,n1,,0,false,10,user2);" +
"b\t" // app5 in b
+ "(3,1,n1,,25,false,10,user1);" +
"b\t" // app6 in b
+ "(1,1,n1,,10,false,10,user2)";
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2/app4 needs more resource and its well under its user-limit. Hence
// preempt resources from app1 (compare to app3, app1 has low priority).
verify(mDisp, times(4)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1))));
verify(mDisp, times(4)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(5))));
}
@Test
public void testIntraQueuePreemptionWithTwoRequestingUsers()
throws IOException {
/**
* Queue structure is:
*
* <pre>
* root
* |
* a
* </pre>
*
* Scenario:
* Queue total resources: 100
* Minimum user limit percent: 50%
* +--------------+----------+------+---------+
* | APP | USER | PRIORITY | USED | PENDING |
* +--------------+----------+------+---------+
* | app1 | user1 | 1 | 60 | 10 |
* | app2 | user2 | 1 | 40 | 10 |
* +--------------+----------+------+---------+
* Hence in queueA of 100, each user has a quota of 50. Now have multiple
* apps and check for preemption across apps.
*/
// Set max preemption limit as 50%.
conf.setFloat(CapacitySchedulerConfiguration.
INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
(float) 0.5);
String labelsConfig = "=100,true;";
String nodesConfig = // n1 has no label
"n1= res=100";
String queuesConfig =
// guaranteed,max,used,pending,reserved
"root(=[100 100 100 20 0]);" + // root
"-a(=[100 100 100 20 0])"; // a
String appsConfig =
// queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
"a\t" // app1 in a
+ "(1,1,n1,,60,false,10,user1);" + // app1 a
"a\t" // app2 in a
+ "(1,1,n1,,40,false,10,user2)";
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2 needs more resource and its well under its user-limit. Hence preempt
// resources from app1.
verify(mDisp, times(9)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1))));
verify(mDisp, times(0)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(2))));
}
@Test
public void testNoIntraQueuePreemptionIfBelowUserLimitAndLowPriorityExtraUsers()
throws IOException {
/**
* Queue structure is:
*
* <pre>
* root
* |
* a
* </pre>
*
* Scenario:
* Preconditions:
* Queue total resources: 100
* Minimum user limit percent: 50%
* +--------------+----------+------+---------+
* | APP | USER | PRIORITY | USED | PENDING |
* +--------------+----------+------+---------+
* | app1 | user1 | 1 | 50 | 0 |
* | app2 | user2 | 1 | 50 | 0 |
* | app3 | user3 | 0 | 0 | 10 |
* +--------------+----------+------+---------+
* This scenario should never preempt from either user1 or user2
*/
// Set max preemption per round to 50% (this is different from minimum user
// limit percent).
conf.setFloat(CapacitySchedulerConfiguration.
INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
(float) 0.7);
String labelsConfig = "=100,true;";
String nodesConfig = // n1 has no label
"n1= res=100";
String queuesConfig =
// guaranteed,max,used,pending,reserved
"root(=[100 100 100 10 0]);" + // root
"-a(=[100 100 100 10 0])"; // a
String appsConfig =
// queueName\t\
// (priority,resource,host,label,#repeat,reserved,pending,user)\tMULP;
"a\t(1,1,n1,,50,false,0,user1)\t50;" + // app1, user1
"a\t(1,1,n1,,50,false,0,user2)\t50;" + // app2, user2
"a\t(0,1,n1,,0,false,10,user3)\t50"; // app3, user3
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2/app4 needs more resource and its well under its user-limit. Hence
// preempt resources from app1 (compare to app3, app1 has low priority).
verify(mDisp, times(0)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1))));
verify(mDisp, times(0)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(2))));
}
@Test
public void testNoIntraQueuePreemptionIfBelowUserLimitAndSamePriorityExtraUsers()
throws IOException {
/**
* Queue structure is:
*
* <pre>
* root
* |
* a
* </pre>
*
* Scenario:
* Preconditions:
* Queue total resources: 100
* Minimum user limit percent: 50%
* +--------------+----------+------+---------+
* | APP | USER | PRIORITY | USED | PENDING |
* +--------------+----------+------+---------+
* | app1 | user1 | 1 | 50 | 0 |
* | app2 | user2 | 1 | 50 | 0 |
* | app3 | user3 | 1 | 0 | 10 |
* +--------------+----------+------+---------+
* This scenario should never preempt from either user1 or user2
*/
// Set max preemption per round to 50% (this is different from minimum user
// limit percent).
conf.setFloat(CapacitySchedulerConfiguration.
INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
(float) 0.7);
String labelsConfig = "=100,true;";
String nodesConfig = // n1 has no label
"n1= res=100";
String queuesConfig =
// guaranteed,max,used,pending,reserved
"root(=[100 100 100 10 0]);" + // root
"-a(=[100 100 100 10 0])"; // a
String appsConfig =
// queueName\t\
// (priority,resource,host,label,#repeat,reserved,pending,user)\tMULP;
"a\t(1,1,n1,,50,false,0,user1)\t50;" + // app1, user1
"a\t(1,1,n1,,50,false,0,user2)\t50;" + // app2, user2
"a\t(1,1,n1,,0,false,10,user3)\t50"; // app3, user3
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2/app4 needs more resource and its well under its user-limit. Hence
// preempt resources from app1 (compare to app3, app1 has low priority).
verify(mDisp, times(0)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1))));
verify(mDisp, times(0)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(2))));
}
@Test
public void testNoIntraQueuePreemptionIfBelowUserLimitAndHighPriorityExtraUsers()
throws IOException {
/**
* Queue structure is:
*
* <pre>
* root
* |
* a
* </pre>
*
* Scenario:
* Preconditions:
* Queue total resources: 100
* Minimum user limit percent: 50%
* +--------------+----------+------+---------+
* | APP | USER | PRIORITY | USED | PENDING |
* +--------------+----------+------+---------+
* | app1 | user1 | 1 | 50 | 0 |
* | app2 | user2 | 1 | 50 | 0 |
* | app3 | user3 | 5 | 0 | 10 |
* +--------------+----------+------+---------+
* This scenario should never preempt from either user1 or user2
*/
// Set max preemption per round to 50% (this is different from minimum user
// limit percent).
conf.setFloat(CapacitySchedulerConfiguration.
INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
(float) 0.7);
String labelsConfig = "=100,true;";
String nodesConfig = // n1 has no label
"n1= res=100";
String queuesConfig =
// guaranteed,max,used,pending,reserved
"root(=[100 100 100 10 0]);" + // root
"-a(=[100 100 100 10 0])"; // a
String appsConfig =
// queueName\t\
// (priority,resource,host,label,#repeat,reserved,pending,user)\tMULP;
"a\t(1,1,n1,,50,false,0,user1)\t50;" + // app1, user1
"a\t(1,1,n1,,50,false,0,user2)\t50;" + // app2, user2
"a\t(5,1,n1,,0,false,10,user3)\t50"; // app3, user3
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2/app4 needs more resource and its well under its user-limit. Hence
// preempt resources from app1 (compare to app3, app1 has low priority).
verify(mDisp, times(0)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1))));
verify(mDisp, times(0)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(2))));
}
@Test
public void testNoIntraQueuePreemptionWithUserLimitDeadzone()
throws IOException {
/**
* Queue structure is:
*
* <pre>
* root
* |
* a
* </pre>
*
* Scenario:
* Queue total resources: 100
* Minimum user limit percent: 50%
* +--------------+----------+------+---------+
* | APP | USER | PRIORITY | USED | PENDING |
* +--------------+----------+------+---------+
* | app1 | user1 | 1 | 60 | 10 |
* | app2 | user2 | 1 | 40 | 10 |
* +--------------+----------+------+---------+
* Hence in queueA of 100, each user has a quota of 50. Now have multiple
* apps and check for preemption across apps but also ensure that user's
* usage not coming under its user-limit.
*/
// Set max preemption limit as 50%.
conf.setFloat(CapacitySchedulerConfiguration.
INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
(float) 0.5);
String labelsConfig = "=100,true;";
String nodesConfig = // n1 has no label
"n1= res=100";
String queuesConfig =
// guaranteed,max,used,pending,reserved
"root(=[100 100 100 20 0]);" + // root
"-a(=[100 100 100 20 0])"; // a
String appsConfig =
// queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
"a\t" // app1 in a
+ "(1,3,n1,,20,false,10,user1);" + // app1 a
"a\t" // app2 in a
+ "(1,1,n1,,40,false,10,user2)";
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2 needs more resource and its well under its user-limit. Hence preempt
// 3 resources (9GB) from app1. We will not preempt last container as it may
// pull user's usage under its user-limit.
verify(mDisp, times(3)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1))));
verify(mDisp, times(0)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(2))));
}
@Test
public void testIntraQueuePreemptionWithUserLimitDeadzoneAndPriority()
throws IOException {
/**
* Queue structure is:
*
* <pre>
* root
* |
* a
* </pre>
*
* Scenario:
* Queue total resources: 100
* Minimum user limit percent: 50%
* +--------------+----------+------+---------+
* | APP | USER | PRIORITY | USED | PENDING |
* +--------------+----------+------+---------+
* | app1 | user1 | 1 | 60 | 10 |
* | app2 | user2 | 1 | 40 | 10 |
* +--------------+----------+------+---------+
* Hence in queueA of 100, each user has a quota of 50. Now have multiple
* apps and check for preemption across apps but also ensure that user's
* usage not coming under its user-limit.
*/
// Set max preemption limit as 50%.
conf.setFloat(CapacitySchedulerConfiguration.
INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
(float) 0.5);
String labelsConfig = "=100,true;";
String nodesConfig = // n1 has no label
"n1= res=100";
String queuesConfig =
// guaranteed,max,used,pending,reserved
"root(=[100 100 100 20 0]);" + // root
"-a(=[100 100 100 20 0])"; // a
String appsConfig =
// queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
"a\t" // app1 in a
+ "(1,3,n1,,20,false,10,user1);" + // app1 a
"a\t" // app2 in a
+ "(2,1,n1,,0,false,10,user1);" + // app1 a
"a\t" // app2 in a
+ "(1,1,n1,,40,false,20,user2)";
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2 needs more resource and its well under its user-limit. Hence preempt
// 3 resources (9GB) from app1. We will not preempt last container as it may
// pull user's usage under its user-limit.
verify(mDisp, times(3)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1))));
verify(mDisp, times(0)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(2))));
// After first round, 3 containers were preempted from app1 and resource
// distribution will be like below.
appsConfig =
// queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
"a\t" // app1 in a
+ "(1,3,n1,,17,false,10,user1);" + // app1 a
"a\t" // app2 in a
+ "(2,1,n1,,0,false,10,user1);" + // app2 a
"a\t" // app2 in a
+ "(1,1,n1,,49,false,11,user2)";
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2 has priority demand within same user 'user1'. However user1's used
// is alredy under UL. Hence no preemption. We will still get 3 container
// while asserting as it was aleady selected in earlier round.
verify(mDisp, times(3)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1))));
}
@Test
public void testSimpleIntraQueuePreemptionOneUserUnderOneUserAtOneUserAbove()
throws IOException {
conf.setFloat(CapacitySchedulerConfiguration.
INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
(float) 0.5);
String labelsConfig = "=100,true;";
String nodesConfig = // n1 has no label
"n1= res=100";
String queuesConfig =
// guaranteed,max,used,pending,reserved
"root(=[100 100 100 1 0]);" + // root
"-a(=[100 100 100 1 0])"; // a
String appsConfig =
// queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
"a\t" // app1 in a
+ "(1,1,n1,,65,false,0,user1);" +
"a\t" // app2 in a
+ "(1,1,n1,,35,false,0,user2);" +
"a\t" // app3 in a
+ "(1,1,n1,,0,false,1,user3)"
;
buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
policy.editSchedule();
// app2 is right at its user limit and app1 needs one resource. Should
// preempt 1 container.
verify(mDisp, times(1)).handle(argThat(
new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
getAppAttemptId(1))));
}
}