|
@@ -20,20 +20,29 @@ package org.apache.hadoop.yarn.server.resourcemanager;
|
|
|
|
|
|
import static java.lang.Thread.sleep;
|
|
|
|
|
|
+import java.io.IOException;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
import java.util.EnumSet;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
|
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;
|
|
@@ -44,6 +53,7 @@ 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.YarnException;
|
|
|
import org.apache.hadoop.yarn.proto.YarnServiceProtos.SchedulerResourceTypes;
|
|
|
import org.apache.hadoop.yarn.security.ContainerTokenIdentifier;
|
|
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
|
|
@@ -61,7 +71,7 @@ import org.apache.hadoop.yarn.server.utils.BuilderUtils;
|
|
|
import org.apache.hadoop.yarn.util.resource.DominantResourceCalculator;
|
|
|
import org.apache.hadoop.yarn.util.resource.Resources;
|
|
|
import org.junit.Assert;
|
|
|
-import org.junit.BeforeClass;
|
|
|
+import org.junit.Before;
|
|
|
import org.junit.Test;
|
|
|
|
|
|
public class TestApplicationMasterService {
|
|
@@ -71,13 +81,160 @@ public class TestApplicationMasterService {
|
|
|
private final int GB = 1024;
|
|
|
private static YarnConfiguration conf;
|
|
|
|
|
|
- @BeforeClass
|
|
|
- public static void setup() {
|
|
|
+ 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 {
|
|
|
+ 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 {
|
|
|
+ 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);
|