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

siddhant 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 e40928ac0ce HDDS-14662. Container Balancer does not validate 
include/exclude datanode names (#9812)
e40928ac0ce is described below

commit e40928ac0ceca13ac955b3d42e36acd9bfdeef3e
Author: sravani <[email protected]>
AuthorDate: Mon Mar 2 11:36:35 2026 +0530

    HDDS-14662. Container Balancer does not validate include/exclude datanode 
names (#9812)
---
 .../scm/container/balancer/ContainerBalancer.java  | 29 +++++++++++++++++
 .../container/balancer/TestContainerBalancer.java  | 37 ++++++++++++++++++++++
 2 files changed, 66 insertions(+)

diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancer.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancer.java
index 07319471dcc..2d3d7a3bc4b 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancer.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancer.java
@@ -21,6 +21,7 @@
 import java.io.IOException;
 import java.time.Duration;
 import java.time.OffsetDateTime;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.ReentrantLock;
@@ -492,6 +493,9 @@ private void 
validateConfiguration(ContainerBalancerConfiguration conf)
       LOG.warn(msg);
       throw new InvalidContainerBalancerConfigurationException(msg);
     }
+
+    validateNodeList(conf.getIncludeNodes(), "included");
+    validateNodeList(conf.getExcludeNodes(), "excluded");
   }
 
   public ContainerBalancerMetrics getMetrics() {
@@ -510,4 +514,29 @@ public String toString() {
         "%-30s %b%n", "Key", "Value", "Running", isBalancerRunning());
     return status + config.toString();
   }
+
+  /**
+   * Validates if the provided datanodes are known by SCM.
+   *
+   * @param nodes set of datanode hostnames or IP addresses
+   * @param type context label for the error message
+   * @throws InvalidContainerBalancerConfigurationException if a node is 
unknown
+   */
+  private void validateNodeList(Set<String> nodes, String type)
+      throws InvalidContainerBalancerConfigurationException {
+    if (nodes == null || nodes.isEmpty()) {
+      return;
+    }
+
+    for (String node : nodes) {
+      // Check if SCM knows about this node by hostname or IP
+      if (scm.getScmNodeManager().getNodesByAddress(node).isEmpty()) {
+        String errorMessage = String.format("Invalid configuration: The %s 
datanode '%s' " +
+                "does not exist or is not registered with SCM. Please check 
the hostname/IP.",
+            type, node);
+        LOG.warn(errorMessage);
+        throw new InvalidContainerBalancerConfigurationException(errorMessage);
+      }
+    }
+  }
 }
diff --git 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancer.java
 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancer.java
index 33ed8f0e83c..78a6491a70e 100644
--- 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancer.java
+++ 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancer.java
@@ -35,11 +35,13 @@
 
 import com.google.protobuf.ByteString;
 import java.io.IOException;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.hdds.protocol.DatanodeDetails;
 import org.apache.hadoop.hdds.scm.ha.SCMContext;
 import org.apache.hadoop.hdds.scm.ha.SCMServiceManager;
 import org.apache.hadoop.hdds.scm.ha.StatefulServiceStateManager;
@@ -291,6 +293,41 @@ public void testGetBalancerStatusInfo() throws Exception {
     assertSame(ContainerBalancerTask.Status.STOPPED, 
containerBalancer.getBalancerStatus());
   }
 
+  @Test
+  public void testStartBalancerWithInvalidNodes() throws Exception {
+    NodeManager nm = scm.getScmNodeManager();
+    String validHost = "1.2.3.4";
+    String invalidHost = "invalid-host-name";
+
+    
when(nm.getNodesByAddress(invalidHost)).thenReturn(Collections.emptyList());
+    
when(nm.getNodesByAddress(validHost)).thenReturn(Collections.singletonList(mock(DatanodeDetails.class)));
+
+    // Test invalid includeNodes
+    balancerConfiguration.setIncludeNodes(invalidHost);
+    InvalidContainerBalancerConfigurationException ex =
+        assertThrows(InvalidContainerBalancerConfigurationException.class,
+            () -> containerBalancer.startBalancer(balancerConfiguration));
+    assertThat(ex.getMessage()).contains(invalidHost);
+    assertSame(ContainerBalancerTask.Status.STOPPED, 
containerBalancer.getBalancerStatus());
+
+    // Test invalid excludeNodes
+    balancerConfiguration.setIncludeNodes("");
+    balancerConfiguration.setExcludeNodes(invalidHost);
+    ex = assertThrows(InvalidContainerBalancerConfigurationException.class,
+        () -> containerBalancer.startBalancer(balancerConfiguration));
+    assertThat(ex.getMessage()).contains(invalidHost);
+    assertSame(ContainerBalancerTask.Status.STOPPED, 
containerBalancer.getBalancerStatus());
+
+    // Test a valid case
+    balancerConfiguration.setExcludeNodes("");
+    balancerConfiguration.setIncludeNodes(validHost);
+    assertDoesNotThrow(() -> startBalancer(balancerConfiguration));
+    assertSame(ContainerBalancerTask.Status.RUNNING, 
containerBalancer.getBalancerStatus());
+
+    stopBalancer();
+    assertSame(ContainerBalancerTask.Status.STOPPED, 
containerBalancer.getBalancerStatus());
+  }
+
   private void startBalancer(ContainerBalancerConfiguration config)
       throws IllegalContainerBalancerStateException, IOException,
       InvalidContainerBalancerConfigurationException, TimeoutException {


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

Reply via email to