YARN-5124. Modify AMRMClient to set the ExecutionType in the ResourceRequest. (asuresh)

(cherry picked from commit 5143277958)
This commit is contained in:
Arun Suresh 2016-06-12 09:42:38 -07:00
parent 5985221b46
commit fccb641942
11 changed files with 1191 additions and 573 deletions

View File

@ -35,6 +35,7 @@ import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterRespo
import org.apache.hadoop.yarn.api.records.Container; import org.apache.hadoop.yarn.api.records.Container;
import org.apache.hadoop.yarn.api.records.ContainerId; import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.api.records.ExecutionType; import org.apache.hadoop.yarn.api.records.ExecutionType;
import org.apache.hadoop.yarn.api.records.ExecutionTypeRequest;
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus; import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
import org.apache.hadoop.yarn.api.records.Priority; import org.apache.hadoop.yarn.api.records.Priority;
import org.apache.hadoop.yarn.api.records.Resource; import org.apache.hadoop.yarn.api.records.Resource;
@ -109,7 +110,7 @@ public abstract class AMRMClient<T extends AMRMClient.ContainerRequest> extends
final Priority priority; final Priority priority;
final boolean relaxLocality; final boolean relaxLocality;
final String nodeLabelsExpression; final String nodeLabelsExpression;
final ExecutionType executionType; final ExecutionTypeRequest executionTypeRequest;
/** /**
* Instantiates a {@link ContainerRequest} with the given constraints and * Instantiates a {@link ContainerRequest} with the given constraints and
@ -180,7 +181,7 @@ public abstract class AMRMClient<T extends AMRMClient.ContainerRequest> extends
Priority priority, boolean relaxLocality, String nodeLabelsExpression) { Priority priority, boolean relaxLocality, String nodeLabelsExpression) {
this(capability, nodes, racks, priority, relaxLocality, this(capability, nodes, racks, priority, relaxLocality,
nodeLabelsExpression, nodeLabelsExpression,
ExecutionType.GUARANTEED); ExecutionTypeRequest.newInstance());
} }
/** /**
@ -203,12 +204,12 @@ public abstract class AMRMClient<T extends AMRMClient.ContainerRequest> extends
* @param nodeLabelsExpression * @param nodeLabelsExpression
* Set node labels to allocate resource, now we only support * Set node labels to allocate resource, now we only support
* asking for only a single node label * asking for only a single node label
* @param executionType * @param executionTypeRequest
* Set the execution type of the container request. * Set the execution type of the container request.
*/ */
public ContainerRequest(Resource capability, String[] nodes, String[] racks, public ContainerRequest(Resource capability, String[] nodes, String[] racks,
Priority priority, boolean relaxLocality, String nodeLabelsExpression, Priority priority, boolean relaxLocality, String nodeLabelsExpression,
ExecutionType executionType) { ExecutionTypeRequest executionTypeRequest) {
// Validate request // Validate request
Preconditions.checkArgument(capability != null, Preconditions.checkArgument(capability != null,
"The Resource to be requested for each container " + "The Resource to be requested for each container " +
@ -226,7 +227,7 @@ public abstract class AMRMClient<T extends AMRMClient.ContainerRequest> extends
this.priority = priority; this.priority = priority;
this.relaxLocality = relaxLocality; this.relaxLocality = relaxLocality;
this.nodeLabelsExpression = nodeLabelsExpression; this.nodeLabelsExpression = nodeLabelsExpression;
this.executionType = executionType; this.executionTypeRequest = executionTypeRequest;
} }
public Resource getCapability() { public Resource getCapability() {
@ -253,15 +254,16 @@ public abstract class AMRMClient<T extends AMRMClient.ContainerRequest> extends
return nodeLabelsExpression; return nodeLabelsExpression;
} }
public ExecutionType getExecutionType() { public ExecutionTypeRequest getExecutionTypeRequest() {
return executionType; return executionTypeRequest;
} }
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("Capability[").append(capability).append("]"); sb.append("Capability[").append(capability).append("]");
sb.append("Priority[").append(priority).append("]"); sb.append("Priority[").append(priority).append("]");
sb.append("ExecutionType[").append(executionType).append("]"); sb.append("ExecutionTypeRequest[").append(executionTypeRequest)
.append("]");
return sb.toString(); return sb.toString();
} }
} }
@ -388,10 +390,35 @@ public abstract class AMRMClient<T extends AMRMClient.ContainerRequest> extends
* collection, requests will be returned in the same order as they were added. * collection, requests will be returned in the same order as they were added.
* @return Collection of request matching the parameters * @return Collection of request matching the parameters
*/ */
@InterfaceStability.Evolving
public abstract List<? extends Collection<T>> getMatchingRequests( public abstract List<? extends Collection<T>> getMatchingRequests(
Priority priority, Priority priority,
String resourceName, String resourceName,
Resource capability); Resource capability);
/**
* Get outstanding <code>ContainerRequest</code>s matching the given
* parameters. These ContainerRequests should have been added via
* <code>addContainerRequest</code> earlier in the lifecycle. For performance,
* the AMRMClient may return its internal collection directly without creating
* a copy. Users should not perform mutable operations on the return value.
* Each collection in the list contains requests with identical
* <code>Resource</code> size that fit in the given capability. In a
* collection, requests will be returned in the same order as they were added.
* specify an <code>ExecutionType</code> .
* @param priority Priority
* @param resourceName Location
* @param executionType ExecutionType
* @param capability Capability
* @return Collection of request matching the parameters
*/
@InterfaceStability.Evolving
public List<? extends Collection<T>> getMatchingRequests(
Priority priority, String resourceName, ExecutionType executionType,
Resource capability) {
throw new UnsupportedOperationException("The sub-class extending" +
" AMRMClient is expected to implement this !!");
}
/** /**
* Update application's blacklist with addition or removal resources. * Update application's blacklist with addition or removal resources.

View File

@ -35,6 +35,7 @@ import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterRespo
import org.apache.hadoop.yarn.api.records.Container; import org.apache.hadoop.yarn.api.records.Container;
import org.apache.hadoop.yarn.api.records.ContainerId; import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.api.records.ContainerStatus; import org.apache.hadoop.yarn.api.records.ContainerStatus;
import org.apache.hadoop.yarn.api.records.ExecutionType;
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus; import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
import org.apache.hadoop.yarn.api.records.NodeReport; import org.apache.hadoop.yarn.api.records.NodeReport;
import org.apache.hadoop.yarn.api.records.Priority; import org.apache.hadoop.yarn.api.records.Priority;
@ -196,6 +197,22 @@ extends AbstractService {
Priority priority, Priority priority,
String resourceName, String resourceName,
Resource capability); Resource capability);
/**
* Returns all matching ContainerRequests that match the given Priority,
* ResourceName, ExecutionType and Capability.
* @param priority Priority.
* @param resourceName Location.
* @param executionType ExecutionType.
* @param capability Capability.
* @return All matching ContainerRequests
*/
public List<? extends Collection<T>> getMatchingRequests(
Priority priority, String resourceName, ExecutionType executionType,
Resource capability) {
return client.getMatchingRequests(priority, resourceName,
executionType, capability);
}
/** /**
* Registers this application master with the resource manager. On successful * Registers this application master with the resource manager. On successful

View File

@ -19,19 +19,19 @@
package org.apache.hadoop.yarn.client.api.impl; package org.apache.hadoop.yarn.client.api.impl;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.AbstractMap.SimpleEntry; import java.util.AbstractMap.SimpleEntry;
@ -54,6 +54,8 @@ import org.apache.hadoop.yarn.api.records.Container;
import org.apache.hadoop.yarn.api.records.ContainerId; import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.api.records.ContainerResourceChangeRequest; import org.apache.hadoop.yarn.api.records.ContainerResourceChangeRequest;
import org.apache.hadoop.yarn.api.records.ContainerStatus; import org.apache.hadoop.yarn.api.records.ContainerStatus;
import org.apache.hadoop.yarn.api.records.ExecutionType;
import org.apache.hadoop.yarn.api.records.ExecutionTypeRequest;
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus; import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
import org.apache.hadoop.yarn.api.records.NMToken; import org.apache.hadoop.yarn.api.records.NMToken;
import org.apache.hadoop.yarn.api.records.Priority; import org.apache.hadoop.yarn.api.records.Priority;
@ -102,7 +104,7 @@ public class AMRMClientImpl<T extends ContainerRequest> extends AMRMClient<T> {
protected final Set<String> blacklistAdditions = new HashSet<String>(); protected final Set<String> blacklistAdditions = new HashSet<String>();
protected final Set<String> blacklistRemovals = new HashSet<String>(); protected final Set<String> blacklistRemovals = new HashSet<String>();
class ResourceRequestInfo { static class ResourceRequestInfo<T> {
ResourceRequest remoteRequest; ResourceRequest remoteRequest;
LinkedHashSet<T> containerRequests; LinkedHashSet<T> containerRequests;
@ -115,11 +117,12 @@ public class AMRMClientImpl<T extends ContainerRequest> extends AMRMClient<T> {
} }
} }
/** /**
* Class compares Resource by memory then cpu in reverse order * Class compares Resource by memory then cpu in reverse order
*/ */
class ResourceReverseMemoryThenCpuComparator implements Comparator<Resource> { static class ResourceReverseMemoryThenCpuComparator implements
Comparator<Resource>, Serializable {
static final long serialVersionUID = 12345L;
@Override @Override
public int compare(Resource arg0, Resource arg1) { public int compare(Resource arg0, Resource arg1) {
long mem0 = arg0.getMemorySize(); long mem0 = arg0.getMemorySize();
@ -141,7 +144,7 @@ public class AMRMClientImpl<T extends ContainerRequest> extends AMRMClient<T> {
return -1; return -1;
} }
} }
static boolean canFit(Resource arg0, Resource arg1) { static boolean canFit(Resource arg0, Resource arg1) {
long mem0 = arg0.getMemorySize(); long mem0 = arg0.getMemorySize();
long mem1 = arg1.getMemorySize(); long mem1 = arg1.getMemorySize();
@ -150,17 +153,8 @@ public class AMRMClientImpl<T extends ContainerRequest> extends AMRMClient<T> {
return (mem0 <= mem1 && cpu0 <= cpu1); return (mem0 <= mem1 && cpu0 <= cpu1);
} }
//Key -> Priority final RemoteRequestsTable remoteRequestsTable = new RemoteRequestsTable<T>();
//Value -> Map
//Key->ResourceName (e.g., nodename, rackname, *)
//Value->Map
//Key->Resource Capability
//Value->ResourceRequest
protected final
Map<Priority, Map<String, TreeMap<Resource, ResourceRequestInfo>>>
remoteRequestsTable =
new TreeMap<Priority, Map<String, TreeMap<Resource, ResourceRequestInfo>>>();
protected final Set<ResourceRequest> ask = new TreeSet<ResourceRequest>( protected final Set<ResourceRequest> ask = new TreeSet<ResourceRequest>(
new org.apache.hadoop.yarn.api.records.ResourceRequest.ResourceRequestComparator()); new org.apache.hadoop.yarn.api.records.ResourceRequest.ResourceRequestComparator());
@ -185,6 +179,12 @@ public class AMRMClientImpl<T extends ContainerRequest> extends AMRMClient<T> {
super(AMRMClientImpl.class.getName()); super(AMRMClientImpl.class.getName());
} }
@VisibleForTesting
AMRMClientImpl(ApplicationMasterProtocol protocol) {
super(AMRMClientImpl.class.getName());
this.rmClient = protocol;
}
@Override @Override
protected void serviceInit(Configuration conf) throws Exception { protected void serviceInit(Configuration conf) throws Exception {
RackResolver.init(conf); RackResolver.init(conf);
@ -195,8 +195,10 @@ public class AMRMClientImpl<T extends ContainerRequest> extends AMRMClient<T> {
protected void serviceStart() throws Exception { protected void serviceStart() throws Exception {
final YarnConfiguration conf = new YarnConfiguration(getConfig()); final YarnConfiguration conf = new YarnConfiguration(getConfig());
try { try {
rmClient = if (rmClient == null) {
ClientRMProxy.createRMProxy(conf, ApplicationMasterProtocol.class); rmClient = ClientRMProxy.createRMProxy(
conf, ApplicationMasterProtocol.class);
}
} catch (IOException e) { } catch (IOException e) {
throw new YarnRuntimeException(e); throw new YarnRuntimeException(e);
} }
@ -263,7 +265,8 @@ public class AMRMClientImpl<T extends ContainerRequest> extends AMRMClient<T> {
// RPC layer is using it to send info across // RPC layer is using it to send info across
askList.add(ResourceRequest.newInstance(r.getPriority(), askList.add(ResourceRequest.newInstance(r.getPriority(),
r.getResourceName(), r.getCapability(), r.getNumContainers(), r.getResourceName(), r.getCapability(), r.getNumContainers(),
r.getRelaxLocality(), r.getNodeLabelExpression())); r.getRelaxLocality(), r.getNodeLabelExpression(),
r.getExecutionTypeRequest()));
} }
List<ContainerResourceChangeRequest> increaseList = new ArrayList<>(); List<ContainerResourceChangeRequest> increaseList = new ArrayList<>();
List<ContainerResourceChangeRequest> decreaseList = new ArrayList<>(); List<ContainerResourceChangeRequest> decreaseList = new ArrayList<>();
@ -315,13 +318,11 @@ public class AMRMClientImpl<T extends ContainerRequest> extends AMRMClient<T> {
synchronized (this) { synchronized (this) {
release.addAll(this.pendingRelease); release.addAll(this.pendingRelease);
blacklistAdditions.addAll(this.blacklistedNodes); blacklistAdditions.addAll(this.blacklistedNodes);
for (Map<String, TreeMap<Resource, ResourceRequestInfo>> rr : remoteRequestsTable @SuppressWarnings("unchecked")
.values()) { Iterator<ResourceRequestInfo<T>> reqIter =
for (Map<Resource, ResourceRequestInfo> capabalities : rr.values()) { remoteRequestsTable.iterator();
for (ResourceRequestInfo request : capabalities.values()) { while (reqIter.hasNext()) {
addResourceRequestToAsk(request.remoteRequest); addResourceRequestToAsk(reqIter.next().remoteRequest);
}
}
} }
change.putAll(this.pendingChange); change.putAll(this.pendingChange);
} }
@ -517,26 +518,28 @@ public class AMRMClientImpl<T extends ContainerRequest> extends AMRMClient<T> {
+ joiner.join(req.getNodes())); + joiner.join(req.getNodes()));
} }
for (String node : dedupedNodes) { for (String node : dedupedNodes) {
addResourceRequest(req.getPriority(), node, req.getCapability(), req, addResourceRequest(req.getPriority(), node,
true, req.getNodeLabelExpression()); req.getExecutionTypeRequest(), req.getCapability(), req, true,
req.getNodeLabelExpression());
} }
} }
for (String rack : dedupedRacks) { for (String rack : dedupedRacks) {
addResourceRequest(req.getPriority(), rack, req.getCapability(), req, addResourceRequest(req.getPriority(), rack, req.getExecutionTypeRequest(),
true, req.getNodeLabelExpression()); req.getCapability(), req, true, req.getNodeLabelExpression());
} }
// Ensure node requests are accompanied by requests for // Ensure node requests are accompanied by requests for
// corresponding rack // corresponding rack
for (String rack : inferredRacks) { for (String rack : inferredRacks) {
addResourceRequest(req.getPriority(), rack, req.getCapability(), req, addResourceRequest(req.getPriority(), rack, req.getExecutionTypeRequest(),
req.getRelaxLocality(), req.getNodeLabelExpression()); req.getCapability(), req, req.getRelaxLocality(),
req.getNodeLabelExpression());
} }
// Off-switch // Off-switch
addResourceRequest(req.getPriority(), ResourceRequest.ANY, addResourceRequest(req.getPriority(), ResourceRequest.ANY,
req.getCapability(), req, req.getRelaxLocality(), req.getNodeLabelExpression()); req.getExecutionTypeRequest(), req.getCapability(), req,
req.getRelaxLocality(), req.getNodeLabelExpression());
} }
@Override @Override
@ -552,16 +555,18 @@ public class AMRMClientImpl<T extends ContainerRequest> extends AMRMClient<T> {
// Update resource requests // Update resource requests
if (req.getNodes() != null) { if (req.getNodes() != null) {
for (String node : new HashSet<String>(req.getNodes())) { for (String node : new HashSet<String>(req.getNodes())) {
decResourceRequest(req.getPriority(), node, req.getCapability(), req); decResourceRequest(req.getPriority(), node,
req.getExecutionTypeRequest(), req.getCapability(), req);
} }
} }
for (String rack : allRacks) { for (String rack : allRacks) {
decResourceRequest(req.getPriority(), rack, req.getCapability(), req); decResourceRequest(req.getPriority(), rack,
req.getExecutionTypeRequest(), req.getCapability(), req);
} }
decResourceRequest(req.getPriority(), ResourceRequest.ANY, decResourceRequest(req.getPriority(), ResourceRequest.ANY,
req.getCapability(), req); req.getExecutionTypeRequest(), req.getCapability(), req);
} }
@Override @Override
@ -601,47 +606,38 @@ public class AMRMClientImpl<T extends ContainerRequest> extends AMRMClient<T> {
public synchronized int getClusterNodeCount() { public synchronized int getClusterNodeCount() {
return clusterNodeCount; return clusterNodeCount;
} }
@Override @Override
public synchronized List<? extends Collection<T>> getMatchingRequests( public synchronized List<? extends Collection<T>> getMatchingRequests(
Priority priority, Priority priority,
String resourceName, String resourceName,
Resource capability) { Resource capability) {
return getMatchingRequests(priority, resourceName,
ExecutionType.GUARANTEED, capability);
}
@Override
public synchronized List<? extends Collection<T>> getMatchingRequests(
Priority priority, String resourceName, ExecutionType executionType,
Resource capability) {
Preconditions.checkArgument(capability != null, Preconditions.checkArgument(capability != null,
"The Resource to be requested should not be null "); "The Resource to be requested should not be null ");
Preconditions.checkArgument(priority != null, Preconditions.checkArgument(priority != null,
"The priority at which to request containers should not be null "); "The priority at which to request containers should not be null ");
List<LinkedHashSet<T>> list = new LinkedList<LinkedHashSet<T>>(); List<LinkedHashSet<T>> list = new LinkedList<LinkedHashSet<T>>();
Map<String, TreeMap<Resource, ResourceRequestInfo>> remoteRequests =
this.remoteRequestsTable.get(priority);
if (remoteRequests == null) {
return list;
}
TreeMap<Resource, ResourceRequestInfo> reqMap = remoteRequests
.get(resourceName);
if (reqMap == null) {
return list;
}
ResourceRequestInfo resourceRequestInfo = reqMap.get(capability); @SuppressWarnings("unchecked")
if (resourceRequestInfo != null && List<ResourceRequestInfo<T>> matchingRequests =
!resourceRequestInfo.containerRequests.isEmpty()) { this.remoteRequestsTable.getMatchingRequests(priority, resourceName,
list.add(resourceRequestInfo.containerRequests); executionType, capability);
return list; // If no exact match. Container may be larger than what was requested.
} // get all resources <= capability. map is reverse sorted.
for (ResourceRequestInfo<T> resReqInfo : matchingRequests) {
// no exact match. Container may be larger than what was requested. if (canFit(resReqInfo.remoteRequest.getCapability(), capability) &&
// get all resources <= capability. map is reverse sorted. !resReqInfo.containerRequests.isEmpty()) {
SortedMap<Resource, ResourceRequestInfo> tailMap = list.add(resReqInfo.containerRequests);
reqMap.tailMap(capability);
for(Map.Entry<Resource, ResourceRequestInfo> entry : tailMap.entrySet()) {
if (canFit(entry.getKey(), capability) &&
!entry.getValue().containerRequests.isEmpty()) {
// match found that fits in the larger resource
list.add(entry.getValue().containerRequests);
} }
} }
// no match found // no match found
return list; return list;
} }
@ -663,34 +659,30 @@ public class AMRMClientImpl<T extends ContainerRequest> extends AMRMClient<T> {
return racks; return racks;
} }
/** /**
* ContainerRequests with locality relaxation cannot be made at the same * ContainerRequests with locality relaxation cannot be made at the same
* priority as ContainerRequests without locality relaxation. * priority as ContainerRequests without locality relaxation.
*/ */
private void checkLocalityRelaxationConflict(Priority priority, private void checkLocalityRelaxationConflict(Priority priority,
Collection<String> locations, boolean relaxLocality) { Collection<String> locations, boolean relaxLocality) {
Map<String, TreeMap<Resource, ResourceRequestInfo>> remoteRequests =
this.remoteRequestsTable.get(priority);
if (remoteRequests == null) {
return;
}
// Locality relaxation will be set to relaxLocality for all implicitly // Locality relaxation will be set to relaxLocality for all implicitly
// requested racks. Make sure that existing rack requests match this. // requested racks. Make sure that existing rack requests match this.
for (String location : locations) {
TreeMap<Resource, ResourceRequestInfo> reqs = @SuppressWarnings("unchecked")
remoteRequests.get(location); List<ResourceRequestInfo> allCapabilityMaps =
if (reqs != null && !reqs.isEmpty()) { remoteRequestsTable.getAllResourceRequestInfos(priority, locations);
boolean existingRelaxLocality = for (ResourceRequestInfo reqs : allCapabilityMaps) {
reqs.values().iterator().next().remoteRequest.getRelaxLocality(); ResourceRequest remoteRequest = reqs.remoteRequest;
if (relaxLocality != existingRelaxLocality) { boolean existingRelaxLocality = remoteRequest.getRelaxLocality();
throw new InvalidContainerRequestException("Cannot submit a " if (relaxLocality != existingRelaxLocality) {
+ "ContainerRequest asking for location " + location throw new InvalidContainerRequestException("Cannot submit a "
+ " with locality relaxation " + relaxLocality + " when it has " + "ContainerRequest asking for location "
+ "already been requested with locality relaxation " + existingRelaxLocality); + remoteRequest.getResourceName() + " with locality relaxation "
} + relaxLocality + " when it has already been requested"
} + "with locality relaxation " + existingRelaxLocality);
} }
}
} }
/** /**
@ -747,46 +739,13 @@ public class AMRMClientImpl<T extends ContainerRequest> extends AMRMClient<T> {
ask.add(remoteRequest); ask.add(remoteRequest);
} }
private void private void addResourceRequest(Priority priority, String resourceName,
addResourceRequest(Priority priority, String resourceName, ExecutionTypeRequest execTypeReq, Resource capability, T req,
Resource capability, T req, boolean relaxLocality, boolean relaxLocality, String labelExpression) {
String labelExpression) { @SuppressWarnings("unchecked")
Map<String, TreeMap<Resource, ResourceRequestInfo>> remoteRequests = ResourceRequestInfo resourceRequestInfo = remoteRequestsTable
this.remoteRequestsTable.get(priority); .addResourceRequest(priority, resourceName,
if (remoteRequests == null) { execTypeReq, capability, req, relaxLocality, labelExpression);
remoteRequests =
new HashMap<String, TreeMap<Resource, ResourceRequestInfo>>();
this.remoteRequestsTable.put(priority, remoteRequests);
if (LOG.isDebugEnabled()) {
LOG.debug("Added priority=" + priority);
}
}
TreeMap<Resource, ResourceRequestInfo> reqMap =
remoteRequests.get(resourceName);
if (reqMap == null) {
// capabilities are stored in reverse sorted order. smallest last.
reqMap = new TreeMap<Resource, ResourceRequestInfo>(
new ResourceReverseMemoryThenCpuComparator());
remoteRequests.put(resourceName, reqMap);
}
ResourceRequestInfo resourceRequestInfo = reqMap.get(capability);
if (resourceRequestInfo == null) {
resourceRequestInfo =
new ResourceRequestInfo(priority, resourceName, capability,
relaxLocality);
reqMap.put(capability, resourceRequestInfo);
}
resourceRequestInfo.remoteRequest.setNumContainers(
resourceRequestInfo.remoteRequest.getNumContainers() + 1);
if (relaxLocality) {
resourceRequestInfo.containerRequests.add(req);
}
if (ResourceRequest.ANY.equals(resourceName)) {
resourceRequestInfo.remoteRequest.setNodeLabelExpression(labelExpression);
}
// Note this down for next interaction with ResourceManager // Note this down for next interaction with ResourceManager
addResourceRequestToAsk(resourceRequestInfo.remoteRequest); addResourceRequestToAsk(resourceRequestInfo.remoteRequest);
@ -800,70 +759,31 @@ public class AMRMClientImpl<T extends ContainerRequest> extends AMRMClient<T> {
} }
} }
private void decResourceRequest(Priority priority, private void decResourceRequest(Priority priority, String resourceName,
String resourceName, ExecutionTypeRequest execTypeReq, Resource capability, T req) {
Resource capability, @SuppressWarnings("unchecked")
T req) { ResourceRequestInfo resourceRequestInfo =
Map<String, TreeMap<Resource, ResourceRequestInfo>> remoteRequests = remoteRequestsTable.decResourceRequest(priority, resourceName,
this.remoteRequestsTable.get(priority); execTypeReq, capability, req);
if(remoteRequests == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("Not decrementing resource as priority " + priority
+ " is not present in request table");
}
return;
}
Map<Resource, ResourceRequestInfo> reqMap = remoteRequests.get(resourceName);
if (reqMap == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("Not decrementing resource as " + resourceName
+ " is not present in request table");
}
return;
}
ResourceRequestInfo resourceRequestInfo = reqMap.get(capability);
if (LOG.isDebugEnabled()) {
LOG.debug("BEFORE decResourceRequest:" + " applicationId="
+ " priority=" + priority.getPriority()
+ " resourceName=" + resourceName + " numContainers="
+ resourceRequestInfo.remoteRequest.getNumContainers()
+ " #asks=" + ask.size());
}
resourceRequestInfo.remoteRequest.setNumContainers(
resourceRequestInfo.remoteRequest.getNumContainers() - 1);
resourceRequestInfo.containerRequests.remove(req);
if(resourceRequestInfo.remoteRequest.getNumContainers() < 0) {
// guard against spurious removals
resourceRequestInfo.remoteRequest.setNumContainers(0);
}
// send the ResourceRequest to RM even if is 0 because it needs to override // send the ResourceRequest to RM even if is 0 because it needs to override
// a previously sent value. If ResourceRequest was not sent previously then // a previously sent value. If ResourceRequest was not sent previously then
// sending 0 aught to be a no-op on RM // sending 0 aught to be a no-op on RM
addResourceRequestToAsk(resourceRequestInfo.remoteRequest); if (resourceRequestInfo != null) {
addResourceRequestToAsk(resourceRequestInfo.remoteRequest);
// delete entries from map if no longer needed // delete entry from map if no longer needed
if (resourceRequestInfo.remoteRequest.getNumContainers() == 0) { if (resourceRequestInfo.remoteRequest.getNumContainers() == 0) {
reqMap.remove(capability); this.remoteRequestsTable.remove(priority, resourceName,
if (reqMap.size() == 0) { execTypeReq.getExecutionType(), capability);
remoteRequests.remove(resourceName);
} }
if (remoteRequests.size() == 0) {
remoteRequestsTable.remove(priority);
}
}
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug("AFTER decResourceRequest:" + " applicationId=" LOG.debug("AFTER decResourceRequest:" + " applicationId="
+ " priority=" + priority.getPriority() + " priority=" + priority.getPriority()
+ " resourceName=" + resourceName + " numContainers=" + " resourceName=" + resourceName + " numContainers="
+ resourceRequestInfo.remoteRequest.getNumContainers() + resourceRequestInfo.remoteRequest.getNumContainers()
+ " #asks=" + ask.size()); + " #asks=" + ask.size());
}
} }
} }

View File

@ -0,0 +1,332 @@
/**
* 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.client.api.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.yarn.api.records.ExecutionType;
import org.apache.hadoop.yarn.api.records.ExecutionTypeRequest;
import org.apache.hadoop.yarn.api.records.Priority;
import org.apache.hadoop.yarn.api.records.Resource;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.apache.hadoop.yarn.api.records.ResourceRequest;
import org.apache.hadoop.yarn.client.api.impl.AMRMClientImpl.ResourceRequestInfo;
import org.apache.hadoop.yarn.client.api.impl.AMRMClientImpl.ResourceReverseMemoryThenCpuComparator;
class RemoteRequestsTable<T> implements Iterable<ResourceRequestInfo>{
private static final Log LOG = LogFactory.getLog(RemoteRequestsTable.class);
static ResourceReverseMemoryThenCpuComparator resourceComparator =
new ResourceReverseMemoryThenCpuComparator();
/**
* Nested Iterator that iterates over just the ResourceRequestInfo
* object.
*/
class RequestInfoIterator implements Iterator<ResourceRequestInfo> {
private Iterator<Map<String, Map<ExecutionType, TreeMap<Resource,
ResourceRequestInfo>>>> iLocMap;
private Iterator<Map<ExecutionType, TreeMap<Resource,
ResourceRequestInfo>>> iExecTypeMap;
private Iterator<TreeMap<Resource, ResourceRequestInfo>> iCapMap;
private Iterator<ResourceRequestInfo> iResReqInfo;
public RequestInfoIterator(Iterator<Map<String,
Map<ExecutionType, TreeMap<Resource, ResourceRequestInfo>>>>
iLocationMap) {
this.iLocMap = iLocationMap;
if (iLocMap.hasNext()) {
iExecTypeMap = iLocMap.next().values().iterator();
} else {
iExecTypeMap =
new LinkedList<Map<ExecutionType, TreeMap<Resource,
ResourceRequestInfo>>>().iterator();
}
if (iExecTypeMap.hasNext()) {
iCapMap = iExecTypeMap.next().values().iterator();
} else {
iCapMap =
new LinkedList<TreeMap<Resource, ResourceRequestInfo>>()
.iterator();
}
if (iCapMap.hasNext()) {
iResReqInfo = iCapMap.next().values().iterator();
} else {
iResReqInfo = new LinkedList<ResourceRequestInfo>().iterator();
}
}
@Override
public boolean hasNext() {
return iLocMap.hasNext()
|| iExecTypeMap.hasNext()
|| iCapMap.hasNext()
|| iResReqInfo.hasNext();
}
@Override
public ResourceRequestInfo next() {
if (!iResReqInfo.hasNext()) {
if (!iCapMap.hasNext()) {
if (!iExecTypeMap.hasNext()) {
iExecTypeMap = iLocMap.next().values().iterator();
}
iCapMap = iExecTypeMap.next().values().iterator();
}
iResReqInfo = iCapMap.next().values().iterator();
}
return iResReqInfo.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException("Remove is not supported" +
"for this iterator !!");
}
}
// Nest map with Primary key :
// Priority -> ResourceName(String) -> ExecutionType -> Capability(Resource)
// and value : ResourceRequestInfo
private Map<Priority, Map<String, Map<ExecutionType, TreeMap<Resource,
ResourceRequestInfo>>>> remoteRequestsTable = new HashMap<>();
@Override
public Iterator<ResourceRequestInfo> iterator() {
return new RequestInfoIterator(remoteRequestsTable.values().iterator());
}
ResourceRequestInfo get(Priority priority, String location,
ExecutionType execType, Resource capability) {
TreeMap<Resource, ResourceRequestInfo> capabilityMap =
getCapabilityMap(priority, location, execType);
if (capabilityMap == null) {
return null;
}
return capabilityMap.get(capability);
}
void put(Priority priority, String resourceName, ExecutionType execType,
Resource capability, ResourceRequestInfo resReqInfo) {
Map<String, Map<ExecutionType, TreeMap<Resource,
ResourceRequestInfo>>> locationMap =
remoteRequestsTable.get(priority);
if (locationMap == null) {
locationMap = new HashMap<>();
this.remoteRequestsTable.put(priority, locationMap);
if (LOG.isDebugEnabled()) {
LOG.debug("Added priority=" + priority);
}
}
Map<ExecutionType, TreeMap<Resource, ResourceRequestInfo>> execTypeMap =
locationMap.get(resourceName);
if (execTypeMap == null) {
execTypeMap = new HashMap<>();
locationMap.put(resourceName, execTypeMap);
if (LOG.isDebugEnabled()) {
LOG.debug("Added resourceName=" + resourceName);
}
}
TreeMap<Resource, ResourceRequestInfo> capabilityMap =
execTypeMap.get(execType);
if (capabilityMap == null) {
capabilityMap = new TreeMap<>(resourceComparator);
execTypeMap.put(execType, capabilityMap);
if (LOG.isDebugEnabled()) {
LOG.debug("Added Execution Type=" + execType);
}
}
capabilityMap.put(capability, resReqInfo);
}
ResourceRequestInfo remove(Priority priority, String resourceName,
ExecutionType execType, Resource capability) {
ResourceRequestInfo retVal = null;
Map<String, Map<ExecutionType, TreeMap<Resource,
ResourceRequestInfo>>> locationMap = remoteRequestsTable.get(priority);
if (locationMap == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("No such priority=" + priority);
}
return null;
}
Map<ExecutionType, TreeMap<Resource, ResourceRequestInfo>>
execTypeMap = locationMap.get(resourceName);
if (execTypeMap == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("No such resourceName=" + resourceName);
}
return null;
}
TreeMap<Resource, ResourceRequestInfo> capabilityMap =
execTypeMap.get(execType);
if (capabilityMap == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("No such Execution Type=" + execType);
}
return null;
}
retVal = capabilityMap.remove(capability);
if (capabilityMap.size() == 0) {
execTypeMap.remove(execType);
if (execTypeMap.size() == 0) {
locationMap.remove(resourceName);
if (locationMap.size() == 0) {
this.remoteRequestsTable.remove(priority);
}
}
}
return retVal;
}
Map<String, Map<ExecutionType, TreeMap<Resource,
ResourceRequestInfo>>> getLocationMap(Priority priority) {
return remoteRequestsTable.get(priority);
}
Map<ExecutionType, TreeMap<Resource, ResourceRequestInfo>>
getExecutionTypeMap(Priority priority, String location) {
Map<String, Map<ExecutionType, TreeMap<Resource,
ResourceRequestInfo>>> locationMap = getLocationMap(priority);
if (locationMap == null) {
return null;
}
return locationMap.get(location);
}
TreeMap<Resource, ResourceRequestInfo> getCapabilityMap(Priority
priority, String location,
ExecutionType execType) {
Map<ExecutionType, TreeMap<Resource, ResourceRequestInfo>>
executionTypeMap = getExecutionTypeMap(priority, location);
if (executionTypeMap == null) {
return null;
}
return executionTypeMap.get(execType);
}
@SuppressWarnings("unchecked")
List<ResourceRequestInfo> getAllResourceRequestInfos(Priority priority,
Collection<String> locations) {
List retList = new LinkedList<>();
for (String location : locations) {
for (ExecutionType eType : ExecutionType.values()) {
TreeMap<Resource, ResourceRequestInfo> capabilityMap =
getCapabilityMap(priority, location, eType);
if (capabilityMap != null) {
retList.addAll(capabilityMap.values());
}
}
}
return retList;
}
List<ResourceRequestInfo> getMatchingRequests(
Priority priority, String resourceName, ExecutionType executionType,
Resource capability) {
List<ResourceRequestInfo> list = new LinkedList<>();
TreeMap<Resource, ResourceRequestInfo> capabilityMap =
getCapabilityMap(priority, resourceName, executionType);
if (capabilityMap != null) {
ResourceRequestInfo resourceRequestInfo = capabilityMap.get(capability);
if (resourceRequestInfo != null) {
list.add(resourceRequestInfo);
} else {
list.addAll(capabilityMap.tailMap(capability).values());
}
}
return list;
}
@SuppressWarnings("unchecked")
ResourceRequestInfo addResourceRequest(Priority priority, String resourceName,
ExecutionTypeRequest execTypeReq, Resource capability, T req,
boolean relaxLocality, String labelExpression) {
ResourceRequestInfo resourceRequestInfo = get(priority, resourceName,
execTypeReq.getExecutionType(), capability);
if (resourceRequestInfo == null) {
resourceRequestInfo =
new ResourceRequestInfo(priority, resourceName, capability,
relaxLocality);
put(priority, resourceName, execTypeReq.getExecutionType(), capability,
resourceRequestInfo);
}
resourceRequestInfo.remoteRequest.setExecutionTypeRequest(execTypeReq);
resourceRequestInfo.remoteRequest.setNumContainers(
resourceRequestInfo.remoteRequest.getNumContainers() + 1);
if (relaxLocality) {
resourceRequestInfo.containerRequests.add(req);
}
if (ResourceRequest.ANY.equals(resourceName)) {
resourceRequestInfo.remoteRequest.setNodeLabelExpression(labelExpression);
}
return resourceRequestInfo;
}
ResourceRequestInfo decResourceRequest(Priority priority, String resourceName,
ExecutionTypeRequest execTypeReq, Resource capability, T req) {
ResourceRequestInfo resourceRequestInfo = get(priority, resourceName,
execTypeReq.getExecutionType(), capability);
if (resourceRequestInfo == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("Not decrementing resource as ResourceRequestInfo with" +
"priority=" + priority + ", " +
"resourceName=" + resourceName + ", " +
"executionType=" + execTypeReq + ", " +
"capability=" + capability + " is not present in request table");
}
return null;
}
if (LOG.isDebugEnabled()) {
LOG.debug("BEFORE decResourceRequest:" + " applicationId="
+ " priority=" + priority.getPriority()
+ " resourceName=" + resourceName + " numContainers="
+ resourceRequestInfo.remoteRequest.getNumContainers());
}
resourceRequestInfo.remoteRequest.setNumContainers(
resourceRequestInfo.remoteRequest.getNumContainers() - 1);
resourceRequestInfo.containerRequests.remove(req);
if (resourceRequestInfo.remoteRequest.getNumContainers() < 0) {
// guard against spurious removals
resourceRequestInfo.remoteRequest.setNumContainers(0);
}
return resourceRequestInfo;
}
boolean isEmpty() {
return remoteRequestsTable.isEmpty();
}
}

