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

Gargi-jais11 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 d9d22ca0bd1 HDDS-15438. [DiskBalancer] Validate persisted 
diskbalancer.info while reading YAML. (#10395).
d9d22ca0bd1 is described below

commit d9d22ca0bd1666ed4f8c98ca713a1df44630e206
Author: slfan1989 <[email protected]>
AuthorDate: Thu Jun 4 12:27:31 2026 +0800

    HDDS-15438. [DiskBalancer] Validate persisted diskbalancer.info while 
reading YAML. (#10395).
---
 .../container/diskbalancer/DiskBalancerYaml.java   | 57 ++++++++++++++++++----
 .../diskbalancer/TestDiskBalancerYaml.java         | 53 ++++++++++++++++++++
 2 files changed, 101 insertions(+), 9 deletions(-)

diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/DiskBalancerYaml.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/DiskBalancerYaml.java
index 1b8ecef32f2..2c539173d4f 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/DiskBalancerYaml.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/DiskBalancerYaml.java
@@ -76,10 +76,9 @@ public static DiskBalancerInfo readDiskBalancerInfoFile(File 
path)
         throw new IOException("Unable to parse yaml file.", e);
       }
 
-      // getContainerStates() may be null if the key is absent; 
isNotBlank(null) is false.
-      String cs = diskBalancerInfoYaml.getContainerStates();
-      String containerStates = StringUtils.isNotBlank(cs)
-          ? cs.trim() : DiskBalancerConfiguration.DEFAULT_CONTAINER_STATES;
+      validateRequiredFields(diskBalancerInfoYaml);
+      DiskBalancerVersion version = getValidatedVersion(diskBalancerInfoYaml);
+      String containerStates = 
getValidatedContainerStates(diskBalancerInfoYaml);
       diskBalancerInfo = new DiskBalancerInfo(
           diskBalancerInfoYaml.operationalState,
           diskBalancerInfoYaml.getThreshold(),
@@ -87,13 +86,53 @@ public static DiskBalancerInfo 
readDiskBalancerInfoFile(File path)
           diskBalancerInfoYaml.getParallelThread(),
           diskBalancerInfoYaml.isStopAfterDiskEven(),
           containerStates,
-          DiskBalancerVersion.getDiskBalancerVersion(
-              diskBalancerInfoYaml.version));
+          version);
+      validatePersistedConfiguration(diskBalancerInfo);
     }
 
     return diskBalancerInfo;
   }
 
