/** * 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 java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.yarn.api.ApplicationConstants; import org.apache.hadoop.yarn.api.ContainerManager; import org.apache.hadoop.yarn.api.protocolrecords.GetContainerStatusRequest; import org.apache.hadoop.yarn.api.protocolrecords.GetContainerStatusResponse; import org.apache.hadoop.yarn.api.protocolrecords.StartContainerRequest; import org.apache.hadoop.yarn.api.protocolrecords.StartContainerResponse; import org.apache.hadoop.yarn.api.protocolrecords.StopContainerRequest; import org.apache.hadoop.yarn.api.protocolrecords.StopContainerResponse; import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; import org.apache.hadoop.yarn.api.records.ContainerId; import org.apache.hadoop.yarn.exceptions.YarnRemoteException; import org.apache.hadoop.yarn.server.resourcemanager.amlauncher.AMLauncher; 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.attempt.RMAppAttempt; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptState; import org.apache.hadoop.yarn.util.ConverterUtils; import org.apache.log4j.Level; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.junit.Assert; import org.junit.Test; public class TestApplicationMasterLauncher { private static final Log LOG = LogFactory .getLog(TestApplicationMasterLauncher.class); private static final class MyContainerManagerImpl implements ContainerManager { boolean launched = false; boolean cleanedup = false; String attemptIdAtContainerManager = null; String containerIdAtContainerManager = null; String nmHostAtContainerManager = null; int nmPortAtContainerManager; int nmHttpPortAtContainerManager; long submitTimeAtContainerManager; @Override public StartContainerResponse startContainer(StartContainerRequest request) throws YarnRemoteException { LOG.info("Container started by MyContainerManager: " + request); launched = true; Map<String, String> env = request.getContainerLaunchContext().getEnvironment(); containerIdAtContainerManager = env.get(ApplicationConstants.AM_CONTAINER_ID_ENV); ContainerId containerId = ConverterUtils.toContainerId(containerIdAtContainerManager); attemptIdAtContainerManager = containerId.getApplicationAttemptId().toString(); nmHostAtContainerManager = env.get(ApplicationConstants.NM_HOST_ENV); nmPortAtContainerManager = Integer.parseInt(env.get(ApplicationConstants.NM_PORT_ENV)); nmHttpPortAtContainerManager = Integer.parseInt(env.get(ApplicationConstants.NM_HTTP_PORT_ENV)); submitTimeAtContainerManager = Long.parseLong(env.get(ApplicationConstants.APP_SUBMIT_TIME_ENV)); return null; } @Override public StopContainerResponse stopContainer(StopContainerRequest request) throws YarnRemoteException { LOG.info("Container cleaned up by MyContainerManager"); cleanedup = true; return null; } @Override public GetContainerStatusResponse getContainerStatus( GetContainerStatusRequest request) throws YarnRemoteException { return null; } } static class MockRMWithCustomAMLauncher extends MockRM { private final ContainerManager containerManager; public MockRMWithCustomAMLauncher(ContainerManager containerManager) { this(new Configuration(), containerManager); } public MockRMWithCustomAMLauncher(Configuration conf, ContainerManager containerManager) { super(conf); this.containerManager = containerManager; } @Override protected ApplicationMasterLauncher createAMLauncher() { return new ApplicationMasterLauncher(super.clientToAMSecretManager, getRMContext()) { @Override protected Runnable createRunnableLauncher(RMAppAttempt application, AMLauncherEventType event) { return new AMLauncher(context, application, event, clientToAMSecretManager, getConfig()) { @Override protected ContainerManager getContainerMgrProxy( ContainerId containerId) { return containerManager; } }; } }; } } @Test public void testAMLaunchAndCleanup() throws Exception { Logger rootLogger = LogManager.getRootLogger(); rootLogger.setLevel(Level.DEBUG); MyContainerManagerImpl containerManager = new MyContainerManagerImpl(); MockRMWithCustomAMLauncher rm = new MockRMWithCustomAMLauncher( containerManager); rm.start(); MockNM nm1 = rm.registerNode("h1:1234", 5120); RMApp app = rm.submitApp(2000); // kick the scheduling nm1.nodeHeartbeat(true); int waitCount = 0; while (containerManager.launched == false && waitCount++ < 20) { LOG.info("Waiting for AM Launch to happen.."); Thread.sleep(1000); } Assert.assertTrue(containerManager.launched); RMAppAttempt attempt = app.getCurrentAppAttempt(); ApplicationAttemptId appAttemptId = attempt.getAppAttemptId(); Assert.assertEquals(appAttemptId.toString(), containerManager.attemptIdAtContainerManager); Assert.assertEquals(app.getSubmitTime(), containerManager.submitTimeAtContainerManager); Assert.assertEquals(app.getRMAppAttempt(appAttemptId) .getSubmissionContext().getAMContainerSpec().getContainerId() .toString(), containerManager.containerIdAtContainerManager); Assert.assertEquals(nm1.getNodeId().getHost(), containerManager.nmHostAtContainerManager); Assert.assertEquals(nm1.getNodeId().getPort(), containerManager.nmPortAtContainerManager); Assert.assertEquals(nm1.getHttpPort(), containerManager.nmHttpPortAtContainerManager); MockAM am = new MockAM(rm.getRMContext(), rm .getApplicationMasterService(), appAttemptId); am.registerAppAttempt(); am.unregisterAppAttempt(); waitCount = 0; while (containerManager.cleanedup == false && waitCount++ < 20) { LOG.info("Waiting for AM Cleanup to happen.."); Thread.sleep(1000); } Assert.assertTrue(containerManager.cleanedup); am.waitForState(RMAppAttemptState.FINISHED); rm.stop(); } }