use of org.apache.hadoop.hdds.scm.container.placement.algorithms.ContainerPlacementStatusDefault in project ozone by apache.
the class SCMCommonPlacementPolicy method validateContainerPlacement.
/**
* This default implementation handles rack aware policies and non rack
* aware policies. If a future placement policy needs to check more than racks
* to validate the policy (eg node groups, HDFS like upgrade domain) this
* method should be overridden in the sub class.
* This method requires that subclasses which implement rack aware policies
* override the default method getRequiredRackCount and getNetworkTopology.
* @param dns List of datanodes holding a replica of the container
* @param replicas The expected number of replicas
* @return ContainerPlacementStatus indicating if the placement policy is
* met or not. Not this only considers the rack count and not the
* number of replicas.
*/
@Override
public ContainerPlacementStatus validateContainerPlacement(List<DatanodeDetails> dns, int replicas) {
NetworkTopology topology = nodeManager.getClusterNetworkTopologyMap();
int requiredRacks = getRequiredRackCount(replicas);
if (topology == null || replicas == 1 || requiredRacks == 1) {
if (dns.size() > 0) {
// placement is always satisfied if there is at least one DN.
return validPlacement;
} else {
return invalidPlacement;
}
}
// We have a network topology so calculate if it is satisfied or not.
int numRacks = 1;
final int maxLevel = topology.getMaxLevel();
// The leaf nodes are all at max level, so the number of nodes at
// leafLevel - 1 is the rack count
numRacks = topology.getNumOfNodes(maxLevel - 1);
final long currentRackCount = dns.stream().map(d -> topology.getAncestor(d, 1)).distinct().count();
if (replicas < requiredRacks) {
requiredRacks = replicas;
}
return new ContainerPlacementStatusDefault((int) currentRackCount, requiredRacks, numRacks);
}
use of org.apache.hadoop.hdds.scm.container.placement.algorithms.ContainerPlacementStatusDefault in project ozone by apache.
the class TestContainerHealthTaskRecordGenerator method testCorrectRecordsGenerated.
@Test
public void testCorrectRecordsGenerated() {
Set<ContainerReplica> replicas = generateReplicas(container, CLOSED, CLOSED, CLOSED);
// HEALTHY container - no records generated.
ContainerHealthStatus status = new ContainerHealthStatus(container, replicas, placementPolicy);
List<UnhealthyContainers> records = ContainerHealthTask.ContainerHealthRecords.generateUnhealthyRecords(status, (long) 1234567);
assertEquals(0, records.size());
// Over-replicated - expect 1 over replicated record
replicas = generateReplicas(container, CLOSED, CLOSED, CLOSED, CLOSED, CLOSED);
status = new ContainerHealthStatus(container, replicas, placementPolicy);
records = ContainerHealthTask.ContainerHealthRecords.generateUnhealthyRecords(status, (long) 1234567);
assertEquals(1, records.size());
UnhealthyContainers rec = records.get(0);
assertEquals(UnHealthyContainerStates.OVER_REPLICATED.toString(), rec.getContainerState());
assertEquals(3, rec.getExpectedReplicaCount().intValue());
assertEquals(5, rec.getActualReplicaCount().intValue());
assertEquals(-2, rec.getReplicaDelta().intValue());
// Under and Mis Replicated - expect 2 records - mis and under replicated
replicas = generateReplicas(container, CLOSED, CLOSED);
when(placementPolicy.validateContainerPlacement(Mockito.anyList(), Mockito.anyInt())).thenReturn(new ContainerPlacementStatusDefault(1, 2, 5));
status = new ContainerHealthStatus(container, replicas, placementPolicy);
records = ContainerHealthTask.ContainerHealthRecords.generateUnhealthyRecords(status, (long) 1234567);
assertEquals(2, records.size());
rec = findRecordForState(records, UnHealthyContainerStates.MIS_REPLICATED);
assertEquals(UnHealthyContainerStates.MIS_REPLICATED.toString(), rec.getContainerState());
assertEquals(2, rec.getExpectedReplicaCount().intValue());
assertEquals(1, rec.getActualReplicaCount().intValue());
assertEquals(1, rec.getReplicaDelta().intValue());
assertNotNull(rec.getReason());
rec = findRecordForState(records, UnHealthyContainerStates.UNDER_REPLICATED);
assertEquals(UnHealthyContainerStates.UNDER_REPLICATED.toString(), rec.getContainerState());
assertEquals(3, rec.getExpectedReplicaCount().intValue());
assertEquals(2, rec.getActualReplicaCount().intValue());
assertEquals(1, rec.getReplicaDelta().intValue());
// Missing Record - expect just a single missing record even though
// it is mis-replicated too
replicas.clear();
when(placementPolicy.validateContainerPlacement(Mockito.anyList(), Mockito.anyInt())).thenReturn(new ContainerPlacementStatusDefault(1, 2, 5));
status = new ContainerHealthStatus(container, replicas, placementPolicy);
records = ContainerHealthTask.ContainerHealthRecords.generateUnhealthyRecords(status, (long) 1234567);
assertEquals(1, records.size());
rec = records.get(0);
assertEquals(UnHealthyContainerStates.MISSING.toString(), rec.getContainerState());
assertEquals(3, rec.getExpectedReplicaCount().intValue());
assertEquals(0, rec.getActualReplicaCount().intValue());
assertEquals(3, rec.getReplicaDelta().intValue());
}
use of org.apache.hadoop.hdds.scm.container.placement.algorithms.ContainerPlacementStatusDefault in project ozone by apache.
the class TestContainerHealthTaskRecordGenerator method testMisReplicatedRecordRetainedAndUpdated.
@Test
public void testMisReplicatedRecordRetainedAndUpdated() {
// under replicated container
Set<ContainerReplica> replicas = generateReplicas(container, CLOSED, CLOSED, CLOSED);
when(placementPolicy.validateContainerPlacement(Mockito.anyList(), Mockito.anyInt())).thenReturn(new ContainerPlacementStatusDefault(2, 3, 5));
ContainerHealthStatus status = new ContainerHealthStatus(container, replicas, placementPolicy);
UnhealthyContainersRecord rec = misReplicatedRecord();
assertTrue(ContainerHealthTask.ContainerHealthRecords.retainOrUpdateRecord(status, rec));
// The record actual count should be updated from 1 -> 2
assertEquals(2, rec.getActualReplicaCount().intValue());
assertEquals(1, rec.getReplicaDelta().intValue());
assertNotNull(rec.getReason());
// Missing / Over / Mis replicated should not be retained
assertFalse(ContainerHealthTask.ContainerHealthRecords.retainOrUpdateRecord(status, missingRecord()));
assertFalse(ContainerHealthTask.ContainerHealthRecords.retainOrUpdateRecord(status, underReplicatedRecord()));
assertFalse(ContainerHealthTask.ContainerHealthRecords.retainOrUpdateRecord(status, overReplicatedRecord()));
// Container is now placed OK - should be removed.
when(placementPolicy.validateContainerPlacement(Mockito.anyList(), Mockito.anyInt())).thenReturn(new ContainerPlacementStatusDefault(3, 3, 5));
status = new ContainerHealthStatus(container, replicas, placementPolicy);
assertFalse(ContainerHealthTask.ContainerHealthRecords.retainOrUpdateRecord(status, rec));
}
use of org.apache.hadoop.hdds.scm.container.placement.algorithms.ContainerPlacementStatusDefault in project ozone by apache.
the class TestContainerHealthTaskRecordGenerator method setup.
@Before
public void setup() {
placementPolicy = mock(PlacementPolicy.class);
container = mock(ContainerInfo.class);
when(container.getReplicationConfig()).thenReturn(RatisReplicationConfig.getInstance(HddsProtos.ReplicationFactor.THREE));
when(container.containerID()).thenReturn(ContainerID.valueOf(123456));
when(container.getContainerID()).thenReturn((long) 123456);
when(placementPolicy.validateContainerPlacement(Mockito.anyList(), Mockito.anyInt())).thenReturn(new ContainerPlacementStatusDefault(1, 1, 1));
}
use of org.apache.hadoop.hdds.scm.container.placement.algorithms.ContainerPlacementStatusDefault in project ozone by apache.
the class TestReplicationManager method additionalReplicaScheduledWhenMisReplicated.
@Test
public void additionalReplicaScheduledWhenMisReplicated() throws IOException {
final ContainerInfo container = getContainer(LifeCycleState.CLOSED);
container.setUsedBytes(100);
final ContainerID id = container.containerID();
final UUID originNodeId = UUID.randomUUID();
final ContainerReplica replicaOne = getReplicas(id, State.CLOSED, 1000L, originNodeId, randomDatanodeDetails());
final ContainerReplica replicaTwo = getReplicas(id, State.CLOSED, 1000L, originNodeId, randomDatanodeDetails());
final ContainerReplica replicaThree = getReplicas(id, State.CLOSED, 1000L, originNodeId, randomDatanodeDetails());
containerStateManager.addContainer(container.getProtobuf());
containerStateManager.updateContainerReplica(id, replicaOne);
containerStateManager.updateContainerReplica(id, replicaTwo);
containerStateManager.updateContainerReplica(id, replicaThree);
// Ensure a mis-replicated status is returned for any containers in this
// test where there are 3 replicas. When there are 2 or 4 replicas
// the status returned will be healthy.
Mockito.when(containerPlacementPolicy.validateContainerPlacement(Mockito.argThat(list -> list.size() == 3), Mockito.anyInt())).thenAnswer(invocation -> {
return new ContainerPlacementStatusDefault(1, 2, 3);
});
int currentReplicateCommandCount = datanodeCommandHandler.getInvocationCount(SCMCommandProto.Type.replicateContainerCommand);
final long currentBytesToReplicate = replicationManager.getMetrics().getNumReplicationBytesTotal();
replicationManager.processAll();
eventQueue.processAll(1000);
// At this stage, due to the mocked calls to validateContainerPlacement
// the policy will not be satisfied, and replication will be triggered.
Assert.assertEquals(currentReplicateCommandCount + 1, datanodeCommandHandler.getInvocationCount(SCMCommandProto.Type.replicateContainerCommand));
Assert.assertEquals(currentReplicateCommandCount + 1, replicationManager.getMetrics().getNumReplicationCmdsSent());
Assert.assertEquals(currentBytesToReplicate + 100, replicationManager.getMetrics().getNumReplicationBytesTotal());
Assert.assertEquals(1, replicationManager.getInflightReplication().size());
Assert.assertEquals(1, replicationManager.getMetrics().getInflightReplication());
ReplicationManagerReport report = replicationManager.getContainerReport();
Assert.assertEquals(1, report.getStat(LifeCycleState.CLOSED));
Assert.assertEquals(1, report.getStat(ReplicationManagerReport.HealthState.MIS_REPLICATED));
// Now make it so that all containers seem mis-replicated no matter how
// many replicas. This will test replicas are not scheduled if the new
// replica does not fix the mis-replication.
Mockito.when(containerPlacementPolicy.validateContainerPlacement(Mockito.anyList(), Mockito.anyInt())).thenAnswer(invocation -> {
return new ContainerPlacementStatusDefault(1, 2, 3);
});
currentReplicateCommandCount = datanodeCommandHandler.getInvocationCount(SCMCommandProto.Type.replicateContainerCommand);
replicationManager.processAll();
eventQueue.processAll(1000);
// At this stage, due to the mocked calls to validateContainerPlacement
// the mis-replicated racks will not have improved, so expect to see nothing
// scheduled.
Assert.assertEquals(currentReplicateCommandCount, datanodeCommandHandler.getInvocationCount(SCMCommandProto.Type.replicateContainerCommand));
Assert.assertEquals(currentReplicateCommandCount, replicationManager.getMetrics().getNumReplicationCmdsSent());
Assert.assertEquals(1, replicationManager.getInflightReplication().size());
Assert.assertEquals(1, replicationManager.getMetrics().getInflightReplication());
}
Aggregations