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

sodonnel pushed a commit to branch HDDS-14496-zdu
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/HDDS-14496-zdu by this push:
     new 22948f4d15d HDDS-15528. Adjust upgrade finalize command to call OM 
instread of SCM (#10493)
22948f4d15d is described below

commit 22948f4d15d3ba35bb099f68c6dc2a9edfef1882
Author: Stephen O'Donnell <[email protected]>
AuthorDate: Thu Jun 18 11:10:22 2026 +0100

    HDDS-15528. Adjust upgrade finalize command to call OM instread of SCM 
(#10493)
---
 .../ozone/admin/upgrade/FinalizeSubCommand.java    |  32 ++++--
 .../admin/upgrade/TestFinalizeSubCommand.java      |  48 +++++++--
 .../main/java/org/apache/hadoop/ozone/OmUtils.java |   2 +
 .../ozone/om/protocol/OzoneManagerProtocol.java    |  16 +++
 ...OzoneManagerProtocolClientSideTranslatorPB.java |  13 +++
 .../apache/hadoop/fs/ozone/TestHSyncUpgrade.java   |   7 +-
 .../hadoop/ozone/om/TestOMBucketLayoutUpgrade.java |  14 +--
 .../hadoop/ozone/om/TestOMUpgradeFinalization.java |  15 +--
 .../om/multitenant/TestMultiTenantVolume.java      |   6 +-
 .../hadoop/ozone/om/snapshot/TestOmSnapshot.java   |   6 +-
 .../src/main/proto/OmClientProtocol.proto          |  15 ++-
 .../org/apache/hadoop/ozone/om/OzoneManager.java   |   7 ++
 .../om/ratis/utils/OzoneManagerRatisUtils.java     |   3 +
 .../upgrade/OMStartFinalizeUpgradeRequest.java     | 100 +++++++++++++++++
 .../upgrade/OMStartFinalizeUpgradeResponse.java    |  49 +++++++++
 .../om/ratis/TestOzoneManagerRatisRequest.java     |  15 +++
 .../upgrade/TestOMStartFinalizeUpgradeRequest.java | 119 +++++++++++++++++++++
 .../TestOMStartFinalizeUpgradeResponse.java        |  75 +++++++++++++
 18 files changed, 476 insertions(+), 66 deletions(-)

diff --git 
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/upgrade/FinalizeSubCommand.java
 
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/upgrade/FinalizeSubCommand.java
index e882f3e537c..7f36b84b93e 100644
--- 
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/upgrade/FinalizeSubCommand.java
+++ 
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/upgrade/FinalizeSubCommand.java
@@ -17,27 +17,37 @@
 
 package org.apache.hadoop.ozone.admin.upgrade;
 
-import java.io.IOException;
+import java.util.concurrent.Callable;
+import org.apache.hadoop.hdds.cli.AbstractSubcommand;
 import org.apache.hadoop.hdds.cli.HddsVersionProvider;
-import org.apache.hadoop.hdds.scm.cli.ScmSubcommand;
-import org.apache.hadoop.hdds.scm.client.ScmClient;
+import org.apache.hadoop.ozone.admin.om.OmAddressOptions;
+import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol;
 import picocli.CommandLine;
 
 /**
- * Sub command to finalize a cluster upgrade.
+ * Handler for the ozone admin upgrade finalize command.
  */
 @CommandLine.Command(
     name = "finalize",
-    description = "Finalize a cluster upgrade",
+    description = "Initiates the the process to finalize a cluster upgrade.",
     mixinStandardHelpOptions = true,
-    versionProvider = HddsVersionProvider.class)
-public class FinalizeSubCommand extends ScmSubcommand {
+    versionProvider = HddsVersionProvider.class
+)
+public class FinalizeSubCommand extends AbstractSubcommand implements 
Callable<Void> {
+
+  @CommandLine.Mixin
+  private OmAddressOptions.OptionalServiceIdOrHostMixin omAddressOptions;
 
   @Override
-  public void execute(ScmClient client) throws IOException {
-    client.finalizeUpgrade();
+  public Void call() throws Exception {
+    try (OzoneManagerProtocol client = getClient()) {
+      client.finalizeUpgrade();
+      out().println("Cluster finalization has been started. Monitor progress 
with `ozone admin upgrade status`");
+    }
+    return null;
+  }
 
-    out().println("Cluster finalization has been started. Monitor progress 
with `ozone admin upgrade status`");
+  protected OzoneManagerProtocol getClient() throws Exception {
+    return omAddressOptions.newClient();
   }
 }
-
diff --git 
a/hadoop-ozone/cli-admin/src/test/java/org/apache/hadoop/ozone/admin/upgrade/TestFinalizeSubCommand.java
 
b/hadoop-ozone/cli-admin/src/test/java/org/apache/hadoop/ozone/admin/upgrade/TestFinalizeSubCommand.java
index a380f5388ca..0f7e9f2116a 100644
--- 
a/hadoop-ozone/cli-admin/src/test/java/org/apache/hadoop/ozone/admin/upgrade/TestFinalizeSubCommand.java
+++ 
b/hadoop-ozone/cli-admin/src/test/java/org/apache/hadoop/ozone/admin/upgrade/TestFinalizeSubCommand.java
@@ -17,16 +17,18 @@
 
 package org.apache.hadoop.ozone.admin.upgrade;
 
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.PrintStream;
-import java.io.UnsupportedEncodingException;
 import java.nio.charset.StandardCharsets;
-import org.apache.hadoop.hdds.scm.client.ScmClient;
+import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -42,10 +44,21 @@ public class TestFinalizeSubCommand {
   private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
   private final PrintStream originalOut = System.out;
   private FinalizeSubCommand cmd;
+  private OzoneManagerProtocol omClient;
 
   @BeforeEach
-  public void setup() throws UnsupportedEncodingException {
-    cmd = new FinalizeSubCommand();
+  public void setup() throws IOException {
+    omClient = mock(OzoneManagerProtocol.class);
+
+    // Mock close() to do nothing - needed for try-with-resources
+    doNothing().when(omClient).close();
+
+    cmd = new FinalizeSubCommand() {
+      @Override
+      protected OzoneManagerProtocol getClient() throws Exception {
+        return omClient;
+      }
+    };
     System.setOut(new PrintStream(outContent, false, DEFAULT_ENCODING));
   }
 
@@ -55,14 +68,31 @@ public void tearDown() {
   }
 
   @Test
-  public void testCommandRunsAndPrintsOutput() throws IOException {
-    ScmClient scmClient = mock(ScmClient.class);
-
+  public void testCommandRunsAndPrintsOutput() throws Exception {
     new CommandLine(cmd).parseArgs();
-    cmd.execute(scmClient);
+    cmd.call();
 
     String output = outContent.toString(DEFAULT_ENCODING);
     assertTrue(output.contains("Cluster finalization has been started"));
-    verify(scmClient).finalizeUpgrade();
+    verify(omClient).finalizeUpgrade();
+  }
+
+  @Test
+  public void testClientIsClosedAfterSuccessfulCall() throws Exception {
+    new CommandLine(cmd).parseArgs();
+    cmd.call();
+
+    verify(omClient).close();
+  }
+
+  @Test
+  public void testExceptionFromServerIsPropagated() throws Exception {
+    doThrow(new IOException("OM 
unavailable")).when(omClient).finalizeUpgrade();
+
+    new CommandLine(cmd).parseArgs();
+    assertThrows(IOException.class, cmd::call);
+
+    // Client must still be closed even when finalizeUpgrade() throws.
+    verify(omClient).close();
   }
 }
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java
index a4a28c0073b..23e1d3c8382 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java
@@ -295,6 +295,7 @@ public static boolean isReadOnly(OMRequest omRequest) {
       // TODO: Remove once migrated to proto3 and mark fields in proto
       // as deprecated
     case FinalizeUpgrade:
+    case StartFinalizeUpgrade:
     case Prepare:
     case CancelPrepare:
     case DeleteOpenKeys:
@@ -410,6 +411,7 @@ public static boolean shouldSendToFollower(OMRequest 
omRequest) {
       // TODO: Remove once migrated to proto3 and mark fields in proto
       // as deprecated
     case FinalizeUpgrade:
+    case StartFinalizeUpgrade:
     case Prepare:
     case CancelPrepare:
     case DeleteOpenKeys:
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
index 1376174720a..30b0c140402 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
@@ -491,6 +491,22 @@ ListOpenFilesResult listOpenFiles(String path, int 
maxKeys, String contToken)
    */
   UpgradeFinalization.StatusAndMessages finalizeUpgrade(String 
upgradeClientID) throws IOException;
 
+  /**
+   * Initiate metadata upgrade finalization.
+   * This method when called, performs two actions. First, it will result in 
OM making a call to SCM to start
+   * finalizing the HDDS layer. After that call completes successfully, the 
HDDS finalization will be in progress.
+   * Second, a key will be written to the OM database to persist the fact that 
OM finalization is pending. It will
+   * complete once the HDDS layer has completed. OM will poll SCM periodically 
to check the status of the SCM
+   * finalization progress, and OM will only finalize when SCM indicates it is 
OK for it to do so.
+   *
+   * This command is async, and will return before finalization is complete. 
The caller must issue a Query Finalization
+   * Progress command to monitor the progress.
+   *
+   * @throws IOException If any error occurs. If this happens finalization is 
not in progress and the command must be
+   *                     retried.
+   */
+  void finalizeUpgrade() throws IOException;
+
   /**
    * Queries the current status of finalization.
    * This method when called, returns the status messages from the finalization
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
index 15b76d952e2..be95623fb90 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
@@ -224,6 +224,7 @@
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SetVolumePropertyRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SetVolumePropertyResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SnapshotInfoRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.StartFinalizeUpgradeRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.TenantAssignAdminRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.TenantAssignUserAccessIdRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.TenantAssignUserAccessIdResponse;
@@ -2033,6 +2034,18 @@ public StatusAndMessages finalizeUpgrade(String 
upgradeClientID)
     );
   }
 
+  @Override
+  public void finalizeUpgrade() throws IOException {
+    StartFinalizeUpgradeRequest req = StartFinalizeUpgradeRequest.newBuilder()
+        .build();
+
+    OMRequest omRequest = createOMRequest(Type.StartFinalizeUpgrade)
+        .setStartFinalizeUpgradeRequest(req)
+        .build();
+
+    handleError(submitRequest(omRequest));
+  }
+
   @Override
   public StatusAndMessages queryUpgradeFinalizationProgress(
       String upgradeClientID, boolean takeover, boolean readonly
diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestHSyncUpgrade.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestHSyncUpgrade.java
index 56e82f8927f..f922f791524 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestHSyncUpgrade.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestHSyncUpgrade.java
@@ -48,7 +48,6 @@
 import org.apache.hadoop.ozone.ClientConfigForTesting;
 import org.apache.hadoop.ozone.MiniOzoneCluster;
 import org.apache.hadoop.ozone.OzoneConfigKeys;
-import org.apache.hadoop.ozone.OzoneConsts;
 import org.apache.hadoop.ozone.TestDataUtil;
 import org.apache.hadoop.ozone.client.OzoneBucket;
 import org.apache.hadoop.ozone.client.OzoneClient;
@@ -212,11 +211,7 @@ private void finalizeOMUpgrade() throws Exception {
     // Trigger OM upgrade finalization. Ref: FinalizeUpgradeSubCommand#call
     final OzoneManagerProtocol omClient = client.getObjectStore()
         .getClientProxy().getOzoneManagerClient();
-    // TODO - OZONE_FINAL_COMMAND - change to sending command when it is 
ready. This will trigger OM finalization
-    cluster.getOzoneManager().getMetadataManager().getMetaTable()
-        .addCacheEntry(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY, "ignore", 1);
-    cluster.getOzoneManager().getMetadataManager().getMetaTable()
-        .put(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY, "ignore");
+    omClient.finalizeUpgrade();
     OMUpgradeTestUtils.waitForFinalization(omClient);
   }
 
diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMBucketLayoutUpgrade.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMBucketLayoutUpgrade.java
index 3ec9a492acc..a6f2f5a4e7d 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMBucketLayoutUpgrade.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMBucketLayoutUpgrade.java
@@ -33,11 +33,8 @@
 import org.apache.hadoop.hdds.ComponentVersion;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.hdds.utils.IOUtils;
-import org.apache.hadoop.hdds.utils.db.CodecException;
-import org.apache.hadoop.hdds.utils.db.RocksDatabaseException;
 import org.apache.hadoop.ozone.MiniOzoneCluster;
 import org.apache.hadoop.ozone.MiniOzoneHAClusterImpl;
-import org.apache.hadoop.ozone.OzoneConsts;
 import org.apache.hadoop.ozone.OzoneManagerVersion;
 import org.apache.hadoop.ozone.client.OzoneClient;
 import org.apache.hadoop.ozone.om.exceptions.OMException;
@@ -155,16 +152,7 @@ void allowsLegacyBucketBeforeUpgrade() throws Exception {
   @Test
   @Order(DURING_UPGRADE)
   void finalizeUpgrade() throws Exception {
-    // TODO - OZONE_FINAL_COMMAND - change to sending command when it is 
ready. This will trigger OM finalization
-    cluster.getOzoneManagersList().forEach(om -> {
-      try {
-        
om.getMetadataManager().getMetaTable().addCacheEntry(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY,
 "ignore", 1);
-        om.getMetadataManager().getMetaTable()
-            .put(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY, "ignore");
-      } catch (RocksDatabaseException | CodecException e) {
-        throw new RuntimeException(e);
-      }
-    });
+    omClient.finalizeUpgrade();
     waitForFinalization(omClient);
 
     final String expectedVersion =
diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMUpgradeFinalization.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMUpgradeFinalization.java
index 35c4ce3aafe..36fd6c7ac03 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMUpgradeFinalization.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMUpgradeFinalization.java
@@ -32,8 +32,6 @@
 import java.util.UUID;
 import java.util.concurrent.TimeoutException;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
-import org.apache.hadoop.hdds.utils.db.CodecException;
-import org.apache.hadoop.hdds.utils.db.RocksDatabaseException;
 import org.apache.hadoop.ozone.MiniOzoneCluster;
 import org.apache.hadoop.ozone.MiniOzoneHAClusterImpl;
 import org.apache.hadoop.ozone.OzoneConsts;
@@ -100,18 +98,7 @@ void testOMUpgradeFinalizationWithOneOMDown() throws 
Exception {
         AuditLogTestUtils.verifyAuditLog(OMAction.UPGRADE_PREPARE, 
AuditEventStatus.SUCCESS);
         omClient.cancelOzoneManagerPrepare();
         AuditLogTestUtils.verifyAuditLog(OMAction.UPGRADE_CANCEL, 
AuditEventStatus.SUCCESS);
-        // TODO - OZONE_FINAL_COMMAND - change to sending command when it is 
ready. This will trigger OM finalization
-        cluster.getOzoneManagersList().forEach(om -> {
-          try {
-            om.getMetadataManager().getMetaTable()
-                .addCacheEntry(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY, 
"ignore", 1);
-            om.getMetadataManager().getMetaTable()
-                .put(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY, "ignore");
-          } catch (RocksDatabaseException | CodecException e) {
-            throw new RuntimeException(e);
-          }
-        });
-
+        omClient.finalizeUpgrade();
         waitForFinalization(omClient);
         AuditLogTestUtils.verifySystemAuditLog(OMAction.UPGRADE_FINALIZE, 
AuditEventStatus.SUCCESS);
         // Ensure the finalization in progress key has been removed.
diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestMultiTenantVolume.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestMultiTenantVolume.java
index 654cb7ca671..49b4e682579 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestMultiTenantVolume.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/multitenant/TestMultiTenantVolume.java
@@ -143,11 +143,7 @@ private static void finalizeOMUpgrade()
     // Trigger OM upgrade finalization. Ref: FinalizeUpgradeSubCommand#call
     final OzoneManagerProtocol omClient = client.getObjectStore()
         .getClientProxy().getOzoneManagerClient();
-    // TODO - OZONE_FINAL_COMMAND - change to sending command when it is 
ready. This will trigger OM finalization
-    cluster.getOzoneManager().getMetadataManager().getMetaTable()
-        .addCacheEntry(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY, "ignore", 1);
-    cluster.getOzoneManager().getMetadataManager().getMetaTable()
-        .put(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY, "ignore");
+    omClient.finalizeUpgrade();
     OMUpgradeTestUtils.waitForFinalization(omClient);
   }
 
diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshot.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshot.java
index 2515117f423..a7f60ef4ba1 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshot.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshot.java
@@ -325,11 +325,7 @@ private static void 
assertFinalizationException(OMException omException) {
   private void finalizeOMUpgrade() throws Exception {
     final OzoneManagerProtocol omClient = client.getObjectStore()
         .getClientProxy().getOzoneManagerClient();
-    // TODO - OZONE_FINAL_COMMAND - change to sending command when it is 
ready. This will trigger OM finalization
-    cluster.getOzoneManager().getMetadataManager().getMetaTable()
-        .addCacheEntry(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY, "ignore", 1);
-    cluster.getOzoneManager().getMetadataManager().getMetaTable()
-        .put(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY, "ignore");
+    omClient.finalizeUpgrade();
     OMUpgradeTestUtils.waitForFinalization(omClient);
   }
 
diff --git 
a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto 
b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
index 94ac3746c6a..7efd46983bc 100644
--- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
+++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
@@ -73,7 +73,7 @@ enum Type {
 
   ServiceList = 51;
   DBUpdates = 53;
-  FinalizeUpgrade = 54;
+  FinalizeUpgrade = 54; // [deprecated = true]
   FinalizeUpgradeProgress = 55;
   Prepare = 56;
   PrepareStatus = 57;
@@ -157,6 +157,7 @@ enum Type {
   GetObjectTagging = 141;
   DeleteObjectTagging = 142;
   SubmitSnapshotDiff = 143;
+  StartFinalizeUpgrade = 144;
 }
 
 enum SafeMode {
@@ -215,7 +216,7 @@ message OMRequest {
 
   optional ServiceListRequest               serviceListRequest             = 
51;
   optional DBUpdatesRequest                  dbUpdatesRequest              = 
53;
-  optional FinalizeUpgradeRequest           finalizeUpgradeRequest         = 
54;
+  optional FinalizeUpgradeRequest           finalizeUpgradeRequest         = 
54 [deprecated = true];
   optional FinalizeUpgradeProgressRequest   finalizeUpgradeProgressRequest = 
55;
   optional PrepareRequest                   prepareRequest                 = 
56;
   optional PrepareStatusRequest             prepareStatusRequest           = 
57;
@@ -309,6 +310,7 @@ message OMRequest {
   repeated SetSnapshotPropertyRequest       SetSnapshotPropertyRequests    = 
143;
 
   optional SubmitSnapshotDiffRequest        submitSnapshotDiffRequest       = 
144;
+  optional StartFinalizeUpgradeRequest      startFinalizeUpgradeRequest     = 
145;
 }
 
 message OMResponse {
@@ -358,7 +360,7 @@ message OMResponse {
 
   optional ServiceListResponse               ServiceListResponse           = 
51;
   optional DBUpdatesResponse                 dbUpdatesResponse             = 
52;
-  optional FinalizeUpgradeResponse           finalizeUpgradeResponse       = 
54;
+  optional FinalizeUpgradeResponse           finalizeUpgradeResponse       = 
54 [deprecated = true];
   optional FinalizeUpgradeProgressResponse finalizeUpgradeProgressResponse = 
55;
   optional PrepareResponse                 prepareResponse                 = 
56;
   optional PrepareStatusResponse           prepareStatusResponse           = 
57;
@@ -444,6 +446,7 @@ message OMResponse {
   optional DeleteObjectTaggingResponse       deleteObjectTaggingResponse   = 
142;
 
   optional SubmitSnapshotDiffResponse        submitSnapshotDiffResponse    = 
143;
+  optional StartFinalizeUpgradeResponse      startFinalizeUpgradeResponse  = 
144;
 }
 
 enum Status {
@@ -1631,6 +1634,12 @@ message FinalizeUpgradeResponse {
   required hadoop.hdds.UpgradeFinalizationStatus status = 1;
 }
 
+message StartFinalizeUpgradeRequest {
+}
+
+message StartFinalizeUpgradeResponse {
+}
+
 message FinalizeUpgradeProgressRequest {
     // Ignored by OM; retained for wire compatibility.
     required string upgradeClientId = 1;
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
index 04336f659db..8d99f122e49 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
@@ -3641,6 +3641,13 @@ public StatusAndMessages finalizeUpgrade(String 
unusedUpgradeClientId)
     return STARTING_MSG;
   }
 
+  @Override
+  public void finalizeUpgrade() throws IOException {
+    // Server-side stub; the real implementation is handled via the Ratis 
request path through
+    // OMStartFinalizeUpgradeRequest
+    throw new UnsupportedOperationException();
+  }
+
   @Override
   public StatusAndMessages queryUpgradeFinalizationProgress(
       String unusedUpgradeClientId, boolean unusedTakeover, boolean 
unusedReadonly)
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/utils/OzoneManagerRatisUtils.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/utils/OzoneManagerRatisUtils.java
index 1778de3520d..a845aff6080 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/utils/OzoneManagerRatisUtils.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/utils/OzoneManagerRatisUtils.java
@@ -87,6 +87,7 @@
 import org.apache.hadoop.ozone.om.request.upgrade.OMCancelPrepareRequest;
 import org.apache.hadoop.ozone.om.request.upgrade.OMFinalizeUpgradeRequest;
 import org.apache.hadoop.ozone.om.request.upgrade.OMPrepareRequest;
+import 
org.apache.hadoop.ozone.om.request.upgrade.OMStartFinalizeUpgradeRequest;
 import org.apache.hadoop.ozone.om.request.util.OMEchoRPCWriteRequest;
 import org.apache.hadoop.ozone.om.request.volume.OMQuotaRepairRequest;
 import org.apache.hadoop.ozone.om.request.volume.OMVolumeCreateRequest;
@@ -185,6 +186,8 @@ public static OMClientRequest createClientRequest(OMRequest 
omRequest,
       return new S3GetSecretRequest(omRequest);
     case FinalizeUpgrade:
       return new OMFinalizeUpgradeRequest(omRequest);
+    case StartFinalizeUpgrade:
+      return new OMStartFinalizeUpgradeRequest(omRequest);
     case Prepare:
       return new OMPrepareRequest(omRequest);
     case CancelPrepare:
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/upgrade/OMStartFinalizeUpgradeRequest.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/upgrade/OMStartFinalizeUpgradeRequest.java
new file mode 100644
index 00000000000..aa3849d935c
--- /dev/null
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/upgrade/OMStartFinalizeUpgradeRequest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.ozone.om.request.upgrade;
+
+import static 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type.StartFinalizeUpgrade;
+
+import java.io.IOException;
+import java.util.HashMap;
+import org.apache.hadoop.hdds.utils.db.cache.CacheKey;
+import org.apache.hadoop.hdds.utils.db.cache.CacheValue;
+import org.apache.hadoop.ozone.OzoneConsts;
+import org.apache.hadoop.ozone.audit.AuditLogger;
+import org.apache.hadoop.ozone.audit.OMAction;
+import org.apache.hadoop.ozone.om.OMMetadataManager;
+import org.apache.hadoop.ozone.om.OzoneManager;
+import org.apache.hadoop.ozone.om.exceptions.OMException;
+import org.apache.hadoop.ozone.om.execution.flowcontrol.ExecutionContext;
+import org.apache.hadoop.ozone.om.request.OMClientRequest;
+import org.apache.hadoop.ozone.om.request.util.OmResponseUtil;
+import org.apache.hadoop.ozone.om.response.OMClientResponse;
+import 
org.apache.hadoop.ozone.om.response.upgrade.OMStartFinalizeUpgradeResponse;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Starts the cluster upgrade finalization process.
+ */
+public class OMStartFinalizeUpgradeRequest extends OMClientRequest {
+  private static final Logger LOG = 
LoggerFactory.getLogger(OMStartFinalizeUpgradeRequest.class);
+
+  public OMStartFinalizeUpgradeRequest(OMRequest omRequest) {
+    super(omRequest);
+  }
+
+  @Override
+  public OMRequest preExecute(OzoneManager ozoneManager) throws IOException {
+    OMRequest omRequest = super.preExecute(ozoneManager);
+    if (ozoneManager.isAdminAuthorizationEnabled()) {
+      UserGroupInformation ugi = createUGIForApi();
+      if (!ozoneManager.isAdmin(ugi)) {
+        throw new OMException("Access denied for user " + ugi + ". "
+            + "Superuser privilege is required to start finalize upgrade.", 
OMException.ResultCodes.ACCESS_DENIED);
+      }
+    }
+    ozoneManager.getScmClient().getContainerClient().finalizeUpgrade();
+    LOG.info("Successfully triggered the finalize upgrade process in SCM");
+    return omRequest;
+  }
+
+  @Override
+  public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, 
ExecutionContext context) {
+    LOG.trace("Request: {}", getOmRequest());
+    AuditLogger auditLogger = ozoneManager.getSystemAuditLogger();
+    OzoneManagerProtocolProtos.UserInfo userInfo = 
getOmRequest().getUserInfo();
+    OMResponse.Builder responseBuilder = 
OmResponseUtil.getOMResponseBuilder(getOmRequest());
+    responseBuilder.setCmdType(StartFinalizeUpgrade);
+    OMClientResponse response = null;
+    Exception exception = null;
+
+    try {
+      OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager();
+      omMetadataManager.getMetaTable().addCacheEntry(
+          new CacheKey<>(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY), 
CacheValue.get(context.getIndex(), "ignored"));
+
+
+      OzoneManagerProtocolProtos.StartFinalizeUpgradeResponse omResponse =
+          OzoneManagerProtocolProtos.StartFinalizeUpgradeResponse.newBuilder()
+              .build();
+      responseBuilder.setStartFinalizeUpgradeResponse(omResponse);
+      response = new OMStartFinalizeUpgradeResponse(responseBuilder.build());
+      LOG.trace("Returning response: {}", response);
+    } catch (Exception e) {
+      exception = e;
+      response = new 
OMStartFinalizeUpgradeResponse(createErrorOMResponse(responseBuilder, e));
+    }
+
+    markForAudit(auditLogger, buildAuditMessage(OMAction.UPGRADE_FINALIZE, new 
HashMap<>(), exception, userInfo));
+    return response;
+  }
+
+}
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/upgrade/OMStartFinalizeUpgradeResponse.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/upgrade/OMStartFinalizeUpgradeResponse.java
new file mode 100644
index 00000000000..baf160c428b
--- /dev/null
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/upgrade/OMStartFinalizeUpgradeResponse.java
@@ -0,0 +1,49 @@
+/*
+ * 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.ozone.om.response.upgrade;
+
+import static org.apache.hadoop.ozone.om.codec.OMDBDefinition.META_TABLE;
+
+import java.io.IOException;
+import org.apache.hadoop.hdds.utils.db.BatchOperation;
+import org.apache.hadoop.ozone.OzoneConsts;
+import org.apache.hadoop.ozone.om.OMMetadataManager;
+import org.apache.hadoop.ozone.om.response.CleanupTableInfo;
+import org.apache.hadoop.ozone.om.response.OMClientResponse;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Response for finalizeUpgrade request.
+ */
+@CleanupTableInfo(cleanupTables = {META_TABLE})
+public class OMStartFinalizeUpgradeResponse extends OMClientResponse {
+  private static final Logger LOG = 
LoggerFactory.getLogger(OMStartFinalizeUpgradeResponse.class);
+
+  public OMStartFinalizeUpgradeResponse(OzoneManagerProtocolProtos.OMResponse 
omResponse) {
+    super(omResponse);
+  }
+
+  @Override
+  protected void addToDBBatch(OMMetadataManager omMetadataManager,
+      BatchOperation batchOperation) throws IOException {
+    LOG.info("Persisting Finalization In Progress Key to the Meta DB table");
+    omMetadataManager.getMetaTable().putWithBatch(batchOperation, 
OzoneConsts.FINALIZATION_IN_PROGRESS_KEY, "ignored");
+  }
+}
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/ratis/TestOzoneManagerRatisRequest.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/ratis/TestOzoneManagerRatisRequest.java
index f671c877c1f..b5c96eaded5 100644
--- 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/ratis/TestOzoneManagerRatisRequest.java
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/ratis/TestOzoneManagerRatisRequest.java
@@ -19,6 +19,7 @@
 
 import static 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Status.INVALID_REQUEST;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -41,6 +42,7 @@
 import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
 import org.apache.hadoop.ozone.om.ratis.utils.OzoneManagerRatisUtils;
 import org.apache.hadoop.ozone.om.request.OMRequestTestUtils;
+import 
org.apache.hadoop.ozone.om.request.upgrade.OMStartFinalizeUpgradeRequest;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
 import 
org.apache.hadoop.ozone.protocolPB.OzoneManagerProtocolServerSideTranslatorPB;
 import org.junit.jupiter.api.Test;
@@ -90,6 +92,19 @@ public void testRequestWithNonExistentBucket() throws 
Exception {
         omException.getResult());
   }
 
+  @Test
+  public void testStartFinalizeUpgradeRequestIsDispatched() throws IOException 
{
+    OzoneManagerProtocolProtos.OMRequest omRequest =
+        OzoneManagerProtocolProtos.OMRequest.newBuilder()
+            .setCmdType(OzoneManagerProtocolProtos.Type.StartFinalizeUpgrade)
+            .setClientId("test-client-id")
+            .build();
+
+    OzoneManager mockOm = mock(OzoneManager.class);
+    assertInstanceOf(OMStartFinalizeUpgradeRequest.class,
+        OzoneManagerRatisUtils.createClientRequest(omRequest, mockOm));
+  }
+
   @Test
   public void testUnknownRequestHandling()
       throws IOException, ServiceException {
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/upgrade/TestOMStartFinalizeUpgradeRequest.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/upgrade/TestOMStartFinalizeUpgradeRequest.java
new file mode 100644
index 00000000000..306b1fe7d16
--- /dev/null
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/upgrade/TestOMStartFinalizeUpgradeRequest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.ozone.om.request.upgrade;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import org.apache.hadoop.ozone.OzoneConsts;
+import org.apache.hadoop.ozone.om.exceptions.OMException;
+import org.apache.hadoop.ozone.om.execution.flowcontrol.ExecutionContext;
+import org.apache.hadoop.ozone.om.request.key.TestOMKeyRequest;
+import org.apache.hadoop.ozone.om.response.OMClientResponse;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.ratis.protocol.ClientId;
+import org.apache.ratis.server.protocol.TermIndex;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for OMStartFinalizeUpgradeRequest.
+ */
+public class TestOMStartFinalizeUpgradeRequest extends TestOMKeyRequest {
+  
+  @Test
+  public void testPreExecuteCallsScmFinalizeUpgrade() throws IOException {
+    doNothing().when(scmContainerLocationProtocol).finalizeUpgrade();
+
+    OzoneManagerProtocolProtos.OMRequest original = buildRequest();
+    OMStartFinalizeUpgradeRequest request = new 
OMStartFinalizeUpgradeRequest(original);
+
+    OzoneManagerProtocolProtos.OMRequest modified = 
request.preExecute(ozoneManager);
+
+    // UserInfo must have been added by the base class preExecute.
+    assertNotEquals(original, modified);
+    assertNotNull(modified.getUserInfo());
+
+    // SCM must have been asked to begin finalization.
+    verify(scmContainerLocationProtocol).finalizeUpgrade();
+  }
+
+  @Test
+  public void testValidateAndUpdateCacheAddsFinalizationInProgressKey() throws 
IOException {
+    doNothing().when(scmContainerLocationProtocol).finalizeUpgrade();
+
+    
assertNull(omMetadataManager.getMetaTable().get(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY),
+        "key should not exist before the request");
+
+    submitRequest();
+
+    
assertNotNull(omMetadataManager.getMetaTable().get(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY),
+        "key should be present in the cache after validateAndUpdateCache");
+  }
+
+  @Test
+  public void testAccessDeniedWhenUserIsNotAdmin() throws IOException {
+    when(ozoneManager.isAdminAuthorizationEnabled()).thenReturn(true);
+    when(ozoneManager.isAdmin(any())).thenReturn(false);
+
+    OzoneManagerProtocolProtos.OMRequest original = buildRequest();
+    OMStartFinalizeUpgradeRequest request = new 
OMStartFinalizeUpgradeRequest(original);
+    // In the test environment there is no live RPC thread, so
+    // ProtobufRpcEngine.Server.getRemoteUser() returns null and 
super.preExecute()
+    // cannot resolve a username. setUGI() pre-seeds the identity so that
+    // createUGIForApi() succeeds without needing the RPC thread-local.
+    request.setUGI(UserGroupInformation.createRemoteUser("testuser"));
+
+    // With auth in preExecute(), a non-admin is rejected before the request
+    // reaches Raft or touches SCM.
+    OMException ex = assertThrows(OMException.class,
+        () -> request.preExecute(ozoneManager));
+    assertEquals(OMException.ResultCodes.ACCESS_DENIED, ex.getResult(),
+        "non-admin user should receive ACCESS_DENIED from preExecute");
+
+    // SCM must NOT have been called — auth is checked before the SCM call.
+    verify(scmContainerLocationProtocol, never()).finalizeUpgrade();
+  }
+
+  private OMClientResponse submitRequest() throws IOException {
+    OzoneManagerProtocolProtos.OMRequest original = buildRequest();
+    OMStartFinalizeUpgradeRequest request = new 
OMStartFinalizeUpgradeRequest(original);
+    ExecutionContext context = ExecutionContext.of(1, TermIndex.INITIAL_VALUE);
+
+    OzoneManagerProtocolProtos.OMRequest modified = 
request.preExecute(ozoneManager);
+    assertNotEquals(original, modified);
+
+    return request.validateAndUpdateCache(ozoneManager, context);
+  }
+
+  private OzoneManagerProtocolProtos.OMRequest buildRequest() {
+    return OzoneManagerProtocolProtos.OMRequest.newBuilder()
+        .setCmdType(OzoneManagerProtocolProtos.Type.StartFinalizeUpgrade)
+        .setClientId(ClientId.randomId().toString())
+        .build();
+  }
+}
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/upgrade/TestOMStartFinalizeUpgradeResponse.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/upgrade/TestOMStartFinalizeUpgradeResponse.java
new file mode 100644
index 00000000000..b5564218513
--- /dev/null
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/upgrade/TestOMStartFinalizeUpgradeResponse.java
@@ -0,0 +1,75 @@
+/*
+ * 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.ozone.om.response.upgrade;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.hdds.utils.db.BatchOperation;
+import org.apache.hadoop.ozone.OzoneConsts;
+import org.apache.hadoop.ozone.om.OMConfigKeys;
+import org.apache.hadoop.ozone.om.OMMetadataManager;
+import org.apache.hadoop.ozone.om.OmMetadataManagerImpl;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+/**
+ * Tests for OMStartFinalizeUpgradeResponse.
+ */
+public class TestOMStartFinalizeUpgradeResponse {
+
+  @TempDir
+  private Path folder;
+  private OMMetadataManager omMetadataManager;
+  private BatchOperation batchOperation;
+
+  @BeforeEach
+  public void setup() throws Exception {
+    OzoneConfiguration ozoneConfiguration = new OzoneConfiguration();
+    ozoneConfiguration.set(OMConfigKeys.OZONE_OM_DB_DIRS,
+        folder.toAbsolutePath().toString());
+    omMetadataManager = new OmMetadataManagerImpl(ozoneConfiguration, null);
+    batchOperation = omMetadataManager.getStore().initBatchOperation();
+  }
+
+  @Test
+  public void testAddToDBBatchPersistsFinalizationInProgressKey() throws 
IOException {
+    
assertNull(omMetadataManager.getMetaTable().get(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY),
+        "key should not exist before the response is applied");
+
+    OMStartFinalizeUpgradeResponse response = new 
OMStartFinalizeUpgradeResponse(buildOkResponse());
+    response.addToDBBatch(omMetadataManager, batchOperation);
+    omMetadataManager.getStore().commitBatchOperation(batchOperation);
+
+    assertEquals("ignored",
+        
omMetadataManager.getMetaTable().get(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY),
+        "key should be persisted to the meta table after the response is 
committed");
+  }
+
+  private OzoneManagerProtocolProtos.OMResponse buildOkResponse() {
+    return OzoneManagerProtocolProtos.OMResponse.newBuilder()
+        .setCmdType(OzoneManagerProtocolProtos.Type.StartFinalizeUpgrade)
+        .setStatus(OzoneManagerProtocolProtos.Status.OK)
+        .build();
+  }
+}


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


Reply via email to