|
@@ -31,6 +31,8 @@ import static org.mockito.Mockito.when;
|
|
|
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.ByteBuffer;
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
+import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
import java.util.concurrent.ConcurrentMap;
|
|
import java.util.concurrent.ConcurrentMap;
|
|
@@ -50,6 +52,8 @@ import org.apache.hadoop.yarn.api.records.ApplicationAccessType;
|
|
import org.apache.hadoop.yarn.api.records.ApplicationId;
|
|
import org.apache.hadoop.yarn.api.records.ApplicationId;
|
|
import org.apache.hadoop.yarn.api.records.ApplicationSubmissionContext;
|
|
import org.apache.hadoop.yarn.api.records.ApplicationSubmissionContext;
|
|
import org.apache.hadoop.yarn.api.records.ContainerLaunchContext;
|
|
import org.apache.hadoop.yarn.api.records.ContainerLaunchContext;
|
|
|
|
+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;
|
|
@@ -57,11 +61,13 @@ import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
|
import org.apache.hadoop.yarn.event.AsyncDispatcher;
|
|
import org.apache.hadoop.yarn.event.AsyncDispatcher;
|
|
import org.apache.hadoop.yarn.event.Dispatcher;
|
|
import org.apache.hadoop.yarn.event.Dispatcher;
|
|
import org.apache.hadoop.yarn.event.EventHandler;
|
|
import org.apache.hadoop.yarn.event.EventHandler;
|
|
|
|
+import org.apache.hadoop.yarn.exceptions.InvalidResourceRequestException;
|
|
import org.apache.hadoop.yarn.exceptions.YarnException;
|
|
import org.apache.hadoop.yarn.exceptions.YarnException;
|
|
import org.apache.hadoop.yarn.factories.RecordFactory;
|
|
import org.apache.hadoop.yarn.factories.RecordFactory;
|
|
import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
|
|
import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.ahs.RMApplicationHistoryWriter;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.ahs.RMApplicationHistoryWriter;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.metrics.SystemMetricsPublisher;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.metrics.SystemMetricsPublisher;
|
|
|
|
+import org.apache.hadoop.yarn.server.resourcemanager.nodelabels.RMNodeLabelsManager;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.placement.PlacementManager;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.placement.PlacementManager;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.MockRMApp;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.MockRMApp;
|
|
@@ -72,6 +78,7 @@ import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppImpl;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppMetrics;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppMetrics;
|
|
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.AMLivelinessMonitor;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.AMLivelinessMonitor;
|
|
|
|
+import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptImpl;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.ContainerAllocationExpirer;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.rmcontainer.ContainerAllocationExpirer;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.YarnScheduler;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.YarnScheduler;
|
|
@@ -307,7 +314,7 @@ public class TestAppManager{
|
|
ResourceRequest resReg =
|
|
ResourceRequest resReg =
|
|
ResourceRequest.newInstance(Priority.newInstance(0),
|
|
ResourceRequest.newInstance(Priority.newInstance(0),
|
|
ResourceRequest.ANY, Resource.newInstance(1024, 1), 1);
|
|
ResourceRequest.ANY, Resource.newInstance(1024, 1), 1);
|
|
- sub.setAMContainerResourceRequest(resReg);
|
|
|
|
|
|
+ sub.setAMContainerResourceRequests(Collections.singletonList(resReg));
|
|
req.setApplicationSubmissionContext(sub);
|
|
req.setApplicationSubmissionContext(sub);
|
|
sub.setAMContainerSpec(mock(ContainerLaunchContext.class));
|
|
sub.setAMContainerSpec(mock(ContainerLaunchContext.class));
|
|
try {
|
|
try {
|
|
@@ -517,8 +524,157 @@ public class TestAppManager{
|
|
Assert.assertEquals("app event type is wrong before", RMAppEventType.KILL, appEventType);
|
|
Assert.assertEquals("app event type is wrong before", RMAppEventType.KILL, appEventType);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @SuppressWarnings("deprecation")
|
|
|
|
+ @Test
|
|
|
|
+ public void testRMAppSubmitAMContainerResourceRequests() throws Exception {
|
|
|
|
+ asContext.setResource(Resources.createResource(1024));
|
|
|
|
+ asContext.setAMContainerResourceRequest(
|
|
|
|
+ ResourceRequest.newInstance(Priority.newInstance(0),
|
|
|
|
+ ResourceRequest.ANY, Resources.createResource(1024), 1, true));
|
|
|
|
+ List<ResourceRequest> reqs = new ArrayList<>();
|
|
|
|
+ reqs.add(ResourceRequest.newInstance(Priority.newInstance(0),
|
|
|
|
+ ResourceRequest.ANY, Resources.createResource(1025), 1, false));
|
|
|
|
+ reqs.add(ResourceRequest.newInstance(Priority.newInstance(0),
|
|
|
|
+ "/rack", Resources.createResource(1025), 1, false));
|
|
|
|
+ reqs.add(ResourceRequest.newInstance(Priority.newInstance(0),
|
|
|
|
+ "/rack/node", Resources.createResource(1025), 1, true));
|
|
|
|
+ asContext.setAMContainerResourceRequests(cloneResourceRequests(reqs));
|
|
|
|
+ // getAMContainerResourceRequest uses the first entry of
|
|
|
|
+ // getAMContainerResourceRequests
|
|
|
|
+ Assert.assertEquals(reqs.get(0), asContext.getAMContainerResourceRequest());
|
|
|
|
+ Assert.assertEquals(reqs, asContext.getAMContainerResourceRequests());
|
|
|
|
+ RMApp app = testRMAppSubmit();
|
|
|
|
+ for (ResourceRequest req : reqs) {
|
|
|
|
+ req.setNodeLabelExpression(RMNodeLabelsManager.NO_LABEL);
|
|
|
|
+ }
|
|
|
|
+ // setAMContainerResourceRequests has priority over
|
|
|
|
+ // setAMContainerResourceRequest and setResource
|
|
|
|
+ Assert.assertEquals(reqs, app.getAMResourceRequests());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @SuppressWarnings("deprecation")
|
|
|
|
+ @Test
|
|
|
|
+ public void testRMAppSubmitAMContainerResourceRequest() throws Exception {
|
|
|
|
+ asContext.setResource(Resources.createResource(1024));
|
|
|
|
+ asContext.setAMContainerResourceRequests(null);
|
|
|
|
+ ResourceRequest req =
|
|
|
|
+ ResourceRequest.newInstance(Priority.newInstance(0),
|
|
|
|
+ ResourceRequest.ANY, Resources.createResource(1025), 1, true);
|
|
|
|
+ asContext.setAMContainerResourceRequest(cloneResourceRequest(req));
|
|
|
|
+ // getAMContainerResourceRequests uses a singleton list of
|
|
|
|
+ // getAMContainerResourceRequest
|
|
|
|
+ Assert.assertEquals(req, asContext.getAMContainerResourceRequest());
|
|
|
|
+ Assert.assertEquals(req, asContext.getAMContainerResourceRequests().get(0));
|
|
|
|
+ Assert.assertEquals(1, asContext.getAMContainerResourceRequests().size());
|
|
|
|
+ RMApp app = testRMAppSubmit();
|
|
|
|
+ req.setNodeLabelExpression(RMNodeLabelsManager.NO_LABEL);
|
|
|
|
+ // setAMContainerResourceRequest has priority over setResource
|
|
|
|
+ Assert.assertEquals(Collections.singletonList(req),
|
|
|
|
+ app.getAMResourceRequests());
|
|
|
|
+ }
|
|
|
|
+
|
|
@Test
|
|
@Test
|
|
- public void testRMAppSubmit() throws Exception {
|
|
|
|
|
|
+ public void testRMAppSubmitResource() throws Exception {
|
|
|
|
+ asContext.setResource(Resources.createResource(1024));
|
|
|
|
+ asContext.setAMContainerResourceRequests(null);
|
|
|
|
+ RMApp app = testRMAppSubmit();
|
|
|
|
+ // setResource
|
|
|
|
+ Assert.assertEquals(Collections.singletonList(
|
|
|
|
+ ResourceRequest.newInstance(RMAppAttemptImpl.AM_CONTAINER_PRIORITY,
|
|
|
|
+ ResourceRequest.ANY, Resources.createResource(1024), 1, true, "")),
|
|
|
|
+ app.getAMResourceRequests());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Test
|
|
|
|
+ public void testRMAppSubmitNoResourceRequests() throws Exception {
|
|
|
|
+ asContext.setResource(null);
|
|
|
|
+ asContext.setAMContainerResourceRequests(null);
|
|
|
|
+ try {
|
|
|
|
+ testRMAppSubmit();
|
|
|
|
+ Assert.fail("Should have failed due to no ResourceRequest");
|
|
|
|
+ } catch (InvalidResourceRequestException e) {
|
|
|
|
+ Assert.assertEquals(
|
|
|
|
+ "Invalid resource request, no resources requested",
|
|
|
|
+ e.getMessage());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Test
|
|
|
|
+ public void testRMAppSubmitAMContainerResourceRequestsDisagree()
|
|
|
|
+ throws Exception {
|
|
|
|
+ asContext.setResource(null);
|
|
|
|
+ List<ResourceRequest> reqs = new ArrayList<>();
|
|
|
|
+ ResourceRequest anyReq = ResourceRequest.newInstance(
|
|
|
|
+ Priority.newInstance(1),
|
|
|
|
+ ResourceRequest.ANY, Resources.createResource(1024), 1, false, "label1",
|
|
|
|
+ ExecutionTypeRequest.newInstance(ExecutionType.GUARANTEED));
|
|
|
|
+ reqs.add(anyReq);
|
|
|
|
+ reqs.add(ResourceRequest.newInstance(Priority.newInstance(2),
|
|
|
|
+ "/rack", Resources.createResource(1025), 2, false, "",
|
|
|
|
+ ExecutionTypeRequest.newInstance(ExecutionType.OPPORTUNISTIC)));
|
|
|
|
+ reqs.add(ResourceRequest.newInstance(Priority.newInstance(3),
|
|
|
|
+ "/rack/node", Resources.createResource(1026), 3, true, "",
|
|
|
|
+ ExecutionTypeRequest.newInstance(ExecutionType.OPPORTUNISTIC)));
|
|
|
|
+ asContext.setAMContainerResourceRequests(cloneResourceRequests(reqs));
|
|
|
|
+ RMApp app = testRMAppSubmit();
|
|
|
|
+ // It should force the requests to all agree on these points
|
|
|
|
+ for (ResourceRequest req : reqs) {
|
|
|
|
+ req.setCapability(anyReq.getCapability());
|
|
|
|
+ req.setExecutionTypeRequest(
|
|
|
|
+ ExecutionTypeRequest.newInstance(ExecutionType.GUARANTEED));
|
|
|
|
+ req.setNumContainers(1);
|
|
|
|
+ req.setPriority(Priority.newInstance(0));
|
|
|
|
+ }
|
|
|
|
+ Assert.assertEquals(reqs, app.getAMResourceRequests());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Test
|
|
|
|
+ public void testRMAppSubmitAMContainerResourceRequestsNoAny()
|
|
|
|
+ throws Exception {
|
|
|
|
+ asContext.setResource(null);
|
|
|
|
+ List<ResourceRequest> reqs = new ArrayList<>();
|
|
|
|
+ reqs.add(ResourceRequest.newInstance(Priority.newInstance(1),
|
|
|
|
+ "/rack", Resources.createResource(1025), 1, false));
|
|
|
|
+ reqs.add(ResourceRequest.newInstance(Priority.newInstance(1),
|
|
|
|
+ "/rack/node", Resources.createResource(1025), 1, true));
|
|
|
|
+ asContext.setAMContainerResourceRequests(cloneResourceRequests(reqs));
|
|
|
|
+ // getAMContainerResourceRequest uses the first entry of
|
|
|
|
+ // getAMContainerResourceRequests
|
|
|
|
+ Assert.assertEquals(reqs, asContext.getAMContainerResourceRequests());
|
|
|
|
+ try {
|
|
|
|
+ testRMAppSubmit();
|
|
|
|
+ Assert.fail("Should have failed due to missing ANY ResourceRequest");
|
|
|
|
+ } catch (InvalidResourceRequestException e) {
|
|
|
|
+ Assert.assertEquals(
|
|
|
|
+ "Invalid resource request, no resource request specified with *",
|
|
|
|
+ e.getMessage());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Test
|
|
|
|
+ public void testRMAppSubmitAMContainerResourceRequestsTwoManyAny()
|
|
|
|
+ throws Exception {
|
|
|
|
+ asContext.setResource(null);
|
|
|
|
+ List<ResourceRequest> reqs = new ArrayList<>();
|
|
|
|
+ reqs.add(ResourceRequest.newInstance(Priority.newInstance(1),
|
|
|
|
+ ResourceRequest.ANY, Resources.createResource(1025), 1, false));
|
|
|
|
+ reqs.add(ResourceRequest.newInstance(Priority.newInstance(1),
|
|
|
|
+ ResourceRequest.ANY, Resources.createResource(1025), 1, false));
|
|
|
|
+ asContext.setAMContainerResourceRequests(cloneResourceRequests(reqs));
|
|
|
|
+ // getAMContainerResourceRequest uses the first entry of
|
|
|
|
+ // getAMContainerResourceRequests
|
|
|
|
+ Assert.assertEquals(reqs, asContext.getAMContainerResourceRequests());
|
|
|
|
+ try {
|
|
|
|
+ testRMAppSubmit();
|
|
|
|
+ Assert.fail("Should have failed due to too many ANY ResourceRequests");
|
|
|
|
+ } catch (InvalidResourceRequestException e) {
|
|
|
|
+ Assert.assertEquals(
|
|
|
|
+ "Invalid resource request, only one resource request with * is " +
|
|
|
|
+ "allowed", e.getMessage());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private RMApp testRMAppSubmit() throws Exception {
|
|
appMonitor.submitApplication(asContext, "test");
|
|
appMonitor.submitApplication(asContext, "test");
|
|
RMApp app = rmContext.getRMApps().get(appId);
|
|
RMApp app = rmContext.getRMApps().get(appId);
|
|
Assert.assertNotNull("app is null", app);
|
|
Assert.assertNotNull("app is null", app);
|
|
@@ -529,12 +685,14 @@ public class TestAppManager{
|
|
|
|
|
|
// wait for event to be processed
|
|
// wait for event to be processed
|
|
int timeoutSecs = 0;
|
|
int timeoutSecs = 0;
|
|
- while ((getAppEventType() == RMAppEventType.KILL) &&
|
|
|
|
|
|
+ while ((getAppEventType() == RMAppEventType.KILL) &&
|
|
timeoutSecs++ < 20) {
|
|
timeoutSecs++ < 20) {
|
|
Thread.sleep(1000);
|
|
Thread.sleep(1000);
|
|
}
|
|
}
|
|
Assert.assertEquals("app event type sent is wrong", RMAppEventType.START,
|
|
Assert.assertEquals("app event type sent is wrong", RMAppEventType.START,
|
|
getAppEventType());
|
|
getAppEventType());
|
|
|
|
+
|
|
|
|
+ return app;
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
@Test
|
|
@@ -732,6 +890,15 @@ public class TestAppManager{
|
|
ResourceCalculator rs = mock(ResourceCalculator.class);
|
|
ResourceCalculator rs = mock(ResourceCalculator.class);
|
|
when(scheduler.getResourceCalculator()).thenReturn(rs);
|
|
when(scheduler.getResourceCalculator()).thenReturn(rs);
|
|
|
|
|
|
|
|
+ when(scheduler.getNormalizedResource((Resource) any()))
|
|
|
|
+ .thenAnswer(new Answer<Resource>() {
|
|
|
|
+ @Override
|
|
|
|
+ public Resource answer(InvocationOnMock invocationOnMock)
|
|
|
|
+ throws Throwable {
|
|
|
|
+ return (Resource) invocationOnMock.getArguments()[0];
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
return scheduler;
|
|
return scheduler;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -748,4 +915,26 @@ public class TestAppManager{
|
|
YarnConfiguration.DEFAULT_RM_SCHEDULER_MINIMUM_ALLOCATION_MB);
|
|
YarnConfiguration.DEFAULT_RM_SCHEDULER_MINIMUM_ALLOCATION_MB);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private static ResourceRequest cloneResourceRequest(ResourceRequest req) {
|
|
|
|
+ return ResourceRequest.newInstance(
|
|
|
|
+ Priority.newInstance(req.getPriority().getPriority()),
|
|
|
|
+ new String(req.getResourceName()),
|
|
|
|
+ Resource.newInstance(req.getCapability().getMemorySize(),
|
|
|
|
+ req.getCapability().getVirtualCores()),
|
|
|
|
+ req.getNumContainers(),
|
|
|
|
+ req.getRelaxLocality(),
|
|
|
|
+ req.getNodeLabelExpression() != null
|
|
|
|
+ ? new String(req.getNodeLabelExpression()) : null,
|
|
|
|
+ ExecutionTypeRequest.newInstance(
|
|
|
|
+ req.getExecutionTypeRequest().getExecutionType()));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static List<ResourceRequest> cloneResourceRequests(
|
|
|
|
+ List<ResourceRequest> reqs) {
|
|
|
|
+ List<ResourceRequest> cloneReqs = new ArrayList<>();
|
|
|
|
+ for (ResourceRequest req : reqs) {
|
|
|
|
+ cloneReqs.add(cloneResourceRequest(req));
|
|
|
|
+ }
|
|
|
|
+ return cloneReqs;
|
|
|
|
+ }
|
|
}
|
|
}
|