View File

@ -0,0 +1,197 @@
/**
* 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.client.api.impl;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.yarn.api.ApplicationMasterProtocol;
import org.apache.hadoop.yarn.api.protocolrecords.AllocateRequest;
import org.apache.hadoop.yarn.api.protocolrecords.SubmitApplicationRequest;
import org.apache.hadoop.yarn.api.records.ApplicationAccessType;
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.ApplicationReport;
import org.apache.hadoop.yarn.api.records.ApplicationSubmissionContext;
import org.apache.hadoop.yarn.api.records.ContainerLaunchContext;
import org.apache.hadoop.yarn.api.records.LocalResource;
import org.apache.hadoop.yarn.api.records.NodeReport;
import org.apache.hadoop.yarn.api.records.Priority;
import org.apache.hadoop.yarn.api.records.Resource;
import org.apache.hadoop.yarn.api.records.ResourceBlacklistRequest;
import org.apache.hadoop.yarn.api.records.ResourceRequest;
import org.apache.hadoop.yarn.api.records.YarnApplicationState;
import org.apache.hadoop.yarn.client.ClientRMProxy;
import org.apache.hadoop.yarn.client.api.AMRMClient;
import org.apache.hadoop.yarn.client.api.YarnClient;
import org.apache.hadoop.yarn.exceptions.YarnException;
import org.apache.hadoop.yarn.security.AMRMTokenIdentifier;
import org.apache.hadoop.yarn.server.MiniYARNCluster;
import org.apache.hadoop.yarn.server.nodemanager.amrmproxy.AMRMProxyTokenSecretManager;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.ContainerManagerImpl;
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.server.utils.BuilderUtils;
import org.apache.hadoop.yarn.util.Records;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
/**
* Base test case to be used for Testing frameworks that use AMRMProxy.
*/
public abstract class BaseAMRMProxyE2ETest {
protected ApplicationMasterProtocol createAMRMProtocol(YarnClient rmClient,
ApplicationId appId, MiniYARNCluster cluster,
final Configuration yarnConf)
throws IOException, InterruptedException, YarnException {
UserGroupInformation user = null;
// Get the AMRMToken from AMRMProxy
ApplicationReport report = rmClient.getApplicationReport(appId);
user = UserGroupInformation.createProxyUser(
report.getCurrentApplicationAttemptId().toString(),
UserGroupInformation.getCurrentUser());
ContainerManagerImpl containerManager = (ContainerManagerImpl) cluster
.getNodeManager(0).getNMContext().getContainerManager();
AMRMProxyTokenSecretManager amrmTokenSecretManager =
containerManager.getAMRMProxyService().getSecretManager();
org.apache.hadoop.security.token.Token<AMRMTokenIdentifier> token =
amrmTokenSecretManager
.createAndGetAMRMToken(report.getCurrentApplicationAttemptId());
SecurityUtil.setTokenService(token,
containerManager.getAMRMProxyService().getBindAddress());
user.addToken(token);
// Start Application Master
return user
.doAs(new PrivilegedExceptionAction<ApplicationMasterProtocol>() {
@Override
public ApplicationMasterProtocol run() throws Exception {
return ClientRMProxy.createRMProxy(yarnConf,
ApplicationMasterProtocol.class);
}
});
}
protected AllocateRequest createAllocateRequest(List<NodeReport> listNode) {
// The test needs AMRMClient to create a real allocate request
AMRMClientImpl<AMRMClient.ContainerRequest> amClient =
new AMRMClientImpl<>();
Resource capability = Resource.newInstance(1024, 2);
Priority priority = Priority.newInstance(1);
List<NodeReport> nodeReports = listNode;
String node = nodeReports.get(0).getNodeId().getHost();
String[] nodes = new String[] {node};
AMRMClient.ContainerRequest storedContainer1 =
new AMRMClient.ContainerRequest(capability, nodes, null, priority);
amClient.addContainerRequest(storedContainer1);
amClient.addContainerRequest(storedContainer1);
List<ResourceRequest> resourceAsk = new ArrayList<>();
for (ResourceRequest rr : amClient.ask) {
resourceAsk.add(rr);
}
ResourceBlacklistRequest resourceBlacklistRequest = ResourceBlacklistRequest
.newInstance(new ArrayList<>(), new ArrayList<>());
int responseId = 1;
return AllocateRequest.newInstance(responseId, 0, resourceAsk,
new ArrayList<>(), resourceBlacklistRequest);
}
protected ApplicationAttemptId createApp(YarnClient yarnClient,
MiniYARNCluster yarnCluster, Configuration conf) throws Exception {
ApplicationSubmissionContext appContext =
yarnClient.createApplication().getApplicationSubmissionContext();
ApplicationId appId = appContext.getApplicationId();
appContext.setApplicationName("Test");
Priority pri = Records.newRecord(Priority.class);
pri.setPriority(0);
appContext.setPriority(pri);
appContext.setQueue("default");
ContainerLaunchContext amContainer = BuilderUtils.newContainerLaunchContext(
Collections.<String, LocalResource> emptyMap(),
new HashMap<String, String>(), Arrays.asList("sleep", "10000"),
new HashMap<String, ByteBuffer>(), null,
new HashMap<ApplicationAccessType, String>());
appContext.setAMContainerSpec(amContainer);
appContext.setResource(Resource.newInstance(1024, 1));
SubmitApplicationRequest appRequest =
Records.newRecord(SubmitApplicationRequest.class);
appRequest.setApplicationSubmissionContext(appContext);
yarnClient.submitApplication(appContext);
RMAppAttempt appAttempt = null;
ApplicationAttemptId attemptId = null;
while (true) {
ApplicationReport appReport = yarnClient.getApplicationReport(appId);
if (appReport
.getYarnApplicationState() == YarnApplicationState.ACCEPTED) {
attemptId =
appReport.getCurrentApplicationAttemptId();
appAttempt = yarnCluster.getResourceManager().getRMContext().getRMApps()
.get(attemptId.getApplicationId()).getCurrentAppAttempt();
while (true) {
if (appAttempt.getAppAttemptState() == RMAppAttemptState.LAUNCHED) {
break;
}
}
break;
}
}
Thread.sleep(1000);
// Just dig into the ResourceManager and get the AMRMToken just for the sake
// of testing.
UserGroupInformation.setLoginUser(UserGroupInformation
.createRemoteUser(UserGroupInformation.getCurrentUser().getUserName()));
// emulate RM setup of AMRM token in credentials by adding the token
// *before* setting the token service
UserGroupInformation.getCurrentUser().addToken(appAttempt.getAMRMToken());
appAttempt.getAMRMToken().setService(
ClientRMProxy.getAMRMTokenService(conf));
return attemptId;
}
}

