diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/amlauncher/AMLauncher.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/amlauncher/AMLauncher.java index 7051f8c..cdf36f3 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/amlauncher/AMLauncher.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/amlauncher/AMLauncher.java @@ -101,16 +101,23 @@ private void connect() throws IOException { containerMgrProxy = getContainerMgrProxy(masterContainerID); } - private void launch() throws IOException, YarnException { + @Private + @VisibleForTesting + protected void launch() throws IOException, YarnException { connect(); ContainerId masterContainerID = masterContainer.getId(); ApplicationSubmissionContext applicationContext = - application.getSubmissionContext(); + application.getSubmissionContext(); LOG.info("Setting up container " + masterContainer + " for AM " + application.getAppAttemptId()); ContainerLaunchContext launchContext = createAMContainerLaunchContext(applicationContext, masterContainerID); + if (launchContext == null) { + throw new YarnException(masterContainerID + + " hbas beed cleaned before launched"); + } + StartContainerRequest scRequest = StartContainerRequest.newInstance(launchContext, masterContainer.getContainerToken()); @@ -189,10 +196,12 @@ private ContainerLaunchContext createAMContainerLaunchContext( ContainerLaunchContext container = applicationMasterContext.getAMContainerSpec(); - // Finalize the container - setupTokens(container, containerID); - // set the flow context optionally for timeline service v.2 - setFlowContext(container); + if (container != null) { + // Finalize the container + setupTokens(container, containerID); + // set the flow context optionally for timeline service v.2 + setFlowContext(container); + } return container; } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestApplicationMasterLauncher.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestApplicationMasterLauncher.java index 172993b..af534e9 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestApplicationMasterLauncher.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestApplicationMasterLauncher.java @@ -30,6 +30,7 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.io.DataOutputBuffer; import org.apache.hadoop.security.Credentials; +import org.apache.hadoop.util.StringUtils; import org.apache.hadoop.yarn.api.ApplicationConstants; import org.apache.hadoop.yarn.api.ContainerManagementProtocol; import org.apache.hadoop.yarn.api.protocolrecords.AllocateResponse; @@ -73,7 +74,9 @@ import org.apache.hadoop.yarn.server.resourcemanager.amlauncher.AMLauncherEventType; import org.apache.hadoop.yarn.server.resourcemanager.amlauncher.ApplicationMasterLauncher; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppState; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttempt; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptImpl; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptState; import org.apache.hadoop.yarn.server.utils.AMRMClientUtils; import org.apache.hadoop.yarn.server.utils.BuilderUtils; @@ -257,6 +260,38 @@ public void testAMLaunchAndCleanup() throws Exception { rm.stop(); } + @Test(timeout = 100000) + public void testAMCleanupBeforeLaunch() throws Exception{ + @SuppressWarnings("resource") + MockRM rm = new MockRM(); + rm.start(); + MockNM nm1 = rm.registerNode("h1:1234", 5000); + RMApp app = rm.submitApp(2000); + // kick the scheduling + nm1.nodeHeartbeat(true); + RMAppAttemptImpl attempt = (RMAppAttemptImpl) app.getCurrentAppAttempt(); + //wait allocate container for attempt + while (attempt.getMasterContainer()==null){ + LOG.info("Waiting for AM container allocate.."); + Thread.sleep(1000); + } + //send kill before Launch + rm.killApp(app.getApplicationId()); + rm.waitForState(app.getApplicationId(), RMAppState.KILLED); + //Launch after kill + MyAMLauncher launcher = new MyAMLauncher(rm.getRMContext(), + attempt, AMLauncherEventType.LAUNCH, rm.getConfig()); + try{ + launcher.launch(); + }catch (YarnException e) { + LOG.info("Catch the YarnException " + + StringUtils.stringifyException(e)); + }catch (Exception e) { + Assert.assertTrue("Unexpected exception " + + StringUtils.stringifyException(e), false); + } + } + @Test public void testRetriesOnFailures() throws Exception { final ContainerManagementProtocol mockProxy = @@ -303,7 +338,7 @@ protected YarnRPC getYarnRPC() { rm.drainEvents(); MockRM.waitForState(app.getCurrentAppAttempt(), - RMAppAttemptState.LAUNCHED, 500); + RMAppAttemptState.LAUNCHED, 500); } @@ -422,5 +457,9 @@ protected void setupTokens(ContainerLaunchContext container, ContainerId containerID) throws IOException { super.setupTokens(container, containerID); } + + protected void launch() throws IOException, YarnException { + super.launch(); + } } }