This is an automated email from the ASF dual-hosted git repository.

adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new a3f987ffe1 HDDS-10917. Refactor more tests from 
TestContainerBalancerTask (#6734)
a3f987ffe1 is described below

commit a3f987ffe12c50ca60887cabbb9af8db85f7969d
Author: Andrei Mikhalev <[email protected]>
AuthorDate: Wed Jul 31 22:21:25 2024 -0700

    HDDS-10917. Refactor more tests from TestContainerBalancerTask (#6734)
---
 .../TestContainerBalancerDatanodeNodeLimit.java    | 275 ++++++++++++++++++++-
 .../balancer/TestContainerBalancerTask.java        | 259 -------------------
 2 files changed, 269 insertions(+), 265 deletions(-)

diff --git 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancerDatanodeNodeLimit.java
 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancerDatanodeNodeLimit.java
index fc8eaf2ff5..7a8f655f06 100644
--- 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancerDatanodeNodeLimit.java
+++ 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancerDatanodeNodeLimit.java
@@ -21,8 +21,16 @@ package org.apache.hadoop.hdds.scm.container.balancer;
 import jakarta.annotation.Nonnull;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.hdds.protocol.DatanodeDetails;
+import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos;
+import org.apache.hadoop.hdds.scm.ContainerPlacementStatus;
 import org.apache.hadoop.hdds.scm.container.ContainerID;
+import org.apache.hadoop.hdds.scm.container.ContainerInfo;
+import org.apache.hadoop.hdds.scm.container.ContainerNotFoundException;
+import org.apache.hadoop.hdds.scm.container.ContainerReplica;
+import org.apache.hadoop.hdds.scm.container.ContainerReplicaNotFoundException;
 import org.apache.hadoop.hdds.scm.node.DatanodeUsageInfo;
+import org.apache.hadoop.hdds.scm.node.NodeStatus;
 import org.apache.hadoop.hdds.scm.node.states.NodeNotFoundException;
 import org.apache.hadoop.ozone.OzoneConsts;
 import org.apache.ozone.test.GenericTestUtils;
@@ -37,9 +45,13 @@ import java.io.IOException;
 import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeoutException;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import static 
org.apache.hadoop.hdds.scm.container.balancer.TestableCluster.RANDOM;
@@ -47,6 +59,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.atLeastOnce;
@@ -256,14 +269,11 @@ public class TestContainerBalancerDatanodeNodeLimit {
     mockedSCM.disableLegacyReplicationManager();
     mockedSCM.startBalancerTask(config);
 
-    verify(mockedSCM.getMoveManager(), atLeastOnce())
-        .move(any(ContainerID.class),
-            any(DatanodeDetails.class),
-            any(DatanodeDetails.class));
+    verify(mockedSCM.getMoveManager(), atLeastOnce()).
+        move(any(ContainerID.class), any(DatanodeDetails.class), 
any(DatanodeDetails.class));
 
     verify(mockedSCM.getReplicationManager(), times(0))
-        .move(any(ContainerID.class), any(
-            DatanodeDetails.class), any(DatanodeDetails.class));
+        .move(any(ContainerID.class), any(DatanodeDetails.class), 
any(DatanodeDetails.class));
   }
 
   @ParameterizedTest(name = "MockedSCM #{index}: {0}")
@@ -325,6 +335,259 @@ public class TestContainerBalancerDatanodeNodeLimit {
     assertEquals(1, metrics.getNumContainerMovesFailed());
   }
 
+  @ParameterizedTest(name = "MockedSCM #{index}: {0}")
+  @MethodSource("createMockedSCMs")
+  public void containerBalancerShouldSelectOnlyClosedContainers(@Nonnull 
MockedSCM mockedSCM) {
+    ContainerBalancerConfiguration config = balancerConfigByOzoneConfig(new 
OzoneConfiguration());
+    int nodeCount = mockedSCM.getCluster().getNodeCount();
+    if (nodeCount < DATANODE_COUNT_LIMIT_FOR_SMALL_CLUSTER) {
+      config.setMaxDatanodesPercentageToInvolvePerIteration(100);
+    }
+    config.setIterations(1);
+    config.setThreshold(10);
+    config.setMaxSizeToMovePerIteration(50 * STORAGE_UNIT);
+    config.setMaxSizeEnteringTarget(50 * STORAGE_UNIT);
+
+    Map<ContainerID, ContainerInfo> cidToInfoMap = 
mockedSCM.getCluster().getCidToInfoMap();
+    // Make all containers open, balancer should not select any of them
+    for (ContainerInfo containerInfo : cidToInfoMap.values()) {
+      containerInfo.setState(HddsProtos.LifeCycleState.OPEN);
+    }
+
+    ContainerBalancerTask task = mockedSCM.startBalancerTask(config);
+
+    // Balancer should have identified unbalanced nodes
+    
assertFalse(TestContainerBalancerDatanodeNodeLimit.getUnBalancedNodes(task).isEmpty());
+    // No container should have been selected
+    assertTrue(task.getContainerToSourceMap().isEmpty());
+
+    // Iteration result should be CAN_NOT_BALANCE_ANY_MORE because no 
container move is generated
+    
assertEquals(ContainerBalancerTask.IterationResult.CAN_NOT_BALANCE_ANY_MORE, 
task.getIterationResult());
+
+    // Now, close all containers
+    for (ContainerInfo containerInfo : cidToInfoMap.values()) {
+      containerInfo.setState(HddsProtos.LifeCycleState.CLOSED);
+    }
+    ContainerBalancerTask nextTask = mockedSCM.startBalancerTask(config);
+
+    // Check whether all selected containers are closed
+    for (ContainerID cid: nextTask.getContainerToSourceMap().keySet()) {
+      assertSame(cidToInfoMap.get(cid).getState(), 
HddsProtos.LifeCycleState.CLOSED);
+    }
+  }
+
+  @ParameterizedTest(name = "MockedSCM #{index}: {0}")
+  @MethodSource("createMockedSCMs")
+  public void balancerShouldNotSelectNonClosedContainerReplicas(@Nonnull 
MockedSCM mockedSCM)
+      throws ContainerNotFoundException {
+    ContainerBalancerConfiguration config = balancerConfigByOzoneConfig(new 
OzoneConfiguration());
+    int nodeCount = mockedSCM.getCluster().getNodeCount();
+    if (nodeCount < DATANODE_COUNT_LIMIT_FOR_SMALL_CLUSTER) {
+      config.setMaxDatanodesPercentageToInvolvePerIteration(100);
+    }
+    config.setIterations(1);
+    config.setThreshold(10);
+    config.setMaxSizeToMovePerIteration(50 * STORAGE_UNIT);
+    config.setMaxSizeEnteringTarget(50 * STORAGE_UNIT);
+
+    // Let's mock such that all replicas have CLOSING state
+    Map<ContainerID, Set<ContainerReplica>> cidToReplicasMap = 
mockedSCM.getCluster().getCidToReplicasMap();
+    
when(mockedSCM.getContainerManager().getContainerReplicas(any(ContainerID.class)))
+        .thenAnswer(invocationOnMock -> {
+          ContainerID cid = (ContainerID) invocationOnMock.getArguments()[0];
+          Set<ContainerReplica> replicas = cidToReplicasMap.get(cid);
+          Set<ContainerReplica> replicasToReturn = new 
HashSet<>(replicas.size());
+          for (ContainerReplica replica : replicas) {
+            ContainerReplica newReplica = replica.toBuilder()
+                
.setContainerState(StorageContainerDatanodeProtocolProtos.ContainerReplicaProto.State.CLOSING)
+                .build();
+            replicasToReturn.add(newReplica);
+          }
+
+          return replicasToReturn;
+        });
+
+    ContainerBalancerTask task = mockedSCM.startBalancerTask(config);
+
+    // Balancer should have identified unbalanced nodes
+    
assertFalse(TestContainerBalancerDatanodeNodeLimit.getUnBalancedNodes(task).isEmpty());
+    // No container should have moved because all replicas are CLOSING
+    assertTrue(task.getContainerToSourceMap().isEmpty());
+  }
+
+  @ParameterizedTest(name = "MockedSCM #{index}: {0}")
+  @MethodSource("createMockedSCMs")
+  public void containerBalancerShouldObeyMaxSizeToMoveLimit(@Nonnull MockedSCM 
mockedSCM) {
+    ContainerBalancerConfiguration config = balancerConfigByOzoneConfig(new 
OzoneConfiguration());
+    int nodeCount = mockedSCM.getCluster().getNodeCount();
+    if (nodeCount < DATANODE_COUNT_LIMIT_FOR_SMALL_CLUSTER) {
+      config.setMaxDatanodesPercentageToInvolvePerIteration(100);
+    }
+    config.setIterations(1);
+    config.setThreshold(1);
+    config.setMaxSizeToMovePerIteration(10 * STORAGE_UNIT);
+    config.setMaxSizeEnteringTarget(10 * STORAGE_UNIT);
+
+    ContainerBalancerTask task = mockedSCM.startBalancerTask(config);
+
+    // Balancer should not have moved more size than the limit
+    
assertThat(task.getSizeScheduledForMoveInLatestIteration()).isLessThanOrEqualTo(10
 * STORAGE_UNIT);
+
+    long size = task.getMetrics().getDataSizeMovedGBInLatestIteration();
+    assertThat(size).isGreaterThan(0);
+    assertThat(size).isLessThanOrEqualTo(10);
+  }
+
+  @ParameterizedTest(name = "MockedSCM #{index}: {0}")
+  @MethodSource("createMockedSCMs")
+  public void targetDatanodeShouldNotAlreadyContainSelectedContainer(@Nonnull 
MockedSCM mockedSCM) {
+    ContainerBalancerConfiguration config = balancerConfigByOzoneConfig(new 
OzoneConfiguration());
+    int nodeCount = mockedSCM.getCluster().getNodeCount();
+    if (nodeCount < DATANODE_COUNT_LIMIT_FOR_SMALL_CLUSTER) {
+      config.setMaxDatanodesPercentageToInvolvePerIteration(100);
+    }
+    config.setIterations(1);
+    config.setThreshold(10);
+    config.setMaxSizeToMovePerIteration(50 * STORAGE_UNIT);
+    config.setMaxSizeEnteringTarget(50 * STORAGE_UNIT);
+
+    ContainerBalancerTask task = mockedSCM.startBalancerTask(config);
+
+    Map<ContainerID, DatanodeDetails> map = task.getContainerToTargetMap();
+    Map<ContainerID, Set<ContainerReplica>> cidToReplicasMap = 
mockedSCM.getCluster().getCidToReplicasMap();
+    for (Map.Entry<ContainerID, DatanodeDetails> entry : map.entrySet()) {
+      ContainerID container = entry.getKey();
+      DatanodeDetails target = entry.getValue();
+      assertTrue(cidToReplicasMap.get(container)
+          .stream()
+          .map(ContainerReplica::getDatanodeDetails)
+          .noneMatch(target::equals));
+    }
+  }
+
+  @ParameterizedTest(name = "MockedSCM #{index}: {0}")
+  @MethodSource("createMockedSCMs")
+  public void containerMoveSelectionShouldFollowPlacementPolicy(@Nonnull 
MockedSCM mockedSCM) {
+    ContainerBalancerConfiguration config = balancerConfigByOzoneConfig(new 
OzoneConfiguration());
+    int nodeCount = mockedSCM.getCluster().getNodeCount();
+    if (nodeCount < DATANODE_COUNT_LIMIT_FOR_SMALL_CLUSTER) {
+      config.setMaxDatanodesPercentageToInvolvePerIteration(100);
+    }
+    config.setIterations(1);
+    config.setThreshold(10);
+    config.setMaxSizeToMovePerIteration(50 * STORAGE_UNIT);
+    config.setMaxSizeEnteringTarget(50 * STORAGE_UNIT);
+
+    ContainerBalancerTask task = mockedSCM.startBalancerTask(config);
+
+    Map<ContainerID, DatanodeDetails> containerFromSourceMap = 
task.getContainerToSourceMap();
+    Map<ContainerID, DatanodeDetails> containerToTargetMap = 
task.getContainerToTargetMap();
+
+    // For each move selection, check if {replicas - source + target} 
satisfies placement policy
+    for (Map.Entry<ContainerID, DatanodeDetails> entry : 
containerFromSourceMap.entrySet()) {
+      ContainerID container = entry.getKey();
+      DatanodeDetails source = entry.getValue();
+
+      List<DatanodeDetails> replicas = 
mockedSCM.getCluster().getCidToReplicasMap().get(container)
+          .stream()
+          .map(ContainerReplica::getDatanodeDetails)
+          .collect(Collectors.toList());
+      // Remove source and add target
+      replicas.remove(source);
+      replicas.add(containerToTargetMap.get(container));
+
+      ContainerInfo containerInfo = 
mockedSCM.getCluster().getCidToInfoMap().get(container);
+      ContainerPlacementStatus placementStatus;
+      int requiredNodes = 
containerInfo.getReplicationConfig().getRequiredNodes();
+      if (containerInfo.getReplicationType() == 
HddsProtos.ReplicationType.RATIS) {
+        placementStatus = 
mockedSCM.getPlacementPolicy().validateContainerPlacement(replicas, 
requiredNodes);
+      } else {
+        placementStatus = 
mockedSCM.getEcPlacementPolicy().validateContainerPlacement(replicas, 
requiredNodes);
+      }
+      assertTrue(placementStatus.isPolicySatisfied());
+    }
+  }
+
+  @ParameterizedTest(name = "MockedSCM #{index}: {0}")
+  @MethodSource("createMockedSCMs")
+  public void targetDatanodeShouldBeInServiceHealthy(@Nonnull MockedSCM 
mockedSCM) throws NodeNotFoundException {
+    ContainerBalancerConfiguration config = balancerConfigByOzoneConfig(new 
OzoneConfiguration());
+    int nodeCount = mockedSCM.getCluster().getNodeCount();
+    if (nodeCount < DATANODE_COUNT_LIMIT_FOR_SMALL_CLUSTER) {
+      config.setMaxDatanodesPercentageToInvolvePerIteration(100);
+    }
+    config.setIterations(1);
+    config.setThreshold(10);
+    config.setMaxSizeToMovePerIteration(50 * STORAGE_UNIT);
+    config.setMaxSizeEnteringTarget(50 * STORAGE_UNIT);
+
+    ContainerBalancerTask task = mockedSCM.startBalancerTask(config);
+
+    for (DatanodeDetails target : task.getSelectedTargets()) {
+      NodeStatus status = mockedSCM.getNodeManager().getNodeStatus(target);
+      assertSame(HddsProtos.NodeOperationalState.IN_SERVICE, 
status.getOperationalState());
+      assertTrue(status.isHealthy());
+    }
+  }
+
+
+  @ParameterizedTest(name = "MockedSCM #{index}: {0}")
+  @MethodSource("createMockedSCMs")
+  public void selectedContainerShouldNotAlreadyHaveBeenSelected(@Nonnull 
MockedSCM mockedSCM)
+      throws NodeNotFoundException, ContainerNotFoundException, 
TimeoutException, ContainerReplicaNotFoundException {
+    ContainerBalancerConfiguration config = balancerConfigByOzoneConfig(new 
OzoneConfiguration());
+    int nodeCount = mockedSCM.getCluster().getNodeCount();
+    if (nodeCount < DATANODE_COUNT_LIMIT_FOR_SMALL_CLUSTER) {
+      config.setMaxDatanodesPercentageToInvolvePerIteration(100);
+    }
+    config.setIterations(1);
+    config.setThreshold(10);
+    config.setMaxSizeToMovePerIteration(50 * STORAGE_UNIT);
+    config.setMaxSizeEnteringTarget(50 * STORAGE_UNIT);
+
+    mockedSCM.enableLegacyReplicationManager();
+
+    ContainerBalancerTask task = mockedSCM.startBalancerTask(config);
+    int numContainers = task.getContainerToTargetMap().size();
+
+    /* Assuming move is called exactly once for each unique container, number 
of  calls to move should equal number of
+     unique containers. If number of  calls to move is more than number of 
unique containers, at least one container
+     has been re-selected. It's expected that number of calls to move should 
equal number of unique, selected containers
+      (from containerToTargetMap).
+     */
+    verify(mockedSCM.getReplicationManager(), times(numContainers))
+        .move(any(ContainerID.class), any(DatanodeDetails.class), 
any(DatanodeDetails.class));
+
+    // Try the same test by disabling LegacyReplicationManager so that 
MoveManager is used.
+    mockedSCM.disableLegacyReplicationManager();
+    ContainerBalancerTask nextTask = mockedSCM.startBalancerTask(config);
+
+    numContainers = nextTask.getContainerToTargetMap().size();
+    verify(mockedSCM.getMoveManager(), times(numContainers))
+        .move(any(ContainerID.class), any(DatanodeDetails.class), 
any(DatanodeDetails.class));
+  }
+
+  @ParameterizedTest(name = "MockedSCM #{index}: {0}")
+  @MethodSource("createMockedSCMs")
+  public void balancerShouldNotSelectConfiguredExcludeContainers(@Nonnull 
MockedSCM mockedSCM) {
+    ContainerBalancerConfiguration config = balancerConfigByOzoneConfig(new 
OzoneConfiguration());
+    int nodeCount = mockedSCM.getCluster().getNodeCount();
+    if (nodeCount < DATANODE_COUNT_LIMIT_FOR_SMALL_CLUSTER) {
+      config.setMaxDatanodesPercentageToInvolvePerIteration(100);
+    }
+    config.setIterations(1);
+    config.setThreshold(10);
+    config.setMaxSizeToMovePerIteration(50 * STORAGE_UNIT);
+    config.setMaxSizeEnteringTarget(50 * STORAGE_UNIT);
+    config.setExcludeContainers("1, 4, 5");
+
+    ContainerBalancerTask task = mockedSCM.startBalancerTask(config);
+
+    Set<ContainerID> excludeContainers = config.getExcludeContainers();
+    for (ContainerID container : task.getContainerToSourceMap().keySet()) {
+      assertThat(excludeContainers).doesNotContain(container);
+    }
+  }
 
   public static List<DatanodeUsageInfo> getUnBalancedNodes(@Nonnull 
ContainerBalancerTask task) {
     ArrayList<DatanodeUsageInfo> result = new ArrayList<>();
diff --git 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancerTask.java
 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancerTask.java
index 0f4551b45c..d0e9cd53fe 100644
--- 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancerTask.java
+++ 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancerTask.java
@@ -27,7 +27,6 @@ import org.apache.hadoop.hdds.protocol.DatanodeDetails;
 import org.apache.hadoop.hdds.protocol.MockDatanodeDetails;
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReplicaProto;
-import org.apache.hadoop.hdds.scm.ContainerPlacementStatus;
 import org.apache.hadoop.hdds.scm.PlacementPolicy;
 import org.apache.hadoop.hdds.scm.PlacementPolicyValidateProxy;
 import org.apache.hadoop.hdds.scm.container.ContainerID;
@@ -47,7 +46,6 @@ import 
org.apache.hadoop.hdds.scm.ha.StatefulServiceStateManager;
 import org.apache.hadoop.hdds.scm.ha.StatefulServiceStateManagerImpl;
 import org.apache.hadoop.hdds.scm.net.NetworkTopology;
 import org.apache.hadoop.hdds.scm.node.DatanodeUsageInfo;
-import org.apache.hadoop.hdds.scm.node.NodeStatus;
 import org.apache.hadoop.hdds.scm.node.states.NodeNotFoundException;
 import org.apache.hadoop.hdds.scm.server.StorageContainerManager;
 import org.apache.hadoop.hdds.server.events.EventPublisher;
@@ -74,11 +72,9 @@ import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-import java.util.stream.Collectors;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotSame;
-import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static 
org.apache.hadoop.hdds.scm.container.replication.ReplicationManager.ReplicationManagerConfiguration;
@@ -86,10 +82,8 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.anyString;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.when;
 
 /**
@@ -248,259 +242,6 @@ public class TestContainerBalancerTask {
         sb.getMetrics(), balancerConfiguration, false);
   }
 
-  @Test
-  public void containerBalancerShouldSelectOnlyClosedContainers()
-      throws IllegalContainerBalancerStateException, IOException,
-      InvalidContainerBalancerConfigurationException, TimeoutException {
-    // make all containers open, balancer should not select any of them
-    for (ContainerInfo containerInfo : cidToInfoMap.values()) {
-      containerInfo.setState(HddsProtos.LifeCycleState.OPEN);
-    }
-    balancerConfiguration.setThreshold(10);
-    startBalancer(balancerConfiguration);
-    stopBalancer();
-
-    // balancer should have identified unbalanced nodes
-    
assertFalse(TestContainerBalancerDatanodeNodeLimit.getUnBalancedNodes(containerBalancerTask).isEmpty());
-    // no container should have been selected
-    assertTrue(containerBalancerTask.getContainerToSourceMap()
-        .isEmpty());
-    /*
-    Iteration result should be CAN_NOT_BALANCE_ANY_MORE because no container
-    move is generated
-     */
-    assertEquals(
-        ContainerBalancerTask.IterationResult.CAN_NOT_BALANCE_ANY_MORE,
-        containerBalancerTask.getIterationResult());
-
-    // now, close all containers
-    for (ContainerInfo containerInfo : cidToInfoMap.values()) {
-      containerInfo.setState(HddsProtos.LifeCycleState.CLOSED);
-    }
-    startBalancer(balancerConfiguration);
-    stopBalancer();
-
-    // check whether all selected containers are closed
-    for (ContainerID cid:
-         containerBalancerTask.getContainerToSourceMap().keySet()) {
-      assertSame(
-          cidToInfoMap.get(cid).getState(), HddsProtos.LifeCycleState.CLOSED);
-    }
-  }
-
-  /**
-   * Container Balancer should not select a non-CLOSED replica for moving.
-   */
-  @Test
-  public void balancerShouldNotSelectNonClosedContainerReplicas()
-      throws IOException, IllegalContainerBalancerStateException,
-      InvalidContainerBalancerConfigurationException, TimeoutException {
-
-    // let's mock such that all replicas have CLOSING state
-    when(containerManager.getContainerReplicas(any(ContainerID.class)))
-        .thenAnswer(invocationOnMock -> {
-          ContainerID cid = (ContainerID) invocationOnMock.getArguments()[0];
-          Set<ContainerReplica> replicas = cidToReplicasMap.get(cid);
-          Set<ContainerReplica> replicasToReturn =
-              new HashSet<>(replicas.size());
-          for (ContainerReplica replica : replicas) {
-            ContainerReplica newReplica =
-                replica.toBuilder().setContainerState(
-                    ContainerReplicaProto.State.CLOSING).build();
-            replicasToReturn.add(newReplica);
-          }
-
-          return replicasToReturn;
-        });
-
-    balancerConfiguration.setThreshold(10);
-    balancerConfiguration.setMaxDatanodesPercentageToInvolvePerIteration(100);
-    balancerConfiguration.setMaxSizeToMovePerIteration(50 * STORAGE_UNIT);
-    balancerConfiguration.setMaxSizeEnteringTarget(50 * STORAGE_UNIT);
-
-    startBalancer(balancerConfiguration);
-    stopBalancer();
-
-    // balancer should have identified unbalanced nodes
-    
assertFalse(TestContainerBalancerDatanodeNodeLimit.getUnBalancedNodes(containerBalancerTask).isEmpty());
-    // no container should have moved because all replicas are CLOSING
-    assertTrue(
-        containerBalancerTask.getContainerToSourceMap().isEmpty());
-  }
-
-  @Test
-  public void containerBalancerShouldObeyMaxSizeToMoveLimit()
-      throws IllegalContainerBalancerStateException, IOException,
-      InvalidContainerBalancerConfigurationException, TimeoutException {
-    balancerConfiguration.setThreshold(1);
-    balancerConfiguration.setMaxSizeToMovePerIteration(10 * STORAGE_UNIT);
-    balancerConfiguration.setIterations(1);
-    startBalancer(balancerConfiguration);
-
-    // balancer should not have moved more size than the limit
-    
assertThat(containerBalancerTask.getSizeScheduledForMoveInLatestIteration())
-        .isLessThanOrEqualTo(10 * STORAGE_UNIT);
-
-    long size = containerBalancerTask.getMetrics()
-        .getDataSizeMovedGBInLatestIteration();
-    assertThat(size).isGreaterThan(0);
-    assertThat(size).isLessThanOrEqualTo(10);
-    stopBalancer();
-  }
-
-  @Test
-  public void targetDatanodeShouldNotAlreadyContainSelectedContainer()
-      throws IllegalContainerBalancerStateException, IOException,
-      InvalidContainerBalancerConfigurationException, TimeoutException {
-    balancerConfiguration.setThreshold(10);
-    balancerConfiguration.setMaxSizeToMovePerIteration(100 * STORAGE_UNIT);
-    balancerConfiguration.setMaxDatanodesPercentageToInvolvePerIteration(100);
-    startBalancer(balancerConfiguration);
-
-    stopBalancer();
-    Map<ContainerID, DatanodeDetails> map =
-        containerBalancerTask.getContainerToTargetMap();
-    for (Map.Entry<ContainerID, DatanodeDetails> entry : map.entrySet()) {
-      ContainerID container = entry.getKey();
-      DatanodeDetails target = entry.getValue();
-      assertTrue(cidToReplicasMap.get(container)
-          .stream()
-          .map(ContainerReplica::getDatanodeDetails)
-          .noneMatch(target::equals));
-    }
-  }
-
-  @Test
-  public void containerMoveSelectionShouldFollowPlacementPolicy()
-      throws IllegalContainerBalancerStateException, IOException,
-      InvalidContainerBalancerConfigurationException, TimeoutException {
-    balancerConfiguration.setThreshold(10);
-    balancerConfiguration.setMaxSizeToMovePerIteration(50 * STORAGE_UNIT);
-    balancerConfiguration.setMaxDatanodesPercentageToInvolvePerIteration(100);
-    balancerConfiguration.setIterations(1);
-    startBalancer(balancerConfiguration);
-
-    stopBalancer();
-    Map<ContainerID, DatanodeDetails> containerFromSourceMap =
-        containerBalancerTask.getContainerToSourceMap();
-    Map<ContainerID, DatanodeDetails> containerToTargetMap =
-        containerBalancerTask.getContainerToTargetMap();
-
-    // for each move selection, check if {replicas - source + target}
-    // satisfies placement policy
-    for (Map.Entry<ContainerID, DatanodeDetails> entry :
-        containerFromSourceMap.entrySet()) {
-      ContainerID container = entry.getKey();
-      DatanodeDetails source = entry.getValue();
-
-      List<DatanodeDetails> replicas = cidToReplicasMap.get(container)
-          .stream()
-          .map(ContainerReplica::getDatanodeDetails)
-          .collect(Collectors.toList());
-      // remove source and add target
-      replicas.remove(source);
-      replicas.add(containerToTargetMap.get(container));
-
-      ContainerInfo containerInfo = cidToInfoMap.get(container);
-      ContainerPlacementStatus placementStatus;
-      if (containerInfo.getReplicationType() ==
-          HddsProtos.ReplicationType.RATIS) {
-        placementStatus = placementPolicy.validateContainerPlacement(replicas,
-            containerInfo.getReplicationConfig().getRequiredNodes());
-      } else {
-        placementStatus =
-            ecPlacementPolicy.validateContainerPlacement(replicas,
-                containerInfo.getReplicationConfig().getRequiredNodes());
-      }
-      assertTrue(placementStatus.isPolicySatisfied());
-    }
-  }
-
-  @Test
-  public void targetDatanodeShouldBeInServiceHealthy()
-      throws NodeNotFoundException, IllegalContainerBalancerStateException,
-      IOException, InvalidContainerBalancerConfigurationException,
-      TimeoutException {
-    balancerConfiguration.setThreshold(10);
-    balancerConfiguration.setMaxDatanodesPercentageToInvolvePerIteration(100);
-    balancerConfiguration.setMaxSizeToMovePerIteration(50 * STORAGE_UNIT);
-    balancerConfiguration.setMaxSizeEnteringTarget(50 * STORAGE_UNIT);
-    balancerConfiguration.setIterations(1);
-    startBalancer(balancerConfiguration);
-
-    stopBalancer();
-    for (DatanodeDetails target : containerBalancerTask.getSelectedTargets()) {
-      NodeStatus status = mockNodeManager.getNodeStatus(target);
-      assertSame(HddsProtos.NodeOperationalState.IN_SERVICE,
-          status.getOperationalState());
-      assertTrue(status.isHealthy());
-    }
-  }
-
-  @Test
-  public void selectedContainerShouldNotAlreadyHaveBeenSelected()
-      throws IllegalContainerBalancerStateException, IOException,
-      InvalidContainerBalancerConfigurationException, NodeNotFoundException,
-      TimeoutException {
-    balancerConfiguration.setThreshold(10);
-    balancerConfiguration.setMaxDatanodesPercentageToInvolvePerIteration(100);
-    balancerConfiguration.setMaxSizeToMovePerIteration(50 * STORAGE_UNIT);
-    balancerConfiguration.setMaxSizeEnteringTarget(50 * STORAGE_UNIT);
-    balancerConfiguration.setIterations(1);
-    rmConf.setEnableLegacy(true);
-
-    startBalancer(balancerConfiguration);
-
-    stopBalancer();
-
-    int numContainers = containerBalancerTask.getContainerToTargetMap().size();
-
-    /*
-    Assuming move is called exactly once for each unique container, number of
-     calls to move should equal number of unique containers. If number of
-     calls to move is more than number of unique containers, at least one
-     container has been re-selected. It's expected that number of calls to
-     move should equal number of unique, selected containers (from
-     containerToTargetMap).
-     */
-    verify(replicationManager, times(numContainers))
-        .move(any(ContainerID.class), any(DatanodeDetails.class),
-            any(DatanodeDetails.class));
-
-    /*
-     Try the same test by disabling LegacyReplicationManager so that
-     MoveManager is used.
-     */
-    rmConf.setEnableLegacy(false);
-    startBalancer(balancerConfiguration);
-    stopBalancer();
-    numContainers = containerBalancerTask.getContainerToTargetMap().size();
-    verify(moveManager, times(numContainers))
-        .move(any(ContainerID.class), any(DatanodeDetails.class),
-            any(DatanodeDetails.class));
-  }
-
-  @Test
-  public void balancerShouldNotSelectConfiguredExcludeContainers()
-      throws IllegalContainerBalancerStateException, IOException,
-      InvalidContainerBalancerConfigurationException, TimeoutException {
-    balancerConfiguration.setThreshold(10);
-    balancerConfiguration.setMaxDatanodesPercentageToInvolvePerIteration(100);
-    balancerConfiguration.setMaxSizeToMovePerIteration(50 * STORAGE_UNIT);
-    balancerConfiguration.setMaxSizeEnteringTarget(50 * STORAGE_UNIT);
-    balancerConfiguration.setExcludeContainers("1, 4, 5");
-
-    startBalancer(balancerConfiguration);
-
-    stopBalancer();
-    Set<ContainerID> excludeContainers =
-        balancerConfiguration.getExcludeContainers();
-    for (ContainerID container :
-        containerBalancerTask.getContainerToSourceMap().keySet()) {
-      assertThat(excludeContainers).doesNotContain(container);
-    }
-  }
-
   /**
    * Tests if {@link ContainerBalancer} follows the includeNodes and
    * excludeNodes configurations in {@link ContainerBalancerConfiguration}.


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to