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

nanda 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 959a39d4d7 HDDS-11851. Finer-grained subcommand interface for 
OzoneDebug and OzoneRepair. (#7526)
959a39d4d7 is described below

commit 959a39d4d7bc7fdbaef8a7d52562081121549a15
Author: Doroszlai, Attila <[email protected]>
AuthorDate: Fri Dec 6 18:47:08 2024 +0100

    HDDS-11851. Finer-grained subcommand interface for OzoneDebug and 
OzoneRepair. (#7526)
---
 .../org/apache/hadoop/hdds/cli/GenericCli.java     | 19 +-----------------
 .../hadoop/hdds/cli/SubcommandWithParent.java      | 23 +++++++++++++++++++++-
 .../apache/hadoop/hdds/cli/DebugSubcommand.java    | 23 ++++++++++++++++++++++
 .../apache/hadoop/hdds/cli/RepairSubcommand.java   | 23 ++++++++++++++++++++++
 .../org/apache/hadoop/ozone/debug/TestLDBCli.java  |  3 ---
 .../hadoop/ozone/shell/TestOzoneDebugShell.java    |  2 --
 .../hadoop/ozone/shell/TestOzoneRepairShell.java   | 14 ++++---------
 .../ozone/debug/CompactionLogDagPrinter.java       | 11 +++--------
 .../hadoop/ozone/debug/FindMissingPadding.java     | 14 +++----------
 .../apache/hadoop/ozone/debug/LeaseRecoverer.java  | 14 +++----------
 .../org/apache/hadoop/ozone/debug/OzoneDebug.java  |  9 ++++++++-
 .../apache/hadoop/ozone/debug/PrefixParser.java    | 11 +++--------
 .../apache/hadoop/ozone/debug/ReadReplicas.java    | 11 +++--------
 .../apache/hadoop/ozone/debug/VersionDebug.java    | 11 +++--------
 .../hadoop/ozone/debug/chunk/ChunkKeyHandler.java  | 12 +++--------
 .../ozone/debug/container/ContainerCommands.java   | 11 +++--------
 .../apache/hadoop/ozone/debug/ldb/DBScanner.java   | 10 +---------
 .../apache/hadoop/ozone/debug/ldb/DropTable.java   |  8 +-------
 .../apache/hadoop/ozone/debug/ldb/ListTables.java  | 11 +----------
 .../apache/hadoop/ozone/debug/ldb/RDBParser.java   | 18 ++++++++---------
 .../apache/hadoop/ozone/debug/ldb/ValueSchema.java | 10 +---------
 .../ozone/debug/segmentparser/RatisLogParser.java  | 12 +++--------
 .../apache/hadoop/ozone/repair/OzoneRepair.java    |  8 +++++++-
 .../hadoop/ozone/repair/RecoverSCMCertificate.java | 11 +++--------
 .../apache/hadoop/ozone/repair/ldb/RDBRepair.java  | 16 +++++++--------
 .../hadoop/ozone/repair/ldb/SnapshotRepair.java    | 10 +---------
 .../ozone/repair/ldb/TransactionInfoRepair.java    | 12 +----------
 .../hadoop/ozone/repair/quota/QuotaRepair.java     | 15 +++++++-------
 .../hadoop/ozone/repair/quota/QuotaStatus.java     | 11 +----------
 .../hadoop/ozone/repair/quota/QuotaTrigger.java    | 10 +---------
 30 files changed, 149 insertions(+), 224 deletions(-)

diff --git 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/GenericCli.java 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/GenericCli.java
index a64c4bd84a..865b94f514 100644
--- 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/GenericCli.java
+++ 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/GenericCli.java
@@ -19,7 +19,6 @@ package org.apache.hadoop.hdds.cli;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.ServiceLoader;
 import java.util.concurrent.Callable;
 
 import org.apache.hadoop.fs.Path;
@@ -27,7 +26,6 @@ import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 
 import com.google.common.annotations.VisibleForTesting;
 import picocli.CommandLine;
-import picocli.CommandLine.Command;
 import picocli.CommandLine.ExitCode;
 import picocli.CommandLine.Model.CommandSpec;
 import picocli.CommandLine.Option;
@@ -67,26 +65,11 @@ public class GenericCli implements Callable<Void>, 
GenericParentCommand {
     });
 
     if (type != null) {
-      addSubcommands(cmd, type);
+      SubcommandWithParent.addSubcommands(getCmd(), type);
     }
-
     ExtensibleParentCommand.addSubcommands(cmd);
   }
 
-  private void addSubcommands(CommandLine cli, Class<?> type) {
-    ServiceLoader<SubcommandWithParent> registeredSubcommands =
-        ServiceLoader.load(SubcommandWithParent.class);
-    for (SubcommandWithParent subcommand : registeredSubcommands) {
-      if (subcommand.getParentType().equals(type)) {
-        final Command commandAnnotation =
-            subcommand.getClass().getAnnotation(Command.class);
-        CommandLine subcommandCommandLine = new CommandLine(subcommand, 
cli.getFactory());
-        addSubcommands(subcommandCommandLine, subcommand.getClass());
-        cli.addSubcommand(commandAnnotation.name(), subcommandCommandLine);
-      }
-    }
-  }
-
   /**
    * Handle the error when subcommand is required but not set.
    */
diff --git 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/SubcommandWithParent.java
 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/SubcommandWithParent.java
index 8421ab19cf..398c4f61ba 100644
--- 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/SubcommandWithParent.java
+++ 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/SubcommandWithParent.java
@@ -17,11 +17,32 @@
  */
 package org.apache.hadoop.hdds.cli;
 
+import picocli.CommandLine;
+
+import java.util.ServiceLoader;
+
 /**
- * Defineds parent command for SPI based subcommand registration.
+ * Defines parent command for SPI based subcommand registration.
+ * @deprecated use more specific interfaces
+ * @see ExtensibleParentCommand
  */
