PageRenderTime 30ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/amlauncher/AMLauncher.java

https://github.com/rbodkin/hadoop-common
Java | 288 lines | 230 code | 31 blank | 27 comment | 6 complexity | 262aaf46029a530115587eb2bdf4beff MD5 | raw file
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. package org.apache.hadoop.yarn.server.resourcemanager.amlauncher;
  19. import java.io.IOException;
  20. import java.net.InetSocketAddress;
  21. import java.nio.ByteBuffer;
  22. import java.security.PrivilegedAction;
  23. import java.util.ArrayList;
  24. import java.util.HashMap;
  25. import java.util.List;
  26. import java.util.Map;
  27. import javax.crypto.SecretKey;
  28. import org.apache.commons.codec.binary.Base64;
  29. import org.apache.commons.logging.Log;
  30. import org.apache.commons.logging.LogFactory;
  31. import org.apache.hadoop.conf.Configuration;
  32. import org.apache.hadoop.io.DataInputByteBuffer;
  33. import org.apache.hadoop.io.DataOutputBuffer;
  34. import org.apache.hadoop.io.Text;
  35. import org.apache.hadoop.net.NetUtils;
  36. import org.apache.hadoop.security.Credentials;
  37. import org.apache.hadoop.security.SecurityInfo;
  38. import org.apache.hadoop.security.UserGroupInformation;
  39. import org.apache.hadoop.security.token.Token;
  40. import org.apache.hadoop.util.StringUtils;
  41. import org.apache.hadoop.yarn.api.ApplicationConstants;
  42. import org.apache.hadoop.yarn.api.ContainerManager;
  43. import org.apache.hadoop.yarn.api.protocolrecords.StartContainerRequest;
  44. import org.apache.hadoop.yarn.api.protocolrecords.StopContainerRequest;
  45. import org.apache.hadoop.yarn.api.records.ApplicationId;
  46. import org.apache.hadoop.yarn.api.records.ApplicationSubmissionContext;
  47. import org.apache.hadoop.yarn.api.records.Container;
  48. import org.apache.hadoop.yarn.api.records.ContainerId;
  49. import org.apache.hadoop.yarn.api.records.ContainerLaunchContext;
  50. import org.apache.hadoop.yarn.api.records.ContainerToken;
  51. import org.apache.hadoop.yarn.conf.YarnConfiguration;
  52. import org.apache.hadoop.yarn.event.EventHandler;
  53. import org.apache.hadoop.yarn.factories.RecordFactory;
  54. import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
  55. import org.apache.hadoop.yarn.ipc.YarnRPC;
  56. import org.apache.hadoop.yarn.security.ApplicationTokenIdentifier;
  57. import org.apache.hadoop.yarn.security.ApplicationTokenSecretManager;
  58. import org.apache.hadoop.yarn.security.ContainerManagerSecurityInfo;
  59. import org.apache.hadoop.yarn.security.ContainerTokenIdentifier;
  60. import org.apache.hadoop.yarn.security.client.ClientToAMSecretManager;
  61. import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
  62. import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttempt;
  63. import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptEvent;
  64. import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptEventType;
  65. import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.event.RMAppAttemptLaunchFailedEvent;
  66. /**
  67. * The launch of the AM itself.
  68. */
  69. public class AMLauncher implements Runnable {
  70. private static final Log LOG = LogFactory.getLog(AMLauncher.class);
  71. private ContainerManager containerMgrProxy;
  72. private final RMAppAttempt application;
  73. private final Configuration conf;
  74. private final RecordFactory recordFactory = RecordFactoryProvider.getRecordFactory(null);
  75. private final ApplicationTokenSecretManager applicationTokenSecretManager;
  76. private final ClientToAMSecretManager clientToAMSecretManager;
  77. private final AMLauncherEventType eventType;
  78. @SuppressWarnings("rawtypes")
  79. private final EventHandler handler;
  80. @SuppressWarnings("unchecked")
  81. public AMLauncher(RMContext rmContext, RMAppAttempt application,
  82. AMLauncherEventType eventType,ApplicationTokenSecretManager applicationTokenSecretManager,
  83. ClientToAMSecretManager clientToAMSecretManager, Configuration conf) {
  84. this.application = application;
  85. this.conf = new Configuration(conf); // Just not to touch the sec-info class
  86. this.applicationTokenSecretManager = applicationTokenSecretManager;
  87. this.clientToAMSecretManager = clientToAMSecretManager;
  88. this.conf.setClass(
  89. YarnConfiguration.YARN_SECURITY_INFO,
  90. ContainerManagerSecurityInfo.class, SecurityInfo.class);
  91. this.eventType = eventType;
  92. this.handler = rmContext.getDispatcher().getEventHandler();
  93. }
  94. private void connect() throws IOException {
  95. ContainerId masterContainerID = application.getMasterContainer().getId();
  96. containerMgrProxy =
  97. getContainerMgrProxy(masterContainerID.getAppId());
  98. }
  99. private void launch() throws IOException {
  100. connect();
  101. ContainerId masterContainerID = application.getMasterContainer().getId();
  102. ApplicationSubmissionContext applicationContext =
  103. application.getSubmissionContext();
  104. LOG.info("Setting up container " + application.getMasterContainer()
  105. + " for AM " + application.getAppAttemptId());
  106. ContainerLaunchContext launchContext =
  107. createAMContainerLaunchContext(applicationContext, masterContainerID);
  108. StartContainerRequest request = recordFactory.newRecordInstance(StartContainerRequest.class);
  109. request.setContainerLaunchContext(launchContext);
  110. containerMgrProxy.startContainer(request);
  111. LOG.info("Done launching container " + application.getMasterContainer()
  112. + " for AM " + application.getAppAttemptId());
  113. }
  114. private void cleanup() throws IOException {
  115. connect();
  116. ContainerId containerId = application.getMasterContainer().getId();
  117. StopContainerRequest stopRequest = recordFactory.newRecordInstance(StopContainerRequest.class);
  118. stopRequest.setContainerId(containerId);
  119. containerMgrProxy.stopContainer(stopRequest);
  120. }
  121. private ContainerManager getContainerMgrProxy(
  122. final ApplicationId applicationID) throws IOException {
  123. Container container = application.getMasterContainer();
  124. final String containerManagerBindAddress = container.getNodeId().toString();
  125. final YarnRPC rpc = YarnRPC.create(conf); // TODO: Don't create again and again.
  126. UserGroupInformation currentUser =
  127. UserGroupInformation.createRemoteUser("TODO"); // TODO
  128. if (UserGroupInformation.isSecurityEnabled()) {
  129. ContainerToken containerToken = container.getContainerToken();
  130. Token<ContainerTokenIdentifier> token =
  131. new Token<ContainerTokenIdentifier>(
  132. containerToken.getIdentifier().array(),
  133. containerToken.getPassword().array(), new Text(
  134. containerToken.getKind()), new Text(
  135. containerToken.getService()));
  136. currentUser.addToken(token);
  137. }
  138. return currentUser.doAs(new PrivilegedAction<ContainerManager>() {
  139. @Override
  140. public ContainerManager run() {
  141. return (ContainerManager) rpc.getProxy(ContainerManager.class,
  142. NetUtils.createSocketAddr(containerManagerBindAddress), conf);
  143. }
  144. });
  145. }
  146. private ContainerLaunchContext createAMContainerLaunchContext(
  147. ApplicationSubmissionContext applicationMasterContext,
  148. ContainerId containerID) throws IOException {
  149. // Construct the actual Container
  150. ContainerLaunchContext container = recordFactory.newRecordInstance(ContainerLaunchContext.class);
  151. container.addAllCommands(applicationMasterContext.getCommandList());
  152. StringBuilder mergedCommand = new StringBuilder();
  153. String failCount = Integer.toString(application.getAppAttemptId()
  154. .getAttemptId());
  155. List<String> commandList = new ArrayList<String>();
  156. for (String str : container.getCommandList()) {
  157. // This is out-right wrong. AM FAIL count should be passed via env.
  158. String result =
  159. str.replaceFirst(ApplicationConstants.AM_FAIL_COUNT_STRING,
  160. failCount);
  161. mergedCommand.append(result).append(" ");
  162. commandList.add(result);
  163. }
  164. container.clearCommands();
  165. container.addAllCommands(commandList);
  166. /** add the failed count to the app master command line */
  167. LOG.info("Command to launch container " +
  168. containerID + " : " + mergedCommand);
  169. container.addAllEnv(applicationMasterContext.getAllEnvironment());
  170. container.addAllEnv(setupTokensInEnv(applicationMasterContext));
  171. // Construct the actual Container
  172. container.setContainerId(containerID);
  173. container.setUser(applicationMasterContext.getUser());
  174. container.setResource(applicationMasterContext.getMasterCapability());
  175. container.addAllLocalResources(applicationMasterContext.getAllResourcesTodo());
  176. container.setContainerTokens(applicationMasterContext.getFsTokensTodo());
  177. return container;
  178. }
  179. private Map<String, String> setupTokensInEnv(
  180. ApplicationSubmissionContext asc)
  181. throws IOException {
  182. Map<String, String> env =
  183. new HashMap<String, String>();
  184. if (UserGroupInformation.isSecurityEnabled()) {
  185. // TODO: Security enabled/disabled info should come from RM.
  186. Credentials credentials = new Credentials();
  187. DataInputByteBuffer dibb = new DataInputByteBuffer();
  188. if (asc.getFsTokensTodo() != null) {
  189. // TODO: Don't do this kind of checks everywhere.
  190. dibb.reset(asc.getFsTokensTodo());
  191. credentials.readTokenStorageStream(dibb);
  192. }
  193. ApplicationTokenIdentifier id = new ApplicationTokenIdentifier(
  194. application.getAppAttemptId().getApplicationId());
  195. Token<ApplicationTokenIdentifier> token =
  196. new Token<ApplicationTokenIdentifier>(id,
  197. this.applicationTokenSecretManager);
  198. String schedulerAddressStr =
  199. this.conf.get(YarnConfiguration.RM_SCHEDULER_ADDRESS,
  200. YarnConfiguration.DEFAULT_RM_SCHEDULER_ADDRESS);
  201. InetSocketAddress unresolvedAddr =
  202. NetUtils.createSocketAddr(schedulerAddressStr);
  203. String resolvedAddr =
  204. unresolvedAddr.getAddress().getHostAddress() + ":"
  205. + unresolvedAddr.getPort();
  206. token.setService(new Text(resolvedAddr));
  207. String appMasterTokenEncoded = token.encodeToUrlString();
  208. LOG.debug("Putting appMaster token in env : " + appMasterTokenEncoded);
  209. env.put(ApplicationConstants.APPLICATION_MASTER_TOKEN_ENV_NAME,
  210. appMasterTokenEncoded);
  211. // Add the RM token
  212. credentials.addToken(new Text(resolvedAddr), token);
  213. DataOutputBuffer dob = new DataOutputBuffer();
  214. credentials.writeTokenStorageToStream(dob);
  215. asc.setFsTokensTodo(ByteBuffer.wrap(dob.getData(), 0, dob.getLength()));
  216. ApplicationTokenIdentifier identifier = new ApplicationTokenIdentifier(
  217. application.getAppAttemptId().getApplicationId());
  218. SecretKey clientSecretKey =
  219. this.clientToAMSecretManager.getMasterKey(identifier);
  220. String encoded =
  221. Base64.encodeBase64URLSafeString(clientSecretKey.getEncoded());
  222. LOG.debug("The encoded client secret-key to be put in env : " + encoded);
  223. env.put(ApplicationConstants.APPLICATION_CLIENT_SECRET_ENV_NAME, encoded);
  224. }
  225. return env;
  226. }
  227. @SuppressWarnings("unchecked")
  228. public void run() {
  229. switch (eventType) {
  230. case LAUNCH:
  231. try {
  232. LOG.info("Launching master" + application.getAppAttemptId());
  233. launch();
  234. handler.handle(new RMAppAttemptEvent(application.getAppAttemptId(),
  235. RMAppAttemptEventType.LAUNCHED));
  236. } catch(Exception ie) {
  237. String message = "Error launching " + application.getAppAttemptId()
  238. + ". Got exception: " + StringUtils.stringifyException(ie);
  239. LOG.info(message);
  240. handler.handle(new RMAppAttemptLaunchFailedEvent(application
  241. .getAppAttemptId(), message));
  242. }
  243. break;
  244. case CLEANUP:
  245. try {
  246. LOG.info("Cleaning master " + application.getAppAttemptId());
  247. cleanup();
  248. } catch(IOException ie) {
  249. LOG.info("Error cleaning master ", ie);
  250. }
  251. break;
  252. default:
  253. LOG.warn("Received unknown event-type " + eventType + ". Ignoring.");
  254. break;
  255. }
  256. }
  257. }