+  private static void validateRequiredFields(
+      DiskBalancerInfoYaml diskBalancerInfoYaml) throws IOException {
+    if (diskBalancerInfoYaml.getOperationalState() == null) {
+      throw new IOException("DiskBalancer operationalState is missing from 
persisted info.");
+    }
+    if (diskBalancerInfoYaml.getVersion() == null) {
+      throw new IOException("DiskBalancer info version is missing from 
persisted info.");
+    }
+  }
+
+  private static DiskBalancerVersion getValidatedVersion(
+      DiskBalancerInfoYaml diskBalancerInfoYaml) throws IOException {
+    int rawVersion = diskBalancerInfoYaml.getVersion();
+    DiskBalancerVersion version =
+        DiskBalancerVersion.getDiskBalancerVersion(rawVersion);
+    if (version == null) {
+      throw new IOException("Unsupported DiskBalancer info version: " + 
rawVersion);
+    }
+    return version;
+  }
+
+  private static String getValidatedContainerStates(
+      DiskBalancerInfoYaml diskBalancerInfoYaml) {
+    // getContainerStates() may be null if the key is absent; isNotBlank(null) 
is false.
+    String containerStates = diskBalancerInfoYaml.getContainerStates();
+    return StringUtils.isNotBlank(containerStates)
+        ? containerStates.trim() : 
DiskBalancerConfiguration.DEFAULT_CONTAINER_STATES;
+  }
+
+  private static void validatePersistedConfiguration(
+      DiskBalancerInfo diskBalancerInfo) throws IOException {
+    try {
+      diskBalancerInfo.toConfiguration();
+    } catch (IllegalArgumentException ex) {
+      throw new IOException(
+          "Invalid DiskBalancer configuration in persisted info: "
+              + ex.getMessage(), ex);
+    }
+  }
+
   /**
    * Datanode DiskBalancer Info to be written to the yaml file.
    */
@@ -105,7 +144,7 @@ public static class DiskBalancerInfoYaml {
     private boolean stopAfterDiskEven;
     private String containerStates;
 
-    private int version;
+    private Integer version;
 
     public DiskBalancerInfoYaml() {
       // Needed for snake-yaml introspection.
@@ -163,11 +202,11 @@ public void setStopAfterDiskEven(boolean 
stopAfterDiskEven) {
       this.stopAfterDiskEven = stopAfterDiskEven;
     }
 
-    public void setVersion(int version) {
+    public void setVersion(Integer version) {
       this.version = version;
     }
 
-    public int getVersion() {
+    public Integer getVersion() {
       return this.version;
     }
 
diff --git 
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/diskbalancer/TestDiskBalancerYaml.java
 
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/diskbalancer/TestDiskBalancerYaml.java
index 9ec501a9a9d..fa4f05b0074 100644
--- 
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/diskbalancer/TestDiskBalancerYaml.java
+++ 
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/diskbalancer/TestDiskBalancerYaml.java
@@ -18,6 +18,7 @@
 package org.apache.hadoop.ozone.container.diskbalancer;
 
 import static 
org.apache.hadoop.ozone.OzoneConsts.OZONE_SCM_DATANODE_DISK_BALANCER_INFO_FILE_DEFAULT;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
 import java.io.File;
 import java.io.IOException;
@@ -101,4 +102,56 @@ public void testReadYamlNullContainerStatesUsesDefault() 
throws IOException {
     DiskBalancerInfo info = DiskBalancerYaml.readDiskBalancerInfoFile(file);
     
Assertions.assertEquals(DiskBalancerConfiguration.DEFAULT_CONTAINER_STATES, 
info.getContainerStates());
   }
+
+  @ParameterizedTest
+  @MethodSource("invalidDiskBalancerYamlCases")
+  public void testReadYamlRejectsInvalidPersistedInfo(String yaml,
+      String expectedMessage) throws IOException {
+    File file = new File(tmpDir.toString(),
+        OZONE_SCM_DATANODE_DISK_BALANCER_INFO_FILE_DEFAULT);
+    Files.write(file.toPath(), yaml.getBytes(StandardCharsets.UTF_8));
+
+    IOException ex = assertThrows(IOException.class,
+        () -> DiskBalancerYaml.readDiskBalancerInfoFile(file));
+
+    Assertions.assertTrue(ex.getMessage().contains(expectedMessage),
+        () -> "Expected message to contain '" + expectedMessage + "': "
+            + ex.getMessage());
+  }
+
+  public static Stream<Arguments> invalidDiskBalancerYamlCases() {
+    return Stream.of(
+        Arguments.of(validYaml()
+            .replace("version: 1\n", "version: 99\n"),
+            "Unsupported DiskBalancer info version: 99"),
+        Arguments.of(validYaml()
+            .replace("version: 1\n", ""),
+            "DiskBalancer info version is missing"),
+        Arguments.of(validYaml()
+            .replace("operationalState: RUNNING\n", ""),
+            "DiskBalancer operationalState is missing"),
+        Arguments.of(validYaml()
+            .replace("threshold: 10.0\n", "threshold: 0.0\n"),
+            "Invalid DiskBalancer configuration in persisted info"),
+        Arguments.of(validYaml()
+            .replace("bandwidthInMB: 100\n", "bandwidthInMB: 0\n"),
+            "Invalid DiskBalancer configuration in persisted info"),
+        Arguments.of(validYaml()
+            .replace("parallelThread: 5\n", "parallelThread: 0\n"),
+            "Invalid DiskBalancer configuration in persisted info"),
+        Arguments.of(validYaml()
+            .replace("containerStates: CLOSED,QUASI_CLOSED\n",
+                "containerStates: OPEN\n"),
+            "Invalid DiskBalancer configuration in persisted info"));
+  }
+
+  private static String validYaml() {
+    return "operationalState: RUNNING\n"
+        + "threshold: 10.0\n"
+        + "bandwidthInMB: 100\n"
+        + "parallelThread: 5\n"
+        + "stopAfterDiskEven: true\n"
+        + "containerStates: CLOSED,QUASI_CLOSED\n"
+        + "version: 1\n";
+  }
 }


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

Reply via email to