View File

@ -61,6 +61,7 @@ import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.api.records.ContainerLaunchContext; import org.apache.hadoop.yarn.api.records.ContainerLaunchContext;
import org.apache.hadoop.yarn.api.records.ContainerState; import org.apache.hadoop.yarn.api.records.ContainerState;
import org.apache.hadoop.yarn.api.records.ContainerStatus; import org.apache.hadoop.yarn.api.records.ContainerStatus;
import org.apache.hadoop.yarn.api.records.ExecutionType;
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus; import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
import org.apache.hadoop.yarn.api.records.LocalResource; import org.apache.hadoop.yarn.api.records.LocalResource;
import org.apache.hadoop.yarn.api.records.NMToken; import org.apache.hadoop.yarn.api.records.NMToken;
@ -413,11 +414,13 @@ public class TestAMRMClient {
amClient.addContainerRequest(storedContainer3); amClient.addContainerRequest(storedContainer3);
// test addition and storage // test addition and storage
int containersRequestedAny = amClient.remoteRequestsTable.get(priority) int containersRequestedAny = amClient.remoteRequestsTable.get(priority,
.get(ResourceRequest.ANY).get(capability).remoteRequest.getNumContainers(); ResourceRequest.ANY, ExecutionType.GUARANTEED, capability)
.remoteRequest.getNumContainers();
assertEquals(2, containersRequestedAny); assertEquals(2, containersRequestedAny);
containersRequestedAny = amClient.remoteRequestsTable.get(priority1) containersRequestedAny = amClient.remoteRequestsTable.get(priority1,
.get(ResourceRequest.ANY).get(capability).remoteRequest.getNumContainers(); ResourceRequest.ANY, ExecutionType.GUARANTEED, capability)
.remoteRequest.getNumContainers();
assertEquals(1, containersRequestedAny); assertEquals(1, containersRequestedAny);
List<? extends Collection<ContainerRequest>> matches = List<? extends Collection<ContainerRequest>> matches =
amClient.getMatchingRequests(priority, node, capability); amClient.getMatchingRequests(priority, node, capability);
@ -919,12 +922,15 @@ public class TestAMRMClient {
amClient.removeContainerRequest( amClient.removeContainerRequest(
new ContainerRequest(capability, nodes, racks, priority)); new ContainerRequest(capability, nodes, racks, priority));
int containersRequestedNode = amClient.remoteRequestsTable.get(priority) int containersRequestedNode = amClient.remoteRequestsTable.get(priority,
.get(node).get(capability).remoteRequest.getNumContainers(); node, ExecutionType.GUARANTEED, capability).remoteRequest
int containersRequestedRack = amClient.remoteRequestsTable.get(priority) .getNumContainers();
.get(rack).get(capability).remoteRequest.getNumContainers(); int containersRequestedRack = amClient.remoteRequestsTable.get(priority,
int containersRequestedAny = amClient.remoteRequestsTable.get(priority) rack, ExecutionType.GUARANTEED, capability).remoteRequest
.get(ResourceRequest.ANY).get(capability).remoteRequest.getNumContainers(); .getNumContainers();
int containersRequestedAny = amClient.remoteRequestsTable.get(priority,
ResourceRequest.ANY, ExecutionType.GUARANTEED, capability)
.remoteRequest.getNumContainers();
assertEquals(2, containersRequestedNode); assertEquals(2, containersRequestedNode);
assertEquals(2, containersRequestedRack); assertEquals(2, containersRequestedRack);

View File

@ -26,6 +26,8 @@ import java.util.List;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CommonConfigurationKeysPublic; import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
import org.apache.hadoop.net.DNSToSwitchMapping; import org.apache.hadoop.net.DNSToSwitchMapping;
import org.apache.hadoop.yarn.api.records.ExecutionType;
import org.apache.hadoop.yarn.api.records.ExecutionTypeRequest;
import org.apache.hadoop.yarn.api.records.Priority; import org.apache.hadoop.yarn.api.records.Priority;
import org.apache.hadoop.yarn.api.records.Resource; import org.apache.hadoop.yarn.api.records.Resource;
import org.apache.hadoop.yarn.api.records.ResourceRequest; import org.apache.hadoop.yarn.api.records.ResourceRequest;
@ -35,6 +37,46 @@ import org.apache.hadoop.yarn.client.api.InvalidContainerRequestException;
import org.junit.Test; import org.junit.Test;
public class TestAMRMClientContainerRequest { public class TestAMRMClientContainerRequest {
@Test
public void testOpportunisticAndGuaranteedRequests() {
AMRMClientImpl<ContainerRequest> client =
new AMRMClientImpl<ContainerRequest>();
Configuration conf = new Configuration();
conf.setClass(
CommonConfigurationKeysPublic.NET_TOPOLOGY_NODE_SWITCH_MAPPING_IMPL_KEY,
MyResolver.class, DNSToSwitchMapping.class);
client.init(conf);
Resource capability = Resource.newInstance(1024, 1);
ContainerRequest request =
new ContainerRequest(capability, new String[] {"host1", "host2"},
new String[] {"/rack2"}, Priority.newInstance(1));
client.addContainerRequest(request);
verifyResourceRequest(client, request, "host1", true);
verifyResourceRequest(client, request, "host2", true);
verifyResourceRequest(client, request, "/rack1", true);
verifyResourceRequest(client, request, "/rack2", true);
verifyResourceRequest(client, request, ResourceRequest.ANY, true);
ContainerRequest request2 =
new ContainerRequest(capability, new String[] {"host1", "host2"},
new String[] {"/rack2"}, Priority.newInstance(1), true, null,
ExecutionTypeRequest.newInstance(
ExecutionType.OPPORTUNISTIC, true));
client.addContainerRequest(request2);
verifyResourceRequest(client, request, "host1", true,
ExecutionType.OPPORTUNISTIC);
verifyResourceRequest(client, request, "host2", true,
ExecutionType.OPPORTUNISTIC);
verifyResourceRequest(client, request, "/rack1", true,
ExecutionType.OPPORTUNISTIC);
verifyResourceRequest(client, request, "/rack2", true,
ExecutionType.OPPORTUNISTIC);
verifyResourceRequest(client, request, ResourceRequest.ANY, true,
ExecutionType.OPPORTUNISTIC);
}
@Test @Test
public void testFillInRacks() { public void testFillInRacks() {
AMRMClientImpl<ContainerRequest> client = AMRMClientImpl<ContainerRequest> client =
@ -224,8 +266,16 @@ public class TestAMRMClientContainerRequest {
private void verifyResourceRequest( private void verifyResourceRequest(
AMRMClientImpl<ContainerRequest> client, ContainerRequest request, AMRMClientImpl<ContainerRequest> client, ContainerRequest request,
String location, boolean expectedRelaxLocality) { String location, boolean expectedRelaxLocality) {
ResourceRequest ask = client.remoteRequestsTable.get(request.getPriority()) verifyResourceRequest(client, request, location, expectedRelaxLocality,
.get(location).get(request.getCapability()).remoteRequest; ExecutionType.GUARANTEED);
}
private void verifyResourceRequest(
AMRMClientImpl<ContainerRequest> client, ContainerRequest request,
String location, boolean expectedRelaxLocality,
ExecutionType executionType) {
ResourceRequest ask = client.remoteRequestsTable.get(request.getPriority(),
location, executionType, request.getCapability()).remoteRequest;
assertEquals(location, ask.getResourceName()); assertEquals(location, ask.getResourceName());
assertEquals(1, ask.getNumContainers()); assertEquals(1, ask.getNumContainers());
assertEquals(expectedRelaxLocality, ask.getRelaxLocality()); assertEquals(expectedRelaxLocality, ask.getRelaxLocality());

View File

@ -19,20 +19,12 @@
package org.apache.hadoop.yarn.client.api.impl; package org.apache.hadoop.yarn.client.api.impl;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.net.NetUtils; import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.yarn.api.ApplicationMasterProtocol; import org.apache.hadoop.yarn.api.ApplicationMasterProtocol;
import org.apache.hadoop.yarn.api.protocolrecords.AllocateRequest; import org.apache.hadoop.yarn.api.protocolrecords.AllocateRequest;
import org.apache.hadoop.yarn.api.protocolrecords.AllocateResponse; import org.apache.hadoop.yarn.api.protocolrecords.AllocateResponse;
@ -40,43 +32,25 @@ import org.apache.hadoop.yarn.api.protocolrecords.FinishApplicationMasterRequest
import org.apache.hadoop.yarn.api.protocolrecords.FinishApplicationMasterResponse; import org.apache.hadoop.yarn.api.protocolrecords.FinishApplicationMasterResponse;
import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterRequest; import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterRequest;
import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterResponse; import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterResponse;
import org.apache.hadoop.yarn.api.protocolrecords.SubmitApplicationRequest;
import org.apache.hadoop.yarn.api.records.ApplicationAccessType;
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
import org.apache.hadoop.yarn.api.records.ApplicationId; import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.ApplicationReport;
import org.apache.hadoop.yarn.api.records.ApplicationSubmissionContext;
import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.api.records.ContainerLaunchContext;
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus; import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
import org.apache.hadoop.yarn.api.records.LocalResource;
import org.apache.hadoop.yarn.api.records.NodeReport;
import org.apache.hadoop.yarn.api.records.NodeState; import org.apache.hadoop.yarn.api.records.NodeState;
import org.apache.hadoop.yarn.api.records.Priority;
import org.apache.hadoop.yarn.api.records.Resource;
import org.apache.hadoop.yarn.api.records.ResourceBlacklistRequest;
import org.apache.hadoop.yarn.api.records.ResourceRequest; import org.apache.hadoop.yarn.api.records.ResourceRequest;
import org.apache.hadoop.yarn.api.records.Token; import org.apache.hadoop.yarn.api.records.Token;
import org.apache.hadoop.yarn.api.records.YarnApplicationState;
import org.apache.hadoop.yarn.client.ClientRMProxy;
import org.apache.hadoop.yarn.client.api.AMRMClient.ContainerRequest;
import org.apache.hadoop.yarn.client.api.YarnClient; import org.apache.hadoop.yarn.client.api.YarnClient;
import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.exceptions.YarnException;
import org.apache.hadoop.yarn.security.AMRMTokenIdentifier;
import org.apache.hadoop.yarn.server.MiniYARNCluster; import org.apache.hadoop.yarn.server.MiniYARNCluster;
import org.apache.hadoop.yarn.server.nodemanager.amrmproxy.AMRMProxyTokenSecretManager;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.ContainerManagerImpl;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; 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.RMAppState;
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.server.utils.BuilderUtils;
import org.apache.hadoop.yarn.util.Records;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
public class TestAMRMProxy { /**
* End-to-End test cases for the AMRMProxy Service.
*/
public class TestAMRMProxy extends BaseAMRMProxyE2ETest {
private static final Log LOG = LogFactory.getLog(TestAMRMProxy.class); private static final Log LOG = LogFactory.getLog(TestAMRMProxy.class);
@ -84,7 +58,7 @@ public class TestAMRMProxy {
* This test validates register, allocate and finish of an application through * This test validates register, allocate and finish of an application through
* the AMRMPRoxy. * the AMRMPRoxy.
*/ */
@Test(timeout = 60000) @Test(timeout = 120000)
public void testAMRMProxyE2E() throws Exception { public void testAMRMProxyE2E() throws Exception {
MiniYARNCluster cluster = new MiniYARNCluster("testAMRMProxyE2E", 1, 1, 1); MiniYARNCluster cluster = new MiniYARNCluster("testAMRMProxyE2E", 1, 1, 1);
YarnClient rmClient = null; YarnClient rmClient = null;
@ -107,7 +81,8 @@ public class TestAMRMProxy {
// Submit application // Submit application
ApplicationId appId = createApp(rmClient, cluster); ApplicationAttemptId appAttmptId = createApp(rmClient, cluster, conf);
ApplicationId appId = appAttmptId.getApplicationId();
client = createAMRMProtocol(rmClient, appId, cluster, yarnConf); client = createAMRMProtocol(rmClient, appId, cluster, yarnConf);
@ -173,7 +148,7 @@ public class TestAMRMProxy {
* that the received token it is different from the previous one within 5 * that the received token it is different from the previous one within 5
* requests. * requests.
*/ */
@Test(timeout = 60000) @Test(timeout = 120000)
public void testE2ETokenRenewal() throws Exception { public void testE2ETokenRenewal() throws Exception {
MiniYARNCluster cluster = MiniYARNCluster cluster =
new MiniYARNCluster("testE2ETokenRenewal", 1, 1, 1); new MiniYARNCluster("testE2ETokenRenewal", 1, 1, 1);
@ -201,7 +176,8 @@ public class TestAMRMProxy {
// Submit // Submit
ApplicationId appId = createApp(rmClient, cluster); ApplicationAttemptId appAttmptId = createApp(rmClient, cluster, conf);
ApplicationId appId = appAttmptId.getApplicationId();
client = createAMRMProtocol(rmClient, appId, cluster, yarnConf); client = createAMRMProtocol(rmClient, appId, cluster, yarnConf);
@ -252,7 +228,7 @@ public class TestAMRMProxy {
* This test validates that an AM cannot register directly to the RM, with the * This test validates that an AM cannot register directly to the RM, with the
* token provided by the AMRMProxy. * token provided by the AMRMProxy.
*/ */
@Test(timeout = 60000) @Test(timeout = 120000)
public void testE2ETokenSwap() throws Exception { public void testE2ETokenSwap() throws Exception {
MiniYARNCluster cluster = new MiniYARNCluster("testE2ETokenSwap", 1, 1, 1); MiniYARNCluster cluster = new MiniYARNCluster("testE2ETokenSwap", 1, 1, 1);
YarnClient rmClient = null; YarnClient rmClient = null;
@ -270,7 +246,8 @@ public class TestAMRMProxy {
rmClient.init(yarnConf); rmClient.init(yarnConf);
rmClient.start(); rmClient.start();
ApplicationId appId = createApp(rmClient, cluster); ApplicationAttemptId appAttmptId = createApp(rmClient, cluster, conf);
ApplicationId appId = appAttmptId.getApplicationId();
client = createAMRMProtocol(rmClient, appId, cluster, yarnConf); client = createAMRMProtocol(rmClient, appId, cluster, yarnConf);
@ -290,124 +267,4 @@ public class TestAMRMProxy {
cluster.stop(); cluster.stop();
} }
} }
protected ApplicationMasterProtocol createAMRMProtocol(YarnClient rmClient,
ApplicationId appId, MiniYARNCluster cluster,
final Configuration yarnConf)
throws IOException, InterruptedException, YarnException {
UserGroupInformation user = null;
// Get the AMRMToken from AMRMProxy
ApplicationReport report = rmClient.getApplicationReport(appId);
user = UserGroupInformation.createProxyUser(
report.getCurrentApplicationAttemptId().toString(),
UserGroupInformation.getCurrentUser());
ContainerManagerImpl containerManager = (ContainerManagerImpl) cluster
.getNodeManager(0).getNMContext().getContainerManager();
AMRMProxyTokenSecretManager amrmTokenSecretManager =
containerManager.getAMRMProxyService().getSecretManager();
org.apache.hadoop.security.token.Token<AMRMTokenIdentifier> token =
amrmTokenSecretManager
.createAndGetAMRMToken(report.getCurrentApplicationAttemptId());
SecurityUtil.setTokenService(token,
containerManager.getAMRMProxyService().getBindAddress());
user.addToken(token);
// Start Application Master
return user
.doAs(new PrivilegedExceptionAction<ApplicationMasterProtocol>() {
@Override
public ApplicationMasterProtocol run() throws Exception {
return ClientRMProxy.createRMProxy(yarnConf,
ApplicationMasterProtocol.class);
}
});
}
protected AllocateRequest createAllocateRequest(List<NodeReport> listNode) {
// The test needs AMRMClient to create a real allocate request
AMRMClientImpl<ContainerRequest> amClient =
new AMRMClientImpl<ContainerRequest>();
Resource capability = Resource.newInstance(1024, 2);
Priority priority = Priority.newInstance(1);
List<NodeReport> nodeReports = listNode;
String node = nodeReports.get(0).getNodeId().getHost();
String[] nodes = new String[] { node };
ContainerRequest storedContainer1 =
new ContainerRequest(capability, nodes, null, priority);
amClient.addContainerRequest(storedContainer1);
amClient.addContainerRequest(storedContainer1);
List<ResourceRequest> resourceAsk = new ArrayList<ResourceRequest>();
for (ResourceRequest rr : amClient.ask) {
resourceAsk.add(rr);
}
ResourceBlacklistRequest resourceBlacklistRequest = ResourceBlacklistRequest
.newInstance(new ArrayList<String>(), new ArrayList<String>());
int responseId = 1;
return AllocateRequest.newInstance(responseId, 0, resourceAsk,
new ArrayList<ContainerId>(), resourceBlacklistRequest);
}
protected ApplicationId createApp(YarnClient yarnClient,
MiniYARNCluster yarnCluster) throws Exception {
ApplicationSubmissionContext appContext =
yarnClient.createApplication().getApplicationSubmissionContext();
ApplicationId appId = appContext.getApplicationId();
appContext.setApplicationName("Test");
Priority pri = Records.newRecord(Priority.class);
pri.setPriority(0);
appContext.setPriority(pri);
appContext.setQueue("default");
ContainerLaunchContext amContainer = BuilderUtils.newContainerLaunchContext(
Collections.<String, LocalResource> emptyMap(),
new HashMap<String, String>(), Arrays.asList("sleep", "10000"),
new HashMap<String, ByteBuffer>(), null,
new HashMap<ApplicationAccessType, String>());
appContext.setAMContainerSpec(amContainer);
appContext.setResource(Resource.newInstance(1024, 1));
SubmitApplicationRequest appRequest =
Records.newRecord(SubmitApplicationRequest.class);
appRequest.setApplicationSubmissionContext(appContext);
yarnClient.submitApplication(appContext);
RMAppAttempt appAttempt = null;
while (true) {
ApplicationReport appReport = yarnClient.getApplicationReport(appId);
if (appReport
.getYarnApplicationState() == YarnApplicationState.ACCEPTED) {
ApplicationAttemptId attemptId =
appReport.getCurrentApplicationAttemptId();
appAttempt = yarnCluster.getResourceManager().getRMContext().getRMApps()
.get(attemptId.getApplicationId()).getCurrentAppAttempt();
while (true) {
if (appAttempt.getAppAttemptState() == RMAppAttemptState.LAUNCHED) {
break;
}
}
break;
}
}
Thread.sleep(1000);
return appId;
}
} }

View File

@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the * to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance * "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at * with the License. You may obtain a copy of the License at
* * <p>
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* * <p>
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -22,20 +22,31 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.net.NetUtils; import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.service.Service;
import org.apache.hadoop.yarn.api.ApplicationMasterProtocol; import org.apache.hadoop.yarn.api.ApplicationMasterProtocol;
import org.apache.hadoop.yarn.api.protocolrecords.AllocateRequest; import org.apache.hadoop.yarn.api.protocolrecords.AllocateRequest;
import org.apache.hadoop.yarn.api.protocolrecords.AllocateResponse; import org.apache.hadoop.yarn.api.protocolrecords.AllocateResponse;
import org.apache.hadoop.yarn.api.protocolrecords.FinishApplicationMasterRequest; 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.RegisterApplicationMasterRequest;
import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterResponse; import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterResponse;
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
import org.apache.hadoop.yarn.api.records.ApplicationId; import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.Container; import org.apache.hadoop.yarn.api.records.Container;
import org.apache.hadoop.yarn.api.records.ExecutionTypeRequest; import org.apache.hadoop.yarn.api.records.ExecutionTypeRequest;
import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.api.records.ContainerState;
import org.apache.hadoop.yarn.api.records.ContainerStatus;
import org.apache.hadoop.yarn.api.records.ExecutionType; import org.apache.hadoop.yarn.api.records.ExecutionType;
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus; import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
import org.apache.hadoop.yarn.api.records.NMToken;
import org.apache.hadoop.yarn.api.records.NodeReport;
import org.apache.hadoop.yarn.api.records.NodeState; import org.apache.hadoop.yarn.api.records.NodeState;
import org.apache.hadoop.yarn.api.records.Priority;
import org.apache.hadoop.yarn.api.records.Resource;
import org.apache.hadoop.yarn.api.records.ResourceRequest; import org.apache.hadoop.yarn.api.records.ResourceRequest;
import org.apache.hadoop.yarn.api.records.Token;
import org.apache.hadoop.yarn.client.api.AMRMClient;
import org.apache.hadoop.yarn.client.api.YarnClient; import org.apache.hadoop.yarn.client.api.YarnClient;
import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.security.ContainerTokenIdentifier; import org.apache.hadoop.yarn.security.ContainerTokenIdentifier;
@ -43,12 +54,23 @@ import org.apache.hadoop.yarn.server.MiniYARNCluster;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; 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.RMAppState;
import org.apache.hadoop.yarn.server.utils.BuilderUtils; import org.apache.hadoop.yarn.server.utils.BuilderUtils;
import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Ignore; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/** /**
* Validates End2End Distributed Scheduling flow which includes the AM * Validates End2End Distributed Scheduling flow which includes the AM
@ -57,11 +79,70 @@ import java.util.List;
* the NM and the DistributedSchedulingProtocol used by the framework to talk * the NM and the DistributedSchedulingProtocol used by the framework to talk
* to the DistributedSchedulingService running on the RM. * to the DistributedSchedulingService running on the RM.
*/ */
public class TestDistributedScheduling extends TestAMRMProxy { public class TestDistributedScheduling extends BaseAMRMProxyE2ETest {
private static final Log LOG = private static final Log LOG =
LogFactory.getLog(TestDistributedScheduling.class); LogFactory.getLog(TestDistributedScheduling.class);
protected MiniYARNCluster cluster;
protected YarnClient rmClient;
protected ApplicationMasterProtocol client;
protected Configuration conf;
protected Configuration yarnConf;
protected ApplicationAttemptId attemptId;
protected ApplicationId appId;
@Before
public void doBefore() throws Exception {
cluster = new MiniYARNCluster("testDistributedSchedulingE2E", 1, 1, 1);
conf = new YarnConfiguration();
conf.setBoolean(YarnConfiguration.AMRM_PROXY_ENABLED, true);
conf.setBoolean(YarnConfiguration.DIST_SCHEDULING_ENABLED, true);
conf.setBoolean(YarnConfiguration.NM_CONTAINER_QUEUING_ENABLED, true);
cluster.init(conf);
cluster.start();
yarnConf = cluster.getConfig();
// the client has to connect to AMRMProxy
yarnConf.set(YarnConfiguration.RM_SCHEDULER_ADDRESS,
YarnConfiguration.DEFAULT_AMRM_PROXY_ADDRESS);
rmClient = YarnClient.createYarnClient();
rmClient.init(yarnConf);
rmClient.start();
// Submit application
attemptId = createApp(rmClient, cluster, conf);
appId = attemptId.getApplicationId();
client = createAMRMProtocol(rmClient, appId, cluster, yarnConf);
}
@After
public void doAfter() throws Exception {
if (client != null) {
try {
client.finishApplicationMaster(FinishApplicationMasterRequest
.newInstance(FinalApplicationStatus.SUCCEEDED, "success", null));
rmClient.killApplication(attemptId.getApplicationId());
attemptId = null;
} catch (Exception e) {
}
}
if (rmClient != null) {
try {
rmClient.stop();
} catch (Exception e) {
}
}
if (cluster != null) {
try {
cluster.stop();
} catch (Exception e) {
}
}
}
/** /**
* Validates if Allocate Requests containing only OPPORTUNISTIC container * Validates if Allocate Requests containing only OPPORTUNISTIC container
* requests are satisfied instantly. * requests are satisfied instantly.
@ -70,104 +151,63 @@ public class TestDistributedScheduling extends TestAMRMProxy {
*/ */
@Test(timeout = 60000) @Test(timeout = 60000)
public void testOpportunisticExecutionTypeRequestE2E() throws Exception { public void testOpportunisticExecutionTypeRequestE2E() throws Exception {
MiniYARNCluster cluster = LOG.info("testDistributedSchedulingE2E - Register");
new MiniYARNCluster("testDistributedSchedulingE2E", 1, 1, 1);
YarnClient rmClient = null;
ApplicationMasterProtocol client;
try { RegisterApplicationMasterResponse responseRegister =
Configuration conf = new YarnConfiguration(); client.registerApplicationMaster(RegisterApplicationMasterRequest
conf.setBoolean(YarnConfiguration.AMRM_PROXY_ENABLED, true); .newInstance(NetUtils.getHostname(), 1024, ""));
conf.setBoolean(YarnConfiguration.DIST_SCHEDULING_ENABLED, true);
conf.setBoolean(YarnConfiguration.NM_CONTAINER_QUEUING_ENABLED, true);
cluster.init(conf);
cluster.start();
final Configuration yarnConf = cluster.getConfig();
// the client has to connect to AMRMProxy Assert.assertNotNull(responseRegister);
Assert.assertNotNull(responseRegister.getQueue());
Assert.assertNotNull(responseRegister.getApplicationACLs());
Assert.assertNotNull(responseRegister.getClientToAMTokenMasterKey());
Assert
.assertNotNull(responseRegister.getContainersFromPreviousAttempts());
Assert.assertNotNull(responseRegister.getSchedulerResourceTypes());
Assert.assertNotNull(responseRegister.getMaximumResourceCapability());
yarnConf.set(YarnConfiguration.RM_SCHEDULER_ADDRESS, RMApp rmApp =
YarnConfiguration.DEFAULT_AMRM_PROXY_ADDRESS); cluster.getResourceManager().getRMContext().getRMApps().get(appId);
rmClient = YarnClient.createYarnClient(); Assert.assertEquals(RMAppState.RUNNING, rmApp.getState());
rmClient.init(yarnConf);
rmClient.start();
// Submit application LOG.info("testDistributedSchedulingE2E - Allocate");
ApplicationId appId = createApp(rmClient, cluster); AllocateRequest request =
createAllocateRequest(rmClient.getNodeReports(NodeState.RUNNING));
client = createAMRMProtocol(rmClient, appId, cluster, yarnConf); // Replace 'ANY' requests with OPPORTUNISTIC aks and remove
// everything else
LOG.info("testDistributedSchedulingE2E - Register"); List<ResourceRequest> newAskList = new ArrayList<>();
for (ResourceRequest rr : request.getAskList()) {
RegisterApplicationMasterResponse responseRegister = if (ResourceRequest.ANY.equals(rr.getResourceName())) {
client.registerApplicationMaster(RegisterApplicationMasterRequest ResourceRequest newRR = ResourceRequest.newInstance(rr
.newInstance(NetUtils.getHostname(), 1024, "")); .getPriority(), rr.getResourceName(),
rr.getCapability(), rr.getNumContainers(), rr.getRelaxLocality(),
Assert.assertNotNull(responseRegister); rr.getNodeLabelExpression(),
Assert.assertNotNull(responseRegister.getQueue()); ExecutionTypeRequest.newInstance(
Assert.assertNotNull(responseRegister.getApplicationACLs()); ExecutionType.OPPORTUNISTIC, true));
Assert.assertNotNull(responseRegister.getClientToAMTokenMasterKey()); newAskList.add(newRR);
Assert
.assertNotNull(responseRegister.getContainersFromPreviousAttempts());
Assert.assertNotNull(responseRegister.getSchedulerResourceTypes());
Assert.assertNotNull(responseRegister.getMaximumResourceCapability());
RMApp rmApp =
cluster.getResourceManager().getRMContext().getRMApps().get(appId);
Assert.assertEquals(RMAppState.RUNNING, rmApp.getState());
LOG.info("testDistributedSchedulingE2E - Allocate");
AllocateRequest request =
createAllocateRequest(rmClient.getNodeReports(NodeState.RUNNING));
// Replace 'ANY' requests with OPPORTUNISTIC aks and remove
// everything else
List<ResourceRequest> newAskList = new ArrayList<>();
for (ResourceRequest rr : request.getAskList()) {
if (ResourceRequest.ANY.equals(rr.getResourceName())) {
ResourceRequest newRR = ResourceRequest.newInstance(rr
.getPriority(), rr.getResourceName(),
rr.getCapability(), rr.getNumContainers(), rr.getRelaxLocality(),
rr.getNodeLabelExpression(),
ExecutionTypeRequest.newInstance(
ExecutionType.OPPORTUNISTIC, true));
newAskList.add(newRR);
}
} }
request.setAskList(newAskList);
AllocateResponse allocResponse = client.allocate(request);
Assert.assertNotNull(allocResponse);
// Ensure that all the requests are satisfied immediately
Assert.assertEquals(2, allocResponse.getAllocatedContainers().size());
// Verify that the allocated containers are OPPORTUNISTIC
for (Container allocatedContainer : allocResponse
.getAllocatedContainers()) {
ContainerTokenIdentifier containerTokenIdentifier = BuilderUtils
.newContainerTokenIdentifier(
allocatedContainer.getContainerToken());
Assert.assertEquals(ExecutionType.OPPORTUNISTIC,
containerTokenIdentifier.getExecutionType());
}
LOG.info("testDistributedSchedulingE2E - Finish");
FinishApplicationMasterResponse responseFinish =
client.finishApplicationMaster(FinishApplicationMasterRequest
.newInstance(FinalApplicationStatus.SUCCEEDED, "success", null));
Assert.assertNotNull(responseFinish);
} finally {
if (rmClient != null) {
rmClient.stop();
}
cluster.stop();
} }
request.setAskList(newAskList);
AllocateResponse allocResponse = client.allocate(request);
Assert.assertNotNull(allocResponse);
// Ensure that all the requests are satisfied immediately
Assert.assertEquals(2, allocResponse.getAllocatedContainers().size());
// Verify that the allocated containers are OPPORTUNISTIC
for (Container allocatedContainer : allocResponse
.getAllocatedContainers()) {
ContainerTokenIdentifier containerTokenIdentifier = BuilderUtils
.newContainerTokenIdentifier(
allocatedContainer.getContainerToken());
Assert.assertEquals(ExecutionType.OPPORTUNISTIC,
containerTokenIdentifier.getExecutionType());
}
LOG.info("testDistributedSchedulingE2E - Finish");
} }
/** /**
@ -178,135 +218,305 @@ public class TestDistributedScheduling extends TestAMRMProxy {
*/ */
@Test(timeout = 60000) @Test(timeout = 60000)
public void testMixedExecutionTypeRequestE2E() throws Exception { public void testMixedExecutionTypeRequestE2E() throws Exception {
MiniYARNCluster cluster = LOG.info("testDistributedSchedulingE2E - Register");
new MiniYARNCluster("testDistributedSchedulingE2E", 1, 1, 1);
YarnClient rmClient = null;
ApplicationMasterProtocol client;
RegisterApplicationMasterResponse responseRegister =
client.registerApplicationMaster(RegisterApplicationMasterRequest
.newInstance(NetUtils.getHostname(), 1024, ""));
Assert.assertNotNull(responseRegister);
Assert.assertNotNull(responseRegister.getQueue());
Assert.assertNotNull(responseRegister.getApplicationACLs());
Assert.assertNotNull(responseRegister.getClientToAMTokenMasterKey());
Assert
.assertNotNull(responseRegister.getContainersFromPreviousAttempts());
Assert.assertNotNull(responseRegister.getSchedulerResourceTypes());
Assert.assertNotNull(responseRegister.getMaximumResourceCapability());
RMApp rmApp =
cluster.getResourceManager().getRMContext().getRMApps().get(appId);
Assert.assertEquals(RMAppState.RUNNING, rmApp.getState());
LOG.info("testDistributedSchedulingE2E - Allocate");
AllocateRequest request =
createAllocateRequest(rmClient.getNodeReports(NodeState.RUNNING));
List<ResourceRequest> askList = request.getAskList();
List<ResourceRequest> newAskList = new ArrayList<>(askList);
// Duplicate all ANY requests marking them as opportunistic
for (ResourceRequest rr : askList) {
if (ResourceRequest.ANY.equals(rr.getResourceName())) {
ResourceRequest newRR = ResourceRequest.newInstance(rr
.getPriority(), rr.getResourceName(),
rr.getCapability(), rr.getNumContainers(), rr.getRelaxLocality(),
rr.getNodeLabelExpression(),
ExecutionTypeRequest.newInstance(
ExecutionType.OPPORTUNISTIC, true));
newAskList.add(newRR);
}
}
request.setAskList(newAskList);
AllocateResponse allocResponse = client.allocate(request);
Assert.assertNotNull(allocResponse);
// Ensure that all the requests are satisfied immediately
Assert.assertEquals(2, allocResponse.getAllocatedContainers().size());
// Verify that the allocated containers are OPPORTUNISTIC
for (Container allocatedContainer : allocResponse
.getAllocatedContainers()) {
ContainerTokenIdentifier containerTokenIdentifier = BuilderUtils
.newContainerTokenIdentifier(
allocatedContainer.getContainerToken());
Assert.assertEquals(ExecutionType.OPPORTUNISTIC,
containerTokenIdentifier.getExecutionType());
}
request.setAskList(new ArrayList<ResourceRequest>());
request.setResponseId(request.getResponseId() + 1);
Thread.sleep(1000);
// RM should allocate GUARANTEED containers within 2 calls to allocate()
allocResponse = client.allocate(request);
Assert.assertNotNull(allocResponse);
Assert.assertEquals(2, allocResponse.getAllocatedContainers().size());
// Verify that the allocated containers are GUARANTEED
for (Container allocatedContainer : allocResponse
.getAllocatedContainers()) {
ContainerTokenIdentifier containerTokenIdentifier = BuilderUtils
.newContainerTokenIdentifier(
allocatedContainer.getContainerToken());
Assert.assertEquals(ExecutionType.GUARANTEED,
containerTokenIdentifier.getExecutionType());
}
LOG.info("testDistributedSchedulingE2E - Finish");
}
/**
* Validates if AMRMClient can be used with Distributed Scheduling turned on.
*
* @throws Exception
*/
@Test(timeout = 120000)
@SuppressWarnings("unchecked")
public void testAMRMClient() throws Exception {
AMRMClientImpl<AMRMClient.ContainerRequest> amClient = null;
try { try {
Configuration conf = new YarnConfiguration(); Priority priority = Priority.newInstance(1);
conf.setBoolean(YarnConfiguration.AMRM_PROXY_ENABLED, true); Priority priority2 = Priority.newInstance(2);
conf.setBoolean(YarnConfiguration.DIST_SCHEDULING_ENABLED, true); Resource capability = Resource.newInstance(1024, 1);
conf.setBoolean(YarnConfiguration.NM_CONTAINER_QUEUING_ENABLED, true);
cluster.init(conf);
cluster.start();
final Configuration yarnConf = cluster.getConfig();
// the client has to connect to AMRMProxy List<NodeReport> nodeReports = rmClient.getNodeReports(NodeState.RUNNING);
String node = nodeReports.get(0).getNodeId().getHost();
String rack = nodeReports.get(0).getRackName();
String[] nodes = new String[]{node};
String[] racks = new String[]{rack};
yarnConf.set(YarnConfiguration.RM_SCHEDULER_ADDRESS, // start am rm client
YarnConfiguration.DEFAULT_AMRM_PROXY_ADDRESS); amClient = new AMRMClientImpl(client);
rmClient = YarnClient.createYarnClient(); amClient.init(yarnConf);
rmClient.init(yarnConf); amClient.start();
rmClient.start(); amClient.registerApplicationMaster(NetUtils.getHostname(), 1024, "");
// Submit application assertEquals(0, amClient.ask.size());
assertEquals(0, amClient.release.size());
ApplicationId appId = createApp(rmClient, cluster); amClient.addContainerRequest(
new AMRMClient.ContainerRequest(capability, nodes, racks, priority));
client = createAMRMProtocol(rmClient, appId, cluster, yarnConf); amClient.addContainerRequest(
new AMRMClient.ContainerRequest(capability, nodes, racks, priority));
LOG.info("testDistributedSchedulingE2E - Register"); amClient.addContainerRequest(
new AMRMClient.ContainerRequest(capability, nodes, racks, priority));
RegisterApplicationMasterResponse responseRegister = amClient.addContainerRequest(
client.registerApplicationMaster(RegisterApplicationMasterRequest new AMRMClient.ContainerRequest(capability, nodes, racks, priority));
.newInstance(NetUtils.getHostname(), 1024, "")); amClient.addContainerRequest(
new AMRMClient.ContainerRequest(capability, null, null, priority2,
Assert.assertNotNull(responseRegister); true, null,
Assert.assertNotNull(responseRegister.getQueue());
Assert.assertNotNull(responseRegister.getApplicationACLs());
Assert.assertNotNull(responseRegister.getClientToAMTokenMasterKey());
Assert
.assertNotNull(responseRegister.getContainersFromPreviousAttempts());
Assert.assertNotNull(responseRegister.getSchedulerResourceTypes());
Assert.assertNotNull(responseRegister.getMaximumResourceCapability());
RMApp rmApp =
cluster.getResourceManager().getRMContext().getRMApps().get(appId);
Assert.assertEquals(RMAppState.RUNNING, rmApp.getState());
LOG.info("testDistributedSchedulingE2E - Allocate");
AllocateRequest request =
createAllocateRequest(rmClient.getNodeReports(NodeState.RUNNING));
List<ResourceRequest> askList = request.getAskList();
List<ResourceRequest> newAskList = new ArrayList<>(askList);
// Duplicate all ANY requests marking them as opportunistic
for (ResourceRequest rr : askList) {
if (ResourceRequest.ANY.equals(rr.getResourceName())) {
ResourceRequest newRR = ResourceRequest.newInstance(rr
.getPriority(), rr.getResourceName(),
rr.getCapability(), rr.getNumContainers(), rr.getRelaxLocality(),
rr.getNodeLabelExpression(),
ExecutionTypeRequest.newInstance( ExecutionTypeRequest.newInstance(
ExecutionType.OPPORTUNISTIC, true)); ExecutionType.OPPORTUNISTIC, true)));
newAskList.add(newRR); amClient.addContainerRequest(
new AMRMClient.ContainerRequest(capability, null, null, priority2,
true, null,
ExecutionTypeRequest.newInstance(
ExecutionType.OPPORTUNISTIC, true)));
amClient.removeContainerRequest(
new AMRMClient.ContainerRequest(capability, nodes, racks, priority));
amClient.removeContainerRequest(
new AMRMClient.ContainerRequest(capability, nodes, racks, priority));
amClient.removeContainerRequest(
new AMRMClient.ContainerRequest(capability, null, null, priority2,
true, null,
ExecutionTypeRequest.newInstance(
ExecutionType.OPPORTUNISTIC, true)));
int containersRequestedNode = amClient.remoteRequestsTable.get(priority,
node, ExecutionType.GUARANTEED, capability).remoteRequest
.getNumContainers();
int containersRequestedRack = amClient.remoteRequestsTable.get(priority,
rack, ExecutionType.GUARANTEED, capability).remoteRequest
.getNumContainers();
int containersRequestedAny = amClient.remoteRequestsTable.get(priority,
ResourceRequest.ANY, ExecutionType.GUARANTEED, capability)
.remoteRequest.getNumContainers();
int oppContainersRequestedAny =
amClient.remoteRequestsTable.get(priority2, ResourceRequest.ANY,
ExecutionType.OPPORTUNISTIC, capability).remoteRequest
.getNumContainers();
assertEquals(2, containersRequestedNode);
assertEquals(2, containersRequestedRack);
assertEquals(2, containersRequestedAny);
assertEquals(1, oppContainersRequestedAny);
assertEquals(4, amClient.ask.size());
assertEquals(0, amClient.release.size());
// RM should allocate container within 2 calls to allocate()
int allocatedContainerCount = 0;
int iterationsLeft = 10;
Set<ContainerId> releases = new TreeSet<>();
amClient.getNMTokenCache().clearCache();
Assert.assertEquals(0,
amClient.getNMTokenCache().numberOfTokensInCache());
HashMap<String, Token> receivedNMTokens = new HashMap<>();
while (allocatedContainerCount <
(containersRequestedAny + oppContainersRequestedAny)
&& iterationsLeft-- > 0) {
AllocateResponse allocResponse = amClient.allocate(0.1f);
assertEquals(0, amClient.ask.size());
assertEquals(0, amClient.release.size());
allocatedContainerCount += allocResponse.getAllocatedContainers()
.size();
for (Container container : allocResponse.getAllocatedContainers()) {
ContainerId rejectContainerId = container.getId();
releases.add(rejectContainerId);
}
for (NMToken token : allocResponse.getNMTokens()) {
String nodeID = token.getNodeId().toString();
receivedNMTokens.put(nodeID, token.getToken());
}
if (allocatedContainerCount < containersRequestedAny) {
// sleep to let NM's heartbeat to RM and trigger allocations
sleep(100);
} }
} }
request.setAskList(newAskList);
AllocateResponse allocResponse = client.allocate(request); assertEquals(allocatedContainerCount,
Assert.assertNotNull(allocResponse); containersRequestedAny + oppContainersRequestedAny);
for (ContainerId rejectContainerId : releases) {
amClient.releaseAssignedContainer(rejectContainerId);
}
assertEquals(3, amClient.release.size());
assertEquals(0, amClient.ask.size());
// Ensure that all the requests are satisfied immediately // need to tell the AMRMClient that we dont need these resources anymore
Assert.assertEquals(2, allocResponse.getAllocatedContainers().size()); amClient.removeContainerRequest(
new AMRMClient.ContainerRequest(capability, nodes, racks, priority));
amClient.removeContainerRequest(
new AMRMClient.ContainerRequest(capability, nodes, racks, priority));
amClient.removeContainerRequest(
new AMRMClient.ContainerRequest(capability, nodes, racks, priority2,
true, null,
ExecutionTypeRequest.newInstance(
ExecutionType.OPPORTUNISTIC, true)));
assertEquals(4, amClient.ask.size());
// Verify that the allocated containers are OPPORTUNISTIC // test RPC exception handling
for (Container allocatedContainer : allocResponse amClient.addContainerRequest(new AMRMClient.ContainerRequest(capability,
.getAllocatedContainers()) { nodes, racks, priority));
ContainerTokenIdentifier containerTokenIdentifier = BuilderUtils amClient.addContainerRequest(new AMRMClient.ContainerRequest(capability,
.newContainerTokenIdentifier( nodes, racks, priority));
allocatedContainer.getContainerToken()); amClient.addContainerRequest(
Assert.assertEquals(ExecutionType.OPPORTUNISTIC, new AMRMClient.ContainerRequest(capability, nodes, racks, priority2,
containerTokenIdentifier.getExecutionType()); true, null,
ExecutionTypeRequest.newInstance(
ExecutionType.OPPORTUNISTIC, true)));
final AMRMClient amc = amClient;
ApplicationMasterProtocol realRM = amClient.rmClient;
try {
ApplicationMasterProtocol mockRM = mock(ApplicationMasterProtocol
.class);
when(mockRM.allocate(any(AllocateRequest.class))).thenAnswer(
new Answer<AllocateResponse>() {
public AllocateResponse answer(InvocationOnMock invocation)
throws Exception {
amc.removeContainerRequest(
new AMRMClient.ContainerRequest(capability, nodes,
racks, priority));
amc.removeContainerRequest(
new AMRMClient.ContainerRequest(capability, nodes, racks,
priority));
amc.removeContainerRequest(
new AMRMClient.ContainerRequest(capability, null, null,
priority2, true, null,
ExecutionTypeRequest.newInstance(
ExecutionType.OPPORTUNISTIC, true)));
throw new Exception();
}
});
amClient.rmClient = mockRM;
amClient.allocate(0.1f);
} catch (Exception ioe) {
} finally {
amClient.rmClient = realRM;
} }
request.setAskList(new ArrayList<ResourceRequest>()); assertEquals(3, amClient.release.size());
request.setResponseId(request.getResponseId() + 1); assertEquals(6, amClient.ask.size());
Thread.sleep(1000); iterationsLeft = 3;
// do a few iterations to ensure RM is not going send new containers
// RM should allocate GUARANTEED containers within 2 calls to allocate() while (iterationsLeft-- > 0) {
allocResponse = client.allocate(request); // inform RM of rejection
Assert.assertNotNull(allocResponse); AllocateResponse allocResponse = amClient.allocate(0.1f);
Assert.assertEquals(2, allocResponse.getAllocatedContainers().size()); // RM did not send new containers because AM does not need any
assertEquals(0, allocResponse.getAllocatedContainers().size());
// Verify that the allocated containers are GUARANTEED if (allocResponse.getCompletedContainersStatuses().size() > 0) {
for (Container allocatedContainer : allocResponse for (ContainerStatus cStatus : allocResponse
.getAllocatedContainers()) { .getCompletedContainersStatuses()) {
ContainerTokenIdentifier containerTokenIdentifier = BuilderUtils if (releases.contains(cStatus.getContainerId())) {
.newContainerTokenIdentifier( assertEquals(cStatus.getState(), ContainerState.COMPLETE);
allocatedContainer.getContainerToken()); assertEquals(-100, cStatus.getExitStatus());
Assert.assertEquals(ExecutionType.GUARANTEED, releases.remove(cStatus.getContainerId());
containerTokenIdentifier.getExecutionType()); }
}
}
if (iterationsLeft > 0) {
// sleep to make sure NM's heartbeat
sleep(100);
}
} }
assertEquals(0, amClient.ask.size());
assertEquals(0, amClient.release.size());
LOG.info("testDistributedSchedulingE2E - Finish"); amClient.unregisterApplicationMaster(FinalApplicationStatus.SUCCEEDED,
null, null);
FinishApplicationMasterResponse responseFinish =
client.finishApplicationMaster(FinishApplicationMasterRequest
.newInstance(FinalApplicationStatus.SUCCEEDED, "success", null));
Assert.assertNotNull(responseFinish);
} finally { } finally {
if (rmClient != null) { if (amClient != null && amClient.getServiceState() == Service.STATE
rmClient.stop(); .STARTED) {
amClient.stop();
} }
cluster.stop();
} }
} }
@Ignore private void sleep(int sleepTime) {
@Override try {
public void testAMRMProxyE2E() throws Exception { } Thread.sleep(sleepTime);
} catch (InterruptedException e) {
@Ignore e.printStackTrace();
@Override }
public void testE2ETokenRenewal() throws Exception { } }
@Ignore
@Override
public void testE2ETokenSwap() throws Exception { }
} }

View File

@ -47,6 +47,7 @@ import org.apache.hadoop.yarn.api.records.ContainerExitStatus;
import org.apache.hadoop.yarn.api.records.ContainerLaunchContext; import org.apache.hadoop.yarn.api.records.ContainerLaunchContext;
import org.apache.hadoop.yarn.api.records.ContainerState; import org.apache.hadoop.yarn.api.records.ContainerState;
import org.apache.hadoop.yarn.api.records.ContainerStatus; import org.apache.hadoop.yarn.api.records.ContainerStatus;
import org.apache.hadoop.yarn.api.records.ExecutionType;
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus; import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
import org.apache.hadoop.yarn.api.records.NMToken; import org.apache.hadoop.yarn.api.records.NMToken;
import org.apache.hadoop.yarn.api.records.NodeReport; import org.apache.hadoop.yarn.api.records.NodeReport;
@ -251,9 +252,9 @@ public class TestNMClient {
racks, priority)); racks, priority));
} }
int containersRequestedAny = rmClient.remoteRequestsTable.get(priority) int containersRequestedAny = rmClient.remoteRequestsTable.get(priority,
.get(ResourceRequest.ANY).get(capability).remoteRequest ResourceRequest.ANY, ExecutionType.GUARANTEED, capability)
.getNumContainers(); .remoteRequest.getNumContainers();
// RM should allocate container within 2 calls to allocate() // RM should allocate container within 2 calls to allocate()
int allocatedContainerCount = 0; int allocatedContainerCount = 0;

View File

@ -214,7 +214,8 @@ public class ResourceRequestPBImpl extends ResourceRequest {
+ ", # Containers: " + getNumContainers() + ", # Containers: " + getNumContainers()
+ ", Location: " + getResourceName() + ", Location: " + getResourceName()
+ ", Relax Locality: " + getRelaxLocality() + ", Relax Locality: " + getRelaxLocality()
+ ", Execution Spec: " + getExecutionTypeRequest() + "}"; + ", Execution Type Request: " + getExecutionTypeRequest()
+ ", Node Label Expression: " + getNodeLabelExpression() + "}";
} }
@Override @Override
@ -235,4 +236,4 @@ public class ResourceRequestPBImpl extends ResourceRequest {
} }
builder.setNodeLabelExpression(nodeLabelExpression); builder.setNodeLabelExpression(nodeLabelExpression);
} }
} }