List<ResourceRequest> requestedContainers;
List<ContainerId> releasedContainers
AllocateRequest req = Records.newRecord(AllocateRequest.class);
// The response id set in the request will be sent back in
// the response so that the ApplicationMaster can
// match it to its original ask and act appropriately.
req.setResponseId(rmRequestID);
// Set ApplicationAttemptId
req.setApplicationAttemptId(appAttemptID);
// Add the list of containers being asked for
req.addAllAsks(requestedContainers);
// If the ApplicationMaster has no need for certain
// containers due to over-allocation or for any other
// reason, it can release them back to the ResourceManager
req.addAllReleases(releasedContainers);
// Assuming the ApplicationMaster can track its progress
req.setProgress(currentProgress);
AllocateResponse allocateResponse = resourceManager.allocate(req);
// Retrieve list of allocated containers from the response
// and on each allocated container, lets assume we are launching
// the same job.
List<Container> allocatedContainers = allocateResponse.getAllocatedContainers();
for (Container allocatedContainer : allocatedContainers) {
LOG.info("Launching shell command on a new container."
+ ", containerId=" + allocatedContainer.getId()
+ ", containerNode=" + allocatedContainer.getNodeId().getHost()
+ ":" + allocatedContainer.getNodeId().getPort()
+ ", containerNodeURI=" + allocatedContainer.getNodeHttpAddress()
+ ", containerState" + allocatedContainer.getState()
+ ", containerResourceMemory"
+ allocatedContainer.getResource().getMemory());
// Launch and start the container on a separate thread to keep the main
// thread unblocked as all containers may not be allocated at one go.
LaunchContainerRunnable runnableLaunchContainer =
new LaunchContainerRunnable(allocatedContainer);
Thread launchThread = new Thread(runnableLaunchContainer);
launchThreads.add(launchThread);
launchThread.start();
}
// Check what the current available resources in the cluster are
Resource availableResources = allocateResponse.getAvailableResources();
// Based on this information, an ApplicationMaster can make appropriate
// decisions
// Check the completed containers
// Let's assume we are keeping a count of total completed containers,
// containers that failed and ones that completed successfully.
List<ContainerStatus> completedContainers =
allocateResponse.getCompletedContainersStatuses();
for (ContainerStatus containerStatus : completedContainers) {
LOG.info("Got container status for containerID= "
+ containerStatus.getContainerId()
+ ", state=" + containerStatus.getState()
+ ", exitStatus=" + containerStatus.getExitStatus()
+ ", diagnostics=" + containerStatus.getDiagnostics());
int exitStatus = containerStatus.getExitStatus();
if (0 != exitStatus) {
// container failed
// -100 is a special case where the container
// was aborted/pre-empted for some reason
if (-100 != exitStatus) {
// application job on container returned a non-zero exit code
// counts as completed
numCompletedContainers.incrementAndGet();
numFailedContainers.incrementAndGet();
}
else {
// something else bad happened
// app job did not complete for some reason
// we should re-try as the container was lost for some reason
// decrementing the requested count so that we ask for an
// additional one in the next allocate call.
numRequestedContainers.decrementAndGet();
// we do not need to release the container as that has already
// been done by the ResourceManager/NodeManager.
}
}
else {
// nothing to do
// container completed successfully
numCompletedContainers.incrementAndGet();
numSuccessfulContainers.incrementAndGet();
}
}
}
//Assuming an allocated Container obtained from AllocateResponse
Container container;
// Connect to ContainerManager on the allocated container
String cmIpPortStr = container.getNodeId().getHost() + ":"
+ container.getNodeId().getPort();
InetSocketAddress cmAddress = NetUtils.createSocketAddr(cmIpPortStr);
ContainerManager cm =
(ContainerManager)rpc.getProxy(ContainerManager.class, cmAddress, conf);
// Now we setup a ContainerLaunchContext
ContainerLaunchContext ctx =
Records.newRecord(ContainerLaunchContext.class);
ctx.setContainerId(container.getId());
ctx.setResource(container.getResource());
try {
ctx.setUser(UserGroupInformation.getCurrentUser().getShortUserName());
} catch (IOException e) {
LOG.info(
"Getting current user failed when trying to launch the container",
+ e.getMessage());
}
// Set the environment
Map<String, String> unixEnv;
// Setup the required env.
// Please note that the launched container does not inherit
// the environment of the ApplicationMaster so all the
// necessary environment settings will need to be re-setup
// for this allocated container.
ctx.setEnvironment(unixEnv);
// Set the local resources
Map<String, LocalResource> localResources =
new HashMap<String, LocalResource>();
// Again, the local resources from the ApplicationMaster is not copied over
// by default to the allocated container. Thus, it is the responsibility
// of the ApplicationMaster to setup all the necessary local resources
// needed by the job that will be executed on the allocated container.
// Assume that we are executing a shell script on the allocated container
// and the shell script's location in the filesystem is known to us.
Path shellScriptPath;
LocalResource shellRsrc = Records.newRecord(LocalResource.class);
shellRsrc.setType(LocalResourceType.FILE);
shellRsrc.setVisibility(LocalResourceVisibility.APPLICATION);
shellRsrc.setResource(
ConverterUtils.getYarnUrlFromURI(new URI(shellScriptPath)));
shellRsrc.setTimestamp(shellScriptPathTimestamp);
shellRsrc.setSize(shellScriptPathLen);
localResources.put("MyExecShell.sh", shellRsrc);
ctx.setLocalResources(localResources);
// Set the necessary command to execute on the allocated container
String command = "/bin/sh ./MyExecShell.sh"
+ " 1>" + ApplicationConstants.LOG_DIR_EXPANSION_VAR + "/stdout"
+ " 2>" + ApplicationConstants.LOG_DIR_EXPANSION_VAR + "/stderr";
List<String> commands = new ArrayList<String>();
commands.add(command);
ctx.setCommands(commands);
// Send the start request to the ContainerManager
StartContainerRequest startReq = Records.newRecord(StartContainerRequest.class);
startReq.setContainerLaunchContext(ctx);
cm.startContainer(startReq);