diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/AllocateRequest.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/AllocateRequest.java index da68d8c517e..8f6a2048cd0 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/AllocateRequest.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/AllocateRequest.java @@ -100,7 +100,21 @@ public static AllocateRequest newInstance(int responseID, float appProgress, allocateRequest.setIncreaseRequests(increaseRequests); return allocateRequest; } - + + @Public + @Unstable + public static AllocateRequest newInstance(int responseID, float appProgress, + List resourceAsk, + List containersToBeReleased, + ResourceBlacklistRequest resourceBlacklistRequest, + String trackingUrl) { + return AllocateRequest.newBuilder().responseId(responseID) + .progress(appProgress).askList(resourceAsk) + .releaseList(containersToBeReleased) + .resourceBlacklistRequest(resourceBlacklistRequest) + .trackingUrl(trackingUrl).build(); + } + @Public @Unstable public static AllocateRequest newInstance(int responseID, float appProgress, @@ -256,6 +270,22 @@ public abstract void setIncreaseRequests( public abstract void setUpdateRequests( List updateRequests); + /** + * Get the tracking url update for this heartbeat. + * @return tracking url to update this application with + */ + @Public + @Unstable + public abstract String getTrackingUrl(); + + /** + * Set the new tracking url for this application. + * @param trackingUrl the new tracking url + */ + @Public + @Unstable + public abstract void setTrackingUrl(String trackingUrl); + @Public @Unstable public static AllocateRequestBuilder newBuilder() { @@ -358,6 +388,19 @@ public AllocateRequestBuilder updateRequests( } /** + * Set the trackingUrl of the request. + * @see AllocateRequest#setTrackingUrl(String) + * @param trackingUrl new tracking url + * @return {@link AllocateRequestBuilder} + */ + @Public + @Unstable + public AllocateRequestBuilder trackingUrl(String trackingUrl) { + allocateRequest.setTrackingUrl(trackingUrl); + return this; + } + + /** * Return generated {@link AllocateRequest} object. * @return {@link AllocateRequest} */ @@ -367,4 +410,4 @@ public AllocateRequest build() { return allocateRequest; } } -} \ No newline at end of file +} diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/proto/yarn_service_protos.proto hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/proto/yarn_service_protos.proto index 8301971f6d2..a5fc568b34d 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/proto/yarn_service_protos.proto +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/proto/yarn_service_protos.proto @@ -89,6 +89,7 @@ message AllocateRequestProto { optional float progress = 5; repeated ContainerResourceIncreaseRequestProto increase_request = 6; repeated UpdateContainerRequestProto update_requests = 7; + optional string tracking_url = 11; } message NMTokenProto { diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/AMRMClient.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/AMRMClient.java index b8eb58cdc0f..989a7e009f3 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/AMRMClient.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/AMRMClient.java @@ -701,6 +701,17 @@ public TimelineV2Client getRegisteredTimelineV2Client() { } /** + * Update application's tracking url on next heartbeat. + * + * @param trackingUrl new tracking url for this application + */ + @Public + @InterfaceStability.Unstable + public void updateTrackingUrl(String trackingUrl) { + // Unimplemented. + } + + /** * Wait for check to return true for each 1000 ms. * See also {@link #waitFor(com.google.common.base.Supplier, int)} * and {@link #waitFor(com.google.common.base.Supplier, int, int)} diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/async/AMRMClientAsync.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/async/AMRMClientAsync.java index 1ecfe1f588c..54d7cfd367e 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/async/AMRMClientAsync.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/async/AMRMClientAsync.java @@ -374,6 +374,17 @@ public abstract void updateBlacklist(List blacklistAdditions, List blacklistRemovals); /** + * Update application's tracking url on next heartbeat. + * + * @param trackingUrl new tracking url for this application + */ + @Public + @Unstable + public void updateTrackingUrl(String trackingUrl) { + // Unimplemented. + } + + /** * Wait for check to return true for each 1000 ms. * See also {@link #waitFor(com.google.common.base.Supplier, int)} * and {@link #waitFor(com.google.common.base.Supplier, int, int)} diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/async/impl/AMRMClientAsyncImpl.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/async/impl/AMRMClientAsyncImpl.java index 05132113e14..0a01514056c 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/async/impl/AMRMClientAsyncImpl.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/async/impl/AMRMClientAsyncImpl.java @@ -250,6 +250,11 @@ public void updateBlacklist(List blacklistAdditions, List blacklistRemovals) { client.updateBlacklist(blacklistAdditions, blacklistRemovals); } + + @Override + public void updateTrackingUrl(String trackingUrl) { + client.updateTrackingUrl(trackingUrl); + } private class HeartbeatThread extends Thread { public HeartbeatThread() { diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/AMRMClientImpl.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/AMRMClientImpl.java index e4561db42c5..8217e34ba52 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/AMRMClientImpl.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/impl/AMRMClientImpl.java @@ -94,6 +94,7 @@ protected String appHostName; protected int appHostPort; protected String appTrackingUrl; + protected String newTrackingUrl; protected ApplicationMasterProtocol rmClient; protected Resource clusterAvailableResources; @@ -286,6 +287,11 @@ public AllocateResponse allocate(float progressIndicator) .askList(askList).resourceBlacklistRequest(blacklistRequest) .releaseList(releaseList).updateRequests(updateList).build(); + if (this.newTrackingUrl != null) { + allocateRequest.setTrackingUrl(this.newTrackingUrl); + this.appTrackingUrl = this.newTrackingUrl; + this.newTrackingUrl = null; + } // clear blacklistAdditions and blacklistRemovals before // unsynchronized part blacklistAdditions.clear(); @@ -930,6 +936,11 @@ public synchronized void updateBlacklist(List blacklistAdditions, } } + @Override + public synchronized void updateTrackingUrl(String trackingUrl) { + this.newTrackingUrl = trackingUrl; + } + private void updateAMRMToken(Token token) throws IOException { org.apache.hadoop.security.token.Token amrmToken = new org.apache.hadoop.security.token.Token(token diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestAMRMClient.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestAMRMClient.java index 9f5bad42073..ff8b27cd9e4 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestAMRMClient.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestAMRMClient.java @@ -20,10 +20,12 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.IOException; @@ -87,6 +89,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import org.mockito.ArgumentCaptor; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.mortbay.log.Log; @@ -2053,4 +2056,78 @@ public ApplicationMasterProtocol run() { } return result; } + + @Test(timeout = 60000) + public void testNoUpdateTrackingUrl() { + try { + AMRMClientImpl amClient = null; + amClient = new AMRMClientImpl<>(); + amClient.init(conf); + amClient.start(); + amClient.registerApplicationMaster("Host", 10000, ""); + + assertEquals("", amClient.appTrackingUrl); + + ApplicationMasterProtocol mockRM = mock(ApplicationMasterProtocol.class); + AllocateResponse mockResponse = mock(AllocateResponse.class); + when(mockRM.allocate(any(AllocateRequest.class))) + .thenReturn(mockResponse); + ApplicationMasterProtocol realRM = amClient.rmClient; + amClient.rmClient = mockRM; + // Do allocate without updated tracking url + amClient.allocate(0.1f); + ArgumentCaptor argument = + ArgumentCaptor.forClass(AllocateRequest.class); + verify(mockRM).allocate(argument.capture()); + assertNull(argument.getValue().getTrackingUrl()); + + amClient.rmClient = realRM; + amClient + .unregisterApplicationMaster(FinalApplicationStatus.SUCCEEDED, null, + null); + } catch (IOException | YarnException e) { + throw new AssertionError( + "testNoUpdateTrackingUrl unexpectedly threw exception: " + e); + } + } + + @Test(timeout = 60000) + public void testUpdateTrackingUrl() { + try { + AMRMClientImpl amClient = null; + amClient = new AMRMClientImpl<>(); + amClient.init(conf); + amClient.start(); + amClient.registerApplicationMaster("Host", 10000, ""); + + String trackingUrl = "hadoop.apache.org"; + assertEquals("", amClient.appTrackingUrl); + + ApplicationMasterProtocol mockRM = mock(ApplicationMasterProtocol.class); + AllocateResponse mockResponse = mock(AllocateResponse.class); + when(mockRM.allocate(any(AllocateRequest.class))) + .thenReturn(mockResponse); + ApplicationMasterProtocol realRM = amClient.rmClient; + amClient.rmClient = mockRM; + // Do allocate with updated tracking url + amClient.updateTrackingUrl(trackingUrl); + assertEquals(trackingUrl, amClient.newTrackingUrl); + assertEquals("", amClient.appTrackingUrl); + amClient.allocate(0.1f); + assertNull(amClient.newTrackingUrl); + assertEquals(trackingUrl, amClient.appTrackingUrl); + ArgumentCaptor argument + = ArgumentCaptor.forClass(AllocateRequest.class); + verify(mockRM).allocate(argument.capture()); + assertEquals(trackingUrl, argument.getValue().getTrackingUrl()); + + amClient.rmClient = realRM; + amClient + .unregisterApplicationMaster(FinalApplicationStatus.SUCCEEDED, null, + null); + } catch (IOException | YarnException e) { + throw new AssertionError( + "testUpdateTrackingUrl unexpectedly threw exception: " + e); + } + } } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/impl/pb/AllocateRequestPBImpl.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/impl/pb/AllocateRequestPBImpl.java index f441d69ed5b..467ac1b5f42 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/impl/pb/AllocateRequestPBImpl.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/impl/pb/AllocateRequestPBImpl.java @@ -57,6 +57,7 @@ private List release = null; private List updateRequests = null; private ResourceBlacklistRequest blacklistRequest = null; + private String trackingUrl = null; // This is deprecated, leave it here only to make unit test not break @Deprecated @@ -114,6 +115,9 @@ private void mergeLocalToBuilder() { if (this.deprecatedIncreaseReqs != null) { addIncreaseRequestsToProto(); } + if (this.trackingUrl != null) { + builder.setTrackingUrl(this.trackingUrl); + } } private void mergeLocalToProto() { @@ -384,7 +388,28 @@ private void initReleases() { this.release.add(convertFromProtoFormat(c)); } } - + + @Override + public String getTrackingUrl() { + AllocateRequestProtoOrBuilder p = viaProto ? proto : builder; + if (this.trackingUrl != null) { + return this.trackingUrl; + } + if (p.hasTrackingUrl()) { + this.trackingUrl = p.getTrackingUrl(); + } + return this.trackingUrl; + } + + @Override + public void setTrackingUrl(String trackingUrl) { + maybeInitBuilder(); + if (trackingUrl == null) { + builder.clearTrackingUrl(); + } + this.trackingUrl = trackingUrl; + } + private void addReleasesToProto() { maybeInitBuilder(); builder.clearRelease(); diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/DefaultAMSProcessor.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/DefaultAMSProcessor.java index d5444b48091..eea42e7f313 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/DefaultAMSProcessor.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/DefaultAMSProcessor.java @@ -356,7 +356,7 @@ private void handleProgress(ApplicationAttemptId appAttemptId, // Send the status update to the appAttempt. getRmContext().getDispatcher().getEventHandler().handle( new RMAppAttemptStatusupdateEvent(appAttemptId, request - .getProgress())); + .getProgress(), request.getTrackingUrl())); } @Override diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttemptImpl.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttemptImpl.java index 07f949d29e9..0b56f092012 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttemptImpl.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/RMAppAttemptImpl.java @@ -1815,6 +1815,28 @@ public void transition(RMAppAttemptImpl appAttempt, // Update progress appAttempt.progress = statusUpdateEvent.getProgress(); + // Update tracking url if changed and save it to state store + String newTrackingUrl = statusUpdateEvent.getTrackingUrl(); + if (newTrackingUrl != null && + !newTrackingUrl.equals(appAttempt.originalTrackingUrl)) { + appAttempt.originalTrackingUrl = newTrackingUrl; + AggregateAppResourceUsage resUsage = + appAttempt.attemptMetrics.getAggregateAppResourceUsage(); + ApplicationAttemptStateData attemptState = ApplicationAttemptStateData + .newInstance(appAttempt.applicationAttemptId, + appAttempt.getMasterContainer(), + appAttempt.rmContext.getStateStore() + .getCredentialsFromAppAttempt(appAttempt), + appAttempt.startTime, appAttempt.recoveredFinalState, + newTrackingUrl, appAttempt.getDiagnostics(), null, + ContainerExitStatus.INVALID, appAttempt.getFinishTime(), + resUsage.getMemorySeconds(), resUsage.getVcoreSeconds(), + appAttempt.attemptMetrics.getPreemptedMemory(), + appAttempt.attemptMetrics.getPreemptedVcore()); + appAttempt.rmContext.getStateStore() + .updateApplicationAttemptState(attemptState); + } + // Ping to AMLivelinessMonitor appAttempt.rmContext.getAMLivelinessMonitor().receivedPing( statusUpdateEvent.getApplicationAttemptId()); diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/event/RMAppAttemptStatusupdateEvent.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/event/RMAppAttemptStatusupdateEvent.java index b1b63b14efd..1b7442d8a3a 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/event/RMAppAttemptStatusupdateEvent.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/attempt/event/RMAppAttemptStatusupdateEvent.java @@ -25,15 +25,26 @@ public class RMAppAttemptStatusupdateEvent extends RMAppAttemptEvent { private final float progress; + private final String trackingUrl; public RMAppAttemptStatusupdateEvent(ApplicationAttemptId appAttemptId, float progress) { + this(appAttemptId, progress, null); + } + + public RMAppAttemptStatusupdateEvent(ApplicationAttemptId appAttemptId, + float progress, String trackingUrl) { super(appAttemptId, RMAppAttemptEventType.STATUS_UPDATE); this.progress = progress; + this.trackingUrl = trackingUrl; } public float getProgress() { return this.progress; } + public String getTrackingUrl() { + return this.trackingUrl; + } + } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestApplicationMasterService.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestApplicationMasterService.java index e684f3c1ad3..65e517d0680 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestApplicationMasterService.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestApplicationMasterService.java @@ -672,4 +672,38 @@ private void sentRMContainerLaunched(MockRM rm, ContainerId containerId) { Assert.fail("Cannot find RMContainer"); } } + + @Test(timeout = 300000) + public void testUpdateTrackingUrl() throws Exception { + conf.setClass(YarnConfiguration.RM_SCHEDULER, CapacityScheduler.class, + ResourceScheduler.class); + MockRM rm = new MockRM(conf); + rm.start(); + + // Register node1 + MockNM nm1 = rm.registerNode("127.0.0.1:1234", 6 * GB); + + RMApp app1 = rm.submitApp(2048); + + nm1.nodeHeartbeat(true); + RMAppAttempt attempt1 = app1.getCurrentAppAttempt(); + MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId()); + am1.registerAppAttempt(); + Assert.assertEquals("N/A", rm.getRMContext().getRMApps().get( + app1.getApplicationId()).getOriginalTrackingUrl()); + + AllocateRequestPBImpl allocateRequest = new AllocateRequestPBImpl(); + String newTrackingUrl = "hadoop.apache.org"; + allocateRequest.setTrackingUrl(newTrackingUrl); + + am1.allocate(allocateRequest); + Assert.assertEquals(newTrackingUrl, rm.getRMContext().getRMApps().get( + app1.getApplicationId()).getOriginalTrackingUrl()); + + // Send it again + am1.allocate(allocateRequest); + Assert.assertEquals(newTrackingUrl, rm.getRMContext().getRMApps().get( + app1.getApplicationId()).getOriginalTrackingUrl()); + rm.stop(); + } } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestRMRestart.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestRMRestart.java index da8c83cfe8d..f8fc4024ef1 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestRMRestart.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestRMRestart.java @@ -2698,6 +2698,51 @@ public void testRMRestartAfterPriorityChangesInAllocatedResponse() rm2.stop(); } + @Test(timeout = 20000) + public void testRMRestartAfterUpdateTrackingUrl() throws Exception { + MockRM rm = new MockRM(conf); + rm.start(); + + MemoryRMStateStore memStore = (MemoryRMStateStore) rm.getRMStateStore(); + + // Register node1 + MockNM nm1 = rm.registerNode("127.0.0.1:1234", 6 * 1024); + + RMApp app1 = rm.submitApp(2048); + + nm1.nodeHeartbeat(true); + RMAppAttempt attempt1 = app1.getCurrentAppAttempt(); + MockAM am1 = rm.sendAMLaunched(attempt1.getAppAttemptId()); + am1.registerAppAttempt(); + + AllocateRequestPBImpl allocateRequest = new AllocateRequestPBImpl(); + String newTrackingUrl = "hadoop.apache.org"; + allocateRequest.setTrackingUrl(newTrackingUrl); + + am1.allocate(allocateRequest); + // Check in-memory and stored tracking url + Assert.assertEquals(newTrackingUrl, rm.getRMContext().getRMApps().get( + app1.getApplicationId()).getOriginalTrackingUrl()); + Assert.assertEquals(newTrackingUrl, rm.getRMContext().getRMApps().get( + app1.getApplicationId()).getCurrentAppAttempt() + .getOriginalTrackingUrl()); + Assert.assertEquals(newTrackingUrl, memStore.getState() + .getApplicationState().get(app1.getApplicationId()) + .getAttempt(attempt1.getAppAttemptId()).getFinalTrackingUrl()); + + // Start new RM, should recover updated tracking url + MockRM rm2 = new MockRM(conf, memStore); + rm2.start(); + Assert.assertEquals(newTrackingUrl, rm.getRMContext().getRMApps().get( + app1.getApplicationId()).getOriginalTrackingUrl()); + Assert.assertEquals(newTrackingUrl, rm.getRMContext().getRMApps().get( + app1.getApplicationId()).getCurrentAppAttempt() + .getOriginalTrackingUrl()); + + rm.stop(); + rm2.stop(); + } + private Credentials getCreds() throws IOException { Credentials ts = new Credentials(); DataOutputBuffer dob = new DataOutputBuffer();