YARN-8732. Add unit tests of min/max allocation for custom resource types in FairScheduler. (Contributed by Szilard Nemeth)
This commit is contained in:
parent
2e9913caf2
commit
b6d5d84e07
|
@ -0,0 +1,582 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.apache.hadoop.yarn.api.protocolrecords.AllocateResponse;
|
||||||
|
import org.apache.hadoop.yarn.api.protocolrecords.FinishApplicationMasterRequest;
|
||||||
|
import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterResponse;
|
||||||
|
import org.apache.hadoop.yarn.api.protocolrecords.impl.pb.AllocateRequestPBImpl;
|
||||||
|
import org.apache.hadoop.yarn.api.records.Container;
|
||||||
|
import org.apache.hadoop.yarn.api.records.ContainerId;
|
||||||
|
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
|
||||||
|
import org.apache.hadoop.yarn.api.records.Resource;
|
||||||
|
import org.apache.hadoop.yarn.api.records.ResourceInformation;
|
||||||
|
import org.apache.hadoop.yarn.api.records.ResourceRequest;
|
||||||
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
||||||
|
import org.apache.hadoop.yarn.exceptions.ApplicationMasterNotRegisteredException;
|
||||||
|
import org.apache.hadoop.yarn.exceptions.InvalidContainerReleaseException;
|
||||||
|
import org.apache.hadoop.yarn.exceptions.InvalidResourceRequestException;
|
||||||
|
import org.apache.hadoop.yarn.proto.YarnServiceProtos;
|
||||||
|
import org.apache.hadoop.yarn.security.ContainerTokenIdentifier;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.resource.TestResourceProfiles;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttempt;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptState;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerConfiguration;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.TestUtils;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fifo.FifoScheduler;
|
||||||
|
import org.apache.hadoop.yarn.server.utils.BuilderUtils;
|
||||||
|
import org.apache.hadoop.yarn.util.resource.DominantResourceCalculator;
|
||||||
|
import org.apache.hadoop.yarn.util.resource.ResourceUtils;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static java.lang.Thread.sleep;
|
||||||
|
import static org.apache.hadoop.yarn.conf.YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB;
|
||||||
|
import static org.apache.hadoop.yarn.conf.YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for Application Master test classes.
|
||||||
|
* Some implementors are for testing CS and FS.
|
||||||
|
*/
|
||||||
|
public abstract class ApplicationMasterServiceTestBase {
|
||||||
|
private static final Log LOG = LogFactory
|
||||||
|
.getLog(ApplicationMasterServiceTestBase.class);
|
||||||
|
|
||||||
|
static final int GB = 1024;
|
||||||
|
|
||||||
|
static final String CUSTOM_RES = "res_1";
|
||||||
|
static final String DEFAULT_HOST = "127.0.0.1";
|
||||||
|
static final String DEFAULT_PORT = "1234";
|
||||||
|
|
||||||
|
protected static YarnConfiguration conf;
|
||||||
|
|
||||||
|
protected abstract YarnConfiguration createYarnConfig();
|
||||||
|
|
||||||
|
protected abstract Resource getResourceUsageForQueue(ResourceManager rm,
|
||||||
|
String queue);
|
||||||
|
|
||||||
|
protected abstract String getDefaultQueueName();
|
||||||
|
|
||||||
|
Map<String, ResourceInformation> initializeMandatoryResources() {
|
||||||
|
Map<String, ResourceInformation> riMap = new HashMap<>();
|
||||||
|
|
||||||
|
ResourceInformation memory = ResourceInformation.newInstance(
|
||||||
|
ResourceInformation.MEMORY_MB.getName(),
|
||||||
|
ResourceInformation.MEMORY_MB.getUnits(),
|
||||||
|
YarnConfiguration.DEFAULT_RM_SCHEDULER_MINIMUM_ALLOCATION_MB,
|
||||||
|
DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB);
|
||||||
|
ResourceInformation vcores = ResourceInformation.newInstance(
|
||||||
|
ResourceInformation.VCORES.getName(),
|
||||||
|
ResourceInformation.VCORES.getUnits(),
|
||||||
|
YarnConfiguration.DEFAULT_RM_SCHEDULER_MINIMUM_ALLOCATION_VCORES,
|
||||||
|
DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES);
|
||||||
|
|
||||||
|
riMap.put(ResourceInformation.MEMORY_URI, memory);
|
||||||
|
riMap.put(ResourceInformation.VCORES_URI, vcores);
|
||||||
|
return riMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void requestResources(MockAM am, long memory, int vCores,
|
||||||
|
Map<String, Integer> customResources) throws Exception {
|
||||||
|
am.allocate(Collections.singletonList(ResourceRequest.newBuilder()
|
||||||
|
.capability(TestUtils.createResource(memory, vCores, customResources))
|
||||||
|
.numContainers(1)
|
||||||
|
.resourceName("*")
|
||||||
|
.build()), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
conf = new YarnConfiguration();
|
||||||
|
conf.setClass(YarnConfiguration.RM_SCHEDULER, FifoScheduler.class,
|
||||||
|
ResourceScheduler.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 3000000)
|
||||||
|
public void testRMIdentifierOnContainerAllocation() throws Exception {
|
||||||
|
MockRM rm = new MockRM(conf);
|
||||||
|
rm.start();
|
||||||
|
|
||||||
|
// Register node1
|
||||||
|
MockNM nm1 = rm.registerNode(DEFAULT_HOST + ":" + DEFAULT_PORT, 6 * GB);
|
||||||
|
|
||||||
|
// Submit an application
|
||||||
|
RMApp app1 = rm.submitApp(2048);
|
||||||
|
|
||||||
|
// kick the scheduling
|
||||||
|
nm1.nodeHeartbeat(true);
|
||||||
|
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
||||||
|
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
||||||
|
am1.registerAppAttempt();
|
||||||
|
|
||||||
|
am1.addRequests(new String[] {DEFAULT_HOST}, GB, 1, 1);
|
||||||
|
AllocateResponse alloc1Response = am1.schedule(); // send the request
|
||||||
|
|
||||||
|
// kick the scheduler
|
||||||
|
nm1.nodeHeartbeat(true);
|
||||||
|
while (alloc1Response.getAllocatedContainers().size() < 1) {
|
||||||
|
LOG.info("Waiting for containers to be created for app 1...");
|
||||||
|
sleep(1000);
|
||||||
|
alloc1Response = am1.schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert RMIdentifier is set properly in allocated containers
|
||||||
|
Container allocatedContainer =
|
||||||
|
alloc1Response.getAllocatedContainers().get(0);
|
||||||
|
ContainerTokenIdentifier tokenId =
|
||||||
|
BuilderUtils.newContainerTokenIdentifier(allocatedContainer
|
||||||
|
.getContainerToken());
|
||||||
|
Assert.assertEquals(MockRM.getClusterTimeStamp(),
|
||||||
|
tokenId.getRMIdentifier());
|
||||||
|
rm.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 3000000)
|
||||||
|
public void testAllocateResponseIdOverflow() throws Exception {
|
||||||
|
MockRM rm = new MockRM(conf);
|
||||||
|
|
||||||
|
try {
|
||||||
|
rm.start();
|
||||||
|
|
||||||
|
// Register node1
|
||||||
|
MockNM nm1 = rm.registerNode(DEFAULT_HOST + ":" + DEFAULT_PORT, 6 * GB);
|
||||||
|
|
||||||
|
// Submit an application
|
||||||
|
RMApp app1 = rm.submitApp(2048);
|
||||||
|
|
||||||
|
// kick off the scheduling
|
||||||
|
nm1.nodeHeartbeat(true);
|
||||||
|
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
||||||
|
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
||||||
|
am1.registerAppAttempt();
|
||||||
|
|
||||||
|
// Set the last responseId to be Integer.MAX_VALUE
|
||||||
|
Assert.assertTrue(am1.setApplicationLastResponseId(Integer.MAX_VALUE));
|
||||||
|
|
||||||
|
// Both allocate should succeed
|
||||||
|
am1.schedule(); // send allocate with responseId = Integer.MAX_VALUE
|
||||||
|
Assert.assertEquals(0, am1.getResponseId());
|
||||||
|
|
||||||
|
am1.schedule(); // send allocate with responseId = 0
|
||||||
|
Assert.assertEquals(1, am1.getResponseId());
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
rm.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=600000)
|
||||||
|
public void testInvalidContainerReleaseRequest() throws Exception {
|
||||||
|
MockRM rm = new MockRM(conf);
|
||||||
|
|
||||||
|
try {
|
||||||
|
rm.start();
|
||||||
|
|
||||||
|
// Register node1
|
||||||
|
MockNM nm1 = rm.registerNode(DEFAULT_HOST + ":" + DEFAULT_PORT, 6 * GB);
|
||||||
|
|
||||||
|
// Submit an application
|
||||||
|
RMApp app1 = rm.submitApp(1024);
|
||||||
|
|
||||||
|
// kick the scheduling
|
||||||
|
nm1.nodeHeartbeat(true);
|
||||||
|
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
||||||
|
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
||||||
|
am1.registerAppAttempt();
|
||||||
|
|
||||||
|
am1.addRequests(new String[] {DEFAULT_HOST}, GB, 1, 1);
|
||||||
|
AllocateResponse alloc1Response = am1.schedule(); // send the request
|
||||||
|
|
||||||
|
// kick the scheduler
|
||||||
|
nm1.nodeHeartbeat(true);
|
||||||
|
while (alloc1Response.getAllocatedContainers().size() < 1) {
|
||||||
|
LOG.info("Waiting for containers to be created for app 1...");
|
||||||
|
sleep(1000);
|
||||||
|
alloc1Response = am1.schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.assertTrue(alloc1Response.getAllocatedContainers().size() > 0);
|
||||||
|
|
||||||
|
RMApp app2 = rm.submitApp(1024);
|
||||||
|
|
||||||
|
nm1.nodeHeartbeat(true);
|
||||||
|
RMAppAttempt attempt2 = app2.getCurrentAppAttempt();
|
||||||
|
MockAM am2 = rm.sendAMLaunched(attempt2.getAppAttemptId());
|
||||||
|
am2.registerAppAttempt();
|
||||||
|
|
||||||
|
// Now trying to release container allocated for app1 -> appAttempt1.
|
||||||
|
ContainerId cId = alloc1Response.getAllocatedContainers().get(0).getId();
|
||||||
|
am2.addContainerToBeReleased(cId);
|
||||||
|
try {
|
||||||
|
am2.schedule();
|
||||||
|
fail("Exception was expected!!");
|
||||||
|
} catch (InvalidContainerReleaseException e) {
|
||||||
|
StringBuilder sb = new StringBuilder("Cannot release container : ");
|
||||||
|
sb.append(cId.toString());
|
||||||
|
sb.append(" not belonging to this application attempt : ");
|
||||||
|
sb.append(attempt2.getAppAttemptId().toString());
|
||||||
|
Assert.assertTrue(e.getMessage().contains(sb.toString()));
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
rm.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=1200000)
|
||||||
|
public void testProgressFilter() throws Exception{
|
||||||
|
MockRM rm = new MockRM(conf);
|
||||||
|
rm.start();
|
||||||
|
|
||||||
|
// Register node1
|
||||||
|
MockNM nm1 = rm.registerNode(DEFAULT_HOST + ":" + DEFAULT_PORT, 6 * GB);
|
||||||
|
|
||||||
|
// Submit an application
|
||||||
|
RMApp app1 = rm.submitApp(2048);
|
||||||
|
|
||||||
|
nm1.nodeHeartbeat(true);
|
||||||
|
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
||||||
|
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
||||||
|
am1.registerAppAttempt();
|
||||||
|
|
||||||
|
AllocateRequestPBImpl allocateRequest = new AllocateRequestPBImpl();
|
||||||
|
List<ContainerId> release = new ArrayList<>();
|
||||||
|
List<ResourceRequest> ask = new ArrayList<>();
|
||||||
|
allocateRequest.setReleaseList(release);
|
||||||
|
allocateRequest.setAskList(ask);
|
||||||
|
|
||||||
|
allocateRequest.setProgress(Float.POSITIVE_INFINITY);
|
||||||
|
am1.allocate(allocateRequest);
|
||||||
|
while(attempt1.getProgress()!=1){
|
||||||
|
LOG.info("Waiting for allocate event to be handled ...");
|
||||||
|
sleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
allocateRequest.setProgress(Float.NaN);
|
||||||
|
am1.allocate(allocateRequest);
|
||||||
|
while(attempt1.getProgress()!=0){
|
||||||
|
LOG.info("Waiting for allocate event to be handled ...");
|
||||||
|
sleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
allocateRequest.setProgress((float)9);
|
||||||
|
am1.allocate(allocateRequest);
|
||||||
|
while(attempt1.getProgress()!=1){
|
||||||
|
LOG.info("Waiting for allocate event to be handled ...");
|
||||||
|
sleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
allocateRequest.setProgress(Float.NEGATIVE_INFINITY);
|
||||||
|
am1.allocate(allocateRequest);
|
||||||
|
while(attempt1.getProgress()!=0){
|
||||||
|
LOG.info("Waiting for allocate event to be handled ...");
|
||||||
|
sleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
allocateRequest.setProgress((float)0.5);
|
||||||
|
am1.allocate(allocateRequest);
|
||||||
|
while(attempt1.getProgress()!=0.5){
|
||||||
|
LOG.info("Waiting for allocate event to be handled ...");
|
||||||
|
sleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
allocateRequest.setProgress((float)-1);
|
||||||
|
am1.allocate(allocateRequest);
|
||||||
|
while(attempt1.getProgress()!=0){
|
||||||
|
LOG.info("Waiting for allocate event to be handled ...");
|
||||||
|
sleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=1200000)
|
||||||
|
public void testFinishApplicationMasterBeforeRegistering() throws Exception {
|
||||||
|
MockRM rm = new MockRM(conf);
|
||||||
|
|
||||||
|
try {
|
||||||
|
rm.start();
|
||||||
|
// Register node1
|
||||||
|
MockNM nm1 = rm.registerNode(DEFAULT_HOST + ":" + DEFAULT_PORT, 6 * GB);
|
||||||
|
// Submit an application
|
||||||
|
RMApp app1 = rm.submitApp(2048);
|
||||||
|
MockAM am1 = MockRM.launchAM(app1, rm, nm1);
|
||||||
|
FinishApplicationMasterRequest req =
|
||||||
|
FinishApplicationMasterRequest.newInstance(
|
||||||
|
FinalApplicationStatus.FAILED, "", "");
|
||||||
|
try {
|
||||||
|
am1.unregisterAppAttempt(req, false);
|
||||||
|
fail("ApplicationMasterNotRegisteredException should be thrown");
|
||||||
|
} catch (ApplicationMasterNotRegisteredException e) {
|
||||||
|
Assert.assertNotNull(e);
|
||||||
|
Assert.assertNotNull(e.getMessage());
|
||||||
|
Assert.assertTrue(e.getMessage().contains(
|
||||||
|
"Application Master is trying to unregister before registering for:"
|
||||||
|
));
|
||||||
|
} catch (Exception e) {
|
||||||
|
fail("ApplicationMasterNotRegisteredException should be thrown");
|
||||||
|
}
|
||||||
|
|
||||||
|
am1.registerAppAttempt();
|
||||||
|
|
||||||
|
am1.unregisterAppAttempt(req, false);
|
||||||
|
rm.waitForState(am1.getApplicationAttemptId(),
|
||||||
|
RMAppAttemptState.FINISHING);
|
||||||
|
} finally {
|
||||||
|
rm.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 3000000)
|
||||||
|
public void testResourceTypes() throws Exception {
|
||||||
|
HashMap<YarnConfiguration,
|
||||||
|
EnumSet<YarnServiceProtos.SchedulerResourceTypes>> driver =
|
||||||
|
new HashMap<>();
|
||||||
|
|
||||||
|
CapacitySchedulerConfiguration csconf =
|
||||||
|
new CapacitySchedulerConfiguration();
|
||||||
|
csconf.setResourceComparator(DominantResourceCalculator.class);
|
||||||
|
|
||||||
|
YarnConfiguration testCapacityDRConf = new YarnConfiguration(csconf);
|
||||||
|
testCapacityDRConf.setClass(YarnConfiguration.RM_SCHEDULER,
|
||||||
|
CapacityScheduler.class, ResourceScheduler.class);
|
||||||
|
|
||||||
|
YarnConfiguration testCapacityDefConf = new YarnConfiguration();
|
||||||
|
testCapacityDefConf.setClass(YarnConfiguration.RM_SCHEDULER,
|
||||||
|
CapacityScheduler.class, ResourceScheduler.class);
|
||||||
|
|
||||||
|
YarnConfiguration testFairDefConf = new YarnConfiguration();
|
||||||
|
testFairDefConf.setClass(YarnConfiguration.RM_SCHEDULER,
|
||||||
|
FairScheduler.class, ResourceScheduler.class);
|
||||||
|
|
||||||
|
driver.put(conf,
|
||||||
|
EnumSet.of(YarnServiceProtos.SchedulerResourceTypes.MEMORY));
|
||||||
|
driver.put(testCapacityDRConf,
|
||||||
|
EnumSet.of(YarnServiceProtos.SchedulerResourceTypes.CPU,
|
||||||
|
YarnServiceProtos.SchedulerResourceTypes.MEMORY));
|
||||||
|
driver.put(testCapacityDefConf,
|
||||||
|
EnumSet.of(YarnServiceProtos.SchedulerResourceTypes.MEMORY));
|
||||||
|
driver.put(testFairDefConf,
|
||||||
|
EnumSet.of(YarnServiceProtos.SchedulerResourceTypes.MEMORY,
|
||||||
|
YarnServiceProtos.SchedulerResourceTypes.CPU));
|
||||||
|
|
||||||
|
for (Map.Entry<YarnConfiguration,
|
||||||
|
EnumSet<YarnServiceProtos.SchedulerResourceTypes>> entry :
|
||||||
|
driver.entrySet()) {
|
||||||
|
EnumSet<YarnServiceProtos.SchedulerResourceTypes> expectedValue =
|
||||||
|
entry.getValue();
|
||||||
|
MockRM rm = new MockRM(entry.getKey());
|
||||||
|
rm.start();
|
||||||
|
MockNM nm1 = rm.registerNode(DEFAULT_HOST + ":" + DEFAULT_PORT, 6 * GB);
|
||||||
|
RMApp app1 = rm.submitApp(2048);
|
||||||
|
//Wait to make sure the attempt has the right state
|
||||||
|
//TODO explore a better way than sleeping for a while (YARN-4929)
|
||||||
|
Thread.sleep(1000);
|
||||||
|
nm1.nodeHeartbeat(true);
|
||||||
|
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
||||||
|
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
||||||
|
RegisterApplicationMasterResponse resp = am1.registerAppAttempt();
|
||||||
|
EnumSet<YarnServiceProtos.SchedulerResourceTypes> types =
|
||||||
|
resp.getSchedulerResourceTypes();
|
||||||
|
LOG.info("types = " + types.toString());
|
||||||
|
Assert.assertEquals(expectedValue, types);
|
||||||
|
rm.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=1200000)
|
||||||
|
public void testAllocateAfterUnregister() throws Exception {
|
||||||
|
MockRM rm = new MockRM(conf);
|
||||||
|
rm.start();
|
||||||
|
// Register node1
|
||||||
|
MockNM nm1 = rm.registerNode(DEFAULT_HOST + ":" + DEFAULT_PORT, 6 * GB);
|
||||||
|
|
||||||
|
// Submit an application
|
||||||
|
RMApp app1 = rm.submitApp(2048);
|
||||||
|
|
||||||
|
nm1.nodeHeartbeat(true);
|
||||||
|
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
||||||
|
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
||||||
|
am1.registerAppAttempt();
|
||||||
|
// unregister app attempt
|
||||||
|
FinishApplicationMasterRequest req =
|
||||||
|
FinishApplicationMasterRequest.newInstance(
|
||||||
|
FinalApplicationStatus.KILLED, "", "");
|
||||||
|
am1.unregisterAppAttempt(req, false);
|
||||||
|
// request container after unregister
|
||||||
|
am1.addRequests(new String[] {DEFAULT_HOST}, GB, 1, 1);
|
||||||
|
AllocateResponse alloc1Response = am1.schedule();
|
||||||
|
|
||||||
|
nm1.nodeHeartbeat(true);
|
||||||
|
rm.drainEvents();
|
||||||
|
alloc1Response = am1.schedule();
|
||||||
|
Assert.assertEquals(0, alloc1Response.getAllocatedContainers().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300000)
|
||||||
|
public void testUpdateTrackingUrl() throws Exception {
|
||||||
|
conf.setClass(YarnConfiguration.RM_SCHEDULER, CapacityScheduler.class,
|
||||||
|
ResourceScheduler.class);
|
||||||
|
MockRM rm = new MockRM(conf);
|
||||||
|
rm.start();
|
||||||
|
|
||||||
|
// Register node1
|
||||||
|
MockNM nm1 = rm.registerNode(DEFAULT_HOST + ":" + DEFAULT_PORT, 6 * GB);
|
||||||
|
|
||||||
|
RMApp app1 = rm.submitApp(2048);
|
||||||
|
|
||||||
|
nm1.nodeHeartbeat(true);
|
||||||
|
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
||||||
|
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
||||||
|
am1.registerAppAttempt();
|
||||||
|
Assert.assertEquals("N/A", rm.getRMContext().getRMApps().get(
|
||||||
|
app1.getApplicationId()).getOriginalTrackingUrl());
|
||||||
|
|
||||||
|
AllocateRequestPBImpl allocateRequest = new AllocateRequestPBImpl();
|
||||||
|
String newTrackingUrl = "hadoop.apache.org";
|
||||||
|
allocateRequest.setTrackingUrl(newTrackingUrl);
|
||||||
|
|
||||||
|
am1.allocate(allocateRequest);
|
||||||
|
Assert.assertEquals(newTrackingUrl, rm.getRMContext().getRMApps().get(
|
||||||
|
app1.getApplicationId()).getOriginalTrackingUrl());
|
||||||
|
|
||||||
|
// Send it again
|
||||||
|
am1.allocate(allocateRequest);
|
||||||
|
Assert.assertEquals(newTrackingUrl, rm.getRMContext().getRMApps().get(
|
||||||
|
app1.getApplicationId()).getOriginalTrackingUrl());
|
||||||
|
rm.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300000)
|
||||||
|
public void testValidateRequestCapacityAgainstMinMaxAllocation()
|
||||||
|
throws Exception {
|
||||||
|
Map<String, ResourceInformation> riMap =
|
||||||
|
initializeMandatoryResources();
|
||||||
|
ResourceUtils.initializeResourcesFromResourceInformationMap(riMap);
|
||||||
|
|
||||||
|
final YarnConfiguration yarnConf = createYarnConfig();
|
||||||
|
|
||||||
|
// Don't reset resource types since we have already configured resource
|
||||||
|
// types
|
||||||
|
yarnConf.setBoolean(TestResourceProfiles.TEST_CONF_RESET_RESOURCE_TYPES,
|
||||||
|
false);
|
||||||
|
yarnConf.setBoolean(YarnConfiguration.RM_RESOURCE_PROFILES_ENABLED, false);
|
||||||
|
|
||||||
|
MockRM rm = new MockRM(yarnConf);
|
||||||
|
rm.start();
|
||||||
|
|
||||||
|
MockNM nm1 = rm.registerNode("199.99.99.1:" + DEFAULT_PORT, TestUtils
|
||||||
|
.createResource(DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB,
|
||||||
|
DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES, null));
|
||||||
|
|
||||||
|
RMApp app1 = rm.submitApp(GB, "app", "user", null, getDefaultQueueName());
|
||||||
|
MockAM am1 = MockRM.launchAndRegisterAM(app1, rm, nm1);
|
||||||
|
|
||||||
|
// Now request resource, memory > allowed
|
||||||
|
boolean exception = false;
|
||||||
|
try {
|
||||||
|
am1.allocate(Collections.singletonList(ResourceRequest.newBuilder()
|
||||||
|
.capability(Resource.newInstance(9 * GB, 1))
|
||||||
|
.numContainers(1)
|
||||||
|
.resourceName("*")
|
||||||
|
.build()), null);
|
||||||
|
} catch (InvalidResourceRequestException e) {
|
||||||
|
exception = true;
|
||||||
|
}
|
||||||
|
Assert.assertTrue(exception);
|
||||||
|
|
||||||
|
exception = false;
|
||||||
|
try {
|
||||||
|
// Now request resource, vcores > allowed
|
||||||
|
am1.allocate(Collections.singletonList(ResourceRequest.newBuilder()
|
||||||
|
.capability(Resource.newInstance(8 * GB, 18))
|
||||||
|
.numContainers(1)
|
||||||
|
.resourceName("*")
|
||||||
|
.build()), null);
|
||||||
|
} catch (InvalidResourceRequestException e) {
|
||||||
|
exception = true;
|
||||||
|
}
|
||||||
|
Assert.assertTrue(exception);
|
||||||
|
|
||||||
|
rm.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300000)
|
||||||
|
public void testRequestCapacityMinMaxAllocationForResourceTypes()
|
||||||
|
throws Exception {
|
||||||
|
Map<String, ResourceInformation> riMap = initializeMandatoryResources();
|
||||||
|
ResourceInformation res1 = ResourceInformation.newInstance(CUSTOM_RES,
|
||||||
|
ResourceInformation.VCORES.getUnits(), 0, 4);
|
||||||
|
riMap.put(CUSTOM_RES, res1);
|
||||||
|
|
||||||
|
ResourceUtils.initializeResourcesFromResourceInformationMap(riMap);
|
||||||
|
|
||||||
|
final YarnConfiguration yarnConf = createYarnConfig();
|
||||||
|
// Don't reset resource types since we have already configured resource
|
||||||
|
// types
|
||||||
|
yarnConf.setBoolean(TestResourceProfiles.TEST_CONF_RESET_RESOURCE_TYPES,
|
||||||
|
false);
|
||||||
|
yarnConf.setBoolean(YarnConfiguration.RM_RESOURCE_PROFILES_ENABLED, false);
|
||||||
|
|
||||||
|
MockRM rm = new MockRM(yarnConf);
|
||||||
|
rm.start();
|
||||||
|
|
||||||
|
MockNM nm1 = rm.registerNode("199.99.99.1:" + DEFAULT_PORT, TestUtils
|
||||||
|
.createResource(DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB,
|
||||||
|
DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES,
|
||||||
|
ImmutableMap.of(CUSTOM_RES, 4)));
|
||||||
|
|
||||||
|
RMApp app1 = rm.submitApp(GB, "app", "user", null, getDefaultQueueName());
|
||||||
|
MockAM am1 = MockRM.launchAndRegisterAM(app1, rm, nm1);
|
||||||
|
|
||||||
|
Assert.assertEquals(Resource.newInstance(GB, 1),
|
||||||
|
getResourceUsageForQueue(rm, getDefaultQueueName()));
|
||||||
|
|
||||||
|
// Request memory > allowed
|
||||||
|
try {
|
||||||
|
requestResources(am1, 9 * GB, 1, ImmutableMap.of());
|
||||||
|
Assert.fail("Should throw InvalidResourceRequestException");
|
||||||
|
} catch (InvalidResourceRequestException ignored) {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Request vcores > allowed
|
||||||
|
requestResources(am1, GB, 18, ImmutableMap.of());
|
||||||
|
Assert.fail("Should throw InvalidResourceRequestException");
|
||||||
|
} catch (InvalidResourceRequestException ignored) {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Request custom resource 'res_1' > allowed
|
||||||
|
requestResources(am1, GB, 2, ImmutableMap.of(CUSTOM_RES, 100));
|
||||||
|
Assert.fail("Should throw InvalidResourceRequestException");
|
||||||
|
} catch (InvalidResourceRequestException ignored) {}
|
||||||
|
|
||||||
|
rm.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,993 +0,0 @@
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
import static java.lang.Thread.sleep;
|
|
||||||
import static org.apache.hadoop.yarn.conf.YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB;
|
|
||||||
import static org.apache.hadoop.yarn.conf.YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES;
|
|
||||||
|
|
||||||
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.apache.hadoop.security.UserGroupInformation;
|
|
||||||
import org.apache.hadoop.yarn.ams.ApplicationMasterServiceContext;
|
|
||||||
import org.apache.hadoop.yarn.ams.ApplicationMasterServiceProcessor;
|
|
||||||
import org.apache.hadoop.yarn.api.protocolrecords.AllocateRequest;
|
|
||||||
import org.apache.hadoop.yarn.api.protocolrecords.AllocateResponse;
|
|
||||||
import org.apache.hadoop.yarn.api.protocolrecords.FinishApplicationMasterRequest;
|
|
||||||
import org.apache.hadoop.yarn.api.protocolrecords.FinishApplicationMasterResponse;
|
|
||||||
import org.apache.hadoop.yarn.api.protocolrecords
|
|
||||||
.RegisterApplicationMasterRequest;
|
|
||||||
import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterResponse;
|
|
||||||
import org.apache.hadoop.yarn.api.protocolrecords.impl.pb.AllocateRequestPBImpl;
|
|
||||||
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
|
|
||||||
import org.apache.hadoop.yarn.api.records.Container;
|
|
||||||
import org.apache.hadoop.yarn.api.records.ContainerId;
|
|
||||||
import org.apache.hadoop.yarn.api.records.ContainerUpdateType;
|
|
||||||
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
|
|
||||||
import org.apache.hadoop.yarn.api.records.Priority;
|
|
||||||
import org.apache.hadoop.yarn.api.records.Resource;
|
|
||||||
import org.apache.hadoop.yarn.api.records.ResourceInformation;
|
|
||||||
import org.apache.hadoop.yarn.api.records.ResourceRequest;
|
|
||||||
import org.apache.hadoop.yarn.api.records.UpdateContainerRequest;
|
|
||||||
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
|
||||||
import org.apache.hadoop.yarn.exceptions.ApplicationMasterNotRegisteredException;
|
|
||||||
import org.apache.hadoop.yarn.exceptions.InvalidContainerReleaseException;
|
|
||||||
import org.apache.hadoop.yarn.exceptions.InvalidResourceRequestException;
|
|
||||||
import org.apache.hadoop.yarn.exceptions.YarnException;
|
|
||||||
import org.apache.hadoop.yarn.proto.YarnServiceProtos.SchedulerResourceTypes;
|
|
||||||
import org.apache.hadoop.yarn.resourcetypes.ResourceTypesTestHelper;
|
|
||||||
import org.apache.hadoop.yarn.security.ContainerTokenIdentifier;
|
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.resource.TestResourceProfiles;
|
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
|
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttempt;
|
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptState;
|
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.RMContainer;
|
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.RMContainerEvent;
|
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.RMContainerEventType;
|
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler;
|
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler;
|
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerConfiguration;
|
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.LeafQueue;
|
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.TestUtils;
|
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler;
|
|
||||||
|
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair
|
|
||||||
.FairSchedulerConfiguration;
|
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fifo.FifoScheduler;
|
|
||||||
import org.apache.hadoop.yarn.server.utils.BuilderUtils;
|
|
||||||
import org.apache.hadoop.yarn.util.resource.DominantResourceCalculator;
|
|
||||||
import org.apache.hadoop.yarn.util.resource.ResourceUtils;
|
|
||||||
import org.apache.hadoop.yarn.util.resource.Resources;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class TestApplicationMasterService {
|
|
||||||
private static final Log LOG = LogFactory
|
|
||||||
.getLog(TestApplicationMasterService.class);
|
|
||||||
|
|
||||||
private final int GB = 1024;
|
|
||||||
private static YarnConfiguration conf;
|
|
||||||
|
|
||||||
private static AtomicInteger beforeRegCount = new AtomicInteger(0);
|
|
||||||
private static AtomicInteger afterRegCount = new AtomicInteger(0);
|
|
||||||
private static AtomicInteger beforeAllocCount = new AtomicInteger(0);
|
|
||||||
private static AtomicInteger afterAllocCount = new AtomicInteger(0);
|
|
||||||
private static AtomicInteger beforeFinishCount = new AtomicInteger(0);
|
|
||||||
private static AtomicInteger afterFinishCount = new AtomicInteger(0);
|
|
||||||
private static AtomicInteger initCount = new AtomicInteger(0);
|
|
||||||
|
|
||||||
static class TestInterceptor1 implements
|
|
||||||
ApplicationMasterServiceProcessor {
|
|
||||||
|
|
||||||
private ApplicationMasterServiceProcessor nextProcessor;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(ApplicationMasterServiceContext amsContext,
|
|
||||||
ApplicationMasterServiceProcessor next) {
|
|
||||||
initCount.incrementAndGet();
|
|
||||||
this.nextProcessor = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerApplicationMaster(
|
|
||||||
ApplicationAttemptId applicationAttemptId,
|
|
||||||
RegisterApplicationMasterRequest request,
|
|
||||||
RegisterApplicationMasterResponse response)
|
|
||||||
throws IOException, YarnException {
|
|
||||||
nextProcessor.registerApplicationMaster(
|
|
||||||
applicationAttemptId, request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void allocate(ApplicationAttemptId appAttemptId,
|
|
||||||
AllocateRequest request,
|
|
||||||
AllocateResponse response) throws YarnException {
|
|
||||||
beforeAllocCount.incrementAndGet();
|
|
||||||
nextProcessor.allocate(appAttemptId, request, response);
|
|
||||||
afterAllocCount.incrementAndGet();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finishApplicationMaster(
|
|
||||||
ApplicationAttemptId applicationAttemptId,
|
|
||||||
FinishApplicationMasterRequest request,
|
|
||||||
FinishApplicationMasterResponse response) {
|
|
||||||
beforeFinishCount.incrementAndGet();
|
|
||||||
afterFinishCount.incrementAndGet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class TestInterceptor2 implements
|
|
||||||
ApplicationMasterServiceProcessor {
|
|
||||||
|
|
||||||
private ApplicationMasterServiceProcessor nextProcessor;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(ApplicationMasterServiceContext amsContext,
|
|
||||||
ApplicationMasterServiceProcessor next) {
|
|
||||||
initCount.incrementAndGet();
|
|
||||||
this.nextProcessor = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerApplicationMaster(
|
|
||||||
ApplicationAttemptId applicationAttemptId,
|
|
||||||
RegisterApplicationMasterRequest request,
|
|
||||||
RegisterApplicationMasterResponse response)
|
|
||||||
throws IOException, YarnException {
|
|
||||||
beforeRegCount.incrementAndGet();
|
|
||||||
nextProcessor.registerApplicationMaster(applicationAttemptId,
|
|
||||||
request, response);
|
|
||||||
afterRegCount.incrementAndGet();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void allocate(ApplicationAttemptId appAttemptId,
|
|
||||||
AllocateRequest request, AllocateResponse response)
|
|
||||||
throws YarnException {
|
|
||||||
beforeAllocCount.incrementAndGet();
|
|
||||||
nextProcessor.allocate(appAttemptId, request, response);
|
|
||||||
afterAllocCount.incrementAndGet();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finishApplicationMaster(
|
|
||||||
ApplicationAttemptId applicationAttemptId,
|
|
||||||
FinishApplicationMasterRequest request,
|
|
||||||
FinishApplicationMasterResponse response) {
|
|
||||||
beforeFinishCount.incrementAndGet();
|
|
||||||
nextProcessor.finishApplicationMaster(
|
|
||||||
applicationAttemptId, request, response);
|
|
||||||
afterFinishCount.incrementAndGet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setup() {
|
|
||||||
conf = new YarnConfiguration();
|
|
||||||
conf.setClass(YarnConfiguration.RM_SCHEDULER, FifoScheduler.class,
|
|
||||||
ResourceScheduler.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 300000)
|
|
||||||
public void testApplicationMasterInterceptor() throws Exception {
|
|
||||||
conf.set(YarnConfiguration.RM_APPLICATION_MASTER_SERVICE_PROCESSORS,
|
|
||||||
TestInterceptor1.class.getName() + ","
|
|
||||||
+ TestInterceptor2.class.getName());
|
|
||||||
MockRM rm = new MockRM(conf);
|
|
||||||
rm.start();
|
|
||||||
|
|
||||||
// Register node1
|
|
||||||
MockNM nm1 = rm.registerNode("127.0.0.1:1234", 6 * GB);
|
|
||||||
|
|
||||||
// Submit an application
|
|
||||||
RMApp app1 = rm.submitApp(2048);
|
|
||||||
|
|
||||||
// kick the scheduling
|
|
||||||
nm1.nodeHeartbeat(true);
|
|
||||||
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
|
||||||
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
|
||||||
am1.registerAppAttempt();
|
|
||||||
int allocCount = 0;
|
|
||||||
|
|
||||||
am1.addRequests(new String[] {"127.0.0.1"}, GB, 1, 1);
|
|
||||||
AllocateResponse alloc1Response = am1.schedule(); // send the request
|
|
||||||
allocCount++;
|
|
||||||
|
|
||||||
// kick the scheduler
|
|
||||||
nm1.nodeHeartbeat(true);
|
|
||||||
while (alloc1Response.getAllocatedContainers().size() < 1) {
|
|
||||||
LOG.info("Waiting for containers to be created for app 1...");
|
|
||||||
sleep(1000);
|
|
||||||
alloc1Response = am1.schedule();
|
|
||||||
allocCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// assert RMIdentifer is set properly in allocated containers
|
|
||||||
Container allocatedContainer =
|
|
||||||
alloc1Response.getAllocatedContainers().get(0);
|
|
||||||
ContainerTokenIdentifier tokenId =
|
|
||||||
BuilderUtils.newContainerTokenIdentifier(allocatedContainer
|
|
||||||
.getContainerToken());
|
|
||||||
am1.unregisterAppAttempt();
|
|
||||||
|
|
||||||
Assert.assertEquals(1, beforeRegCount.get());
|
|
||||||
Assert.assertEquals(1, afterRegCount.get());
|
|
||||||
|
|
||||||
// The allocate calls should be incremented twice
|
|
||||||
Assert.assertEquals(allocCount * 2, beforeAllocCount.get());
|
|
||||||
Assert.assertEquals(allocCount * 2, afterAllocCount.get());
|
|
||||||
|
|
||||||
// Finish should only be called once, since the FirstInterceptor
|
|
||||||
// does not forward the call.
|
|
||||||
Assert.assertEquals(1, beforeFinishCount.get());
|
|
||||||
Assert.assertEquals(1, afterFinishCount.get());
|
|
||||||
rm.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 3000000)
|
|
||||||
public void testRMIdentifierOnContainerAllocation() throws Exception {
|
|
||||||
MockRM rm = new MockRM(conf);
|
|
||||||
rm.start();
|
|
||||||
|
|
||||||
// Register node1
|
|
||||||
MockNM nm1 = rm.registerNode("127.0.0.1:1234", 6 * GB);
|
|
||||||
|
|
||||||
// Submit an application
|
|
||||||
RMApp app1 = rm.submitApp(2048);
|
|
||||||
|
|
||||||
// kick the scheduling
|
|
||||||
nm1.nodeHeartbeat(true);
|
|
||||||
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
|
||||||
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
|
||||||
am1.registerAppAttempt();
|
|
||||||
|
|
||||||
am1.addRequests(new String[] { "127.0.0.1" }, GB, 1, 1);
|
|
||||||
AllocateResponse alloc1Response = am1.schedule(); // send the request
|
|
||||||
|
|
||||||
// kick the scheduler
|
|
||||||
nm1.nodeHeartbeat(true);
|
|
||||||
while (alloc1Response.getAllocatedContainers().size() < 1) {
|
|
||||||
LOG.info("Waiting for containers to be created for app 1...");
|
|
||||||
sleep(1000);
|
|
||||||
alloc1Response = am1.schedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
// assert RMIdentifer is set properly in allocated containers
|
|
||||||
Container allocatedContainer =
|
|
||||||
alloc1Response.getAllocatedContainers().get(0);
|
|
||||||
ContainerTokenIdentifier tokenId =
|
|
||||||
BuilderUtils.newContainerTokenIdentifier(allocatedContainer
|
|
||||||
.getContainerToken());
|
|
||||||
Assert.assertEquals(MockRM.getClusterTimeStamp(), tokenId.getRMIdentifier());
|
|
||||||
rm.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 3000000)
|
|
||||||
public void testAllocateResponseIdOverflow() throws Exception {
|
|
||||||
MockRM rm = new MockRM(conf);
|
|
||||||
try {
|
|
||||||
rm.start();
|
|
||||||
|
|
||||||
// Register node1
|
|
||||||
MockNM nm1 = rm.registerNode("127.0.0.1:1234", 6 * GB);
|
|
||||||
|
|
||||||
// Submit an application
|
|
||||||
RMApp app1 = rm.submitApp(2048);
|
|
||||||
|
|
||||||
// kick the scheduling
|
|
||||||
nm1.nodeHeartbeat(true);
|
|
||||||
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
|
||||||
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
|
||||||
am1.registerAppAttempt();
|
|
||||||
|
|
||||||
// Set the last reponseId to be MAX_INT
|
|
||||||
Assert.assertTrue(am1.setApplicationLastResponseId(Integer.MAX_VALUE));
|
|
||||||
|
|
||||||
// Both allocate should succeed
|
|
||||||
am1.schedule(); // send allocate with reponseId = MAX_INT
|
|
||||||
Assert.assertEquals(0, am1.getResponseId());
|
|
||||||
|
|
||||||
am1.schedule(); // send allocate with reponseId = 0
|
|
||||||
Assert.assertEquals(1, am1.getResponseId());
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (rm != null) {
|
|
||||||
rm.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=600000)
|
|
||||||
public void testInvalidContainerReleaseRequest() throws Exception {
|
|
||||||
MockRM rm = new MockRM(conf);
|
|
||||||
|
|
||||||
try {
|
|
||||||
rm.start();
|
|
||||||
|
|
||||||
// Register node1
|
|
||||||
MockNM nm1 = rm.registerNode("127.0.0.1:1234", 6 * GB);
|
|
||||||
|
|
||||||
// Submit an application
|
|
||||||
RMApp app1 = rm.submitApp(1024);
|
|
||||||
|
|
||||||
// kick the scheduling
|
|
||||||
nm1.nodeHeartbeat(true);
|
|
||||||
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
|
||||||
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
|
||||||
am1.registerAppAttempt();
|
|
||||||
|
|
||||||
am1.addRequests(new String[] { "127.0.0.1" }, GB, 1, 1);
|
|
||||||
AllocateResponse alloc1Response = am1.schedule(); // send the request
|
|
||||||
|
|
||||||
// kick the scheduler
|
|
||||||
nm1.nodeHeartbeat(true);
|
|
||||||
while (alloc1Response.getAllocatedContainers().size() < 1) {
|
|
||||||
LOG.info("Waiting for containers to be created for app 1...");
|
|
||||||
sleep(1000);
|
|
||||||
alloc1Response = am1.schedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.assertTrue(alloc1Response.getAllocatedContainers().size() > 0);
|
|
||||||
|
|
||||||
RMApp app2 = rm.submitApp(1024);
|
|
||||||
|
|
||||||
nm1.nodeHeartbeat(true);
|
|
||||||
RMAppAttempt attempt2 = app2.getCurrentAppAttempt();
|
|
||||||
MockAM am2 = rm.sendAMLaunched(attempt2.getAppAttemptId());
|
|
||||||
am2.registerAppAttempt();
|
|
||||||
|
|
||||||
// Now trying to release container allocated for app1 -> appAttempt1.
|
|
||||||
ContainerId cId = alloc1Response.getAllocatedContainers().get(0).getId();
|
|
||||||
am2.addContainerToBeReleased(cId);
|
|
||||||
try {
|
|
||||||
am2.schedule();
|
|
||||||
fail("Exception was expected!!");
|
|
||||||
} catch (InvalidContainerReleaseException e) {
|
|
||||||
StringBuilder sb = new StringBuilder("Cannot release container : ");
|
|
||||||
sb.append(cId.toString());
|
|
||||||
sb.append(" not belonging to this application attempt : ");
|
|
||||||
sb.append(attempt2.getAppAttemptId().toString());
|
|
||||||
Assert.assertTrue(e.getMessage().contains(sb.toString()));
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (rm != null) {
|
|
||||||
rm.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=1200000)
|
|
||||||
public void testProgressFilter() throws Exception{
|
|
||||||
MockRM rm = new MockRM(conf);
|
|
||||||
rm.start();
|
|
||||||
|
|
||||||
// Register node1
|
|
||||||
MockNM nm1 = rm.registerNode("127.0.0.1:1234", 6 * GB);
|
|
||||||
|
|
||||||
// Submit an application
|
|
||||||
RMApp app1 = rm.submitApp(2048);
|
|
||||||
|
|
||||||
nm1.nodeHeartbeat(true);
|
|
||||||
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
|
||||||
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
|
||||||
am1.registerAppAttempt();
|
|
||||||
|
|
||||||
AllocateRequestPBImpl allocateRequest = new AllocateRequestPBImpl();
|
|
||||||
List<ContainerId> release = new ArrayList<ContainerId>();
|
|
||||||
List<ResourceRequest> ask = new ArrayList<ResourceRequest>();
|
|
||||||
allocateRequest.setReleaseList(release);
|
|
||||||
allocateRequest.setAskList(ask);
|
|
||||||
|
|
||||||
allocateRequest.setProgress(Float.POSITIVE_INFINITY);
|
|
||||||
am1.allocate(allocateRequest);
|
|
||||||
while(attempt1.getProgress()!=1){
|
|
||||||
LOG.info("Waiting for allocate event to be handled ...");
|
|
||||||
sleep(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
allocateRequest.setProgress(Float.NaN);
|
|
||||||
am1.allocate(allocateRequest);
|
|
||||||
while(attempt1.getProgress()!=0){
|
|
||||||
LOG.info("Waiting for allocate event to be handled ...");
|
|
||||||
sleep(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
allocateRequest.setProgress((float)9);
|
|
||||||
am1.allocate(allocateRequest);
|
|
||||||
while(attempt1.getProgress()!=1){
|
|
||||||
LOG.info("Waiting for allocate event to be handled ...");
|
|
||||||
sleep(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
allocateRequest.setProgress(Float.NEGATIVE_INFINITY);
|
|
||||||
am1.allocate(allocateRequest);
|
|
||||||
while(attempt1.getProgress()!=0){
|
|
||||||
LOG.info("Waiting for allocate event to be handled ...");
|
|
||||||
sleep(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
allocateRequest.setProgress((float)0.5);
|
|
||||||
am1.allocate(allocateRequest);
|
|
||||||
while(attempt1.getProgress()!=0.5){
|
|
||||||
LOG.info("Waiting for allocate event to be handled ...");
|
|
||||||
sleep(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
allocateRequest.setProgress((float)-1);
|
|
||||||
am1.allocate(allocateRequest);
|
|
||||||
while(attempt1.getProgress()!=0){
|
|
||||||
LOG.info("Waiting for allocate event to be handled ...");
|
|
||||||
sleep(100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=1200000)
|
|
||||||
public void testFinishApplicationMasterBeforeRegistering() throws Exception {
|
|
||||||
MockRM rm = new MockRM(conf);
|
|
||||||
try {
|
|
||||||
rm.start();
|
|
||||||
// Register node1
|
|
||||||
MockNM nm1 = rm.registerNode("127.0.0.1:1234", 6 * GB);
|
|
||||||
// Submit an application
|
|
||||||
RMApp app1 = rm.submitApp(2048);
|
|
||||||
MockAM am1 = MockRM.launchAM(app1, rm, nm1);
|
|
||||||
FinishApplicationMasterRequest req =
|
|
||||||
FinishApplicationMasterRequest.newInstance(
|
|
||||||
FinalApplicationStatus.FAILED, "", "");
|
|
||||||
try {
|
|
||||||
am1.unregisterAppAttempt(req, false);
|
|
||||||
fail("ApplicationMasterNotRegisteredException should be thrown");
|
|
||||||
} catch (ApplicationMasterNotRegisteredException e) {
|
|
||||||
Assert.assertNotNull(e);
|
|
||||||
Assert.assertNotNull(e.getMessage());
|
|
||||||
Assert.assertTrue(e.getMessage().contains(
|
|
||||||
"Application Master is trying to unregister before registering for:"
|
|
||||||
));
|
|
||||||
} catch (Exception e) {
|
|
||||||
fail("ApplicationMasterNotRegisteredException should be thrown");
|
|
||||||
}
|
|
||||||
|
|
||||||
am1.registerAppAttempt();
|
|
||||||
|
|
||||||
am1.unregisterAppAttempt(req, false);
|
|
||||||
rm.waitForState(am1.getApplicationAttemptId(), RMAppAttemptState.FINISHING);
|
|
||||||
} finally {
|
|
||||||
if (rm != null) {
|
|
||||||
rm.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 3000000)
|
|
||||||
public void testResourceTypes() throws Exception {
|
|
||||||
HashMap<YarnConfiguration, EnumSet<SchedulerResourceTypes>> driver =
|
|
||||||
new HashMap<YarnConfiguration, EnumSet<SchedulerResourceTypes>>();
|
|
||||||
|
|
||||||
CapacitySchedulerConfiguration csconf =
|
|
||||||
new CapacitySchedulerConfiguration();
|
|
||||||
csconf.setResourceComparator(DominantResourceCalculator.class);
|
|
||||||
YarnConfiguration testCapacityDRConf = new YarnConfiguration(csconf);
|
|
||||||
testCapacityDRConf.setClass(YarnConfiguration.RM_SCHEDULER,
|
|
||||||
CapacityScheduler.class, ResourceScheduler.class);
|
|
||||||
YarnConfiguration testCapacityDefConf = new YarnConfiguration();
|
|
||||||
testCapacityDefConf.setClass(YarnConfiguration.RM_SCHEDULER,
|
|
||||||
CapacityScheduler.class, ResourceScheduler.class);
|
|
||||||
YarnConfiguration testFairDefConf = new YarnConfiguration();
|
|
||||||
testFairDefConf.setClass(YarnConfiguration.RM_SCHEDULER,
|
|
||||||
FairScheduler.class, ResourceScheduler.class);
|
|
||||||
|
|
||||||
driver.put(conf, EnumSet.of(SchedulerResourceTypes.MEMORY));
|
|
||||||
driver.put(testCapacityDRConf,
|
|
||||||
EnumSet.of(SchedulerResourceTypes.CPU, SchedulerResourceTypes.MEMORY));
|
|
||||||
driver.put(testCapacityDefConf, EnumSet.of(SchedulerResourceTypes.MEMORY));
|
|
||||||
driver.put(testFairDefConf,
|
|
||||||
EnumSet.of(SchedulerResourceTypes.MEMORY, SchedulerResourceTypes.CPU));
|
|
||||||
|
|
||||||
for (Map.Entry<YarnConfiguration, EnumSet<SchedulerResourceTypes>> entry : driver
|
|
||||||
.entrySet()) {
|
|
||||||
EnumSet<SchedulerResourceTypes> expectedValue = entry.getValue();
|
|
||||||
MockRM rm = new MockRM(entry.getKey());
|
|
||||||
rm.start();
|
|
||||||
MockNM nm1 = rm.registerNode("127.0.0.1:1234", 6 * GB);
|
|
||||||
RMApp app1 = rm.submitApp(2048);
|
|
||||||
//Wait to make sure the attempt has the right state
|
|
||||||
//TODO explore a better way than sleeping for a while (YARN-4929)
|
|
||||||
Thread.sleep(1000);
|
|
||||||
nm1.nodeHeartbeat(true);
|
|
||||||
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
|
||||||
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
|
||||||
RegisterApplicationMasterResponse resp = am1.registerAppAttempt();
|
|
||||||
EnumSet<SchedulerResourceTypes> types = resp.getSchedulerResourceTypes();
|
|
||||||
LOG.info("types = " + types.toString());
|
|
||||||
Assert.assertEquals(expectedValue, types);
|
|
||||||
rm.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=1200000)
|
|
||||||
public void testAllocateAfterUnregister() throws Exception {
|
|
||||||
MockRM rm = new MockRM(conf);
|
|
||||||
rm.start();
|
|
||||||
// Register node1
|
|
||||||
MockNM nm1 = rm.registerNode("127.0.0.1:1234", 6 * GB);
|
|
||||||
|
|
||||||
// Submit an application
|
|
||||||
RMApp app1 = rm.submitApp(2048);
|
|
||||||
|
|
||||||
nm1.nodeHeartbeat(true);
|
|
||||||
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
|
||||||
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
|
||||||
am1.registerAppAttempt();
|
|
||||||
// unregister app attempt
|
|
||||||
FinishApplicationMasterRequest req =
|
|
||||||
FinishApplicationMasterRequest.newInstance(
|
|
||||||
FinalApplicationStatus.KILLED, "", "");
|
|
||||||
am1.unregisterAppAttempt(req, false);
|
|
||||||
// request container after unregister
|
|
||||||
am1.addRequests(new String[] { "127.0.0.1" }, GB, 1, 1);
|
|
||||||
AllocateResponse alloc1Response = am1.schedule();
|
|
||||||
|
|
||||||
nm1.nodeHeartbeat(true);
|
|
||||||
rm.drainEvents();
|
|
||||||
alloc1Response = am1.schedule();
|
|
||||||
Assert.assertEquals(0, alloc1Response.getAllocatedContainers().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=60000)
|
|
||||||
public void testInvalidIncreaseDecreaseRequest() throws Exception {
|
|
||||||
conf = new YarnConfiguration();
|
|
||||||
conf.setClass(YarnConfiguration.RM_SCHEDULER, CapacityScheduler.class,
|
|
||||||
ResourceScheduler.class);
|
|
||||||
MockRM rm = new MockRM(conf);
|
|
||||||
|
|
||||||
try {
|
|
||||||
rm.start();
|
|
||||||
|
|
||||||
// Register node1
|
|
||||||
MockNM nm1 = rm.registerNode("127.0.0.1:1234", 6 * GB);
|
|
||||||
|
|
||||||
// Submit an application
|
|
||||||
RMApp app1 = rm.submitApp(1024);
|
|
||||||
|
|
||||||
// kick the scheduling
|
|
||||||
nm1.nodeHeartbeat(true);
|
|
||||||
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
|
||||||
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
|
||||||
RegisterApplicationMasterResponse registerResponse =
|
|
||||||
am1.registerAppAttempt();
|
|
||||||
|
|
||||||
sentRMContainerLaunched(rm,
|
|
||||||
ContainerId.newContainerId(am1.getApplicationAttemptId(), 1));
|
|
||||||
|
|
||||||
// Ask for a normal increase should be successfull
|
|
||||||
am1.sendContainerResizingRequest(Arrays.asList(
|
|
||||||
UpdateContainerRequest.newInstance(
|
|
||||||
0, ContainerId.newContainerId(attempt1.getAppAttemptId(), 1),
|
|
||||||
ContainerUpdateType.INCREASE_RESOURCE,
|
|
||||||
Resources.createResource(2048), null)));
|
|
||||||
|
|
||||||
// Target resource is negative, should fail
|
|
||||||
AllocateResponse response =
|
|
||||||
am1.sendContainerResizingRequest(Arrays.asList(
|
|
||||||
UpdateContainerRequest.newInstance(0,
|
|
||||||
ContainerId.newContainerId(attempt1.getAppAttemptId(), 1),
|
|
||||||
ContainerUpdateType.INCREASE_RESOURCE,
|
|
||||||
Resources.createResource(-1), null)));
|
|
||||||
Assert.assertEquals(1, response.getUpdateErrors().size());
|
|
||||||
Assert.assertEquals("RESOURCE_OUTSIDE_ALLOWED_RANGE",
|
|
||||||
response.getUpdateErrors().get(0).getReason());
|
|
||||||
|
|
||||||
// Target resource is more than maxAllocation, should fail
|
|
||||||
response = am1.sendContainerResizingRequest(Arrays.asList(
|
|
||||||
UpdateContainerRequest.newInstance(0,
|
|
||||||
ContainerId.newContainerId(attempt1.getAppAttemptId(), 1),
|
|
||||||
ContainerUpdateType.INCREASE_RESOURCE,
|
|
||||||
Resources.add(
|
|
||||||
registerResponse.getMaximumResourceCapability(),
|
|
||||||
Resources.createResource(1)), null)));
|
|
||||||
Assert.assertEquals(1, response.getUpdateErrors().size());
|
|
||||||
Assert.assertEquals("RESOURCE_OUTSIDE_ALLOWED_RANGE",
|
|
||||||
response.getUpdateErrors().get(0).getReason());
|
|
||||||
|
|
||||||
// Contains multiple increase/decrease requests for same contaienrId
|
|
||||||
response = am1.sendContainerResizingRequest(Arrays.asList(
|
|
||||||
UpdateContainerRequest.newInstance(0,
|
|
||||||
ContainerId.newContainerId(attempt1.getAppAttemptId(), 1),
|
|
||||||
ContainerUpdateType.INCREASE_RESOURCE,
|
|
||||||
Resources.createResource(2048, 4), null),
|
|
||||||
UpdateContainerRequest.newInstance(0,
|
|
||||||
ContainerId.newContainerId(attempt1.getAppAttemptId(), 1),
|
|
||||||
ContainerUpdateType.DECREASE_RESOURCE,
|
|
||||||
Resources.createResource(1024, 1), null)));
|
|
||||||
Assert.assertEquals(1, response.getUpdateErrors().size());
|
|
||||||
Assert.assertEquals("UPDATE_OUTSTANDING_ERROR",
|
|
||||||
response.getUpdateErrors().get(0).getReason());
|
|
||||||
} finally {
|
|
||||||
rm.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 300000)
|
|
||||||
public void testPriorityInAllocatedResponse() throws Exception {
|
|
||||||
conf.setClass(YarnConfiguration.RM_SCHEDULER, CapacityScheduler.class,
|
|
||||||
ResourceScheduler.class);
|
|
||||||
// Set Max Application Priority as 10
|
|
||||||
conf.setInt(YarnConfiguration.MAX_CLUSTER_LEVEL_APPLICATION_PRIORITY, 10);
|
|
||||||
MockRM rm = new MockRM(conf);
|
|
||||||
rm.start();
|
|
||||||
|
|
||||||
// Register node1
|
|
||||||
MockNM nm1 = rm.registerNode("127.0.0.1:1234", 6 * GB);
|
|
||||||
|
|
||||||
// Submit an application
|
|
||||||
Priority appPriority1 = Priority.newInstance(5);
|
|
||||||
RMApp app1 = rm.submitApp(2048, appPriority1);
|
|
||||||
|
|
||||||
nm1.nodeHeartbeat(true);
|
|
||||||
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
|
||||||
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
|
||||||
am1.registerAppAttempt();
|
|
||||||
|
|
||||||
AllocateRequestPBImpl allocateRequest = new AllocateRequestPBImpl();
|
|
||||||
List<ContainerId> release = new ArrayList<ContainerId>();
|
|
||||||
List<ResourceRequest> ask = new ArrayList<ResourceRequest>();
|
|
||||||
allocateRequest.setReleaseList(release);
|
|
||||||
allocateRequest.setAskList(ask);
|
|
||||||
|
|
||||||
AllocateResponse response1 = am1.allocate(allocateRequest);
|
|
||||||
Assert.assertEquals(appPriority1, response1.getApplicationPriority());
|
|
||||||
|
|
||||||
// Change the priority of App1 to 8
|
|
||||||
Priority appPriority2 = Priority.newInstance(8);
|
|
||||||
UserGroupInformation ugi = UserGroupInformation
|
|
||||||
.createRemoteUser(app1.getUser());
|
|
||||||
rm.getRMAppManager().updateApplicationPriority(ugi, app1.getApplicationId(),
|
|
||||||
appPriority2);
|
|
||||||
|
|
||||||
AllocateResponse response2 = am1.allocate(allocateRequest);
|
|
||||||
Assert.assertEquals(appPriority2, response2.getApplicationPriority());
|
|
||||||
rm.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 300000)
|
|
||||||
public void testCSValidateRequestCapacityAgainstMinMaxAllocation()
|
|
||||||
throws Exception {
|
|
||||||
testValidateRequestCapacityAgainstMinMaxAllocation(CapacityScheduler.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 300000)
|
|
||||||
public void testFSValidateRequestCapacityAgainstMinMaxAllocation()
|
|
||||||
throws Exception {
|
|
||||||
testValidateRequestCapacityAgainstMinMaxAllocation(FairScheduler.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void testValidateRequestCapacityAgainstMinMaxAllocation(Class<?> schedulerCls)
|
|
||||||
throws Exception {
|
|
||||||
|
|
||||||
// Initialize resource map for 2 types.
|
|
||||||
Map<String, ResourceInformation> riMap = new HashMap<>();
|
|
||||||
|
|
||||||
// Initialize mandatory resources
|
|
||||||
ResourceInformation memory = ResourceInformation.newInstance(
|
|
||||||
ResourceInformation.MEMORY_MB.getName(),
|
|
||||||
ResourceInformation.MEMORY_MB.getUnits(),
|
|
||||||
YarnConfiguration.DEFAULT_RM_SCHEDULER_MINIMUM_ALLOCATION_MB,
|
|
||||||
DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB);
|
|
||||||
ResourceInformation vcores = ResourceInformation.newInstance(
|
|
||||||
ResourceInformation.VCORES.getName(),
|
|
||||||
ResourceInformation.VCORES.getUnits(),
|
|
||||||
YarnConfiguration.DEFAULT_RM_SCHEDULER_MINIMUM_ALLOCATION_VCORES,
|
|
||||||
DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES);
|
|
||||||
riMap.put(ResourceInformation.MEMORY_URI, memory);
|
|
||||||
riMap.put(ResourceInformation.VCORES_URI, vcores);
|
|
||||||
|
|
||||||
ResourceUtils.initializeResourcesFromResourceInformationMap(riMap);
|
|
||||||
|
|
||||||
final YarnConfiguration yarnConf;
|
|
||||||
if (schedulerCls.getCanonicalName()
|
|
||||||
.equals(CapacityScheduler.class.getCanonicalName())) {
|
|
||||||
CapacitySchedulerConfiguration csConf =
|
|
||||||
new CapacitySchedulerConfiguration();
|
|
||||||
csConf.setResourceComparator(DominantResourceCalculator.class);
|
|
||||||
yarnConf = new YarnConfiguration(csConf);
|
|
||||||
} else if (schedulerCls.getCanonicalName()
|
|
||||||
.equals(FairScheduler.class.getCanonicalName())) {
|
|
||||||
FairSchedulerConfiguration fsConf = new FairSchedulerConfiguration();
|
|
||||||
yarnConf = new YarnConfiguration(fsConf);
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"Scheduler class is of wrong type: " + schedulerCls);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't reset resource types since we have already configured resource
|
|
||||||
// types
|
|
||||||
yarnConf.setBoolean(TestResourceProfiles.TEST_CONF_RESET_RESOURCE_TYPES,
|
|
||||||
false);
|
|
||||||
yarnConf.setClass(YarnConfiguration.RM_SCHEDULER, schedulerCls,
|
|
||||||
ResourceScheduler.class);
|
|
||||||
yarnConf.setBoolean(YarnConfiguration.RM_RESOURCE_PROFILES_ENABLED, false);
|
|
||||||
|
|
||||||
MockRM rm = new MockRM(yarnConf);
|
|
||||||
rm.start();
|
|
||||||
|
|
||||||
MockNM nm1 = rm.registerNode("199.99.99.1:1234", TestUtils
|
|
||||||
.createResource(DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB,
|
|
||||||
DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES, null));
|
|
||||||
|
|
||||||
RMApp app1 = rm.submitApp(GB, "app", "user", null, "default");
|
|
||||||
MockAM am1 = MockRM.launchAndRegisterAM(app1, rm, nm1);
|
|
||||||
|
|
||||||
// Now request resource, memory > allowed
|
|
||||||
boolean exception = false;
|
|
||||||
try {
|
|
||||||
am1.allocate(Collections.singletonList(ResourceRequest.newBuilder()
|
|
||||||
.capability(Resource.newInstance(9 * GB, 1))
|
|
||||||
.numContainers(1)
|
|
||||||
.resourceName("*")
|
|
||||||
.build()), null);
|
|
||||||
} catch (InvalidResourceRequestException e) {
|
|
||||||
exception = true;
|
|
||||||
}
|
|
||||||
Assert.assertTrue(exception);
|
|
||||||
|
|
||||||
exception = false;
|
|
||||||
try {
|
|
||||||
// Now request resource, vcores > allowed
|
|
||||||
am1.allocate(Collections.singletonList(ResourceRequest.newBuilder()
|
|
||||||
.capability(Resource.newInstance(8 * GB, 18))
|
|
||||||
.numContainers(1)
|
|
||||||
.resourceName("*")
|
|
||||||
.build()), null);
|
|
||||||
} catch (InvalidResourceRequestException e) {
|
|
||||||
exception = true;
|
|
||||||
}
|
|
||||||
Assert.assertTrue(exception);
|
|
||||||
|
|
||||||
rm.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testValidateRequestCapacityAgainstMinMaxAllocationWithDifferentUnits()
|
|
||||||
throws Exception {
|
|
||||||
|
|
||||||
// Initialize resource map for 2 types.
|
|
||||||
Map<String, ResourceInformation> riMap = new HashMap<>();
|
|
||||||
|
|
||||||
// Initialize mandatory resources
|
|
||||||
ResourceInformation memory =
|
|
||||||
ResourceInformation.newInstance(ResourceInformation.MEMORY_MB.getName(),
|
|
||||||
ResourceInformation.MEMORY_MB.getUnits(),
|
|
||||||
YarnConfiguration.DEFAULT_RM_SCHEDULER_MINIMUM_ALLOCATION_MB,
|
|
||||||
YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB);
|
|
||||||
ResourceInformation vcores =
|
|
||||||
ResourceInformation.newInstance(ResourceInformation.VCORES.getName(),
|
|
||||||
ResourceInformation.VCORES.getUnits(),
|
|
||||||
YarnConfiguration.DEFAULT_RM_SCHEDULER_MINIMUM_ALLOCATION_VCORES,
|
|
||||||
DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES);
|
|
||||||
ResourceInformation res1 =
|
|
||||||
ResourceInformation.newInstance("res_1", "G", 0, 4);
|
|
||||||
riMap.put(ResourceInformation.MEMORY_URI, memory);
|
|
||||||
riMap.put(ResourceInformation.VCORES_URI, vcores);
|
|
||||||
riMap.put("res_1", res1);
|
|
||||||
|
|
||||||
ResourceUtils.initializeResourcesFromResourceInformationMap(riMap);
|
|
||||||
|
|
||||||
FairSchedulerConfiguration fsConf =
|
|
||||||
new FairSchedulerConfiguration();
|
|
||||||
|
|
||||||
YarnConfiguration yarnConf = new YarnConfiguration(fsConf);
|
|
||||||
// Don't reset resource types since we have already configured resource
|
|
||||||
// types
|
|
||||||
yarnConf.setBoolean(TestResourceProfiles.TEST_CONF_RESET_RESOURCE_TYPES,
|
|
||||||
false);
|
|
||||||
yarnConf.setClass(YarnConfiguration.RM_SCHEDULER, FairScheduler.class,
|
|
||||||
ResourceScheduler.class);
|
|
||||||
yarnConf.setBoolean(YarnConfiguration.RM_RESOURCE_PROFILES_ENABLED, false);
|
|
||||||
|
|
||||||
MockRM rm = new MockRM(yarnConf);
|
|
||||||
rm.start();
|
|
||||||
|
|
||||||
MockNM nm1 = rm.registerNode("199.99.99.1:1234",
|
|
||||||
ResourceTypesTestHelper.newResource(
|
|
||||||
DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB,
|
|
||||||
DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES,
|
|
||||||
ImmutableMap.<String, String> builder()
|
|
||||||
.put("res_1", "5G").build()));
|
|
||||||
|
|
||||||
RMApp app1 = rm.submitApp(GB, "app", "user", null, "default");
|
|
||||||
MockAM am1 = MockRM.launchAndRegisterAM(app1, rm, nm1);
|
|
||||||
|
|
||||||
// Now request res_1, 500M < 5G so it should be allowed
|
|
||||||
try {
|
|
||||||
am1.allocate(Collections.singletonList(ResourceRequest.newBuilder()
|
|
||||||
.capability(ResourceTypesTestHelper.newResource(4 * GB, 1,
|
|
||||||
ImmutableMap.<String, String> builder()
|
|
||||||
.put("res_1", "500M")
|
|
||||||
.build()))
|
|
||||||
.numContainers(1).resourceName("*").build()), null);
|
|
||||||
} catch (InvalidResourceRequestException e) {
|
|
||||||
fail(
|
|
||||||
"Allocate request should be accepted but exception was thrown: " + e);
|
|
||||||
}
|
|
||||||
|
|
||||||
rm.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 300000)
|
|
||||||
public void testValidateRequestCapacityAgainstMinMaxAllocationFor3rdResourceTypes()
|
|
||||||
throws Exception {
|
|
||||||
|
|
||||||
// Initialize resource map for 2 types.
|
|
||||||
Map<String, ResourceInformation> riMap = new HashMap<>();
|
|
||||||
|
|
||||||
// Initialize mandatory resources
|
|
||||||
ResourceInformation memory = ResourceInformation.newInstance(
|
|
||||||
ResourceInformation.MEMORY_MB.getName(),
|
|
||||||
ResourceInformation.MEMORY_MB.getUnits(),
|
|
||||||
YarnConfiguration.DEFAULT_RM_SCHEDULER_MINIMUM_ALLOCATION_MB,
|
|
||||||
DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB);
|
|
||||||
ResourceInformation vcores = ResourceInformation.newInstance(
|
|
||||||
ResourceInformation.VCORES.getName(),
|
|
||||||
ResourceInformation.VCORES.getUnits(),
|
|
||||||
YarnConfiguration.DEFAULT_RM_SCHEDULER_MINIMUM_ALLOCATION_VCORES,
|
|
||||||
DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES);
|
|
||||||
ResourceInformation res1 = ResourceInformation.newInstance("res_1",
|
|
||||||
ResourceInformation.VCORES.getUnits(), 0, 4);
|
|
||||||
riMap.put(ResourceInformation.MEMORY_URI, memory);
|
|
||||||
riMap.put(ResourceInformation.VCORES_URI, vcores);
|
|
||||||
riMap.put("res_1", res1);
|
|
||||||
|
|
||||||
ResourceUtils.initializeResourcesFromResourceInformationMap(riMap);
|
|
||||||
|
|
||||||
CapacitySchedulerConfiguration csconf =
|
|
||||||
new CapacitySchedulerConfiguration();
|
|
||||||
csconf.setResourceComparator(DominantResourceCalculator.class);
|
|
||||||
|
|
||||||
YarnConfiguration yarnConf = new YarnConfiguration(csconf);
|
|
||||||
// Don't reset resource types since we have already configured resource
|
|
||||||
// types
|
|
||||||
yarnConf.setBoolean(TestResourceProfiles.TEST_CONF_RESET_RESOURCE_TYPES,
|
|
||||||
false);
|
|
||||||
yarnConf.setClass(YarnConfiguration.RM_SCHEDULER, CapacityScheduler.class,
|
|
||||||
ResourceScheduler.class);
|
|
||||||
yarnConf.setBoolean(YarnConfiguration.RM_RESOURCE_PROFILES_ENABLED, false);
|
|
||||||
|
|
||||||
MockRM rm = new MockRM(yarnConf);
|
|
||||||
rm.start();
|
|
||||||
|
|
||||||
CapacityScheduler cs = (CapacityScheduler) rm.getResourceScheduler();
|
|
||||||
LeafQueue leafQueue = (LeafQueue) cs.getQueue("default");
|
|
||||||
|
|
||||||
MockNM nm1 = rm.registerNode("199.99.99.1:1234", TestUtils
|
|
||||||
.createResource(DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB,
|
|
||||||
DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES,
|
|
||||||
ImmutableMap.of("res_1", 4)));
|
|
||||||
|
|
||||||
RMApp app1 = rm.submitApp(GB, "app", "user", null, "default");
|
|
||||||
MockAM am1 = MockRM.launchAndRegisterAM(app1, rm, nm1);
|
|
||||||
|
|
||||||
Assert.assertEquals(Resource.newInstance(GB, 1),
|
|
||||||
leafQueue.getUsedResources());
|
|
||||||
|
|
||||||
// Now request resource, memory > allowed
|
|
||||||
boolean exception = false;
|
|
||||||
try {
|
|
||||||
am1.allocate(Collections.singletonList(ResourceRequest.newBuilder()
|
|
||||||
.capability(TestUtils.createResource(9 * GB, 1,
|
|
||||||
ImmutableMap.of("res_1", 1)))
|
|
||||||
.numContainers(1)
|
|
||||||
.resourceName("*")
|
|
||||||
.build()), null);
|
|
||||||
} catch (InvalidResourceRequestException e) {
|
|
||||||
exception = true;
|
|
||||||
}
|
|
||||||
Assert.assertTrue(exception);
|
|
||||||
|
|
||||||
exception = false;
|
|
||||||
try {
|
|
||||||
// Now request resource, vcores > allowed
|
|
||||||
am1.allocate(Collections.singletonList(ResourceRequest.newBuilder()
|
|
||||||
.capability(
|
|
||||||
TestUtils.createResource(8 * GB, 18, ImmutableMap.of("res_1", 1)))
|
|
||||||
.numContainers(1)
|
|
||||||
.resourceName("*")
|
|
||||||
.build()), null);
|
|
||||||
} catch (InvalidResourceRequestException e) {
|
|
||||||
exception = true;
|
|
||||||
}
|
|
||||||
Assert.assertTrue(exception);
|
|
||||||
|
|
||||||
exception = false;
|
|
||||||
try {
|
|
||||||
// Now request resource, res_1 > allowed
|
|
||||||
am1.allocate(Collections.singletonList(ResourceRequest.newBuilder()
|
|
||||||
.capability(TestUtils.createResource(8 * GB, 1,
|
|
||||||
ImmutableMap.of("res_1", 100)))
|
|
||||||
.numContainers(1)
|
|
||||||
.resourceName("*")
|
|
||||||
.build()), null);
|
|
||||||
} catch (InvalidResourceRequestException e) {
|
|
||||||
exception = true;
|
|
||||||
}
|
|
||||||
Assert.assertTrue(exception);
|
|
||||||
|
|
||||||
rm.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sentRMContainerLaunched(MockRM rm, ContainerId containerId) {
|
|
||||||
CapacityScheduler cs = (CapacityScheduler) rm.getResourceScheduler();
|
|
||||||
RMContainer rmContainer = cs.getRMContainer(containerId);
|
|
||||||
if (rmContainer != null) {
|
|
||||||
rmContainer.handle(
|
|
||||||
new RMContainerEvent(containerId, RMContainerEventType.LAUNCHED));
|
|
||||||
} else {
|
|
||||||
fail("Cannot find RMContainer");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 300000)
|
|
||||||
public void testUpdateTrackingUrl() throws Exception {
|
|
||||||
conf.setClass(YarnConfiguration.RM_SCHEDULER, CapacityScheduler.class,
|
|
||||||
ResourceScheduler.class);
|
|
||||||
MockRM rm = new MockRM(conf);
|
|
||||||
rm.start();
|
|
||||||
|
|
||||||
// Register node1
|
|
||||||
MockNM nm1 = rm.registerNode("127.0.0.1:1234", 6 * GB);
|
|
||||||
|
|
||||||
RMApp app1 = rm.submitApp(2048);
|
|
||||||
|
|
||||||
nm1.nodeHeartbeat(true);
|
|
||||||
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
|
||||||
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
|
||||||
am1.registerAppAttempt();
|
|
||||||
Assert.assertEquals("N/A", rm.getRMContext().getRMApps().get(
|
|
||||||
app1.getApplicationId()).getOriginalTrackingUrl());
|
|
||||||
|
|
||||||
AllocateRequestPBImpl allocateRequest = new AllocateRequestPBImpl();
|
|
||||||
String newTrackingUrl = "hadoop.apache.org";
|
|
||||||
allocateRequest.setTrackingUrl(newTrackingUrl);
|
|
||||||
|
|
||||||
am1.allocate(allocateRequest);
|
|
||||||
Assert.assertEquals(newTrackingUrl, rm.getRMContext().getRMApps().get(
|
|
||||||
app1.getApplicationId()).getOriginalTrackingUrl());
|
|
||||||
|
|
||||||
// Send it again
|
|
||||||
am1.allocate(allocateRequest);
|
|
||||||
Assert.assertEquals(newTrackingUrl, rm.getRMContext().getRMApps().get(
|
|
||||||
app1.getApplicationId()).getOriginalTrackingUrl());
|
|
||||||
rm.stop();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,207 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.apache.hadoop.security.UserGroupInformation;
|
||||||
|
import org.apache.hadoop.yarn.api.protocolrecords.AllocateResponse;
|
||||||
|
import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterResponse;
|
||||||
|
import org.apache.hadoop.yarn.api.protocolrecords.impl.pb.AllocateRequestPBImpl;
|
||||||
|
import org.apache.hadoop.yarn.api.records.ContainerId;
|
||||||
|
import org.apache.hadoop.yarn.api.records.ContainerUpdateType;
|
||||||
|
import org.apache.hadoop.yarn.api.records.Priority;
|
||||||
|
import org.apache.hadoop.yarn.api.records.Resource;
|
||||||
|
import org.apache.hadoop.yarn.api.records.ResourceRequest;
|
||||||
|
import org.apache.hadoop.yarn.api.records.UpdateContainerRequest;
|
||||||
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttempt;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.RMContainer;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer
|
||||||
|
.RMContainerEvent;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.RMContainerEventType;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerConfiguration;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.LeafQueue;
|
||||||
|
import org.apache.hadoop.yarn.util.resource.DominantResourceCalculator;
|
||||||
|
import org.apache.hadoop.yarn.util.resource.Resources;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for {@link ApplicationMasterService}
|
||||||
|
* with {@link CapacityScheduler}.
|
||||||
|
*/
|
||||||
|
public class TestApplicationMasterServiceCapacity extends
|
||||||
|
ApplicationMasterServiceTestBase {
|
||||||
|
|
||||||
|
private static final String DEFAULT_QUEUE = "default";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected YarnConfiguration createYarnConfig() {
|
||||||
|
CapacitySchedulerConfiguration csConf =
|
||||||
|
new CapacitySchedulerConfiguration();
|
||||||
|
csConf.setResourceComparator(DominantResourceCalculator.class);
|
||||||
|
YarnConfiguration yarnConf = new YarnConfiguration(csConf);
|
||||||
|
yarnConf.setClass(YarnConfiguration.RM_SCHEDULER, CapacityScheduler.class,
|
||||||
|
ResourceScheduler.class);
|
||||||
|
return yarnConf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Resource getResourceUsageForQueue(ResourceManager rm,
|
||||||
|
String queue) {
|
||||||
|
CapacityScheduler cs = (CapacityScheduler) rm.getResourceScheduler();
|
||||||
|
LeafQueue leafQueue = (LeafQueue) cs.getQueue(DEFAULT_QUEUE);
|
||||||
|
return leafQueue.getUsedResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getDefaultQueueName() {
|
||||||
|
return DEFAULT_QUEUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sentRMContainerLaunched(MockRM rm, ContainerId containerId) {
|
||||||
|
CapacityScheduler cs = (CapacityScheduler) rm.getResourceScheduler();
|
||||||
|
RMContainer rmContainer = cs.getRMContainer(containerId);
|
||||||
|
if (rmContainer != null) {
|
||||||
|
rmContainer.handle(
|
||||||
|
new RMContainerEvent(containerId, RMContainerEventType.LAUNCHED));
|
||||||
|
} else {
|
||||||
|
fail("Cannot find RMContainer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=60000)
|
||||||
|
public void testInvalidIncreaseDecreaseRequest() throws Exception {
|
||||||
|
conf = new YarnConfiguration();
|
||||||
|
conf.setClass(YarnConfiguration.RM_SCHEDULER, CapacityScheduler.class,
|
||||||
|
ResourceScheduler.class);
|
||||||
|
|
||||||
|
try (MockRM rm = new MockRM(conf)) {
|
||||||
|
rm.start();
|
||||||
|
|
||||||
|
// Register node1
|
||||||
|
MockNM nm1 = rm.registerNode(DEFAULT_HOST + ":" + DEFAULT_PORT, 6 * GB);
|
||||||
|
|
||||||
|
// Submit an application
|
||||||
|
RMApp app1 = rm.submitApp(1024);
|
||||||
|
|
||||||
|
// kick the scheduling
|
||||||
|
nm1.nodeHeartbeat(true);
|
||||||
|
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
||||||
|
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
||||||
|
RegisterApplicationMasterResponse registerResponse =
|
||||||
|
am1.registerAppAttempt();
|
||||||
|
|
||||||
|
sentRMContainerLaunched(rm,
|
||||||
|
ContainerId.newContainerId(am1.getApplicationAttemptId(), 1));
|
||||||
|
|
||||||
|
// Ask for a normal increase should be successful
|
||||||
|
am1.sendContainerResizingRequest(Arrays.asList(
|
||||||
|
UpdateContainerRequest.newInstance(
|
||||||
|
0, ContainerId.newContainerId(attempt1.getAppAttemptId(), 1),
|
||||||
|
ContainerUpdateType.INCREASE_RESOURCE,
|
||||||
|
Resources.createResource(2048), null)));
|
||||||
|
|
||||||
|
// Target resource is negative, should fail
|
||||||
|
AllocateResponse response =
|
||||||
|
am1.sendContainerResizingRequest(Arrays.asList(
|
||||||
|
UpdateContainerRequest.newInstance(0,
|
||||||
|
ContainerId.newContainerId(attempt1.getAppAttemptId(), 1),
|
||||||
|
ContainerUpdateType.INCREASE_RESOURCE,
|
||||||
|
Resources.createResource(-1), null)));
|
||||||
|
Assert.assertEquals(1, response.getUpdateErrors().size());
|
||||||
|
Assert.assertEquals("RESOURCE_OUTSIDE_ALLOWED_RANGE",
|
||||||
|
response.getUpdateErrors().get(0).getReason());
|
||||||
|
|
||||||
|
// Target resource is more than maxAllocation, should fail
|
||||||
|
response = am1.sendContainerResizingRequest(Arrays.asList(
|
||||||
|
UpdateContainerRequest.newInstance(0,
|
||||||
|
ContainerId.newContainerId(attempt1.getAppAttemptId(), 1),
|
||||||
|
ContainerUpdateType.INCREASE_RESOURCE,
|
||||||
|
Resources.add(
|
||||||
|
registerResponse.getMaximumResourceCapability(),
|
||||||
|
Resources.createResource(1)), null)));
|
||||||
|
Assert.assertEquals(1, response.getUpdateErrors().size());
|
||||||
|
Assert.assertEquals("RESOURCE_OUTSIDE_ALLOWED_RANGE",
|
||||||
|
response.getUpdateErrors().get(0).getReason());
|
||||||
|
|
||||||
|
// Contains multiple increase/decrease requests for same containerId
|
||||||
|
response = am1.sendContainerResizingRequest(Arrays.asList(
|
||||||
|
UpdateContainerRequest.newInstance(0,
|
||||||
|
ContainerId.newContainerId(attempt1.getAppAttemptId(), 1),
|
||||||
|
ContainerUpdateType.INCREASE_RESOURCE,
|
||||||
|
Resources.createResource(2048, 4), null),
|
||||||
|
UpdateContainerRequest.newInstance(0,
|
||||||
|
ContainerId.newContainerId(attempt1.getAppAttemptId(), 1),
|
||||||
|
ContainerUpdateType.DECREASE_RESOURCE,
|
||||||
|
Resources.createResource(1024, 1), null)));
|
||||||
|
Assert.assertEquals(1, response.getUpdateErrors().size());
|
||||||
|
Assert.assertEquals("UPDATE_OUTSTANDING_ERROR",
|
||||||
|
response.getUpdateErrors().get(0).getReason());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300000)
|
||||||
|
public void testPriorityInAllocatedResponse() throws Exception {
|
||||||
|
conf.setClass(YarnConfiguration.RM_SCHEDULER, CapacityScheduler.class,
|
||||||
|
ResourceScheduler.class);
|
||||||
|
// Set Max Application Priority as 10
|
||||||
|
conf.setInt(YarnConfiguration.MAX_CLUSTER_LEVEL_APPLICATION_PRIORITY, 10);
|
||||||
|
MockRM rm = new MockRM(conf);
|
||||||
|
rm.start();
|
||||||
|
|
||||||
|
// Register node1
|
||||||
|
MockNM nm1 = rm.registerNode(DEFAULT_HOST + ":" + DEFAULT_PORT, 6 * GB);
|
||||||
|
|
||||||
|
// Submit an application
|
||||||
|
Priority appPriority1 = Priority.newInstance(5);
|
||||||
|
RMApp app1 = rm.submitApp(2048, appPriority1);
|
||||||
|
|
||||||
|
nm1.nodeHeartbeat(true);
|
||||||
|
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
||||||
|
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
||||||
|
am1.registerAppAttempt();
|
||||||
|
|
||||||
|
AllocateRequestPBImpl allocateRequest = new AllocateRequestPBImpl();
|
||||||
|
List<ContainerId> release = new ArrayList<>();
|
||||||
|
List<ResourceRequest> ask = new ArrayList<>();
|
||||||
|
allocateRequest.setReleaseList(release);
|
||||||
|
allocateRequest.setAskList(ask);
|
||||||
|
|
||||||
|
AllocateResponse response1 = am1.allocate(allocateRequest);
|
||||||
|
Assert.assertEquals(appPriority1, response1.getApplicationPriority());
|
||||||
|
|
||||||
|
// Change the priority of App1 to 8
|
||||||
|
Priority appPriority2 = Priority.newInstance(8);
|
||||||
|
UserGroupInformation ugi = UserGroupInformation
|
||||||
|
.createRemoteUser(app1.getUser());
|
||||||
|
rm.getRMAppManager().updateApplicationPriority(ugi, app1.getApplicationId(),
|
||||||
|
appPriority2);
|
||||||
|
|
||||||
|
AllocateResponse response2 = am1.allocate(allocateRequest);
|
||||||
|
Assert.assertEquals(appPriority2, response2.getApplicationPriority());
|
||||||
|
rm.stop();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import org.apache.hadoop.yarn.api.records.Resource;
|
||||||
|
import org.apache.hadoop.yarn.api.records.ResourceInformation;
|
||||||
|
import org.apache.hadoop.yarn.api.records.ResourceRequest;
|
||||||
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
||||||
|
import org.apache.hadoop.yarn.exceptions.InvalidResourceRequestException;
|
||||||
|
import org.apache.hadoop.yarn.resourcetypes.ResourceTypesTestHelper;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.resource.TestResourceProfiles;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FSLeafQueue;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairSchedulerConfiguration;
|
||||||
|
import org.apache.hadoop.yarn.util.resource.ResourceUtils;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.apache.hadoop.yarn.conf.YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB;
|
||||||
|
import static org.apache.hadoop.yarn.conf.YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for {@link ApplicationMasterService} with {@link FairScheduler}.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class TestApplicationMasterServiceFair extends
|
||||||
|
ApplicationMasterServiceTestBase {
|
||||||
|
private static final String DEFAULT_QUEUE = "root.default";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected YarnConfiguration createYarnConfig() {
|
||||||
|
FairSchedulerConfiguration fsConf = new FairSchedulerConfiguration();
|
||||||
|
YarnConfiguration yarnConf = new YarnConfiguration(fsConf);
|
||||||
|
yarnConf.setClass(YarnConfiguration.RM_SCHEDULER, FairScheduler.class,
|
||||||
|
ResourceScheduler.class);
|
||||||
|
return yarnConf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Resource getResourceUsageForQueue(ResourceManager rm,
|
||||||
|
String queue) {
|
||||||
|
FairScheduler fs = (FairScheduler) rm.getResourceScheduler();
|
||||||
|
FSLeafQueue leafQueue =
|
||||||
|
fs.getQueueManager().getLeafQueue(DEFAULT_QUEUE, false);
|
||||||
|
return leafQueue.getResourceUsage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getDefaultQueueName() {
|
||||||
|
return DEFAULT_QUEUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequestCapacityMinMaxAllocationWithDifferentUnits()
|
||||||
|
throws Exception {
|
||||||
|
Map<String, ResourceInformation> riMap = initializeMandatoryResources();
|
||||||
|
ResourceInformation res1 =
|
||||||
|
ResourceInformation.newInstance(CUSTOM_RES, "G", 0, 4);
|
||||||
|
riMap.put(CUSTOM_RES, res1);
|
||||||
|
|
||||||
|
ResourceUtils.initializeResourcesFromResourceInformationMap(riMap);
|
||||||
|
|
||||||
|
final YarnConfiguration yarnConf = createYarnConfig();
|
||||||
|
// Don't reset resource types since we have already configured resource
|
||||||
|
// types
|
||||||
|
yarnConf.setBoolean(TestResourceProfiles.TEST_CONF_RESET_RESOURCE_TYPES,
|
||||||
|
false);
|
||||||
|
yarnConf.setBoolean(YarnConfiguration.RM_RESOURCE_PROFILES_ENABLED, false);
|
||||||
|
|
||||||
|
MockRM rm = new MockRM(yarnConf);
|
||||||
|
rm.start();
|
||||||
|
|
||||||
|
MockNM nm1 = rm.registerNode("199.99.99.1:" + DEFAULT_PORT,
|
||||||
|
ResourceTypesTestHelper.newResource(
|
||||||
|
DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB,
|
||||||
|
DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_VCORES,
|
||||||
|
ImmutableMap.<String, String> builder()
|
||||||
|
.put(CUSTOM_RES, "5G").build()));
|
||||||
|
|
||||||
|
RMApp app1 = rm.submitApp(GB, "app", "user", null, DEFAULT_QUEUE);
|
||||||
|
MockAM am1 = MockRM.launchAndRegisterAM(app1, rm, nm1);
|
||||||
|
|
||||||
|
// Now request res_1, 500M < 5G so it should be allowed
|
||||||
|
try {
|
||||||
|
am1.allocate(Collections.singletonList(ResourceRequest.newBuilder()
|
||||||
|
.capability(ResourceTypesTestHelper.newResource(4 * GB, 1,
|
||||||
|
ImmutableMap.<String, String> builder()
|
||||||
|
.put(CUSTOM_RES, "500M")
|
||||||
|
.build()))
|
||||||
|
.numContainers(1).resourceName("*").build()), null);
|
||||||
|
} catch (InvalidResourceRequestException e) {
|
||||||
|
fail(
|
||||||
|
"Allocate request should be accepted but exception was thrown: " + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
rm.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,217 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.apache.hadoop.yarn.ams.ApplicationMasterServiceContext;
|
||||||
|
import org.apache.hadoop.yarn.ams.ApplicationMasterServiceProcessor;
|
||||||
|
import org.apache.hadoop.yarn.api.protocolrecords.AllocateRequest;
|
||||||
|
import org.apache.hadoop.yarn.api.protocolrecords.AllocateResponse;
|
||||||
|
import org.apache.hadoop.yarn.api.protocolrecords.FinishApplicationMasterRequest;
|
||||||
|
import org.apache.hadoop.yarn.api.protocolrecords.FinishApplicationMasterResponse;
|
||||||
|
import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterRequest;
|
||||||
|
import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterResponse;
|
||||||
|
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
|
||||||
|
import org.apache.hadoop.yarn.api.records.Container;
|
||||||
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
||||||
|
import org.apache.hadoop.yarn.exceptions.YarnException;
|
||||||
|
import org.apache.hadoop.yarn.security.ContainerTokenIdentifier;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttempt;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler
|
||||||
|
.ResourceScheduler;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fifo.FifoScheduler;
|
||||||
|
import org.apache.hadoop.yarn.server.utils.BuilderUtils;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import static java.lang.Thread.sleep;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class tests whether {@link ApplicationMasterServiceProcessor}s
|
||||||
|
* work fine, e.g. allocation is invoked on preprocessor and the next processor
|
||||||
|
* in the chain is also invoked.
|
||||||
|
*/
|
||||||
|
public class TestApplicationMasterServiceInterceptor {
|
||||||
|
private static final Log LOG = LogFactory
|
||||||
|
.getLog(TestApplicationMasterServiceInterceptor.class);
|
||||||
|
|
||||||
|
private static AtomicInteger beforeRegCount = new AtomicInteger(0);
|
||||||
|
private static AtomicInteger afterRegCount = new AtomicInteger(0);
|
||||||
|
private static AtomicInteger beforeAllocCount = new AtomicInteger(0);
|
||||||
|
private static AtomicInteger afterAllocCount = new AtomicInteger(0);
|
||||||
|
private static AtomicInteger beforeFinishCount = new AtomicInteger(0);
|
||||||
|
private static AtomicInteger afterFinishCount = new AtomicInteger(0);
|
||||||
|
private static AtomicInteger initCount = new AtomicInteger(0);
|
||||||
|
|
||||||
|
static class TestInterceptor1 implements
|
||||||
|
ApplicationMasterServiceProcessor {
|
||||||
|
|
||||||
|
private ApplicationMasterServiceProcessor nextProcessor;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(ApplicationMasterServiceContext amsContext,
|
||||||
|
ApplicationMasterServiceProcessor next) {
|
||||||
|
initCount.incrementAndGet();
|
||||||
|
this.nextProcessor = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerApplicationMaster(
|
||||||
|
ApplicationAttemptId applicationAttemptId,
|
||||||
|
RegisterApplicationMasterRequest request,
|
||||||
|
RegisterApplicationMasterResponse response)
|
||||||
|
throws IOException, YarnException {
|
||||||
|
nextProcessor.registerApplicationMaster(
|
||||||
|
applicationAttemptId, request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void allocate(ApplicationAttemptId appAttemptId,
|
||||||
|
AllocateRequest request,
|
||||||
|
AllocateResponse response) throws YarnException {
|
||||||
|
beforeAllocCount.incrementAndGet();
|
||||||
|
nextProcessor.allocate(appAttemptId, request, response);
|
||||||
|
afterAllocCount.incrementAndGet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finishApplicationMaster(
|
||||||
|
ApplicationAttemptId applicationAttemptId,
|
||||||
|
FinishApplicationMasterRequest request,
|
||||||
|
FinishApplicationMasterResponse response) {
|
||||||
|
beforeFinishCount.incrementAndGet();
|
||||||
|
afterFinishCount.incrementAndGet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TestInterceptor2 implements
|
||||||
|
ApplicationMasterServiceProcessor {
|
||||||
|
|
||||||
|
private ApplicationMasterServiceProcessor nextProcessor;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(ApplicationMasterServiceContext amsContext,
|
||||||
|
ApplicationMasterServiceProcessor next) {
|
||||||
|
initCount.incrementAndGet();
|
||||||
|
this.nextProcessor = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerApplicationMaster(
|
||||||
|
ApplicationAttemptId applicationAttemptId,
|
||||||
|
RegisterApplicationMasterRequest request,
|
||||||
|
RegisterApplicationMasterResponse response)
|
||||||
|
throws IOException, YarnException {
|
||||||
|
beforeRegCount.incrementAndGet();
|
||||||
|
nextProcessor.registerApplicationMaster(applicationAttemptId,
|
||||||
|
request, response);
|
||||||
|
afterRegCount.incrementAndGet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void allocate(ApplicationAttemptId appAttemptId,
|
||||||
|
AllocateRequest request, AllocateResponse response)
|
||||||
|
throws YarnException {
|
||||||
|
beforeAllocCount.incrementAndGet();
|
||||||
|
nextProcessor.allocate(appAttemptId, request, response);
|
||||||
|
afterAllocCount.incrementAndGet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finishApplicationMaster(
|
||||||
|
ApplicationAttemptId applicationAttemptId,
|
||||||
|
FinishApplicationMasterRequest request,
|
||||||
|
FinishApplicationMasterResponse response) {
|
||||||
|
beforeFinishCount.incrementAndGet();
|
||||||
|
nextProcessor.finishApplicationMaster(
|
||||||
|
applicationAttemptId, request, response);
|
||||||
|
afterFinishCount.incrementAndGet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static YarnConfiguration conf;
|
||||||
|
private static final int GB = 1024;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
conf = new YarnConfiguration();
|
||||||
|
conf.setClass(YarnConfiguration.RM_SCHEDULER, FifoScheduler.class,
|
||||||
|
ResourceScheduler.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300000)
|
||||||
|
public void testApplicationMasterInterceptor() throws Exception {
|
||||||
|
conf.set(YarnConfiguration.RM_APPLICATION_MASTER_SERVICE_PROCESSORS,
|
||||||
|
TestInterceptor1.class.getName() + ","
|
||||||
|
+ TestInterceptor2.class.getName());
|
||||||
|
MockRM rm = new MockRM(conf);
|
||||||
|
rm.start();
|
||||||
|
|
||||||
|
// Register node1
|
||||||
|
MockNM nm1 = rm.registerNode("127.0.0.1:1234", 6 * GB);
|
||||||
|
|
||||||
|
// Submit an application
|
||||||
|
RMApp app1 = rm.submitApp(2048);
|
||||||
|
|
||||||
|
// kick the scheduling
|
||||||
|
nm1.nodeHeartbeat(true);
|
||||||
|
RMAppAttempt attempt1 = app1.getCurrentAppAttempt();
|
||||||
|
MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId());
|
||||||
|
am1.registerAppAttempt();
|
||||||
|
int allocCount = 0;
|
||||||
|
|
||||||
|
am1.addRequests(new String[] {"127.0.0.1"}, GB, 1, 1);
|
||||||
|
AllocateResponse alloc1Response = am1.schedule(); // send the request
|
||||||
|
allocCount++;
|
||||||
|
|
||||||
|
// kick the scheduler
|
||||||
|
nm1.nodeHeartbeat(true);
|
||||||
|
while (alloc1Response.getAllocatedContainers().size() < 1) {
|
||||||
|
LOG.info("Waiting for containers to be created for app 1...");
|
||||||
|
sleep(1000);
|
||||||
|
alloc1Response = am1.schedule();
|
||||||
|
allocCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert RMIdentifier is set properly in allocated containers
|
||||||
|
Container allocatedContainer =
|
||||||
|
alloc1Response.getAllocatedContainers().get(0);
|
||||||
|
ContainerTokenIdentifier tokenId =
|
||||||
|
BuilderUtils.newContainerTokenIdentifier(allocatedContainer
|
||||||
|
.getContainerToken());
|
||||||
|
am1.unregisterAppAttempt();
|
||||||
|
|
||||||
|
Assert.assertEquals(1, beforeRegCount.get());
|
||||||
|
Assert.assertEquals(1, afterRegCount.get());
|
||||||
|
|
||||||
|
// The allocate calls should be incremented twice
|
||||||
|
Assert.assertEquals(allocCount * 2, beforeAllocCount.get());
|
||||||
|
Assert.assertEquals(allocCount * 2, afterAllocCount.get());
|
||||||
|
|
||||||
|
// Finish should only be called once, since the FirstInterceptor
|
||||||
|
// does not forward the call.
|
||||||
|
Assert.assertEquals(1, beforeFinishCount.get());
|
||||||
|
Assert.assertEquals(1, afterFinishCount.get());
|
||||||
|
rm.stop();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue