diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmcontainer/RMContainer.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmcontainer/RMContainer.java index 4897312..439ca71 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmcontainer/RMContainer.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmcontainer/RMContainer.java @@ -102,6 +102,8 @@ ExecutionType getExecutionType(); + boolean promote(); + /** * If the container was allocated by a container other than the Resource * Manager (e.g., the distributed scheduler in the NM diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmcontainer/RMContainerImpl.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmcontainer/RMContainerImpl.java index d36bfa6..5e8c196 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmcontainer/RMContainerImpl.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmcontainer/RMContainerImpl.java @@ -18,6 +18,7 @@ package org.apache.hadoop.yarn.server.resourcemanager.rmcontainer; +import java.io.IOException; import java.util.Collections; import java.util.EnumSet; import java.util.Set; @@ -43,6 +44,7 @@ import org.apache.hadoop.yarn.api.records.Priority; import org.apache.hadoop.yarn.api.records.Resource; import org.apache.hadoop.yarn.api.records.ResourceInformation; +import org.apache.hadoop.yarn.api.records.Token; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.event.EventHandler; import org.apache.hadoop.yarn.server.api.protocolrecords.NMContainerStatus; @@ -931,6 +933,29 @@ public ExecutionType getExecutionType() { } @Override + public boolean promote() { + assert(container.getExecutionType() == ExecutionType.OPPORTUNISTIC); + + boolean promoted = false; + try { + if (container.getContainerToken() != null) { + // container token may not have been generated yet + Token newToken = rmContext.getContainerTokenSecretManager(). + createPromotedContainerToken(container.getContainerToken(), nodeId); + container.setContainerToken(newToken); + container.setExecutionType(ExecutionType.GUARANTEED); + } + container.setVersion(container.getVersion() + 1); + promoted = true; + } catch (IOException e) { + LOG.warn("The update of the token of " + container.getId() + + " failed. It will not be promoted automatically. ", e); + } + + return promoted; + } + + @Override public boolean isRemotelyAllocated() { return isExternallyAllocated; } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FairScheduler.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FairScheduler.java index d200588..6669b18 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FairScheduler.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/FairScheduler.java @@ -1156,6 +1156,9 @@ private void attemptToAssignReservedResourcesOrPromoteOpportunisticContainers( rmContainer.getApplicationAttemptId()); appAttempt.opportunisticContainerPromoted(rmContainer); + // update container and container token for promotion + rmContainer.promote(); + promotion.put(rmContainer.getContainer(), ContainerUpdateType.PROMOTE_EXECUTION_TYPE); } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMContainerTokenSecretManager.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMContainerTokenSecretManager.java index 945d89e..aad7983 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMContainerTokenSecretManager.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMContainerTokenSecretManager.java @@ -19,6 +19,7 @@ package org.apache.hadoop.yarn.server.resourcemanager.security; import java.util.Set; +import java.io.IOException; import java.util.Timer; import java.util.TimerTask; @@ -224,4 +225,38 @@ public Token createContainerToken(ContainerId containerId, return BuilderUtils.newContainerToken(nodeId, password, tokenIdentifier); } + + public Token createPromotedContainerToken( + Token containerTokenBeforeUpdate, NodeId nodeId) throws IOException { + ContainerTokenIdentifier oldTokenIdentifier = + BuilderUtils.newContainerTokenIdentifier( + containerTokenBeforeUpdate); + byte[] password; + ContainerTokenIdentifier newTokenIdentifier; + + // Lock so that we use the same MasterKey's keyId and its bytes + this.readLock.lock(); + try { + newTokenIdentifier = new ContainerTokenIdentifier( + oldTokenIdentifier.getContainerID(), + oldTokenIdentifier.getVersion() + 1, + oldTokenIdentifier.getNmHostAddress(), + oldTokenIdentifier.getApplicationSubmitter(), + oldTokenIdentifier.getResource(), + oldTokenIdentifier.getExpiryTimeStamp(), + oldTokenIdentifier.getMasterKeyId(), + oldTokenIdentifier.getRMIdentifier(), + oldTokenIdentifier.getPriority(), + oldTokenIdentifier.getCreationTime(), + oldTokenIdentifier.getLogAggregationContext(), + oldTokenIdentifier.getNodeLabelExpression(), + oldTokenIdentifier.getContainerType(), + ExecutionType.GUARANTEED); + password = this.createPassword(newTokenIdentifier); + } finally { + this.readLock.unlock(); + } + + return BuilderUtils.newContainerToken(nodeId, password, newTokenIdentifier); + } } \ No newline at end of file diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFairScheduler.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFairScheduler.java index 7fbf84a..20ec630 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFairScheduler.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/TestFairScheduler.java @@ -3383,6 +3383,8 @@ public void testSingleOpportunisticContainerPromotionWithoutReservation() MockNodes.MockRMNodeImpl node = MockNodes.newNodeInfo(1, Resources.createResource(4096, 4), overAllocationInfo); scheduler.handle(new NodeAddedSchedulerEvent(node)); + SchedulerNode schedulerNode = + scheduler.getSchedulerNode(node.getNodeID()); // create two scheduling requests that leave no unallocated resources ApplicationAttemptId appAttempt1 = @@ -3396,6 +3398,7 @@ public void testSingleOpportunisticContainerPromotionWithoutReservation() assertEquals("unexpected container execution type", ExecutionType.GUARANTEED, allocatedContainers1.get(0).getExecutionType()); + ApplicationAttemptId appAttempt2 = createSchedulingRequest(2048, "queue1", "user1", 1, false); scheduler.handle(new NodeUpdateSchedulerEvent(node)); @@ -3408,6 +3411,11 @@ public void testSingleOpportunisticContainerPromotionWithoutReservation() ExecutionType.GUARANTEED, allocatedContainers2.get(0).getExecutionType()); + assertEquals(Resource.newInstance(4096, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(0, 0), + schedulerNode.getOpportunisticResourceAllocated()); + // node utilization is low after the two container run on the node ContainerStatus container1Status = ContainerStatus.newInstance( allocatedContainers1.get(0).getId(), ContainerState.RUNNING, "", @@ -3437,6 +3445,10 @@ public void testSingleOpportunisticContainerPromotionWithoutReservation() allocatedContainers3.get(0).getExecutionType()); assertTrue("No reservation should be made for the third request", scheduler.getNode(node.getNodeID()).getReservedContainer() == null); + assertEquals(Resource.newInstance(4096, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(1024, 1), + schedulerNode.getOpportunisticResourceAllocated()); // now the first GUARANTEED container finishes List finishedContainers = Collections.singletonList( @@ -3452,6 +3464,29 @@ public void testSingleOpportunisticContainerPromotionWithoutReservation() getGuaranteedResourceUsage().getMemorySize()); assertEquals(0, scheduler.getQueueManager().getQueue("queue2"). getOpportunisticResourceUsage().getMemorySize()); + + assertEquals(Resource.newInstance(3072, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(0, 0), + schedulerNode.getOpportunisticResourceAllocated()); + + // now the promoted container finishes + finishedContainers = Collections.singletonList( + ContainerStatus.newInstance(allocatedContainers3.get(0).getId(), + ContainerState.RUNNING, "", ContainerExitStatus.SUCCESS)); + node.updateContainersAndNodeUtilization( + new UpdatedContainerInfo(Collections.emptyList(), finishedContainers), + ResourceUtilization.newInstance(1024, 0, 0.1f)); + scheduler.handle(new NodeUpdateSchedulerEvent(node)); + + assertEquals(Resource.newInstance(2048, 1), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(0, 0), + schedulerNode.getOpportunisticResourceAllocated()); + assertEquals(0, scheduler.getQueueManager().getQueue("queue2"). + getGuaranteedResourceUsage().getMemorySize()); + assertEquals(0, scheduler.getQueueManager().getQueue("queue2"). + getOpportunisticResourceUsage().getMemorySize()); } finally { conf.setBoolean(YarnConfiguration.RM_SCHEDULER_OVERSUBSCRIPTION_ENABLED, false); @@ -3492,6 +3527,8 @@ public void testMultipleOpportunisticContainerPromotionWithoutReservation() MockNodes.MockRMNodeImpl node = MockNodes.newNodeInfo(1, Resources.createResource(4096, 4), overAllocationInfo); scheduler.handle(new NodeAddedSchedulerEvent(node)); + SchedulerNode schedulerNode = + scheduler.getSchedulerNode(node.getNodeID()); // create two scheduling requests that leave no unallocated resources ApplicationAttemptId appAttempt1 = @@ -3516,6 +3553,10 @@ public void testMultipleOpportunisticContainerPromotionWithoutReservation() assertEquals("unexpected container execution type", ExecutionType.GUARANTEED, allocatedContainers2.get(0).getExecutionType()); + assertEquals(Resource.newInstance(4096, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(0, 0), + schedulerNode.getOpportunisticResourceAllocated()); // node utilization is low after the two container run on the node ContainerStatus container1Status = ContainerStatus.newInstance( @@ -3548,6 +3589,10 @@ public void testMultipleOpportunisticContainerPromotionWithoutReservation() allocatedContainers3.get(0).getExecutionType()); assertTrue("No reservation should be made for the third request", scheduler.getNode(node.getNodeID()).getReservedContainer() == null); + assertEquals(Resource.newInstance(4096, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(1536, 1), + schedulerNode.getOpportunisticResourceAllocated()); // node utilization is low after the third container run on the node ContainerStatus container3Status = ContainerStatus.newInstance( @@ -3573,6 +3618,10 @@ public void testMultipleOpportunisticContainerPromotionWithoutReservation() assertEquals("unexpected container execution type", ExecutionType.OPPORTUNISTIC, allocatedContainers4.get(0).getExecutionType()); + assertEquals(Resource.newInstance(4096, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(2560, 2), + schedulerNode.getOpportunisticResourceAllocated()); // now the first GUARANTEED container finishes List finishedContainers = Collections.singletonList( @@ -3587,11 +3636,15 @@ public void testMultipleOpportunisticContainerPromotionWithoutReservation() getGuaranteedResourceUsage().getMemorySize()); assertEquals(0, scheduler.getQueueManager().getQueue("queue2"). getOpportunisticResourceUsage().getMemorySize()); - // the second OPPORLTUNISTIC container should not be promoted + // the second OPPORTUNISTIC container should not be promoted assertEquals(1024, scheduler.getQueueManager().getQueue("queue3"). getOpportunisticResourceUsage().getMemorySize()); assertEquals(0, scheduler.getQueueManager().getQueue("queue3"). getGuaranteedResourceUsage().getMemorySize()); + assertEquals(Resource.newInstance(3584, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(1024, 1), + schedulerNode.getOpportunisticResourceAllocated()); // now the second GUARANTEED container finishes finishedContainers = Collections.singletonList( @@ -3606,6 +3659,28 @@ public void testMultipleOpportunisticContainerPromotionWithoutReservation() getGuaranteedResourceUsage().getMemorySize()); assertEquals(0, scheduler.getQueueManager().getQueue("queue3"). getOpportunisticResourceUsage().getMemorySize()); + assertEquals(Resource.newInstance(2560, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(0, 0), + schedulerNode.getOpportunisticResourceAllocated()); + + // now the first promoted container finishes + finishedContainers = Collections.singletonList( + ContainerStatus.newInstance(allocatedContainers3.get(0).getId(), + ContainerState.RUNNING, "", ContainerExitStatus.SUCCESS)); + node.updateContainersAndNodeUtilization( + new UpdatedContainerInfo(Collections.emptyList(), finishedContainers), + ResourceUtilization.newInstance(1024, 0, 0.1f)); + scheduler.handle(new NodeUpdateSchedulerEvent(node)); + + assertEquals(Resource.newInstance(1024, 1), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(0, 0), + schedulerNode.getOpportunisticResourceAllocated()); + assertEquals(0, scheduler.getQueueManager().getQueue("queue2"). + getGuaranteedResourceUsage().getMemorySize()); + assertEquals(0, scheduler.getQueueManager().getQueue("queue2"). + getOpportunisticResourceUsage().getMemorySize()); } finally { conf.setBoolean(YarnConfiguration.RM_SCHEDULER_OVERSUBSCRIPTION_ENABLED, false); @@ -3649,6 +3724,8 @@ public void testOpportunisticContainerPromotionWithPriorReservation() MockNodes.MockRMNodeImpl node = MockNodes.newNodeInfo(1, Resources.createResource(4096, 4), overAllocationInfo); scheduler.handle(new NodeAddedSchedulerEvent(node)); + SchedulerNode schedulerNode = + scheduler.getSchedulerNode(node.getNodeID()); // create two scheduling requests that leave no unallocated resources ApplicationAttemptId appAttempt1 = @@ -3662,6 +3739,7 @@ public void testOpportunisticContainerPromotionWithPriorReservation() assertEquals("unexpected container execution type", ExecutionType.GUARANTEED, allocatedContainers1.get(0).getExecutionType()); + ApplicationAttemptId appAttempt2 = createSchedulingRequest(2048, "queue1", "user1", 1, false); scheduler.handle(new NodeUpdateSchedulerEvent(node)); @@ -3674,6 +3752,11 @@ public void testOpportunisticContainerPromotionWithPriorReservation() ExecutionType.GUARANTEED, allocatedContainers2.get(0).getExecutionType()); + assertEquals(Resource.newInstance(4096, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(0, 0), + schedulerNode.getOpportunisticResourceAllocated()); + // node utilization is low after the two container run on the node ContainerStatus container1Status = ContainerStatus.newInstance( allocatedContainers1.get(0).getId(), ContainerState.RUNNING, "", @@ -3699,8 +3782,12 @@ public void testOpportunisticContainerPromotionWithPriorReservation() assertTrue(allocatedContainers3.size() == 0); // verify that a reservation is made for the second request assertTrue("A reservation should be made for the third request", - scheduler.getNode(node.getNodeID()).getReservedContainer(). + schedulerNode.getReservedContainer(). getReservedResource().equals(Resource.newInstance(2000, 1))); + assertEquals(Resource.newInstance(4096, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(0, 0), + schedulerNode.getOpportunisticResourceAllocated()); // create another scheduling request that asks for more than what's left // unallocated on the node but can be served with overallocation. @@ -3716,8 +3803,12 @@ public void testOpportunisticContainerPromotionWithPriorReservation() ExecutionType.OPPORTUNISTIC, allocatedContainers4.get(0).getExecutionType()); assertTrue("A reservation should still be made for the second request", - scheduler.getNode(node.getNodeID()).getReservedContainer(). + schedulerNode.getReservedContainer(). getReservedResource().equals(Resource.newInstance(2000, 1))); + assertEquals(Resource.newInstance(4096, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(1024, 1), + schedulerNode.getOpportunisticResourceAllocated()); // now the first GUARANTEED container finishes List finishedContainers = Collections.singletonList( @@ -3744,6 +3835,10 @@ public void testOpportunisticContainerPromotionWithPriorReservation() // resources are taken by handling the reservation assertEquals(1024, scheduler.getQueueManager().getQueue("queue3"). getOpportunisticResourceUsage().getMemorySize()); + assertEquals(Resource.newInstance(4048, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(1024, 1), + schedulerNode.getOpportunisticResourceAllocated()); // now the second GUARANTEED container finishes finishedContainers = Collections.singletonList( @@ -3759,7 +3854,28 @@ public void testOpportunisticContainerPromotionWithPriorReservation() getGuaranteedResourceUsage().getMemorySize()); assertEquals(0, scheduler.getQueueManager().getQueue("queue3"). getOpportunisticResourceUsage().getMemorySize()); + assertEquals(Resource.newInstance(3024, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(0, 0), + schedulerNode.getOpportunisticResourceAllocated()); + + // now the promoted container finishes + finishedContainers = Collections.singletonList( + ContainerStatus.newInstance(allocatedContainers4.get(0).getId(), + ContainerState.RUNNING, "", ContainerExitStatus.SUCCESS)); + node.updateContainersAndNodeUtilization( + new UpdatedContainerInfo(Collections.emptyList(), finishedContainers), + ResourceUtilization.newInstance(1024, 0, 0.1f)); + scheduler.handle(new NodeUpdateSchedulerEvent(node)); + assertEquals(0, scheduler.getQueueManager().getQueue("queue3"). + getGuaranteedResourceUsage().getMemorySize()); + assertEquals(0, scheduler.getQueueManager().getQueue("queue3"). + getOpportunisticResourceUsage().getMemorySize()); + assertEquals(Resource.newInstance(2000, 1), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(0, 0), + schedulerNode.getOpportunisticResourceAllocated()); } finally { conf.setBoolean(YarnConfiguration.RM_SCHEDULER_OVERSUBSCRIPTION_ENABLED, false); @@ -3803,6 +3919,8 @@ public void testOpportunisticContainerPromotionWithPostReservation() MockNodes.MockRMNodeImpl node = MockNodes.newNodeInfo(1, Resources.createResource(4096, 4), overAllocationInfo); scheduler.handle(new NodeAddedSchedulerEvent(node)); + SchedulerNode schedulerNode = + scheduler.getSchedulerNode(node.getNodeID()); // create two scheduling requests that leave no unallocated resources ApplicationAttemptId appAttempt1 = @@ -3827,6 +3945,11 @@ public void testOpportunisticContainerPromotionWithPostReservation() assertEquals("unexpected container execution type", ExecutionType.GUARANTEED, allocatedContainers2.get(0).getExecutionType()); + assertEquals(Resource.newInstance(4096, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(0, 0), + schedulerNode.getOpportunisticResourceAllocated()); + // node utilization is low after the two container run on the node ContainerStatus container1Status = ContainerStatus.newInstance( @@ -3856,7 +3979,12 @@ public void testOpportunisticContainerPromotionWithPostReservation() ExecutionType.OPPORTUNISTIC, allocatedContainers3.get(0).getExecutionType()); assertTrue("No reservation should be made for the third request", - scheduler.getNode(node.getNodeID()).getReservedContainer() == null); + schedulerNode.getReservedContainer() == null); + assertEquals(Resource.newInstance(4096, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(1024, 1), + schedulerNode.getOpportunisticResourceAllocated()); + // create another scheduling request that opts out of oversubscription ApplicationAttemptId appAttempt4 = @@ -3869,8 +3997,12 @@ public void testOpportunisticContainerPromotionWithPostReservation() assertTrue(allocatedContainers4.size() == 0); // verify that a reservation is made for the second request assertTrue("A reservation should be made for the fourth request", - scheduler.getNode(node.getNodeID()).getReservedContainer(). + schedulerNode.getReservedContainer(). getReservedResource().equals(Resource.newInstance(2000, 1))); + assertEquals(Resource.newInstance(4096, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(1024, 1), + schedulerNode.getOpportunisticResourceAllocated()); // now the first GUARANTEED container finishes List finishedContainers = Collections.singletonList( @@ -3887,8 +4019,12 @@ public void testOpportunisticContainerPromotionWithPostReservation() assertEquals(0, scheduler.getQueueManager().getQueue("queue2"). getOpportunisticResourceUsage().getMemorySize()); assertTrue("A reservation should still be made for the fourth request", - scheduler.getNode(node.getNodeID()).getReservedContainer(). + schedulerNode.getReservedContainer(). getReservedResource().equals(Resource.newInstance(2000, 1))); + assertEquals(Resource.newInstance(3072, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(0, 0), + schedulerNode.getOpportunisticResourceAllocated()); // now the second GUARANTEED container finishes finishedContainers = Collections.singletonList( @@ -3910,8 +4046,29 @@ public void testOpportunisticContainerPromotionWithPostReservation() ExecutionType.GUARANTEED, allocatedContainers4.get(0).getExecutionType()); assertTrue("The reservation for the fourth request should be canceled", - scheduler.getNode(node.getNodeID()).getReservedContainer() == null); + schedulerNode.getReservedContainer() == null); + assertEquals(Resource.newInstance(3024, 2), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(0, 0), + schedulerNode.getOpportunisticResourceAllocated()); + + // now that the promoted container finishes + finishedContainers = Collections.singletonList( + ContainerStatus.newInstance(allocatedContainers3.get(0).getId(), + ContainerState.RUNNING, "", ContainerExitStatus.SUCCESS)); + node.updateContainersAndNodeUtilization( + new UpdatedContainerInfo(Collections.emptyList(), finishedContainers), + ResourceUtilization.newInstance(1024, 0, 0.1f)); + scheduler.handle(new NodeUpdateSchedulerEvent(node)); + assertEquals(Resource.newInstance(2000, 1), + schedulerNode.getAllocatedResource()); + assertEquals(Resource.newInstance(0, 0), + schedulerNode.getOpportunisticResourceAllocated()); + assertEquals(0, scheduler.getQueueManager().getQueue("queue2"). + getGuaranteedResourceUsage().getMemorySize()); + assertEquals(0, scheduler.getQueueManager().getQueue("queue2"). + getOpportunisticResourceUsage().getMemorySize()); } finally { conf.setBoolean(YarnConfiguration.RM_SCHEDULER_OVERSUBSCRIPTION_ENABLED, false);