+@Deprecated
 public interface SubcommandWithParent {
 
+  static void addSubcommands(CommandLine cli, Class<?> type) {
+    ServiceLoader<SubcommandWithParent> registeredSubcommands =
+        ServiceLoader.load(SubcommandWithParent.class);
+    for (SubcommandWithParent subcommand : registeredSubcommands) {
+      if (subcommand.getParentType().equals(type)) {
+        final CommandLine.Command commandAnnotation =
+            subcommand.getClass().getAnnotation(CommandLine.Command.class);
+        CommandLine subcommandCommandLine = new CommandLine(subcommand);
+        addSubcommands(subcommandCommandLine, subcommand.getClass());
+        cli.addSubcommand(commandAnnotation.name(), subcommandCommandLine);
+      }
+    }
+  }
+
   /**
    * Java type of the parent command.
    */
diff --git 
a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/cli/DebugSubcommand.java
 
b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/cli/DebugSubcommand.java
new file mode 100644
index 0000000000..3915fd8684
--- /dev/null
+++ 
b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/cli/DebugSubcommand.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.hadoop.hdds.cli;
+
+/** Marker interface for subcommands to be added to {@code OzoneDebug}. */
+public interface DebugSubcommand {
+  // marker
+}
diff --git 
a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/cli/RepairSubcommand.java
 
b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/cli/RepairSubcommand.java
new file mode 100644
index 0000000000..1eb12b0125
--- /dev/null
+++ 
b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/cli/RepairSubcommand.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.hadoop.hdds.cli;
+
+/** Marker interface for subcommands to be added to {@code OzoneRepair}. */
+public interface RepairSubcommand {
+  // marker
+}
diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/debug/TestLDBCli.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/debug/TestLDBCli.java
index 56a814da1f..aac55367ad 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/debug/TestLDBCli.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/debug/TestLDBCli.java
@@ -38,7 +38,6 @@ import 
org.apache.hadoop.ozone.container.keyvalue.helpers.BlockUtils;
 import 
org.apache.hadoop.ozone.container.metadata.DatanodeSchemaThreeDBDefinition;
 import org.apache.hadoop.ozone.debug.ldb.DBScanner;
 import org.apache.hadoop.ozone.debug.ldb.RDBParser;
-import org.apache.hadoop.ozone.debug.ldb.ValueSchema;
 import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
 import org.apache.hadoop.ozone.om.request.OMRequestTestUtils;
 import jakarta.annotation.Nonnull;
@@ -103,8 +102,6 @@ public class TestLDBCli {
     pstderr = new PrintWriter(stderr);
 
     cmd = new CommandLine(new RDBParser())
-        .addSubcommand(new DBScanner())
-        .addSubcommand(new ValueSchema())
         .setOut(pstdout)
         .setErr(pstderr);
 
diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneDebugShell.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneDebugShell.java
index f4f980e340..f4026ed98c 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneDebugShell.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneDebugShell.java
@@ -36,7 +36,6 @@ import org.apache.hadoop.ozone.TestDataUtil;
 import org.apache.hadoop.ozone.client.OzoneClient;
 import org.apache.hadoop.ozone.client.OzoneClientFactory;
 import org.apache.hadoop.ozone.client.OzoneSnapshot;
-import org.apache.hadoop.ozone.debug.ldb.DBScanner;
 import org.apache.hadoop.ozone.debug.OzoneDebug;
 import org.apache.hadoop.ozone.debug.ldb.RDBParser;
 import org.apache.hadoop.ozone.om.OMConfigKeys;
@@ -149,7 +148,6 @@ public class TestOzoneDebugShell {
     StringWriter stdout = new StringWriter();
     PrintWriter pstdout = new PrintWriter(stdout);
     CommandLine cmd = new CommandLine(new RDBParser())
-        .addSubcommand(new DBScanner())
         .setOut(pstdout);
     final String volumeName = UUID.randomUUID().toString();
     final String bucketName = UUID.randomUUID().toString();
diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java
index 1860d695f5..e770a36c73 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java
@@ -19,15 +19,10 @@ package org.apache.hadoop.ozone.shell;
 
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.ozone.MiniOzoneCluster;
-import org.apache.hadoop.ozone.debug.ldb.DBScanner;
 import org.apache.hadoop.ozone.debug.ldb.RDBParser;
 import org.apache.hadoop.ozone.om.OMStorage;
 import org.apache.hadoop.ozone.repair.OzoneRepair;
 import org.apache.hadoop.ozone.repair.ldb.RDBRepair;
-import org.apache.hadoop.ozone.repair.ldb.TransactionInfoRepair;
-import org.apache.hadoop.ozone.repair.quota.QuotaRepair;
-import org.apache.hadoop.ozone.repair.quota.QuotaStatus;
-import org.apache.hadoop.ozone.repair.quota.QuotaTrigger;
 import org.apache.ozone.test.GenericTestUtils;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeAll;
@@ -89,7 +84,7 @@ public class TestOzoneRepairShell {
 
   @Test
   public void testUpdateTransactionInfoTable() throws Exception {
-    CommandLine cmd = new CommandLine(new RDBRepair()).addSubcommand(new 
TransactionInfoRepair());
+    CommandLine cmd = new CommandLine(new RDBRepair());
     String dbPath = new File(OMStorage.getOmDbDir(conf) + "/" + 
OM_DB_NAME).getPath();
 
     cluster.getOzoneManager().stop();
@@ -120,7 +115,7 @@ public class TestOzoneRepairShell {
   }
 
   private String scanTransactionInfoTable(String dbPath) throws Exception {
-    CommandLine cmdDBScanner = new CommandLine(new 
RDBParser()).addSubcommand(new DBScanner());
+    CommandLine cmdDBScanner = new CommandLine(new RDBParser());
     String[] argsDBScanner =
         new String[] {"--db=" + dbPath, "scan", "--column_family", 
"transactionInfoTable"};
     cmdDBScanner.execute(argsDBScanner);
@@ -138,12 +133,11 @@ public class TestOzoneRepairShell {
 
   @Test
   public void testQuotaRepair() throws Exception {
-    CommandLine cmd = new CommandLine(new OzoneRepair()).addSubcommand(new 
CommandLine(new QuotaRepair())
-        .addSubcommand(new QuotaStatus()).addSubcommand(new QuotaTrigger()));
+    CommandLine cmd = new OzoneRepair().getCmd();
 
     String[] args = new String[] {"quota", "status", "--service-host", 
conf.get(OZONE_OM_ADDRESS_KEY)};
     int exitCode = cmd.execute(args);
-    assertEquals(0, exitCode);
+    assertEquals(0, exitCode, err::toString);
     args = new String[] {"quota", "start", "--service-host", 
conf.get(OZONE_OM_ADDRESS_KEY)};
     exitCode = cmd.execute(args);
     assertEquals(0, exitCode);
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/CompactionLogDagPrinter.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/CompactionLogDagPrinter.java
index 91d033729a..175fc03e39 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/CompactionLogDagPrinter.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/CompactionLogDagPrinter.java
@@ -18,7 +18,7 @@
 
 package org.apache.hadoop.ozone.debug;
 
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
+import org.apache.hadoop.hdds.cli.DebugSubcommand;
 import org.apache.hadoop.ozone.client.OzoneClient;
 import org.apache.hadoop.ozone.shell.Handler;
 import org.apache.hadoop.ozone.shell.OzoneAddress;
@@ -35,9 +35,9 @@ import java.io.IOException;
     name = "print-log-dag",
     aliases = "pld",
     description = "Create an image of the current compaction log DAG in OM.")
-@MetaInfServices(SubcommandWithParent.class)
+@MetaInfServices(DebugSubcommand.class)
 public class CompactionLogDagPrinter extends Handler
-    implements SubcommandWithParent {
+    implements DebugSubcommand {
 
   @CommandLine.Option(names = {"-f", "--file-name-prefix"},
       description = "Prefix to be use in image file name. (optional)")
@@ -55,11 +55,6 @@ public class CompactionLogDagPrinter extends Handler
       defaultValue = "file_name")
   private String graphType;
 
-  @Override
-  public Class<?> getParentType() {
-    return OzoneDebug.class;
-  }
-
   @Override
   protected void execute(OzoneClient client, OzoneAddress address)
       throws IOException {
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/FindMissingPadding.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/FindMissingPadding.java
index 0c7ba187ce..21b572fbc4 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/FindMissingPadding.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/FindMissingPadding.java
@@ -17,7 +17,7 @@
  */
 package org.apache.hadoop.ozone.debug;
 
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
+import org.apache.hadoop.hdds.cli.DebugSubcommand;
 import org.apache.hadoop.hdds.client.ECReplicationConfig;
 import org.apache.hadoop.hdds.client.StandaloneReplicationConfig;
 import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos;
@@ -74,11 +74,8 @@ import static java.util.Comparator.comparing;
 @CommandLine.Command(name = "find-missing-padding",
     aliases = { "fmp" },
     description = "List all keys with any missing padding, optionally limited 
to a volume/bucket/key URI.")
-@MetaInfServices(SubcommandWithParent.class)
-public class FindMissingPadding extends Handler implements 
SubcommandWithParent {
-
-  @CommandLine.ParentCommand
-  private OzoneDebug parent;
+@MetaInfServices(DebugSubcommand.class)
+public class FindMissingPadding extends Handler implements DebugSubcommand {
 
   @CommandLine.Mixin
   private ScmOption scmOption;
@@ -100,11 +97,6 @@ public class FindMissingPadding extends Handler implements 
SubcommandWithParent
     return new OzoneAddress(uri);
   }
 
-  @Override
-  public Class<?> getParentType() {
-    return OzoneDebug.class;
-  }
-
   @Override
   protected void execute(OzoneClient ozoneClient, OzoneAddress address) throws 
IOException {
     findCandidateKeys(ozoneClient, address);
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/LeaseRecoverer.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/LeaseRecoverer.java
index a8891404e0..9c3865ae24 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/LeaseRecoverer.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/LeaseRecoverer.java
@@ -24,7 +24,7 @@ import java.util.concurrent.Callable;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.fs.LeaseRecoverable;
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
+import org.apache.hadoop.hdds.cli.DebugSubcommand;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 
 import org.kohsuke.MetaInfServices;
@@ -40,11 +40,8 @@ import picocli.CommandLine.Spec;
     customSynopsis = "ozone debug recover --path=<path>",
     description = "recover the lease of a specified file. Make sure to specify 
"
         + "file system scheme if ofs:// is not the default.")
-@MetaInfServices(SubcommandWithParent.class)
-public class LeaseRecoverer implements Callable<Void>, SubcommandWithParent {
-
-  @CommandLine.ParentCommand
-  private OzoneDebug parent;
+@MetaInfServices(DebugSubcommand.class)
+public class LeaseRecoverer implements Callable<Void>, DebugSubcommand {
 
   @Spec
   private CommandSpec spec;
@@ -62,11 +59,6 @@ public class LeaseRecoverer implements Callable<Void>, 
SubcommandWithParent {
     this.path = dbPath;
   }
 
-  @Override
-  public Class<?> getParentType() {
-    return OzoneDebug.class;
-  }
-
   @Override
   public Void call() throws Exception {
     OzoneConfiguration configuration = new OzoneConfiguration();
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/OzoneDebug.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/OzoneDebug.java
index 3d6cf57093..25ce665cf6 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/OzoneDebug.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/OzoneDebug.java
@@ -19,6 +19,8 @@
 package org.apache.hadoop.ozone.debug;
 
 import com.google.common.annotations.VisibleForTesting;
+import org.apache.hadoop.hdds.cli.DebugSubcommand;
+import org.apache.hadoop.hdds.cli.ExtensibleParentCommand;
 import org.apache.hadoop.hdds.cli.GenericCli;
 import org.apache.hadoop.hdds.cli.HddsVersionProvider;
 
@@ -32,7 +34,7 @@ import picocli.CommandLine;
         description = "Developer tools for Ozone Debug operations",
         versionProvider = HddsVersionProvider.class,
         mixinStandardHelpOptions = true)
-public class OzoneDebug extends GenericCli {
+public class OzoneDebug extends GenericCli implements ExtensibleParentCommand {
 
   private OzoneConfiguration ozoneConf;
 
@@ -63,4 +65,9 @@ public class OzoneDebug extends GenericCli {
 
     new OzoneDebug().run(argv);
   }
+
+  @Override
+  public Class<?> subcommandType() {
+    return DebugSubcommand.class;
+  }
 }
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/PrefixParser.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/PrefixParser.java
index fabc7f456a..cdda3e5e0f 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/PrefixParser.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/PrefixParser.java
@@ -26,7 +26,7 @@ import java.util.List;
 import java.util.concurrent.Callable;
 
 import java.nio.file.Path;
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
+import org.apache.hadoop.hdds.cli.DebugSubcommand;
 
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.hdds.utils.MetadataKeyFilters;
@@ -53,8 +53,8 @@ import static 
org.apache.hadoop.ozone.OzoneConsts.OM_KEY_PREFIX;
 @CommandLine.Command(
     name = "prefix",
     description = "Parse prefix contents")
-@MetaInfServices(SubcommandWithParent.class)
-public class PrefixParser implements Callable<Void>, SubcommandWithParent {
+@MetaInfServices(DebugSubcommand.class)
+public class PrefixParser implements Callable<Void>, DebugSubcommand {
 
   /**
    * Types to represent the level or path component type.
@@ -101,11 +101,6 @@ public class PrefixParser implements Callable<Void>, 
SubcommandWithParent {
     this.dbPath = dbPath;
   }
 
-  @Override
-  public Class<?> getParentType() {
-    return OzoneDebug.class;
-  }
-
   @Override
   public Void call() throws Exception {
     parse(volume, bucket, dbPath, filePath);
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ReadReplicas.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ReadReplicas.java
index fd93d75cd5..c88245a571 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ReadReplicas.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ReadReplicas.java
@@ -17,7 +17,7 @@
 
 package org.apache.hadoop.ozone.debug;
 
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
+import org.apache.hadoop.hdds.cli.DebugSubcommand;
 import org.apache.hadoop.hdds.client.BlockID;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.hdds.protocol.DatanodeDetails;
@@ -60,8 +60,8 @@ import static java.util.Collections.emptyMap;
 @CommandLine.Command(name = "read-replicas",
     description = "Reads every replica for all the blocks associated with a " +
         "given key.")
-@MetaInfServices(SubcommandWithParent.class)
-public class ReadReplicas extends KeyHandler implements SubcommandWithParent {
+@MetaInfServices(DebugSubcommand.class)
+public class ReadReplicas extends KeyHandler implements DebugSubcommand {
 
   @CommandLine.Option(names = {"--outputDir", "-o", "--output-dir"},
       description = "Destination where the directory will be created" +
@@ -82,11 +82,6 @@ public class ReadReplicas extends KeyHandler implements 
SubcommandWithParent {
   private static final String JSON_PROPERTY_REPLICA_UUID = "uuid";
   private static final String JSON_PROPERTY_REPLICA_EXCEPTION = "exception";
 
-  @Override
-  public Class<?> getParentType() {
-    return OzoneDebug.class;
-  }
-
   @Override
   protected void execute(OzoneClient client, OzoneAddress address)
       throws IOException {
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/VersionDebug.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/VersionDebug.java
index b7be569adb..54b2e4c998 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/VersionDebug.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/VersionDebug.java
@@ -20,7 +20,7 @@ package org.apache.hadoop.ozone.debug;
 import com.google.common.collect.ImmutableSortedMap;
 import org.apache.hadoop.hdds.ComponentVersion;
 import org.apache.hadoop.hdds.DatanodeVersion;
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
+import org.apache.hadoop.hdds.cli.DebugSubcommand;
 import org.apache.hadoop.hdds.server.JsonUtils;
 import org.apache.hadoop.ozone.ClientVersion;
 import org.apache.hadoop.ozone.OzoneManagerVersion;
@@ -40,13 +40,8 @@ import java.util.concurrent.Callable;
         "get a cross-component view of versions.  The goal of this command is 
to help quickly get a glance of the " +
         "latest features supported by Ozone on the current node."
 )
-@MetaInfServices(SubcommandWithParent.class)
-public class VersionDebug implements Callable<Void>, SubcommandWithParent {
-
-  @Override
-  public Class<?> getParentType() {
-    return OzoneDebug.class;
-  }
+@MetaInfServices(DebugSubcommand.class)
+public class VersionDebug implements Callable<Void>, DebugSubcommand {
 
   @Override
   public Void call() throws IOException {
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/chunk/ChunkKeyHandler.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/chunk/ChunkKeyHandler.java
index af97b7135d..6944c38049 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/chunk/ChunkKeyHandler.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/chunk/ChunkKeyHandler.java
@@ -27,7 +27,7 @@ import java.util.HashSet;
 
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
+import org.apache.hadoop.hdds.cli.DebugSubcommand;
 import org.apache.hadoop.hdds.client.ECReplicationConfig;
 import org.apache.hadoop.hdds.client.StandaloneReplicationConfig;
 import org.apache.hadoop.hdds.protocol.DatanodeDetails;
@@ -61,9 +61,9 @@ import static 
org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor
 @Command(name = "chunkinfo",
         description = "returns chunk location"
                 + " information about an existing key")
-@MetaInfServices(SubcommandWithParent.class)
+@MetaInfServices(DebugSubcommand.class)
 public class ChunkKeyHandler extends KeyHandler implements
-    SubcommandWithParent {
+    DebugSubcommand {
 
   @CommandLine.ParentCommand
   private OzoneDebug parent;
@@ -201,10 +201,4 @@ public class ChunkKeyHandler extends KeyHandler implements
     return pipeline.getReplicaIndex(dn) >
         ((ECReplicationConfig) pipeline.getReplicationConfig()).getData();
   }
-
-  @Override
-  public Class<?> getParentType() {
-    return OzoneDebug.class;
-  }
-
 }
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/container/ContainerCommands.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/container/ContainerCommands.java
index 47260d62f7..6e3792793d 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/container/ContainerCommands.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/container/ContainerCommands.java
@@ -21,7 +21,7 @@ package org.apache.hadoop.ozone.debug.container;
 import com.google.common.base.Preconditions;
 import org.apache.hadoop.hdds.cli.GenericCli;
 import org.apache.hadoop.hdds.cli.HddsVersionProvider;
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
+import org.apache.hadoop.hdds.cli.DebugSubcommand;
 import org.apache.hadoop.hdds.conf.ConfigurationSource;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos;
@@ -81,8 +81,8 @@ import java.util.stream.Stream;
         ExportSubcommand.class,
         InspectSubcommand.class
     })
-@MetaInfServices(SubcommandWithParent.class)
-public class ContainerCommands implements Callable<Void>, SubcommandWithParent 
{
+@MetaInfServices(DebugSubcommand.class)
+public class ContainerCommands implements Callable<Void>, DebugSubcommand {
 
   private static final Logger LOG =
       LoggerFactory.getLogger(ContainerCommands.class);
@@ -103,11 +103,6 @@ public class ContainerCommands implements Callable<Void>, 
SubcommandWithParent {
     return null;
   }
 
-  @Override
-  public Class<?> getParentType() {
-    return OzoneDebug.class;
-  }
-
   OzoneConfiguration getOzoneConf() {
     return parent.getOzoneConf();
   }
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/DBScanner.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/DBScanner.java
index 95ed0b8be7..6fbbd1a308 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/DBScanner.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/DBScanner.java
@@ -27,7 +27,6 @@ import com.fasterxml.jackson.databind.SerializationFeature;
 import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.hdds.scm.container.ContainerID;
 import org.apache.hadoop.hdds.scm.pipeline.PipelineID;
@@ -47,7 +46,6 @@ import 
org.apache.hadoop.ozone.container.metadata.DatanodeSchemaThreeDBDefinitio
 import org.apache.hadoop.ozone.debug.DBDefinitionFactory;
 import org.apache.hadoop.ozone.debug.RocksDBUtils;
 import org.apache.hadoop.ozone.utils.Filter;
-import org.kohsuke.MetaInfServices;
 import org.rocksdb.ColumnFamilyDescriptor;
 import org.rocksdb.ColumnFamilyHandle;
 import org.rocksdb.RocksDBException;
@@ -89,8 +87,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
     name = "scan",
     description = "Parse specified metadataTable"
 )
-@MetaInfServices(SubcommandWithParent.class)
-public class DBScanner implements Callable<Void>, SubcommandWithParent {
+public class DBScanner implements Callable<Void> {
 
   public static final Logger LOG = LoggerFactory.getLogger(DBScanner.class);
   private static final String SCHEMA_V3 = "V3";
@@ -646,11 +643,6 @@ public class DBScanner implements Callable<Void>, 
SubcommandWithParent {
     return dbPath;
   }
 
-  @Override
-  public Class<?> getParentType() {
-    return RDBParser.class;
-  }
-
   /**
    * Utility for centralized JSON serialization using Jackson.
    */
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/DropTable.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/DropTable.java
index 9b944676b0..5326adc0e2 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/DropTable.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/DropTable.java
@@ -18,7 +18,6 @@
 
 package org.apache.hadoop.ozone.debug.ldb;
 
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
 import org.apache.hadoop.hdds.utils.db.managed.ManagedRocksDB;
 import org.apache.hadoop.ozone.debug.RocksDBUtils;
 import org.rocksdb.ColumnFamilyDescriptor;
@@ -38,7 +37,7 @@ import java.util.concurrent.Callable;
         name = "drop_column_family",
         description = "drop column family in db."
 )
-public class DropTable implements Callable<Void>, SubcommandWithParent {
+public class DropTable implements Callable<Void> {
 
   @CommandLine.Option(names = {"--column-family", "--column_family"},
       description = "Table name")
@@ -74,9 +73,4 @@ public class DropTable implements Callable<Void>, 
SubcommandWithParent {
     }
     return null;
   }
-
-  @Override
-  public Class<?> getParentType() {
-    return RDBParser.class;
-  }
 }
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/ListTables.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/ListTables.java
index c3d9bc4651..d115a44da8 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/ListTables.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/ListTables.java
@@ -22,10 +22,7 @@ import java.nio.charset.StandardCharsets;
 import java.util.List;
 import java.util.concurrent.Callable;
 
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
-
 import org.apache.hadoop.hdds.utils.db.RocksDatabase;
-import org.kohsuke.MetaInfServices;
 import picocli.CommandLine;
 
 /**
@@ -36,8 +33,7 @@ import picocli.CommandLine;
         aliases = "ls",
         description = "list all column families in db."
 )
-@MetaInfServices(SubcommandWithParent.class)
-public class ListTables implements Callable<Void>, SubcommandWithParent {
+public class ListTables implements Callable<Void> {
 
   @CommandLine.ParentCommand
   private RDBParser parent;
@@ -51,9 +47,4 @@ public class ListTables implements Callable<Void>, 
SubcommandWithParent {
     }
     return null;
   }
-
-  @Override
-  public Class<?> getParentType() {
-    return RDBParser.class;
-  }
 }
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/RDBParser.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/RDBParser.java
index da3ff5f303..4e945c7c41 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/RDBParser.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/RDBParser.java
@@ -21,9 +21,8 @@ package org.apache.hadoop.ozone.debug.ldb;
 import java.util.concurrent.Callable;
 
 import org.apache.hadoop.hdds.cli.GenericCli;
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
+import org.apache.hadoop.hdds.cli.DebugSubcommand;
 
-import org.apache.hadoop.ozone.debug.OzoneDebug;
 import org.kohsuke.MetaInfServices;
 import picocli.CommandLine;
 import picocli.CommandLine.Model.CommandSpec;
@@ -34,9 +33,15 @@ import picocli.CommandLine.Spec;
  */
 @CommandLine.Command(
         name = "ldb",
+        subcommands = {
+            DBScanner.class,
+            DropTable.class,
+            ListTables.class,
+            ValueSchema.class,
+        },
         description = "Parse rocksdb file content")
-@MetaInfServices(SubcommandWithParent.class)
-public class RDBParser implements Callable<Void>, SubcommandWithParent {
+@MetaInfServices(DebugSubcommand.class)
+public class RDBParser implements Callable<Void>, DebugSubcommand {
 
   @Spec
   private CommandSpec spec;
@@ -54,11 +59,6 @@ public class RDBParser implements Callable<Void>, 
SubcommandWithParent {
     this.dbPath = dbPath;
   }
 
-  @Override
-  public Class<?> getParentType() {
-    return OzoneDebug.class;
-  }
-
   @Override
   public Void call() throws Exception {
     GenericCli.missingSubcommand(spec);
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/ValueSchema.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/ValueSchema.java
index 9c4ce4e0eb..4b8eb3b320 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/ValueSchema.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/ldb/ValueSchema.java
@@ -18,14 +18,12 @@
 
 package org.apache.hadoop.ozone.debug.ldb;
 
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.hdds.server.JsonUtils;
 import org.apache.hadoop.hdds.utils.db.DBColumnFamilyDefinition;
 import org.apache.hadoop.hdds.utils.db.DBDefinition;
 import org.apache.hadoop.ozone.OzoneConsts;
 import org.apache.hadoop.ozone.debug.DBDefinitionFactory;
-import org.kohsuke.MetaInfServices;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import picocli.CommandLine;
@@ -53,8 +51,7 @@ import java.util.stream.Collectors;
     name = "value-schema",
     description = "Schema of value in metadataTable"
 )
-@MetaInfServices(SubcommandWithParent.class)
-public class ValueSchema implements Callable<Void>, SubcommandWithParent {
+public class ValueSchema implements Callable<Void> {
 
   @CommandLine.ParentCommand
   private RDBParser parent;
@@ -173,11 +170,6 @@ public class ValueSchema implements Callable<Void>, 
SubcommandWithParent {
     return spec.commandLine().getOut();
   }
 
-  @Override
-  public Class<?> getParentType() {
-    return RDBParser.class;
-  }
-
   private static String removeTrailingSlashIfNeeded(String dbPath) {
     if (dbPath.endsWith(OzoneConsts.OZONE_URI_DELIMITER)) {
       dbPath = dbPath.substring(0, dbPath.length() - 1);
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/segmentparser/RatisLogParser.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/segmentparser/RatisLogParser.java
index d80b6d31a1..653ea710ac 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/segmentparser/RatisLogParser.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/debug/segmentparser/RatisLogParser.java
@@ -19,8 +19,7 @@ package org.apache.hadoop.ozone.debug.segmentparser;
 
 import org.apache.hadoop.hdds.cli.GenericCli;
 import org.apache.hadoop.hdds.cli.HddsVersionProvider;
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
-import org.apache.hadoop.ozone.debug.OzoneDebug;
+import org.apache.hadoop.hdds.cli.DebugSubcommand;
 
 import org.kohsuke.MetaInfServices;
 import picocli.CommandLine;
@@ -39,15 +38,10 @@ import picocli.CommandLine;
     },
     versionProvider = HddsVersionProvider.class,
     mixinStandardHelpOptions = true)
-@MetaInfServices(SubcommandWithParent.class)
-public class RatisLogParser extends GenericCli implements SubcommandWithParent 
{
+@MetaInfServices(DebugSubcommand.class)
+public class RatisLogParser extends GenericCli implements DebugSubcommand {
 
   public static void main(String[] args) {
     new RatisLogParser().run(args);
   }
-
-  @Override
-  public Class<?> getParentType() {
-    return OzoneDebug.class;
-  }
 }
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/OzoneRepair.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/OzoneRepair.java
index 1664452280..3bc3f2c99d 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/OzoneRepair.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/OzoneRepair.java
@@ -19,8 +19,10 @@
 package org.apache.hadoop.ozone.repair;
 
 import com.google.common.annotations.VisibleForTesting;
+import org.apache.hadoop.hdds.cli.ExtensibleParentCommand;
 import org.apache.hadoop.hdds.cli.GenericCli;
 import org.apache.hadoop.hdds.cli.HddsVersionProvider;
+import org.apache.hadoop.hdds.cli.RepairSubcommand;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import picocli.CommandLine;
 
@@ -34,7 +36,7 @@ import java.util.Scanner;
     description = "Operational tool to repair Ozone",
     versionProvider = HddsVersionProvider.class,
     mixinStandardHelpOptions = true)
-public class OzoneRepair extends GenericCli {
+public class OzoneRepair extends GenericCli implements ExtensibleParentCommand 
{
 
   public static final String WARNING_SYS_USER_MESSAGE =
       "ATTENTION: Running as user %s. Make sure this is the same user used to 
run the Ozone process." +
@@ -91,4 +93,8 @@ public class OzoneRepair extends GenericCli {
     return (new Scanner(System.in, 
StandardCharsets.UTF_8.name())).nextLine().trim();
   }
 
+  @Override
+  public Class<?> subcommandType() {
+    return RepairSubcommand.class;
+  }
 }
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/RecoverSCMCertificate.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/RecoverSCMCertificate.java
index aca41844a1..e6462aa3f8 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/RecoverSCMCertificate.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/RecoverSCMCertificate.java
@@ -17,7 +17,7 @@
  */
 package org.apache.hadoop.ozone.repair;
 
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
+import org.apache.hadoop.hdds.cli.RepairSubcommand;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.hdds.security.SecurityConfig;
 import org.apache.hadoop.hdds.security.x509.certificate.authority.CAType;
@@ -67,8 +67,8 @@ import static 
org.apache.hadoop.ozone.om.helpers.OzoneFSUtils.removeTrailingSlas
 @CommandLine.Command(
     name = "cert-recover",
     description = "Recover Deleted SCM Certificate from RocksDB")
-@MetaInfServices(SubcommandWithParent.class)
-public class RecoverSCMCertificate implements Callable<Void>, 
SubcommandWithParent {
+@MetaInfServices(RepairSubcommand.class)
+public class RecoverSCMCertificate implements Callable<Void>, RepairSubcommand 
{
 
   @CommandLine.Option(names = {"--db"},
       required = true,
@@ -81,11 +81,6 @@ public class RecoverSCMCertificate implements 
Callable<Void>, SubcommandWithPare
   @CommandLine.Spec
   private CommandLine.Model.CommandSpec spec;
 
-  @Override
-  public Class<?> getParentType() {
-    return OzoneRepair.class;
-  }
-
   private PrintWriter err() {
     return spec.commandLine().getErr();
   }
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/ldb/RDBRepair.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/ldb/RDBRepair.java
index fcf7201978..01ad705b20 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/ldb/RDBRepair.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/ldb/RDBRepair.java
@@ -19,8 +19,7 @@
 package org.apache.hadoop.ozone.repair.ldb;
 
 import org.apache.hadoop.hdds.cli.GenericCli;
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
-import org.apache.hadoop.ozone.repair.OzoneRepair;
+import org.apache.hadoop.hdds.cli.RepairSubcommand;
 import org.kohsuke.MetaInfServices;
 import picocli.CommandLine;
 
@@ -30,9 +29,13 @@ import java.util.concurrent.Callable;
  * Ozone Repair CLI for RocksDB.
  */
 @CommandLine.Command(name = "ldb",
+    subcommands = {
+        SnapshotRepair.class,
+        TransactionInfoRepair.class,
+    },
     description = "Operational tool to repair RocksDB table.")
-@MetaInfServices(SubcommandWithParent.class)
-public class RDBRepair implements Callable<Void>, SubcommandWithParent {
+@MetaInfServices(RepairSubcommand.class)
+public class RDBRepair implements Callable<Void>, RepairSubcommand {
 
   @CommandLine.Spec
   private CommandLine.Model.CommandSpec spec;
@@ -51,9 +54,4 @@ public class RDBRepair implements Callable<Void>, 
SubcommandWithParent {
     GenericCli.missingSubcommand(spec);
     return null;
   }
-
-  @Override
-  public Class<?> getParentType() {
-    return OzoneRepair.class;
-  }
 }
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/ldb/SnapshotRepair.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/ldb/SnapshotRepair.java
index f746e99fe7..45c10f5668 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/ldb/SnapshotRepair.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/ldb/SnapshotRepair.java
@@ -18,7 +18,6 @@
 
 package org.apache.hadoop.ozone.repair.ldb;
 
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
 import org.apache.hadoop.hdds.utils.IOUtils;
 import org.apache.hadoop.hdds.utils.db.StringCodec;
 import org.apache.hadoop.hdds.utils.db.managed.ManagedRocksDB;
@@ -26,7 +25,6 @@ import 
org.apache.hadoop.hdds.utils.db.managed.ManagedRocksIterator;
 import org.apache.hadoop.ozone.debug.RocksDBUtils;
 import org.apache.hadoop.ozone.om.helpers.SnapshotInfo;
 import org.apache.hadoop.ozone.shell.bucket.BucketUri;
-import org.kohsuke.MetaInfServices;
 import org.rocksdb.ColumnFamilyDescriptor;
 import org.rocksdb.ColumnFamilyHandle;
 import org.rocksdb.RocksDBException;
@@ -54,8 +52,7 @@ import static 
org.apache.hadoop.ozone.OzoneConsts.SNAPSHOT_INFO_TABLE;
     name = "snapshot",
     description = "CLI to update global and path previous snapshot for a 
snapshot in case snapshot chain is corrupted."
 )
-@MetaInfServices(SubcommandWithParent.class)
-public class SnapshotRepair implements Callable<Void>, SubcommandWithParent {
+public class SnapshotRepair implements Callable<Void> {
 
   protected static final Logger LOG = 
LoggerFactory.getLogger(SnapshotRepair.class);
 
@@ -177,9 +174,4 @@ public class SnapshotRepair implements Callable<Void>, 
SubcommandWithParent {
     }
     return snapshotIdSet;
   }
-
-  @Override
-  public Class<?> getParentType() {
-    return RDBRepair.class;
-  }
 }
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/ldb/TransactionInfoRepair.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/ldb/TransactionInfoRepair.java
index 369ae3d9a6..277a278824 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/ldb/TransactionInfoRepair.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/ldb/TransactionInfoRepair.java
@@ -22,13 +22,11 @@
 package org.apache.hadoop.ozone.repair.ldb;
 
 import org.apache.hadoop.hdds.cli.HddsVersionProvider;
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
 import org.apache.hadoop.hdds.utils.IOUtils;
 import org.apache.hadoop.hdds.utils.TransactionInfo;
 import org.apache.hadoop.hdds.utils.db.StringCodec;
 import org.apache.hadoop.hdds.utils.db.managed.ManagedRocksDB;
 import org.apache.hadoop.ozone.debug.RocksDBUtils;
-import org.kohsuke.MetaInfServices;
 import org.rocksdb.ColumnFamilyDescriptor;
 import org.rocksdb.ColumnFamilyHandle;
 import org.rocksdb.RocksDBException;
@@ -42,7 +40,6 @@ import java.util.concurrent.Callable;
 import static org.apache.hadoop.ozone.OzoneConsts.TRANSACTION_INFO_KEY;
 import static 
org.apache.hadoop.ozone.om.OmMetadataManagerImpl.TRANSACTION_INFO_TABLE;
 
-
 /**
  * Tool to update the highest term-index in transactionInfoTable.
  */
@@ -52,9 +49,7 @@ import static 
org.apache.hadoop.ozone.om.OmMetadataManagerImpl.TRANSACTION_INFO_
     mixinStandardHelpOptions = true,
     versionProvider = HddsVersionProvider.class
 )
-@MetaInfServices(SubcommandWithParent.class)
-public class TransactionInfoRepair
-    implements Callable<Void>, SubcommandWithParent  {
+public class TransactionInfoRepair implements Callable<Void>  {
 
   @CommandLine.Spec
   private static CommandLine.Model.CommandSpec spec;
@@ -127,9 +122,4 @@ public class TransactionInfoRepair
     return parent;
   }
 
-  @Override
-  public Class<?> getParentType() {
-    return RDBRepair.class;
-  }
-
 }
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaRepair.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaRepair.java
index 5f21b739c8..6ead713e14 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaRepair.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaRepair.java
@@ -22,7 +22,7 @@ import java.io.IOException;
 import java.util.Collection;
 import java.util.concurrent.Callable;
 import org.apache.hadoop.hdds.cli.GenericCli;
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
+import org.apache.hadoop.hdds.cli.RepairSubcommand;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.ipc.ProtobufRpcEngine;
 import org.apache.hadoop.ipc.RPC;
@@ -45,9 +45,13 @@ import static 
org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_SERVICE_IDS_KEY;
  * Ozone Repair CLI for quota.
  */
 @CommandLine.Command(name = "quota",
+    subcommands = {
+        QuotaStatus.class,
+        QuotaTrigger.class,
+    },
     description = "Operational tool to repair quota in OM DB.")
-@MetaInfServices(SubcommandWithParent.class)
-public class QuotaRepair implements Callable<Void>, SubcommandWithParent {
+@MetaInfServices(RepairSubcommand.class)
+public class QuotaRepair implements Callable<Void>, RepairSubcommand {
 
   @CommandLine.Spec
   private CommandLine.Model.CommandSpec spec;
@@ -113,9 +117,4 @@ public class QuotaRepair implements Callable<Void>, 
SubcommandWithParent {
   protected OzoneRepair getParent() {
     return parent;
   }
-
-  @Override
-  public Class<?> getParentType() {
-    return OzoneRepair.class;
-  }
 }
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaStatus.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaStatus.java
index a78d248e05..820ac6f8ea 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaStatus.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaStatus.java
@@ -23,12 +23,9 @@ package org.apache.hadoop.ozone.repair.quota;
 
 import java.util.concurrent.Callable;
 import org.apache.hadoop.hdds.cli.HddsVersionProvider;
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
 import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol;
-import org.kohsuke.MetaInfServices;
 import picocli.CommandLine;
 
-
 /**
  * Tool to get status of last triggered quota repair.
  */
@@ -38,8 +35,7 @@ import picocli.CommandLine;
     mixinStandardHelpOptions = true,
     versionProvider = HddsVersionProvider.class
 )
-@MetaInfServices(SubcommandWithParent.class)
-public class QuotaStatus implements Callable<Void>, SubcommandWithParent  {
+public class QuotaStatus implements Callable<Void>  {
   @CommandLine.Spec
   private static CommandLine.Model.CommandSpec spec;
 
@@ -72,9 +68,4 @@ public class QuotaStatus implements Callable<Void>, 
SubcommandWithParent  {
   protected QuotaRepair getParent() {
     return parent;
   }
-
-  @Override
-  public Class<?> getParentType() {
-    return QuotaRepair.class;
-  }
 }
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaTrigger.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaTrigger.java
index 19ad92340c..04d78f05dc 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaTrigger.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaTrigger.java
@@ -27,9 +27,7 @@ import java.util.List;
 import java.util.concurrent.Callable;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hadoop.hdds.cli.HddsVersionProvider;
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
 import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol;
-import org.kohsuke.MetaInfServices;
 import picocli.CommandLine;
 
 /**
@@ -41,8 +39,7 @@ import picocli.CommandLine;
     mixinStandardHelpOptions = true,
     versionProvider = HddsVersionProvider.class
 )
-@MetaInfServices(SubcommandWithParent.class)
-public class QuotaTrigger implements Callable<Void>, SubcommandWithParent  {
+public class QuotaTrigger implements Callable<Void>  {
   @CommandLine.Spec
   private static CommandLine.Model.CommandSpec spec;
 
@@ -92,9 +89,4 @@ public class QuotaTrigger implements Callable<Void>, 
SubcommandWithParent  {
     return parent;
   }
 
-  @Override
-  public Class<?> getParentType() {
-    return QuotaRepair.class;
-  }
-
 }


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

Reply via email to