|
22 | 22 | import static org.junit.Assert.assertNotNull; |
23 | 23 | import static org.junit.Assert.assertNull; |
24 | 24 | import static org.junit.Assert.assertTrue; |
| 25 | +import static org.junit.Assert.fail; |
25 | 26 | import static org.mockito.Matchers.anyBoolean; |
26 | 27 | import static org.mockito.Matchers.anyInt; |
27 | 28 | import static org.mockito.Matchers.anyLong; |
|
147 | 148 | import org.apache.hadoop.yarn.server.nodemanager.security.NMTokenSecretManagerInNM; |
148 | 149 | import org.apache.hadoop.yarn.server.security.ApplicationACLsManager; |
149 | 150 | import org.apache.hadoop.yarn.server.utils.BuilderUtils; |
150 | | -import org.apache.hadoop.yarn.util.ConverterUtils; |
151 | 151 | import org.junit.After; |
152 | 152 | import org.junit.Before; |
153 | 153 | import org.junit.BeforeClass; |
@@ -1482,6 +1482,114 @@ public void testPublicResourceInitializesLocalDir() throws Exception { |
1482 | 1482 | } |
1483 | 1483 | } |
1484 | 1484 |
|
| 1485 | + @Test(timeout = 20000) |
| 1486 | + @SuppressWarnings("unchecked") |
| 1487 | + public void testLocalizerHeartbeatWhenAppCleaningUp() throws Exception { |
| 1488 | + conf.set(YarnConfiguration.NM_LOCAL_DIRS, |
| 1489 | + lfs.makeQualified(new Path(basedir, 0 + "")).toString()); |
| 1490 | + // Start dispatcher. |
| 1491 | + DrainDispatcher dispatcher = new DrainDispatcher(); |
| 1492 | + dispatcher.init(conf); |
| 1493 | + dispatcher.start(); |
| 1494 | + dispatcher.register(ApplicationEventType.class, mock(EventHandler.class)); |
| 1495 | + dispatcher.register(ContainerEventType.class, mock(EventHandler.class)); |
| 1496 | + |
| 1497 | + DummyExecutor exec = new DummyExecutor(); |
| 1498 | + LocalDirsHandlerService dirsHandler = new LocalDirsHandlerService(); |
| 1499 | + dirsHandler.init(conf); |
| 1500 | + // Start resource localization service. |
| 1501 | + ResourceLocalizationService rawService = new ResourceLocalizationService( |
| 1502 | + dispatcher, exec, mock(DeletionService.class), dirsHandler, nmContext); |
| 1503 | + ResourceLocalizationService spyService = spy(rawService); |
| 1504 | + doReturn(mockServer).when(spyService).createServer(); |
| 1505 | + doReturn(lfs).when(spyService). |
| 1506 | + getLocalFileContext(isA(Configuration.class)); |
| 1507 | + try { |
| 1508 | + spyService.init(conf); |
| 1509 | + spyService.start(); |
| 1510 | + |
| 1511 | + // Init application resources. |
| 1512 | + final Application app = mock(Application.class); |
| 1513 | + final ApplicationId appId = BuilderUtils.newApplicationId(1234567890L, 3); |
| 1514 | + when(app.getUser()).thenReturn("user0"); |
| 1515 | + when(app.getAppId()).thenReturn(appId); |
| 1516 | + when(app.toString()).thenReturn(appId.toString()); |
| 1517 | + spyService.handle(new ApplicationLocalizationEvent( |
| 1518 | + LocalizationEventType.INIT_APPLICATION_RESOURCES, app)); |
| 1519 | + dispatcher.await(); |
| 1520 | + |
| 1521 | + // Initialize localizer. |
| 1522 | + Random r = new Random(); |
| 1523 | + long seed = r.nextLong(); |
| 1524 | + System.out.println("SEED: " + seed); |
| 1525 | + r.setSeed(seed); |
| 1526 | + final Container c = getMockContainer(appId, 46, "user0"); |
| 1527 | + FSDataOutputStream out = |
| 1528 | + new FSDataOutputStream(new DataOutputBuffer(), null); |
| 1529 | + doReturn(out).when(spylfs).createInternal(isA(Path.class), |
| 1530 | + isA(EnumSet.class), isA(FsPermission.class), anyInt(), anyShort(), |
| 1531 | + anyLong(), isA(Progressable.class), isA(ChecksumOpt.class), |
| 1532 | + anyBoolean()); |
| 1533 | + final LocalResource resource1 = getAppMockedResource(r); |
| 1534 | + final LocalResource resource2 = getAppMockedResource(r); |
| 1535 | + |
| 1536 | + // Send localization requests for container. |
| 1537 | + // 2 resources generated with APPLICATION visibility. |
| 1538 | + final LocalResourceRequest req1 = new LocalResourceRequest(resource1); |
| 1539 | + final LocalResourceRequest req2 = new LocalResourceRequest(resource2); |
| 1540 | + Map<LocalResourceVisibility, Collection<LocalResourceRequest>> rsrcs = |
| 1541 | + new HashMap<LocalResourceVisibility, |
| 1542 | + Collection<LocalResourceRequest>>(); |
| 1543 | + List<LocalResourceRequest> appResourceList = Arrays.asList(req1, req2); |
| 1544 | + rsrcs.put(LocalResourceVisibility.APPLICATION, appResourceList); |
| 1545 | + spyService.handle(new ContainerLocalizationRequestEvent(c, rsrcs)); |
| 1546 | + dispatcher.await(); |
| 1547 | + |
| 1548 | + // Wait for localization to begin. |
| 1549 | + exec.waitForLocalizers(1); |
| 1550 | + final String containerIdStr = c.getContainerId().toString(); |
| 1551 | + LocalizerRunner locRunnerForContainer = |
| 1552 | + spyService.getLocalizerRunner(containerIdStr); |
| 1553 | + // Heartbeats from container localizer |
| 1554 | + LocalResourceStatus rsrcSuccess = mock(LocalResourceStatus.class); |
| 1555 | + LocalizerStatus stat = mock(LocalizerStatus.class); |
| 1556 | + when(stat.getLocalizerId()).thenReturn(containerIdStr); |
| 1557 | + when(rsrcSuccess.getResource()).thenReturn(resource1); |
| 1558 | + when(rsrcSuccess.getLocalSize()).thenReturn(4344L); |
| 1559 | + when(rsrcSuccess.getLocalPath()).thenReturn(getPath("/some/path")); |
| 1560 | + when(rsrcSuccess.getStatus()). |
| 1561 | + thenReturn(ResourceStatusType.FETCH_SUCCESS); |
| 1562 | + when(stat.getResources()). |
| 1563 | + thenReturn(Collections.<LocalResourceStatus>emptyList()); |
| 1564 | + |
| 1565 | + // First heartbeat which schedules first resource. |
| 1566 | + LocalizerHeartbeatResponse response = spyService.heartbeat(stat); |
| 1567 | + assertEquals("NM should tell localizer to be LIVE in Heartbeat.", |
| 1568 | + LocalizerAction.LIVE, response.getLocalizerAction()); |
| 1569 | + |
| 1570 | + // Cleanup application. |
| 1571 | + spyService.handle(new ContainerLocalizationCleanupEvent(c, rsrcs)); |
| 1572 | + spyService.handle(new ApplicationLocalizationEvent( |
| 1573 | + LocalizationEventType.DESTROY_APPLICATION_RESOURCES, app)); |
| 1574 | + dispatcher.await(); |
| 1575 | + try { |
| 1576 | + // Directly send heartbeat to introduce race as app is being cleaned up. |
| 1577 | + locRunnerForContainer.processHeartbeat( |
| 1578 | + Collections.singletonList(rsrcSuccess)); |
| 1579 | + } catch (Exception e) { |
| 1580 | + fail("Exception should not have been thrown on processing heartbeat"); |
| 1581 | + } |
| 1582 | + // Send another heartbeat. |
| 1583 | + response = spyService.heartbeat(stat); |
| 1584 | + assertEquals("NM should tell localizer to DIE in Heartbeat.", |
| 1585 | + LocalizerAction.DIE, response.getLocalizerAction()); |
| 1586 | + exec.setStopLocalization(); |
| 1587 | + } finally { |
| 1588 | + spyService.stop(); |
| 1589 | + dispatcher.stop(); |
| 1590 | + } |
| 1591 | + } |
| 1592 | + |
1485 | 1593 | @Test(timeout=20000) |
1486 | 1594 | @SuppressWarnings("unchecked") // mocked generics |
1487 | 1595 | public void testFailedPublicResource() throws Exception { |
|
0 commit comments