This is an automated email from the ASF dual-hosted git repository.
errose28 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 c46d5edf657 HDDS-16025. Allow old clients to start finalization on a
new server. (#11074)
c46d5edf657 is described below
commit c46d5edf657e1838b581d587d8ea3b94678ad4f4
Author: Ethan Rose <[email protected]>
AuthorDate: Thu Aug 27 11:24:01 2026 -0400
HDDS-16025. Allow old clients to start finalization on a new server.
(#11074)
---
.../apache/hadoop/hdds/scm/client/ScmClient.java | 2 -
.../java/org/apache/hadoop/hdds/utils/HAUtils.java | 7 +-
.../ozone/upgrade/RatisBasedVersionManager.java | 2 +-
.../hdds/scm/server/SCMClientProtocolServer.java | 5 +-
.../scm/server/TestSCMClientProtocolServer.java | 8 +-
.../hdds/scm/cli/ContainerOperationClient.java | 5 -
.../admin/om/FinalizationStatusSubCommand.java | 7 +-
.../ozone/admin/om/FinalizeUpgradeSubCommand.java | 7 +-
.../admin/scm/FinalizationScmStatusSubcommand.java | 8 +-
.../admin/scm/FinalizeScmUpgradeSubcommand.java | 8 +-
.../main/java/org/apache/hadoop/ozone/OmUtils.java | 2 +
.../ozone/om/protocol/OzoneManagerProtocol.java | 5 +
.../om/TestUpgradeFinalizationWithOldClients.java | 158 +++++++++++++
.../src/main/proto/OmClientProtocol.proto | 11 +
.../org/apache/hadoop/ozone/om/OzoneManager.java | 19 +-
.../om/ratis/utils/OzoneManagerRatisUtils.java | 7 +-
....java => OMCompleteFinalizeUpgradeRequest.java} | 54 ++---
...uest.java => OMFinalizeUpgradeRequestBase.java} | 66 +++---
.../upgrade/OMStartFinalizeUpgradeRequest.java | 132 +----------
.../OMStartFinalizeUpgradeRequestLegacy.java | 56 +++++
...java => OMCompleteFinalizeUpgradeResponse.java} | 8 +-
.../upgrade/OMStartFinalizeUpgradeResponse.java | 16 ++
.../ozone/om/upgrade/OMUpgradeFinalizeService.java | 2 +-
.../om/ratis/TestOzoneManagerRatisRequest.java | 14 ++
...a => TestOMCompleteFinalizeUpgradeRequest.java} | 22 +-
.../upgrade/TestOMStartFinalizeUpgradeRequest.java | 249 +--------------------
... => TestOMStartFinalizeUpgradeRequestBase.java} | 225 +++++++++----------
.../TestOMStartFinalizeUpgradeRequestLegacy.java | 63 ++++++
... => TestOMCompleteFinalizeUpgradeResponse.java} | 9 +-
.../TestOMStartFinalizeUpgradeResponse.java | 15 ++
30 files changed, 576 insertions(+), 616 deletions(-)
diff --git
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java
index ea8e575c2c5..2c9e13fb5d3 100644
---
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java
+++
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java
@@ -473,8 +473,6 @@ StatusAndMessages queryUpgradeFinalizationProgress(
String upgradeClientID, boolean force, boolean readonly)
throws IOException;
- void finalizeUpgrade() throws IOException;
-
HddsProtos.UpgradeStatus queryUpgradeStatus() throws IOException;
DecommissionScmResponseProto decommissionScm(
diff --git
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/HAUtils.java
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/HAUtils.java
index 3ae1b451e1f..e4769fae7dd 100644
---
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/HAUtils.java
+++
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/HAUtils.java
@@ -165,8 +165,13 @@ public static StorageContainerLocationProtocol
getScmContainerClient(
public static StorageContainerLocationProtocol getScmContainerClientForNode(
ConfigurationSource conf, ScmNodeTarget targetScmNode) {
+ return getScmContainerClientForNode(conf, targetScmNode, null);
+ }
+
+ public static StorageContainerLocationProtocol getScmContainerClientForNode(
+ ConfigurationSource conf, ScmNodeTarget targetScmNode,
UserGroupInformation ugi) {
SCMContainerLocationFailoverProxyProvider proxyProvider =
- new SCMContainerLocationFailoverProxyProvider(conf, null);
+ new SCMContainerLocationFailoverProxyProvider(conf, ugi);
StorageContainerLocationProtocol scmContainerClient =
TracingUtil.createProxy(
new StorageContainerLocationProtocolClientSideTranslatorPB(
diff --git
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/RatisBasedVersionManager.java
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/RatisBasedVersionManager.java
index 25f13ca40c3..e6d31cc4275 100644
---
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/RatisBasedVersionManager.java
+++
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/RatisBasedVersionManager.java
@@ -53,7 +53,7 @@ public void finalizeFromSnapshotIfRequired(Table<String,
String> finalizationSto
apparentVersionInNewDB);
finalizeUpgrade();
// Update the apparent version in the DB to match the VERSION file.
- // When finalization is not done with a snapshot, this DB value is
updated by OMFinalizeUpgradeRequest.
+ // When finalization is not done with a snapshot, this DB value is
updated by OMCompleteFinalizeUpgradeRequest.
finalizationStore.put(APPARENT_VERSION_KEY,
String.valueOf(getApparentVersion().serialize()));
}
}
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
index a58801f0842..d6304413a5a 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
@@ -1222,7 +1222,10 @@ private void validatePeerScmVersionsBeforeFinalize()
throws SCMException {
target.setNodeId(peerId);
StorageContainerLocationProtocol peerClient = null;
try {
- peerClient = HAUtils.getScmContainerClientForNode(conf, target);
+ // Contact the peer SCM as this SCM's service (Kerberos keytab)
identity, not the remote client's identity.
+ // This runs inside the finalize RPC handler's doAs context, whose UGI
has no credentials to open a fresh
+ // outbound RPC to the peer SCM.
+ peerClient = HAUtils.getScmContainerClientForNode(conf, target,
UserGroupInformation.getLoginUser());
HDDSVersion peerVersion = peerClient.getPeerUpgradeStatus();
if (!peerVersion.equals(leaderVersion)) {
LOG.warn("SCM peer {} is running software version {} but leader is
running version {}. "
diff --git
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMClientProtocolServer.java
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMClientProtocolServer.java
index c21fcf11877..564f9433b85 100644
---
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMClientProtocolServer.java
+++
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMClientProtocolServer.java
@@ -312,7 +312,7 @@ public void testFinalizeProceedsWhenAllPeersMatch() throws
IOException {
try (SCMClientProtocolServer testServer =
peerCheckServer(finalizationManager,
Arrays.asList(peerNode("scm2"), peerNode("scm3")));
MockedStatic<HAUtils> haUtils = mockStatic(HAUtils.class)) {
- haUtils.when(() -> HAUtils.getScmContainerClientForNode(any(),
any())).thenReturn(matching);
+ haUtils.when(() -> HAUtils.getScmContainerClientForNode(any(), any(),
any())).thenReturn(matching);
testServer.finalizeUpgrade();
}
verify(finalizationManager).finalizeUpgrade();
@@ -327,7 +327,7 @@ public void testFinalizeRejectsOlderPeerUnlessForced()
throws IOException {
try (SCMClientProtocolServer testServer =
peerCheckServer(finalizationManager,
Arrays.asList(peerNode("scm2"), peerNode("scm3")));
MockedStatic<HAUtils> haUtils = mockStatic(HAUtils.class)) {
- haUtils.when(() -> HAUtils.getScmContainerClientForNode(any(),
any())).thenReturn(matching, older);
+ haUtils.when(() -> HAUtils.getScmContainerClientForNode(any(), any(),
any())).thenReturn(matching, older);
// A peer on an older version is rejected without force.
assertThrows(SCMException.class, testServer::finalizeUpgrade);
verify(finalizationManager, never()).finalizeUpgrade();
@@ -347,7 +347,7 @@ public void
testFinalizeRejectsUnknownFuturePeerUnlessForced() throws IOExceptio
try (SCMClientProtocolServer testServer =
peerCheckServer(finalizationManager,
Arrays.asList(peerNode("scm2"), peerNode("scm3")));
MockedStatic<HAUtils> haUtils = mockStatic(HAUtils.class)) {
- haUtils.when(() -> HAUtils.getScmContainerClientForNode(any(), any()))
+ haUtils.when(() -> HAUtils.getScmContainerClientForNode(any(), any(),
any()))
.thenReturn(matching, unknown);
// A peer on an unrecognized future version is rejected without force.
assertThrows(SCMException.class, testServer::finalizeUpgrade);
@@ -367,7 +367,7 @@ public void
testFinalizeRejectsUnreachablePeerUnlessForced() throws IOException
try (SCMClientProtocolServer testServer =
peerCheckServer(finalizationManager,
Collections.singletonList(peerNode("scm2")));
MockedStatic<HAUtils> haUtils = mockStatic(HAUtils.class)) {
- haUtils.when(() -> HAUtils.getScmContainerClientForNode(any(),
any())).thenReturn(unreachable);
+ haUtils.when(() -> HAUtils.getScmContainerClientForNode(any(), any(),
any())).thenReturn(unreachable);
// An unreachable peer is rejected without force.
assertThrows(SCMException.class, testServer::finalizeUpgrade);
verify(finalizationManager, never()).finalizeUpgrade();
diff --git
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/ContainerOperationClient.java
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/ContainerOperationClient.java
index d03a6215a68..4edfc16c852 100644
---
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/ContainerOperationClient.java
+++
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/ContainerOperationClient.java
@@ -614,11 +614,6 @@ public StatusAndMessages queryUpgradeFinalizationProgress(
upgradeClientID, force, readonly);
}
- @Override
- public void finalizeUpgrade() throws IOException {
- storageContainerLocationClient.finalizeUpgrade();
- }
-
@Override
public HddsProtos.UpgradeStatus queryUpgradeStatus() throws IOException {
return storageContainerLocationClient.queryUpgradeStatus();
diff --git
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/FinalizationStatusSubCommand.java
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/FinalizationStatusSubCommand.java
index ef739454b65..af3cfa4ac5c 100644
---
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/FinalizationStatusSubCommand.java
+++
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/FinalizationStatusSubCommand.java
@@ -25,14 +25,17 @@
import picocli.CommandLine;
/**
- * Handler of ozone admin om finalizationstatus command.
+ * Handler of `ozone admin om finalizationstatus` command for new clients to
finalize old servers that do not support
+ * the current `ozone admin upgrade status` command.
*/
@CommandLine.Command(
name = "finalizationstatus",
description = "Get the finalization status of om cluster.",
mixinStandardHelpOptions = true,
- versionProvider = HddsVersionProvider.class
+ versionProvider = HddsVersionProvider.class,
+ hidden = true
)
+@Deprecated
public class FinalizationStatusSubCommand implements Callable<Void> {
@CommandLine.Mixin
diff --git
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/FinalizeUpgradeSubCommand.java
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/FinalizeUpgradeSubCommand.java
index df1e69f147a..9645658bd4a 100644
---
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/FinalizeUpgradeSubCommand.java
+++
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/FinalizeUpgradeSubCommand.java
@@ -42,7 +42,8 @@
import picocli.CommandLine;
/**
- * Handler of ozone admin om finalizeUpgrade command.
+ * Handler of `ozone admin om finalizeUpgrade` command for new clients to
finalize old servers that do not support the
+ * current `ozone admin upgrade finalize` command.
*/
@CommandLine.Command(
name = "finalizeupgrade",
@@ -52,8 +53,10 @@
+ "or the Ozone manager host in a non-HA environment, if none provided
"
+ "the default from configuration is being used if not ambiguous.",
mixinStandardHelpOptions = true,
- versionProvider = HddsVersionProvider.class
+ versionProvider = HddsVersionProvider.class,
+ hidden = true
)
+@Deprecated
public class FinalizeUpgradeSubCommand implements Callable<Void> {
@CommandLine.Mixin
diff --git
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/scm/FinalizationScmStatusSubcommand.java
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/scm/FinalizationScmStatusSubcommand.java
index 97151c49b0f..717ec36d50a 100644
---
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/scm/FinalizationScmStatusSubcommand.java
+++
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/scm/FinalizationScmStatusSubcommand.java
@@ -26,13 +26,17 @@
import picocli.CommandLine;
/**
- * Handler of FinalizationStatus SCM command.
+ * Handler of `ozone admin scm finalizeUpgrade` command for new clients to
finalize old servers that do not support the
+ * current `ozone admin upgrade status` command.
*/
@CommandLine.Command(
name = "finalizationstatus",
description = "Finalization SCM Status",
mixinStandardHelpOptions = true,
- versionProvider = HddsVersionProvider.class)
+ versionProvider = HddsVersionProvider.class,
+ hidden = true
+)
+@Deprecated
public class FinalizationScmStatusSubcommand extends ScmSubcommand {
@CommandLine.ParentCommand
diff --git
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/scm/FinalizeScmUpgradeSubcommand.java
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/scm/FinalizeScmUpgradeSubcommand.java
index 4b123c943c1..33da77f9efc 100644
---
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/scm/FinalizeScmUpgradeSubcommand.java
+++
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/scm/FinalizeScmUpgradeSubcommand.java
@@ -44,13 +44,17 @@
import picocli.CommandLine;
/**
- * Handler of Finalize SCM command.
+ * Handler of `ozone admin scm finalizeUpgrade` command for new clients to
finalize old servers that do not support the
+ * current `ozone admin upgrade finalize` command.
*/
@CommandLine.Command(
name = "finalizeupgrade",
description = "Finalize SCM Upgrade",
mixinStandardHelpOptions = true,
- versionProvider = HddsVersionProvider.class)
+ versionProvider = HddsVersionProvider.class,
+ hidden = true
+)
+@Deprecated
public class FinalizeScmUpgradeSubcommand extends ScmSubcommand {
@CommandLine.ParentCommand
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 6de380da870..d589e674b94 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
@@ -305,6 +305,7 @@ public static boolean isReadOnly(OMRequest omRequest) {
// as deprecated
case FinalizeUpgrade:
case StartFinalizeUpgrade:
+ case CompleteFinalizeUpgrade:
case DeleteOpenKeys:
case SetS3Secret:
case RevokeS3Secret:
@@ -430,6 +431,7 @@ public static boolean shouldSendToFollower(OMRequest
omRequest) {
// as deprecated
case FinalizeUpgrade:
case StartFinalizeUpgrade:
+ case CompleteFinalizeUpgrade:
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 22bf9518e9e..7de1715d3ef 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
@@ -494,6 +494,7 @@ ListOpenFilesResult listOpenFiles(String path, int maxKeys,
String contToken)
* @throws OMException
* when finalization is already in progress.
*/
+ @Deprecated
UpgradeFinalization.StatusAndMessages finalizeUpgrade(String
upgradeClientID) throws IOException;
/**
@@ -530,6 +531,9 @@ ListOpenFilesResult listOpenFiles(String path, int maxKeys,
String contToken)
OzoneManagerProtocolProtos.QueryUpgradeStatusResponse queryUpgradeStatus()
throws IOException;
/**
+ * This command is retained so that new clients can query status of old OM
servers. All new finalize requests should
+ * use `void queryUpgradeStatus()`.
+ *
* Queries the current status of finalization.
* This method when called, returns the status messages from the finalization
* progress, if any. The status returned is
@@ -557,6 +561,7 @@ ListOpenFilesResult listOpenFiles(String path, int maxKeys,
String contToken)
* @throws OMException
* if finalization is needed but not yet started
*/
+ @Deprecated
UpgradeFinalization.StatusAndMessages queryUpgradeFinalizationProgress(
String upgradeClientID, boolean takeover, boolean readonly
) throws IOException;
diff --git
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestUpgradeFinalizationWithOldClients.java
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestUpgradeFinalizationWithOldClients.java
new file mode 100644
index 00000000000..8f41417aec3
--- /dev/null
+++
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestUpgradeFinalizationWithOldClients.java
@@ -0,0 +1,158 @@
+/*
+ * 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;
+
+import static org.apache.ozone.test.GenericTestUtils.waitFor;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.UUID;
+import org.apache.hadoop.hdds.HDDSVersion;
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.hdds.scm.protocol.StorageContainerLocationProtocol;
+import org.apache.hadoop.hdds.scm.server.SCMStorageConfig;
+import org.apache.hadoop.hdds.scm.server.StorageContainerManager;
+import org.apache.hadoop.hdds.upgrade.HDDSLayoutFeature;
+import org.apache.hadoop.ozone.HddsDatanodeService;
+import org.apache.hadoop.ozone.MiniOzoneCluster;
+import org.apache.hadoop.ozone.OzoneManagerVersion;
+import org.apache.hadoop.ozone.UniformDatanodesFactory;
+import org.apache.hadoop.ozone.client.OzoneClient;
+import org.apache.hadoop.ozone.container.upgrade.DatanodeVersionManager;
+import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol;
+import org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature;
+import org.apache.hadoop.ozone.upgrade.UpgradeFinalization;
+import org.apache.hadoop.ozone.upgrade.UpgradeFinalization.StatusAndMessages;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Verifies that the finalize upgrade RPCs sent by old CLIs still finalize a
new server.
+ *
+ * <p>In the new finalization model a single call to OM drives the whole
cluster: OM triggers SCM
+ * finalization and then finalizes itself once SCM reports done. Old CLIs
predate this and issue
+ * the deprecated {@code FinalizeUpgrade} RPC to OM (and could target SCM
directly). The server must
+ * keep honoring those RPCs.
+ */
+class TestUpgradeFinalizationWithOldClients {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(TestUpgradeFinalizationWithOldClients.class);
+
+ /**
+ * An old {@code ozone admin om finalizeupgrade} CLI issues the deprecated
{@code FinalizeUpgrade}
+ * RPC via {@link OzoneManagerProtocol#finalizeUpgrade(String)} and then
polls
+ * {@link OzoneManagerProtocol#queryUpgradeFinalizationProgress(String,
boolean, boolean)} until
+ * finalization is done. This drives the whole cluster: OM, SCM, and the
datanode all start
+ * pre-finalized and end finalized.
+ *
+ * <p>It also exercises the deprecated SCM finalize API used by an old
+ * {@code ozone admin scm finalizeupgrade} CLI: finalizing SCM directly is
now a no-op (SCM
+ * finalization is driven from OM), while SCM's finalization status remains
individually queryable.
+ */
+ @Test
+ void testFinalizeUpgradeWithOldClientRpcs() throws Exception {
+ OzoneConfiguration conf = new OzoneConfiguration();
+ conf.set(OMConfigKeys.OZONE_OM_UPGRADE_FINALIZATION_CHECK_INTERVAL,
"10ms");
+ // Start OM, SCM, and the datanode pre-finalized: new binaries sitting on
the initial apparent version,
+ conf.setInt(OMStorage.TESTING_INIT_APPARENT_VERSION_KEY,
OMLayoutFeature.INITIAL_VERSION.serialize());
+ conf.setInt(SCMStorageConfig.TESTING_INIT_APPARENT_VERSION_KEY,
HDDSLayoutFeature.INITIAL_VERSION.serialize());
+
+ try (MiniOzoneCluster cluster = MiniOzoneCluster.newBuilder(conf)
+ .setNumDatanodes(1)
+ .setDatanodeFactory(UniformDatanodesFactory.newBuilder()
+ .setApparentVersion(HDDSLayoutFeature.INITIAL_VERSION)
+ .build())
+ .build()) {
+ cluster.waitForClusterToBeReady();
+ OzoneManager om = cluster.getOzoneManager();
+ StorageContainerManager scm = cluster.getStorageContainerManager();
+ StorageContainerLocationProtocol scmClient =
cluster.getStorageContainerLocationClient();
+
+ try (OzoneClient client = cluster.newClient()) {
+ OzoneManagerProtocol omClient =
client.getObjectStore().getClientProxy().getOzoneManagerClient();
+
+ // OM, SCM, and the datanode all start pre-finalized (needing
finalization). The datanode's
+ // state is read directly off the running datanode instance rather
than through a client RPC.
+ assertEquals(OMLayoutFeature.INITIAL_VERSION,
om.getVersionManager().getApparentVersion());
+ assertTrue(om.getVersionManager().needsFinalization());
+ assertEquals(HDDSLayoutFeature.INITIAL_VERSION,
scm.getVersionManager().getApparentVersion());
+ assertTrue(scm.getVersionManager().needsFinalization());
+ for (HddsDatanodeService dn : cluster.getHddsDatanodes()) {
+ DatanodeVersionManager dnVersionManager =
dn.getDatanodeStateMachine().getVersionManager();
+ assertEquals(HDDSLayoutFeature.INITIAL_VERSION,
dnVersionManager.getApparentVersion());
+ assertTrue(dnVersionManager.needsFinalization());
+ }
+
+ // SCM's finalization status is individually queryable through the
deprecated SCM API.
+ StatusAndMessages scmProgressBefore =
scmClient.queryUpgradeFinalizationProgress(
+ "Upgrade-Client-" + UUID.randomUUID(), false, false);
+ assertEquals(UpgradeFinalization.Status.FINALIZATION_REQUIRED,
scmProgressBefore.status());
+
+ // Finalizing SCM directly via the deprecated API is a no-op: it
reports ALREADY_FINALIZED to
+ // let old scripts move on, but it does not actually finalize SCM
(that is driven from OM).
+ StatusAndMessages scmFinalizeResponse =
+ scmClient.finalizeScmUpgrade("Upgrade-Client-" +
UUID.randomUUID());
+
assertTrue(UpgradeFinalization.isFinalized(scmFinalizeResponse.status()),
+ "Expected ALREADY_FINALIZED but got " +
scmFinalizeResponse.status());
+ assertTrue(scm.getVersionManager().needsFinalization(),
+ "Finalizing SCM directly through the legacy API must not finalize
SCM");
+ assertEquals(UpgradeFinalization.Status.FINALIZATION_REQUIRED,
+ scmClient.queryUpgradeFinalizationProgress("Upgrade-Client-" +
UUID.randomUUID(), false, false).status());
+
+ // The old CLI initiates finalization with the deprecated
FinalizeUpgrade RPC. The server
+ // reports STARTING_FINALIZATION so the old CLI proceeds to monitor
progress.
+ String upgradeClientID = "Upgrade-Client-" + UUID.randomUUID();
+ StatusAndMessages started = omClient.finalizeUpgrade(upgradeClientID);
+ assertTrue(UpgradeFinalization.isStarting(started.status()),
+ "Expected STARTING_FINALIZATION but got " + started.status());
+
+ // The old CLI polls progress until finalization is done, exactly as
FinalizeUpgradeSubCommand does.
+ waitFor(() -> {
+ try {
+ StatusAndMessages progress =
+ omClient.queryUpgradeFinalizationProgress(upgradeClientID,
false, false);
+ LOG.info("Waiting for OM finalization to finish. Current status:
{}", progress.status());
+ return UpgradeFinalization.isDone(progress.status());
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }, 2000, 60000);
+
+ // OM and SCM are finalized: OM advanced to the software version and
both report FINALIZED.
+ assertEquals(OzoneManagerVersion.SOFTWARE_VERSION,
om.getVersionManager().getApparentVersion());
+ assertEquals(HDDSVersion.SOFTWARE_VERSION,
scm.getVersionManager().getApparentVersion());
+
+ // SCM now reports done through the deprecated SCM API too.
+ assertTrue(UpgradeFinalization.isDone(
+ scmClient.queryUpgradeFinalizationProgress(upgradeClientID, false,
false).status()));
+
+ // Server side enforces finalization order of SCM->DNs->OM. Since we
already waited for OM to finalize,
+ // Datanodes should now be finalized.
+ for (HddsDatanodeService dn : cluster.getHddsDatanodes()) {
+ DatanodeVersionManager dnVersionManager =
dn.getDatanodeStateMachine().getVersionManager();
+ assertFalse(dnVersionManager.needsFinalization());
+ assertEquals(HDDSVersion.SOFTWARE_VERSION,
dnVersionManager.getApparentVersion());
+ }
+ }
+ }
+ }
+}
diff --git
a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
index 1b6ada0edca..11d9f1ea414 100644
--- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
+++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
@@ -169,6 +169,7 @@ enum Type {
SaveLifecycleScanState = 152;
StartFinalizeUpgrade = 153;
QueryUpgradeStatus = 154;
+ CompleteFinalizeUpgrade = 155;
}
enum SafeMode {
@@ -334,6 +335,7 @@ message OMRequest {
optional SaveLifecycleScanStateRequest saveLifecycleScanStateRequest = 153;
optional StartFinalizeUpgradeRequest startFinalizeUpgradeRequest =
154;
optional QueryUpgradeStatusRequest queryUpgradeStatusRequest =
155;
+ optional CompleteFinalizeUpgradeRequest completeFinalizeUpgradeRequest =
156;
}
message OMResponse {
@@ -482,6 +484,7 @@ message OMResponse {
optional SaveLifecycleScanStateResponse saveLifecycleScanStateResponse = 152;
optional StartFinalizeUpgradeResponse startFinalizeUpgradeResponse =
153;
optional QueryUpgradeStatusResponse queryUpgradeStatusResponse =
154;
+ optional CompleteFinalizeUpgradeResponse completeFinalizeUpgradeResponse =
155;
}
enum Status {
@@ -1693,6 +1696,14 @@ message StartFinalizeUpgradeRequest {
message StartFinalizeUpgradeResponse {
}
+// Internal request submitted by OMUpgradeFinalizeService to complete OM
finalization
+// once SCM reports FINALIZED.
+message CompleteFinalizeUpgradeRequest {
+}
+
+message CompleteFinalizeUpgradeResponse {
+}
+
message QueryUpgradeStatusRequest {
}
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 79c8f0314be..e9b1a92f832 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
@@ -111,8 +111,6 @@
import static
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OzoneManagerService;
import static
org.apache.hadoop.ozone.upgrade.UpgradeFinalization.FINALIZATION_DONE_MSG;
import static
org.apache.hadoop.ozone.upgrade.UpgradeFinalization.FINALIZATION_REQUIRED_MSG;
-import static
org.apache.hadoop.ozone.upgrade.UpgradeFinalization.FINALIZED_MSG;
-import static org.apache.hadoop.ozone.upgrade.UpgradeFinalization.STARTING_MSG;
import static org.apache.hadoop.security.UserGroupInformation.getCurrentUser;
import static org.apache.hadoop.util.ExitUtil.terminate;
import static org.apache.hadoop.util.Time.monotonicNow;
@@ -3760,22 +3758,15 @@ public boolean triggerSnapshotDefrag(boolean noWait)
throws IOException {
}
@Override
- public StatusAndMessages finalizeUpgrade(String unusedUpgradeClientId)
- throws IOException {
- if (!versionManager.needsFinalization()) {
- return FINALIZED_MSG;
- }
- versionManager.finalizeUpgrade();
- // Old OM clients currently require STARTING_MSG to be returned when this
method succeeds.
-
- return STARTING_MSG;
+ public StatusAndMessages finalizeUpgrade(String unusedUpgradeClientId) {
+ // Server-side stub; the real implementation is handled via the Ratis
request path through
+ // OMStartFinalizeUpgradeRequestLegacy
+ throw new UnsupportedOperationException();
}
@Override
public void finalizeUpgrade() throws IOException {
- // Server-side stub; the real implementation is handled via the Ratis
request path through
- // OMStartFinalizeUpgradeRequest
- throw new UnsupportedOperationException();
+ versionManager.finalizeUpgrade();
}
@Override
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 01fe6b10d0b..65da8398c1e 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
@@ -90,8 +90,9 @@
import org.apache.hadoop.ozone.om.request.snapshot.OMSnapshotPurgeRequest;
import org.apache.hadoop.ozone.om.request.snapshot.OMSnapshotRenameRequest;
import
org.apache.hadoop.ozone.om.request.snapshot.OMSnapshotSetPropertyRequest;
-import org.apache.hadoop.ozone.om.request.upgrade.OMFinalizeUpgradeRequest;
+import
org.apache.hadoop.ozone.om.request.upgrade.OMCompleteFinalizeUpgradeRequest;
import
org.apache.hadoop.ozone.om.request.upgrade.OMStartFinalizeUpgradeRequest;
+import
org.apache.hadoop.ozone.om.request.upgrade.OMStartFinalizeUpgradeRequestLegacy;
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;
@@ -189,9 +190,11 @@ public static OMClientRequest
createClientRequest(OMRequest omRequest,
case GetS3Secret:
return new S3GetSecretRequest(omRequest);
case FinalizeUpgrade:
- return new OMFinalizeUpgradeRequest(omRequest);
+ return new OMStartFinalizeUpgradeRequestLegacy(omRequest);
case StartFinalizeUpgrade:
return new OMStartFinalizeUpgradeRequest(omRequest);
+ case CompleteFinalizeUpgrade:
+ return new OMCompleteFinalizeUpgradeRequest(omRequest);
case SetS3Secret:
return new OMSetSecretRequest(omRequest);
case RevokeS3Secret:
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/upgrade/OMFinalizeUpgradeRequest.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/upgrade/OMCompleteFinalizeUpgradeRequest.java
similarity index 64%
rename from
hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/upgrade/OMFinalizeUpgradeRequest.java
rename to
hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/upgrade/OMCompleteFinalizeUpgradeRequest.java
index 06c3a9bcaf5..2f8c42f0a45 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/upgrade/OMFinalizeUpgradeRequest.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/upgrade/OMCompleteFinalizeUpgradeRequest.java
@@ -18,11 +18,10 @@
package org.apache.hadoop.ozone.om.request.upgrade;
import static org.apache.hadoop.ozone.OzoneConsts.APPARENT_VERSION_KEY;
-import static
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type.FinalizeUpgrade;
+import static
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type.CompleteFinalizeUpgrade;
import java.io.IOException;
import java.util.HashMap;
-import
org.apache.hadoop.hdds.protocol.proto.HddsProtos.UpgradeFinalizationStatus;
import org.apache.hadoop.hdds.utils.db.cache.CacheKey;
import org.apache.hadoop.hdds.utils.db.cache.CacheValue;
import org.apache.hadoop.ozone.OzoneConsts;
@@ -30,30 +29,27 @@
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.OMFinalizeUpgradeResponse;
+import
org.apache.hadoop.ozone.om.response.upgrade.OMCompleteFinalizeUpgradeResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
-import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.FinalizeUpgradeRequest;
-import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.FinalizeUpgradeResponse;
+import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CompleteFinalizeUpgradeResponse;
import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
-import org.apache.hadoop.ozone.upgrade.UpgradeFinalization.StatusAndMessages;
-import org.apache.hadoop.security.UserGroupInformation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Handles finalizeUpgrade request.
+ * Completes OM finalization once SCM has finalized. Submitted internally over
Ratis by
+ * {@code OMUpgradeFinalizeService}; no client ever sends this request.
*/
-public class OMFinalizeUpgradeRequest extends OMClientRequest {
+public class OMCompleteFinalizeUpgradeRequest extends OMClientRequest {
private static final Logger LOG =
- LoggerFactory.getLogger(OMFinalizeUpgradeRequest.class);
+ LoggerFactory.getLogger(OMCompleteFinalizeUpgradeRequest.class);
- public OMFinalizeUpgradeRequest(OMRequest omRequest) {
+ public OMCompleteFinalizeUpgradeRequest(OMRequest omRequest) {
super(omRequest);
}
@@ -64,32 +60,12 @@ public OMClientResponse validateAndUpdateCache(OzoneManager
ozoneManager, Execut
OzoneManagerProtocolProtos.UserInfo userInfo =
getOmRequest().getUserInfo();
OMResponse.Builder responseBuilder =
OmResponseUtil.getOMResponseBuilder(getOmRequest());
- responseBuilder.setCmdType(FinalizeUpgrade);
+ responseBuilder.setCmdType(CompleteFinalizeUpgrade);
OMClientResponse response = null;
Exception exception = null;
try {
- if (ozoneManager.isAdminAuthorizationEnabled()) {
- UserGroupInformation ugi = createUGIForApi();
- if (!ozoneManager.isAdmin(ugi)) {
- throw new OMException("Access denied for user " + ugi + ". "
- + "Superuser privilege is required to finalize upgrade.",
- OMException.ResultCodes.ACCESS_DENIED);
- }
- }
-
- FinalizeUpgradeRequest request =
- getOmRequest().getFinalizeUpgradeRequest();
- String upgradeClientID = request.getUpgradeClientId();
- StatusAndMessages omStatus =
- ozoneManager.finalizeUpgrade(upgradeClientID);
-
- UpgradeFinalizationStatus.Status protoStatus =
- UpgradeFinalizationStatus.Status.valueOf(omStatus.status().name());
- UpgradeFinalizationStatus responseStatus =
- UpgradeFinalizationStatus.newBuilder()
- .setStatus(protoStatus)
- .build();
+ ozoneManager.finalizeUpgrade();
OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager();
int apparentVersion =
ozoneManager.getVersionManager().getApparentVersion().serialize();
@@ -101,17 +77,13 @@ public OMClientResponse
validateAndUpdateCache(OzoneManager ozoneManager, Execut
new CacheKey<>(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY),
CacheValue.get(context.getIndex()));
ozoneManager.getMetrics().setFinalizationInProgress(false);
- FinalizeUpgradeResponse omResponse =
- FinalizeUpgradeResponse.newBuilder()
- .setStatus(responseStatus)
- .build();
- responseBuilder.setFinalizeUpgradeResponse(omResponse);
- response = new OMFinalizeUpgradeResponse(responseBuilder.build(),
+
responseBuilder.setCompleteFinalizeUpgradeResponse(CompleteFinalizeUpgradeResponse.newBuilder().build());
+ response = new OMCompleteFinalizeUpgradeResponse(responseBuilder.build(),
ozoneManager.getVersionManager().getApparentVersion().serialize());
LOG.trace("Returning response: {}", response);
} catch (IOException e) {
exception = e;
- response = new OMFinalizeUpgradeResponse(
+ response = new OMCompleteFinalizeUpgradeResponse(
createErrorOMResponse(responseBuilder, e), -1);
}
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/OMFinalizeUpgradeRequestBase.java
similarity index 69%
copy from
hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/upgrade/OMStartFinalizeUpgradeRequest.java
copy to
hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/upgrade/OMFinalizeUpgradeRequestBase.java
index cce820afdc4..4467a74905c 100644
---
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/OMFinalizeUpgradeRequestBase.java
@@ -17,9 +17,6 @@
package org.apache.hadoop.ozone.om.request.upgrade;
-import static org.apache.hadoop.hdds.utils.HddsServerUtil.getRemoteUser;
-import static
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type.StartFinalizeUpgrade;
-
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
@@ -52,12 +49,15 @@
import org.slf4j.LoggerFactory;
/**
- * Starts the cluster upgrade finalization process.
+ * Shared logic for the client-initiated finalize requests between the current
request and legacy request kept for
+ * backwards compatibility with old clients. It triggers SCM finalization
+ * and writes the finalization-in-progress key so that {@code
OMUpgradeFinalizeService}
+ * can drive OM finalization to completion asynchronously.
*/
-public class OMStartFinalizeUpgradeRequest extends OMClientRequest {
- private static final Logger LOG =
LoggerFactory.getLogger(OMStartFinalizeUpgradeRequest.class);
+public abstract class OMFinalizeUpgradeRequestBase extends OMClientRequest {
+ private static final Logger LOG =
LoggerFactory.getLogger(OMFinalizeUpgradeRequestBase.class);
- public OMStartFinalizeUpgradeRequest(OMRequest omRequest) {
+ public OMFinalizeUpgradeRequestBase(OMRequest omRequest) {
super(omRequest);
}
@@ -68,10 +68,10 @@ public OMRequest preExecute(OzoneManager ozoneManager)
throws IOException {
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);
+ + "Superuser privilege is required to finalize upgrade.",
OMException.ResultCodes.ACCESS_DENIED);
}
}
- boolean force = getOmRequest().getStartFinalizeUpgradeRequest().getForce();
+ boolean force = isForce();
if (force) {
LOG.warn("Forcing upgrade finalization by skipping OM peer software
version checks");
} else {
@@ -100,22 +100,26 @@ public OMClientResponse
validateAndUpdateCache(OzoneManager ozoneManager, Execut
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"));
- ozoneManager.getMetrics().setFinalizationInProgress(true);
-
+ // Only mark finalization in progress when OM actually needs to
finalize. If an admin initiates finalize on an
+ // already-finalized cluster, the marker would be orphaned: the async
OMUpgradeFinalizeService shuts down because
+ // needsFinalization() is false and would never clear it. The response
mirrors this so the marker is not
+ // persisted to the DB when the double buffer flushes either.
+ boolean finalizationNeeded =
ozoneManager.getVersionManager().needsFinalization();
+ if (finalizationNeeded) {
+ OMMetadataManager omMetadataManager =
ozoneManager.getMetadataManager();
+ omMetadataManager.getMetaTable().addCacheEntry(
+ new CacheKey<>(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY),
CacheValue.get(context.getIndex(), "ignored"));
+ ozoneManager.getMetrics().setFinalizationInProgress(true);
+ } else {
+ LOG.info("OM does not need finalization; skipping
finalization-in-progress marker.");
+ }
- OzoneManagerProtocolProtos.StartFinalizeUpgradeResponse omResponse =
- OzoneManagerProtocolProtos.StartFinalizeUpgradeResponse.newBuilder()
- .build();
- responseBuilder.setStartFinalizeUpgradeResponse(omResponse);
- response = new OMStartFinalizeUpgradeResponse(responseBuilder.build());
+ setResponseBody(responseBuilder, ozoneManager);
+ response = new OMStartFinalizeUpgradeResponse(responseBuilder.build(),
finalizationNeeded);
LOG.trace("Returning response: {}", response);
} catch (Exception e) {
exception = e;
@@ -123,13 +127,23 @@ public OMClientResponse
validateAndUpdateCache(OzoneManager ozoneManager, Execut
}
Map<String, String> auditMap = new HashMap<>();
- auditMap.put("force",
String.valueOf(getOmRequest().getStartFinalizeUpgradeRequest().getForce()));
+ auditMap.put("force", String.valueOf(isForce()));
markForAudit(auditLogger, buildAuditMessage(OMAction.UPGRADE_FINALIZE,
auditMap, exception, userInfo));
return response;
}
- private static void validatePeerOmVersionsBeforeFinalize(List<OMNodeDetails>
peerNodes,
- OzoneConfiguration configuration) throws OMException {
+ /**
+ * Whether SCM finalization should be forced (skipping OM peer software
version checks).
+ */
+ protected abstract boolean isForce();
+
+ /**
+ * Sets the command-type-specific response body on the given builder
(including cmdType).
+ */
+ protected abstract void setResponseBody(OMResponse.Builder builder,
OzoneManager ozoneManager);
+
+ static void validatePeerOmVersionsBeforeFinalize(List<OMNodeDetails>
peerNodes, OzoneConfiguration configuration)
+ throws OMException {
if (peerNodes.isEmpty()) {
return;
}
@@ -139,7 +153,10 @@ private static void
validatePeerOmVersionsBeforeFinalize(List<OMNodeDetails> pee
String peerId = peerDetails.getNodeId();
OMAdminProtocolClientSideImpl client = null;
try {
- client =
OMAdminProtocolClientSideImpl.createProxyForSingleOM(configuration,
getRemoteUser(), peerDetails);
+ // Use the OM service login (Kerberos keytab) identity, not the remote
client's identity: this runs inside the
+ // client's RPC handler thread, whose UGI has no credentials to open a
fresh outbound RPC to the peer OM.
+ client = OMAdminProtocolClientSideImpl.createProxyForSingleOM(
+ configuration, UserGroupInformation.getLoginUser(), peerDetails);
OzoneManagerVersion peerVersion = client.getPeerUpgradeStatus();
if (!peerVersion.equals(leaderVersion)) {
LOG.warn("OM peer {} is running software version {} but leader is
running version {}. "
@@ -159,5 +176,4 @@ private static void
validatePeerOmVersionsBeforeFinalize(List<OMNodeDetails> pee
OMException.ResultCodes.NOT_SUPPORTED_OPERATION);
}
}
-
}
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
index cce820afdc4..7441645f585 100644
---
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
@@ -17,147 +17,31 @@
package org.apache.hadoop.ozone.om.request.upgrade;
-import static org.apache.hadoop.hdds.utils.HddsServerUtil.getRemoteUser;
import static
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type.StartFinalizeUpgrade;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.apache.hadoop.hdds.conf.OzoneConfiguration;
-import org.apache.hadoop.hdds.scm.exceptions.SCMException;
-import org.apache.hadoop.hdds.utils.IOUtils;
-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.OzoneManagerVersion;
-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.helpers.OMNodeDetails;
-import org.apache.hadoop.ozone.om.protocolPB.OMAdminProtocolClientSideImpl;
-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.
+ * Starts the cluster upgrade finalization process via {@code ozone admin
upgrade finalize}.
*/
-public class OMStartFinalizeUpgradeRequest extends OMClientRequest {
- private static final Logger LOG =
LoggerFactory.getLogger(OMStartFinalizeUpgradeRequest.class);
+public class OMStartFinalizeUpgradeRequest extends
OMFinalizeUpgradeRequestBase {
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);
- }
- }
- boolean force = getOmRequest().getStartFinalizeUpgradeRequest().getForce();
- if (force) {
- LOG.warn("Forcing upgrade finalization by skipping OM peer software
version checks");
- } else {
- validatePeerOmVersionsBeforeFinalize(ozoneManager.getPeerNodes(),
ozoneManager.getConfiguration());
- }
-
- try {
- if (force) {
-
ozoneManager.getScmClient().getContainerClient().forceFinalizeUpgrade();
- } else {
- ozoneManager.getScmClient().getContainerClient().finalizeUpgrade();
- }
- } catch (SCMException e) {
- if (e.getResult() == SCMException.ResultCodes.UNSUPPORTED_OPERATION) {
- throw new OMException(e.getMessage(), e,
OMException.ResultCodes.NOT_SUPPORTED_OPERATION);
- }
- throw e;
- }
- LOG.info("Successfully triggered the finalize upgrade process in SCM");
- return omRequest;
+ protected boolean isForce() {
+ return getOmRequest().getStartFinalizeUpgradeRequest().getForce();
}
@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"));
- ozoneManager.getMetrics().setFinalizationInProgress(true);
-
-
- 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));
- }
-
- Map<String, String> auditMap = new HashMap<>();
- auditMap.put("force",
String.valueOf(getOmRequest().getStartFinalizeUpgradeRequest().getForce()));
- markForAudit(auditLogger, buildAuditMessage(OMAction.UPGRADE_FINALIZE,
auditMap, exception, userInfo));
- return response;
- }
-
- private static void validatePeerOmVersionsBeforeFinalize(List<OMNodeDetails>
peerNodes,
- OzoneConfiguration configuration) throws OMException {
- if (peerNodes.isEmpty()) {
- return;
- }
- OzoneManagerVersion leaderVersion = OzoneManagerVersion.SOFTWARE_VERSION;
- List<String> failedPeers = new ArrayList<>();
- for (OMNodeDetails peerDetails : peerNodes) {
- String peerId = peerDetails.getNodeId();
- OMAdminProtocolClientSideImpl client = null;
- try {
- client =
OMAdminProtocolClientSideImpl.createProxyForSingleOM(configuration,
getRemoteUser(), peerDetails);
- OzoneManagerVersion peerVersion = client.getPeerUpgradeStatus();
- if (!peerVersion.equals(leaderVersion)) {
- LOG.warn("OM peer {} is running software version {} but leader is
running version {}. "
- + "Rejecting finalize command.", peerId, peerVersion,
leaderVersion);
- failedPeers.add(peerId + " (version: " + peerVersion + ")");
- }
- } catch (IOException e) {
- LOG.warn("Failed to contact OM peer {} to check software version
before finalize.", peerId, e);
- failedPeers.add(peerId + " (unreachable: " + e.getMessage() + ")");
- } finally {
- IOUtils.cleanupWithLogger(LOG, client);
- }
- }
- if (!failedPeers.isEmpty()) {
- throw new OMException("Finalize rejected: the following OM peers did not
confirm matching software version "
- + "(expected version=" + leaderVersion + "): " + String.join(", ",
failedPeers),
- OMException.ResultCodes.NOT_SUPPORTED_OPERATION);
- }
+ protected void setResponseBody(OMResponse.Builder builder, OzoneManager
ozoneManager) {
+ builder.setCmdType(StartFinalizeUpgrade);
+ builder.setStartFinalizeUpgradeResponse(
+
OzoneManagerProtocolProtos.StartFinalizeUpgradeResponse.newBuilder().build());
}
-
}
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/upgrade/OMStartFinalizeUpgradeRequestLegacy.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/upgrade/OMStartFinalizeUpgradeRequestLegacy.java
new file mode 100644
index 00000000000..061af43601b
--- /dev/null
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/upgrade/OMStartFinalizeUpgradeRequestLegacy.java
@@ -0,0 +1,56 @@
+/*
+ * 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.FinalizeUpgrade;
+
+import
org.apache.hadoop.hdds.protocol.proto.HddsProtos.UpgradeFinalizationStatus;
+import org.apache.hadoop.ozone.om.OzoneManager;
+import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.FinalizeUpgradeResponse;
+import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
+import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
+
+/**
+ * Handles the finalizeUpgrade request sent by the old CLI ({@code ozone admin
om finalizeupgrade}).
+ * It initiates the same asynchronous finalization flow as {@link
OMStartFinalizeUpgradeRequest} and
+ * returns {@code STARTING_FINALIZATION} to be compatible with old clients.
+ * The old CLI then polls finalization progress until done.
+ */
+public class OMStartFinalizeUpgradeRequestLegacy extends
OMFinalizeUpgradeRequestBase {
+
+ public OMStartFinalizeUpgradeRequestLegacy(OMRequest omRequest) {
+ super(omRequest);
+ }
+
+ @Override
+ protected boolean isForce() {
+ // The old request has no force field.
+ return false;
+ }
+
+ @Override
+ protected void setResponseBody(OMResponse.Builder builder, OzoneManager
ozoneManager) {
+ builder.setCmdType(FinalizeUpgrade);
+ UpgradeFinalizationStatus status = UpgradeFinalizationStatus.newBuilder()
+ .setStatus(UpgradeFinalizationStatus.Status.STARTING_FINALIZATION)
+ .build();
+ builder.setFinalizeUpgradeResponse(FinalizeUpgradeResponse.newBuilder()
+ .setStatus(status)
+ .build());
+ }
+}
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/upgrade/OMFinalizeUpgradeResponse.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/upgrade/OMCompleteFinalizeUpgradeResponse.java
similarity index 89%
rename from
hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/upgrade/OMFinalizeUpgradeResponse.java
rename to
hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/upgrade/OMCompleteFinalizeUpgradeResponse.java
index 8dc981ba5ed..c5cdda6ec97 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/upgrade/OMFinalizeUpgradeResponse.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/upgrade/OMCompleteFinalizeUpgradeResponse.java
@@ -31,15 +31,15 @@
import org.slf4j.LoggerFactory;
/**
- * Response for finalizeUpgrade request.
+ * Response for completing OM finalization (submitted by
OMUpgradeFinalizeService).
*/
@CleanupTableInfo(cleanupTables = {META_TABLE})
-public class OMFinalizeUpgradeResponse extends OMClientResponse {
+public class OMCompleteFinalizeUpgradeResponse extends OMClientResponse {
private static final Logger LOG =
- LoggerFactory.getLogger(OMFinalizeUpgradeResponse.class);
+ LoggerFactory.getLogger(OMCompleteFinalizeUpgradeResponse.class);
private int serializedApparentVersion = -1;
- public OMFinalizeUpgradeResponse(
+ public OMCompleteFinalizeUpgradeResponse(
OzoneManagerProtocolProtos.OMResponse omResponse,
int serializedApparentVersion) {
super(omResponse);
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
index baf160c428b..6687e5a6950 100644
---
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
@@ -36,13 +36,29 @@
public class OMStartFinalizeUpgradeResponse extends OMClientResponse {
private static final Logger LOG =
LoggerFactory.getLogger(OMStartFinalizeUpgradeResponse.class);
+ private final boolean finalizationNeeded;
+
public OMStartFinalizeUpgradeResponse(OzoneManagerProtocolProtos.OMResponse
omResponse) {
+ this(omResponse, true);
+ }
+
+ /**
+ * @param finalizationNeeded whether OM still needs to finalize. When {@code
false} the finalization-in-progress
+ * marker is not persisted, so that initiating finalize on an
already-finalized cluster does not orphan the key
+ * in the DB (the async {@code OMUpgradeFinalizeService} would never
clear it since finalization is not needed).
+ */
+ public OMStartFinalizeUpgradeResponse(OzoneManagerProtocolProtos.OMResponse
omResponse, boolean finalizationNeeded) {
super(omResponse);
+ this.finalizationNeeded = finalizationNeeded;
}
@Override
protected void addToDBBatch(OMMetadataManager omMetadataManager,
BatchOperation batchOperation) throws IOException {
+ if (!finalizationNeeded) {
+ LOG.info("OM does not need finalization; skipping persistence of the
finalization-in-progress key.");
+ return;
+ }
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/main/java/org/apache/hadoop/ozone/om/upgrade/OMUpgradeFinalizeService.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMUpgradeFinalizeService.java
index f45f963a45e..b168d14c111 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMUpgradeFinalizeService.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMUpgradeFinalizeService.java
@@ -121,7 +121,7 @@ public BackgroundTaskResult call() {
LOG.info("The SCM Upgrade has been finalized. OM will now
finalize. Run count {}", run);
OzoneManagerProtocolProtos.OMRequest omRequest =
OzoneManagerProtocolProtos.OMRequest.newBuilder()
- .setCmdType(OzoneManagerProtocolProtos.Type.FinalizeUpgrade)
+
.setCmdType(OzoneManagerProtocolProtos.Type.CompleteFinalizeUpgrade)
.setClientId(clientId.toString())
.build();
OzoneManagerProtocolProtos.OMResponse response =
OzoneManagerRatisUtils.submitRequest(
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 b5c96eaded5..99b308dcfa1 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
@@ -42,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.OMCompleteFinalizeUpgradeRequest;
import
org.apache.hadoop.ozone.om.request.upgrade.OMStartFinalizeUpgradeRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
import
org.apache.hadoop.ozone.protocolPB.OzoneManagerProtocolServerSideTranslatorPB;
@@ -105,6 +106,19 @@ public void testStartFinalizeUpgradeRequestIsDispatched()
throws IOException {
OzoneManagerRatisUtils.createClientRequest(omRequest, mockOm));
}
+ @Test
+ public void testCompleteFinalizeUpgradeRequestIsDispatched() throws
IOException {
+ OzoneManagerProtocolProtos.OMRequest omRequest =
+ OzoneManagerProtocolProtos.OMRequest.newBuilder()
+
.setCmdType(OzoneManagerProtocolProtos.Type.CompleteFinalizeUpgrade)
+ .setClientId("test-client-id")
+ .build();
+
+ OzoneManager mockOm = mock(OzoneManager.class);
+ assertInstanceOf(OMCompleteFinalizeUpgradeRequest.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/TestOMFinalizeUpgradeRequest.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/upgrade/TestOMCompleteFinalizeUpgradeRequest.java
similarity index 85%
rename from
hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/upgrade/TestOMFinalizeUpgradeRequest.java
rename to
hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/upgrade/TestOMCompleteFinalizeUpgradeRequest.java
index e282ce8dc0c..bb22eae1e1a 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/upgrade/TestOMFinalizeUpgradeRequest.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/upgrade/TestOMCompleteFinalizeUpgradeRequest.java
@@ -22,12 +22,11 @@
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.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.IOException;
-import java.util.Collections;
import org.apache.hadoop.hdds.utils.db.cache.CacheKey;
import org.apache.hadoop.hdds.utils.db.cache.CacheValue;
import org.apache.hadoop.ozone.OzoneConsts;
@@ -41,23 +40,20 @@
import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Status;
import org.apache.hadoop.ozone.upgrade.UpgradeException;
-import org.apache.hadoop.ozone.upgrade.UpgradeFinalization;
import org.apache.ratis.protocol.ClientId;
import org.apache.ratis.server.protocol.TermIndex;
import org.junit.jupiter.api.Test;
/**
- * Tests for the OMFinalizeUpgradeRequest class.
+ * Tests for the OMCompleteFinalizeUpgradeRequest class.
*/
-public class TestOMFinalizeUpgradeRequest extends OMKeyRequestTests {
+public class TestOMCompleteFinalizeUpgradeRequest extends OMKeyRequestTests {
@Test
public void testFinalizationInProgressKeyRemoved() throws IOException {
OMVersionManager omVersionManager = mock(OMVersionManager.class);
when(omVersionManager.getApparentVersion()).thenReturn(OzoneManagerVersion.DEFAULT_VERSION);
when(ozoneManager.getVersionManager()).thenReturn(omVersionManager);
- when(ozoneManager.finalizeUpgrade(any())).thenReturn(new
UpgradeFinalization.StatusAndMessages(
- UpgradeFinalization.Status.FINALIZATION_IN_PROGRESS,
Collections.singletonList("Finalization in progress")));
omMetadataManager.getMetaTable().put(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY,
"ignored");
omMetadataManager.getMetaTable().addCacheEntry(
@@ -89,14 +85,14 @@ public void testFinalizeFailureMapsToInternalError() throws
IOException {
OMVersionManager omVersionManager = mock(OMVersionManager.class);
when(omVersionManager.getApparentVersion()).thenReturn(OzoneManagerVersion.DEFAULT_VERSION);
when(ozoneManager.getVersionManager()).thenReturn(omVersionManager);
- when(ozoneManager.finalizeUpgrade(any())).thenThrow(
- new
UpgradeException(UpgradeException.ResultCodes.FINALIZE_UPGRADE_ACTION_FAILED));
+ doThrow(new
UpgradeException(UpgradeException.ResultCodes.FINALIZE_UPGRADE_ACTION_FAILED))
+ .when(ozoneManager).finalizeUpgrade();
OzoneManagerProtocolProtos.OMRequest omRequest =
OzoneManagerProtocolProtos.OMRequest.newBuilder()
- .setCmdType(OzoneManagerProtocolProtos.Type.FinalizeUpgrade)
+ .setCmdType(OzoneManagerProtocolProtos.Type.CompleteFinalizeUpgrade)
.setClientId(ClientId.randomId().toString())
.build();
- OMFinalizeUpgradeRequest request = new OMFinalizeUpgradeRequest(omRequest);
+ OMCompleteFinalizeUpgradeRequest request = new
OMCompleteFinalizeUpgradeRequest(omRequest);
ExecutionContext context = ExecutionContext.of(1, TermIndex.INITIAL_VALUE);
request.preExecute(ozoneManager);
@@ -108,11 +104,11 @@ public void testFinalizeFailureMapsToInternalError()
throws IOException {
private void submitRequest() throws IOException {
OzoneManagerProtocolProtos.OMRequest omRequest =
OzoneManagerProtocolProtos.OMRequest.newBuilder()
- .setCmdType(OzoneManagerProtocolProtos.Type.FinalizeUpgrade)
+ .setCmdType(OzoneManagerProtocolProtos.Type.CompleteFinalizeUpgrade)
.setClientId(ClientId.randomId().toString())
.build();
- OMFinalizeUpgradeRequest request = new OMFinalizeUpgradeRequest(omRequest);
+ OMCompleteFinalizeUpgradeRequest request = new
OMCompleteFinalizeUpgradeRequest(omRequest);
ExecutionContext context = ExecutionContext.of(1, TermIndex.INITIAL_VALUE);
OzoneManagerProtocolProtos.OMRequest modifiedOmRequest =
request.preExecute(ozoneManager);
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
index 88746f0308a..376c80ce7f5 100644
---
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
@@ -18,14 +18,8 @@
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.assertSame;
-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.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.never;
@@ -33,51 +27,26 @@
import static org.mockito.Mockito.when;
import java.io.IOException;
-import java.util.Arrays;
import java.util.Collections;
-import org.apache.hadoop.hdds.scm.exceptions.SCMException;
-import org.apache.hadoop.ozone.OzoneConsts;
import org.apache.hadoop.ozone.OzoneManagerVersion;
-import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.execution.flowcontrol.ExecutionContext;
-import org.apache.hadoop.ozone.om.helpers.OMNodeDetails;
import org.apache.hadoop.ozone.om.protocolPB.OMAdminProtocolClientSideImpl;
-import org.apache.hadoop.ozone.om.request.key.OMKeyRequestTests;
-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.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
/**
- * Tests for OMStartFinalizeUpgradeRequest.
+ * Tests for OMStartFinalizeUpgradeRequest, the current ({@code ozone admin
upgrade finalize}) initiated
+ * request. Shared initiate behavior is covered by {@link
TestOMStartFinalizeUpgradeRequestBase}; the cases
+ * here exercise the {@code force} flag that is unique to this request.
*/
-public class TestOMStartFinalizeUpgradeRequest extends OMKeyRequestTests {
+public class TestOMStartFinalizeUpgradeRequest extends
TestOMStartFinalizeUpgradeRequestBase {
- @BeforeEach
- public void stubPeerNodes() {
- when(ozoneManager.getPeerNodes()).thenReturn(Collections.emptyList());
- }
-
- @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();
- verify(scmContainerLocationProtocol, never()).forceFinalizeUpgrade();
+ @Override
+ protected OMFinalizeUpgradeRequestBase newRequest() {
+ return new OMStartFinalizeUpgradeRequest(buildRequest(false));
}
@Test
@@ -91,70 +60,6 @@ public void
testForcePreExecuteCallsScmForceFinalizeUpgrade() throws IOException
verify(scmContainerLocationProtocol, never()).finalizeUpgrade();
}
- @Test
- public void testScmFinalizeFailurePropagatesToClient() throws IOException {
- IOException scmFailure = new IOException("SCM finalize upgrade failed");
- doThrow(scmFailure).when(scmContainerLocationProtocol).finalizeUpgrade();
-
- OMStartFinalizeUpgradeRequest request = new
OMStartFinalizeUpgradeRequest(buildRequest());
-
- // The exception raised by SCM must propagate out of preExecute so the OM
- // client sees the failure instead of a successful finalize.
- IOException ex = assertThrows(IOException.class, () ->
request.preExecute(ozoneManager));
- assertSame(scmFailure, ex);
-
- verify(scmContainerLocationProtocol).finalizeUpgrade();
- }
-
- @Test
- public void testScmUnsupportedOperationBecomesOmNotSupportedOperation()
throws IOException {
- SCMException scmFailure =
- new SCMException("SCM version mismatch",
SCMException.ResultCodes.UNSUPPORTED_OPERATION);
- doThrow(scmFailure).when(scmContainerLocationProtocol).finalizeUpgrade();
-
- OMStartFinalizeUpgradeRequest request = new
OMStartFinalizeUpgradeRequest(buildRequest());
-
- // An SCM UNSUPPORTED_OPERATION is re-mapped to an OM
NOT_SUPPORTED_OPERATION,
- // preserving the original message and chaining the SCM exception as the
cause.
- OMException ex = assertThrows(OMException.class, () ->
request.preExecute(ozoneManager));
- assertEquals(OMException.ResultCodes.NOT_SUPPORTED_OPERATION,
ex.getResult());
- assertEquals(scmFailure.getMessage(), ex.getMessage());
- assertSame(scmFailure, ex.getCause());
-
- verify(scmContainerLocationProtocol).finalizeUpgrade();
- }
-
- @Test
- public void testOtherScmExceptionPropagatesUnchanged() throws IOException {
- SCMException scmFailure = new SCMException("SCM is in safe mode",
SCMException.ResultCodes.SAFE_MODE_EXCEPTION);
- doThrow(scmFailure).when(scmContainerLocationProtocol).finalizeUpgrade();
-
- OMStartFinalizeUpgradeRequest request = new
OMStartFinalizeUpgradeRequest(buildRequest());
-
- // Only UNSUPPORTED_OPERATION is re-mapped; any other SCM exception
propagates as-is.
- SCMException ex = assertThrows(SCMException.class, () ->
request.preExecute(ozoneManager));
- assertSame(scmFailure, ex);
-
- 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");
- assertEquals(0, omMetrics.getFinalizationInProgress(),
- "metric should be 0 before the request");
-
- submitRequest();
-
-
assertNotNull(omMetadataManager.getMetaTable().get(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY),
- "key should be present in the cache after validateAndUpdateCache");
- assertEquals(1, omMetrics.getFinalizationInProgress(),
- "metric should be 1 after the request");
- }
-
@Test
public void testAuditMapRecordsForceFlag() throws IOException {
doNothing().when(scmContainerLocationProtocol).finalizeUpgrade();
@@ -171,116 +76,6 @@ public void testAuditMapRecordsForceFlag() throws
IOException {
assertEquals("false", normal.getAuditBuilder().getAuditMap().get("force"));
}
- @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();
- }
-
- @Test
- public void testPeerVersionCheckPassesWhenNoPeers() throws IOException {
- // @BeforeEach already stubs getPeerNodes() to return an empty list.
- // preExecute must complete normally and call SCM finalize.
- doNothing().when(scmContainerLocationProtocol).finalizeUpgrade();
-
- OzoneManagerProtocolProtos.OMRequest original = buildRequest();
- new OMStartFinalizeUpgradeRequest(original).preExecute(ozoneManager);
-
- verify(scmContainerLocationProtocol).finalizeUpgrade();
- }
-
- @Test
- public void testPeerVersionCheckPassesWhenAllPeersMatch() throws IOException
{
- doNothing().when(scmContainerLocationProtocol).finalizeUpgrade();
-
when(ozoneManager.getPeerNodes()).thenReturn(Arrays.asList(buildPeer("om2"),
buildPeer("om3")));
- OMAdminProtocolClientSideImpl matchingClient =
peerClientWithVersion(OzoneManagerVersion.SOFTWARE_VERSION);
-
- try (MockedStatic<OMAdminProtocolClientSideImpl> factory =
- mockStatic(OMAdminProtocolClientSideImpl.class)) {
- factory.when(() ->
OMAdminProtocolClientSideImpl.createProxyForSingleOM(any(), any(), any()))
- .thenReturn(matchingClient);
-
- new
OMStartFinalizeUpgradeRequest(buildRequest()).preExecute(ozoneManager);
- }
-
- verify(scmContainerLocationProtocol).finalizeUpgrade();
- }
-
- @Test
- public void testPeerVersionCheckRejectsOneOlderPeer() throws IOException {
-
when(ozoneManager.getPeerNodes()).thenReturn(Arrays.asList(buildPeer("om2"),
buildPeer("om3")));
- OMAdminProtocolClientSideImpl matchingClient =
peerClientWithVersion(OzoneManagerVersion.SOFTWARE_VERSION);
- OMAdminProtocolClientSideImpl olderClient =
peerClientWithVersion(OzoneManagerVersion.HBASE_SUPPORT);
-
- try (MockedStatic<OMAdminProtocolClientSideImpl> factory =
- mockStatic(OMAdminProtocolClientSideImpl.class)) {
- factory.when(() ->
OMAdminProtocolClientSideImpl.createProxyForSingleOM(any(), any(), any()))
- .thenReturn(matchingClient, olderClient);
-
- OMException ex = assertThrows(OMException.class,
- () -> new
OMStartFinalizeUpgradeRequest(buildRequest()).preExecute(ozoneManager));
- assertEquals(OMException.ResultCodes.NOT_SUPPORTED_OPERATION,
ex.getResult());
- }
-
- verify(scmContainerLocationProtocol, never()).finalizeUpgrade();
- }
-
- @Test
- public void testPeerVersionCheckRejectsOneUnknownFuturePeer() throws
IOException {
-
when(ozoneManager.getPeerNodes()).thenReturn(Arrays.asList(buildPeer("om2"),
buildPeer("om3")));
- OMAdminProtocolClientSideImpl matchingClient =
peerClientWithVersion(OzoneManagerVersion.SOFTWARE_VERSION);
- OMAdminProtocolClientSideImpl unknownClient =
peerClientWithVersion(OzoneManagerVersion.UNKNOWN_VERSION);
-
- try (MockedStatic<OMAdminProtocolClientSideImpl> factory =
- mockStatic(OMAdminProtocolClientSideImpl.class)) {
- factory.when(() ->
OMAdminProtocolClientSideImpl.createProxyForSingleOM(any(), any(), any()))
- .thenReturn(matchingClient, unknownClient);
-
- OMException ex = assertThrows(OMException.class,
- () -> new
OMStartFinalizeUpgradeRequest(buildRequest()).preExecute(ozoneManager));
- assertEquals(OMException.ResultCodes.NOT_SUPPORTED_OPERATION,
ex.getResult());
- }
-
- verify(scmContainerLocationProtocol, never()).finalizeUpgrade();
- }
-
- @Test
- public void testPeerVersionCheckRejectsUnreachablePeer() throws IOException {
-
when(ozoneManager.getPeerNodes()).thenReturn(Collections.singletonList(buildPeer("om2")));
- OMAdminProtocolClientSideImpl unreachableClient =
mock(OMAdminProtocolClientSideImpl.class);
- when(unreachableClient.getPeerUpgradeStatus()).thenThrow(new
IOException("connection refused"));
-
- try (MockedStatic<OMAdminProtocolClientSideImpl> factory =
- mockStatic(OMAdminProtocolClientSideImpl.class)) {
- factory.when(() ->
OMAdminProtocolClientSideImpl.createProxyForSingleOM(any(), any(), any()))
- .thenReturn(unreachableClient);
-
- OMException ex = assertThrows(OMException.class,
- () -> new
OMStartFinalizeUpgradeRequest(buildRequest()).preExecute(ozoneManager));
- assertEquals(OMException.ResultCodes.NOT_SUPPORTED_OPERATION,
ex.getResult());
- }
-
- verify(scmContainerLocationProtocol, never()).finalizeUpgrade();
- }
-
@Test
public void testForceSkipsPeerVersionCheckForUnreachablePeer() throws
IOException {
doNothing().when(scmContainerLocationProtocol).finalizeUpgrade();
@@ -324,36 +119,6 @@ public void
testForceSkipsPeerVersionCheckForMismatchedPeer() throws IOException
verify(scmContainerLocationProtocol, never()).finalizeUpgrade();
}
- private static OMNodeDetails buildPeer(String nodeId) {
- return new OMNodeDetails.Builder()
- .setOMServiceId("testService")
- .setOMNodeId(nodeId)
- .setHostAddress("127.0.0.1")
- .setRpcPort(1)
- .build();
- }
-
- private static OMAdminProtocolClientSideImpl
peerClientWithVersion(OzoneManagerVersion version) throws IOException {
- OMAdminProtocolClientSideImpl client =
mock(OMAdminProtocolClientSideImpl.class);
- when(client.getPeerUpgradeStatus()).thenReturn(version);
- return client;
- }
-
- 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 buildRequest(false);
- }
-
private OzoneManagerProtocolProtos.OMRequest buildRequest(boolean force) {
return OzoneManagerProtocolProtos.OMRequest.newBuilder()
.setCmdType(OzoneManagerProtocolProtos.Type.StartFinalizeUpgrade)
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/TestOMStartFinalizeUpgradeRequestBase.java
similarity index 63%
copy from
hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/upgrade/TestOMStartFinalizeUpgradeRequest.java
copy to
hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/upgrade/TestOMStartFinalizeUpgradeRequestBase.java
index 88746f0308a..47cb54c6a77 100644
---
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/TestOMStartFinalizeUpgradeRequestBase.java
@@ -23,6 +23,7 @@
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
@@ -36,6 +37,7 @@
import java.util.Arrays;
import java.util.Collections;
import org.apache.hadoop.hdds.scm.exceptions.SCMException;
+import org.apache.hadoop.hdds.utils.db.BatchOperation;
import org.apache.hadoop.ozone.OzoneConsts;
import org.apache.hadoop.ozone.OzoneManagerVersion;
import org.apache.hadoop.ozone.om.exceptions.OMException;
@@ -44,59 +46,62 @@
import org.apache.hadoop.ozone.om.protocolPB.OMAdminProtocolClientSideImpl;
import org.apache.hadoop.ozone.om.request.key.OMKeyRequestTests;
import org.apache.hadoop.ozone.om.response.OMClientResponse;
-import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
+import org.apache.hadoop.ozone.om.upgrade.OMVersionManager;
+import org.apache.hadoop.ozone.om.upgrade.OMVersionManagerTestUtils;
+import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.ratis.protocol.ClientId;
import org.apache.ratis.server.protocol.TermIndex;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
/**
- * Tests for OMStartFinalizeUpgradeRequest.
+ * Shared tests for the client-initiated finalize requests handled by
+ * {@link OMFinalizeUpgradeRequestBase}: admin authorization, SCM finalization
+ * triggering and error mapping, OM peer software version validation, and
writing
+ * the finalization-in-progress marker. Subclasses supply the concrete request
via
+ * {@link #newRequest()} and add tests for behavior unique to their command
type.
*/
-public class TestOMStartFinalizeUpgradeRequest extends OMKeyRequestTests {
+public abstract class TestOMStartFinalizeUpgradeRequestBase extends
OMKeyRequestTests {
+
+ /**
+ * A fresh, non-forced initiate request for the command type under test.
+ */
+ protected abstract OMFinalizeUpgradeRequestBase newRequest();
@BeforeEach
- public void stubPeerNodes() {
+ public void mockPreFinalizedOM() {
when(ozoneManager.getPeerNodes()).thenReturn(Collections.emptyList());
+ // A finalize request models a cluster that still needs finalization; the
parent test harness defaults to a
+ // finalized version manager, which is the special already-finalized case
exercised separately below.
+ OMVersionManager versionManager =
OMVersionManagerTestUtils.mockPreFinalizedOmVersionManager();
+ when(ozoneManager.getVersionManager()).thenReturn(versionManager);
}
@Test
public void testPreExecuteCallsScmFinalizeUpgrade() throws IOException {
doNothing().when(scmContainerLocationProtocol).finalizeUpgrade();
- OzoneManagerProtocolProtos.OMRequest original = buildRequest();
- OMStartFinalizeUpgradeRequest request = new
OMStartFinalizeUpgradeRequest(original);
+ OMFinalizeUpgradeRequestBase request = newRequest();
+ OMRequest original = request.getOmRequest();
- OzoneManagerProtocolProtos.OMRequest modified =
request.preExecute(ozoneManager);
+ 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.
+ // A non-forced initiate request must route to SCM's non-force finalize
path.
verify(scmContainerLocationProtocol).finalizeUpgrade();
verify(scmContainerLocationProtocol, never()).forceFinalizeUpgrade();
}
- @Test
- public void testForcePreExecuteCallsScmForceFinalizeUpgrade() throws
IOException {
- OMStartFinalizeUpgradeRequest request = new
OMStartFinalizeUpgradeRequest(buildRequest(true));
-
- request.preExecute(ozoneManager);
-
- // A forced request must route to SCM's force path so SCM skips its own
version checks.
- verify(scmContainerLocationProtocol).forceFinalizeUpgrade();
- verify(scmContainerLocationProtocol, never()).finalizeUpgrade();
- }
-
@Test
public void testScmFinalizeFailurePropagatesToClient() throws IOException {
IOException scmFailure = new IOException("SCM finalize upgrade failed");
doThrow(scmFailure).when(scmContainerLocationProtocol).finalizeUpgrade();
- OMStartFinalizeUpgradeRequest request = new
OMStartFinalizeUpgradeRequest(buildRequest());
+ OMFinalizeUpgradeRequestBase request = newRequest();
// The exception raised by SCM must propagate out of preExecute so the OM
// client sees the failure instead of a successful finalize.
@@ -112,7 +117,7 @@ public void
testScmUnsupportedOperationBecomesOmNotSupportedOperation() throws I
new SCMException("SCM version mismatch",
SCMException.ResultCodes.UNSUPPORTED_OPERATION);
doThrow(scmFailure).when(scmContainerLocationProtocol).finalizeUpgrade();
- OMStartFinalizeUpgradeRequest request = new
OMStartFinalizeUpgradeRequest(buildRequest());
+ OMFinalizeUpgradeRequestBase request = newRequest();
// An SCM UNSUPPORTED_OPERATION is re-mapped to an OM
NOT_SUPPORTED_OPERATION,
// preserving the original message and chaining the SCM exception as the
cause.
@@ -129,7 +134,7 @@ public void testOtherScmExceptionPropagatesUnchanged()
throws IOException {
SCMException scmFailure = new SCMException("SCM is in safe mode",
SCMException.ResultCodes.SAFE_MODE_EXCEPTION);
doThrow(scmFailure).when(scmContainerLocationProtocol).finalizeUpgrade();
- OMStartFinalizeUpgradeRequest request = new
OMStartFinalizeUpgradeRequest(buildRequest());
+ OMFinalizeUpgradeRequestBase request = newRequest();
// Only UNSUPPORTED_OPERATION is re-mapped; any other SCM exception
propagates as-is.
SCMException ex = assertThrows(SCMException.class, () ->
request.preExecute(ozoneManager));
@@ -138,46 +143,12 @@ public void testOtherScmExceptionPropagatesUnchanged()
throws IOException {
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");
- assertEquals(0, omMetrics.getFinalizationInProgress(),
- "metric should be 0 before the request");
-
- submitRequest();
-
-
assertNotNull(omMetadataManager.getMetaTable().get(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY),
- "key should be present in the cache after validateAndUpdateCache");
- assertEquals(1, omMetrics.getFinalizationInProgress(),
- "metric should be 1 after the request");
- }
-
- @Test
- public void testAuditMapRecordsForceFlag() throws IOException {
- doNothing().when(scmContainerLocationProtocol).finalizeUpgrade();
- ExecutionContext context = ExecutionContext.of(1, TermIndex.INITIAL_VALUE);
-
- OMStartFinalizeUpgradeRequest forced = new
OMStartFinalizeUpgradeRequest(buildRequest(true));
- forced.preExecute(ozoneManager);
- forced.validateAndUpdateCache(ozoneManager, context);
- assertEquals("true", forced.getAuditBuilder().getAuditMap().get("force"));
-
- OMStartFinalizeUpgradeRequest normal = new
OMStartFinalizeUpgradeRequest(buildRequest(false));
- normal.preExecute(ozoneManager);
- normal.validateAndUpdateCache(ozoneManager, context);
- assertEquals("false", normal.getAuditBuilder().getAuditMap().get("force"));
- }
-
@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);
+ OMFinalizeUpgradeRequestBase request = newRequest();
// 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
@@ -186,8 +157,7 @@ public void testAccessDeniedWhenUserIsNotAdmin() throws
IOException {
// 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));
+ OMException ex = assertThrows(OMException.class, () ->
request.preExecute(ozoneManager));
assertEquals(OMException.ResultCodes.ACCESS_DENIED, ex.getResult(),
"non-admin user should receive ACCESS_DENIED from preExecute");
@@ -197,12 +167,11 @@ public void testAccessDeniedWhenUserIsNotAdmin() throws
IOException {
@Test
public void testPeerVersionCheckPassesWhenNoPeers() throws IOException {
- // @BeforeEach already stubs getPeerNodes() to return an empty list.
+ assertTrue(ozoneManager.getPeerNodes().isEmpty());
// preExecute must complete normally and call SCM finalize.
doNothing().when(scmContainerLocationProtocol).finalizeUpgrade();
- OzoneManagerProtocolProtos.OMRequest original = buildRequest();
- new OMStartFinalizeUpgradeRequest(original).preExecute(ozoneManager);
+ newRequest().preExecute(ozoneManager);
verify(scmContainerLocationProtocol).finalizeUpgrade();
}
@@ -218,7 +187,7 @@ public void testPeerVersionCheckPassesWhenAllPeersMatch()
throws IOException {
factory.when(() ->
OMAdminProtocolClientSideImpl.createProxyForSingleOM(any(), any(), any()))
.thenReturn(matchingClient);
- new
OMStartFinalizeUpgradeRequest(buildRequest()).preExecute(ozoneManager);
+ newRequest().preExecute(ozoneManager);
}
verify(scmContainerLocationProtocol).finalizeUpgrade();
@@ -235,8 +204,7 @@ public void testPeerVersionCheckRejectsOneOlderPeer()
throws IOException {
factory.when(() ->
OMAdminProtocolClientSideImpl.createProxyForSingleOM(any(), any(), any()))
.thenReturn(matchingClient, olderClient);
- OMException ex = assertThrows(OMException.class,
- () -> new
OMStartFinalizeUpgradeRequest(buildRequest()).preExecute(ozoneManager));
+ OMException ex = assertThrows(OMException.class, () ->
newRequest().preExecute(ozoneManager));
assertEquals(OMException.ResultCodes.NOT_SUPPORTED_OPERATION,
ex.getResult());
}
@@ -254,8 +222,7 @@ public void
testPeerVersionCheckRejectsOneUnknownFuturePeer() throws IOException
factory.when(() ->
OMAdminProtocolClientSideImpl.createProxyForSingleOM(any(), any(), any()))
.thenReturn(matchingClient, unknownClient);
- OMException ex = assertThrows(OMException.class,
- () -> new
OMStartFinalizeUpgradeRequest(buildRequest()).preExecute(ozoneManager));
+ OMException ex = assertThrows(OMException.class, () ->
newRequest().preExecute(ozoneManager));
assertEquals(OMException.ResultCodes.NOT_SUPPORTED_OPERATION,
ex.getResult());
}
@@ -273,8 +240,7 @@ public void testPeerVersionCheckRejectsUnreachablePeer()
throws IOException {
factory.when(() ->
OMAdminProtocolClientSideImpl.createProxyForSingleOM(any(), any(), any()))
.thenReturn(unreachableClient);
- OMException ex = assertThrows(OMException.class,
- () -> new
OMStartFinalizeUpgradeRequest(buildRequest()).preExecute(ozoneManager));
+ OMException ex = assertThrows(OMException.class, () ->
newRequest().preExecute(ozoneManager));
assertEquals(OMException.ResultCodes.NOT_SUPPORTED_OPERATION,
ex.getResult());
}
@@ -282,49 +248,84 @@ public void testPeerVersionCheckRejectsUnreachablePeer()
throws IOException {
}
@Test
- public void testForceSkipsPeerVersionCheckForUnreachablePeer() throws
IOException {
+ public void testValidateAndUpdateCacheAddsFinalizationInProgressKey() throws
IOException {
doNothing().when(scmContainerLocationProtocol).finalizeUpgrade();
-
when(ozoneManager.getPeerNodes()).thenReturn(Collections.singletonList(buildPeer("om2")));
- OMAdminProtocolClientSideImpl unreachableClient =
mock(OMAdminProtocolClientSideImpl.class);
- when(unreachableClient.getPeerUpgradeStatus()).thenThrow(new
IOException("connection refused"));
- try (MockedStatic<OMAdminProtocolClientSideImpl> factory =
- mockStatic(OMAdminProtocolClientSideImpl.class)) {
- factory.when(() ->
OMAdminProtocolClientSideImpl.createProxyForSingleOM(any(), any(), any()))
- .thenReturn(unreachableClient);
+
assertNull(omMetadataManager.getMetaTable().get(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY),
+ "key should not exist before the request");
+ assertEquals(0, omMetrics.getFinalizationInProgress(),
+ "metric should be 0 before the request");
- // With force=true the peer version check is skipped, so an unreachable
peer does not
- // prevent finalization and SCM is still asked to force finalization
(skipping its own checks).
- new
OMStartFinalizeUpgradeRequest(buildRequest(true)).preExecute(ozoneManager);
- }
+ OMClientResponse response = submitRequest();
- verify(unreachableClient, never()).getPeerUpgradeStatus();
- verify(scmContainerLocationProtocol).forceFinalizeUpgrade();
- verify(scmContainerLocationProtocol, never()).finalizeUpgrade();
+
assertNotNull(omMetadataManager.getMetaTable().get(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY),
+ "key should be present in the cache after validateAndUpdateCache");
+ assertEquals(1, omMetrics.getFinalizationInProgress(),
+ "metric should be 1 after the request");
+
+ // Applying the response as the double buffer would must also persist the
marker to the DB.
+ flushResponseToDb(response);
+ assertEquals("ignored",
omMetadataManager.getMetaTable().getSkipCache(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY),
+ "key should be persisted to the DB after the response is flushed");
}
@Test
- public void testForceSkipsPeerVersionCheckForMismatchedPeer() throws
IOException {
+ public void testValidateAndUpdateCacheSkipsMarkerWhenAlreadyFinalized()
throws IOException {
doNothing().when(scmContainerLocationProtocol).finalizeUpgrade();
-
when(ozoneManager.getPeerNodes()).thenReturn(Collections.singletonList(buildPeer("om2")));
- OMAdminProtocolClientSideImpl olderClient =
peerClientWithVersion(OzoneManagerVersion.HBASE_SUPPORT);
+ // Simulate an admin initiating finalize on a cluster that is already
finalized.
+ OMVersionManager finalizedVersionManager =
OMVersionManagerTestUtils.mockFinalizedOmVersionManager();
+ when(ozoneManager.getVersionManager()).thenReturn(finalizedVersionManager);
- try (MockedStatic<OMAdminProtocolClientSideImpl> factory =
- mockStatic(OMAdminProtocolClientSideImpl.class)) {
- factory.when(() ->
OMAdminProtocolClientSideImpl.createProxyForSingleOM(any(), any(), any()))
- .thenReturn(olderClient);
+
assertNull(omMetadataManager.getMetaTable().get(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY),
+ "key should not exist before the request");
+ assertEquals(0, omMetrics.getFinalizationInProgress(),
+ "metric should be 0 before the request");
+
+ OMClientResponse response = submitRequest();
- // With force=true the peer version check is skipped, so a peer running
a different software
- // version does not prevent finalization and SCM is still asked to force
finalization.
- new
OMStartFinalizeUpgradeRequest(buildRequest(true)).preExecute(ozoneManager);
+ // The marker and metric must NOT be set: OMUpgradeFinalizeService would
shut down because needsFinalization()
+ // is false and would never clear a marker written here, leaving it and
the metric stuck.
+
assertNull(omMetadataManager.getMetaTable().get(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY),
+ "key must not be written when the cluster is already finalized");
+ assertEquals(0, omMetrics.getFinalizationInProgress(),
+ "metric must remain 0 when the cluster is already finalized");
+ // Finalizing an already-finalized cluster is a successful no-op.
+ assertTrue(response.getOMResponse().getSuccess(),
+ "response should still report success for an already-finalized
cluster");
+
+ // Even the success response must not persist the marker when the double
buffer flushes; otherwise it would be
+ // orphaned in the DB.
+ flushResponseToDb(response);
+
assertNull(omMetadataManager.getMetaTable().getSkipCache(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY),
+ "key must not be persisted to the DB when the cluster is already
finalized");
+ }
+
+ /**
+ * Applies the response to the DB the way the OM double buffer does on
flush: status-gated addToDBBatch followed by
+ * a batch commit.
+ */
+ private void flushResponseToDb(OMClientResponse response) throws IOException
{
+ try (BatchOperation batch =
omMetadataManager.getStore().initBatchOperation()) {
+ response.checkAndUpdateDB(omMetadataManager, batch);
+ omMetadataManager.getStore().commitBatchOperation(batch);
}
+ }
- verify(olderClient, never()).getPeerUpgradeStatus();
- verify(scmContainerLocationProtocol).forceFinalizeUpgrade();
- verify(scmContainerLocationProtocol, never()).finalizeUpgrade();
+ /**
+ * Runs {@link #newRequest()} through preExecute and validateAndUpdateCache,
returning the response.
+ */
+ protected OMClientResponse submitRequest() throws IOException {
+ OMFinalizeUpgradeRequestBase request = newRequest();
+ OMRequest original = request.getOmRequest();
+ ExecutionContext context = ExecutionContext.of(1, TermIndex.INITIAL_VALUE);
+
+ OMRequest modified = request.preExecute(ozoneManager);
+ assertNotEquals(original, modified);
+
+ return request.validateAndUpdateCache(ozoneManager, context);
}
- private static OMNodeDetails buildPeer(String nodeId) {
+ protected static OMNodeDetails buildPeer(String nodeId) {
return new OMNodeDetails.Builder()
.setOMServiceId("testService")
.setOMNodeId(nodeId)
@@ -333,33 +334,9 @@ private static OMNodeDetails buildPeer(String nodeId) {
.build();
}
- private static OMAdminProtocolClientSideImpl
peerClientWithVersion(OzoneManagerVersion version) throws IOException {
+ protected static OMAdminProtocolClientSideImpl
peerClientWithVersion(OzoneManagerVersion version) throws IOException {
OMAdminProtocolClientSideImpl client =
mock(OMAdminProtocolClientSideImpl.class);
when(client.getPeerUpgradeStatus()).thenReturn(version);
return client;
}
-
- 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 buildRequest(false);
- }
-
- private OzoneManagerProtocolProtos.OMRequest buildRequest(boolean force) {
- return OzoneManagerProtocolProtos.OMRequest.newBuilder()
- .setCmdType(OzoneManagerProtocolProtos.Type.StartFinalizeUpgrade)
- .setClientId(ClientId.randomId().toString())
-
.setStartFinalizeUpgradeRequest(OzoneManagerProtocolProtos.StartFinalizeUpgradeRequest.newBuilder()
- .setForce(force))
- .build();
- }
}
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/upgrade/TestOMStartFinalizeUpgradeRequestLegacy.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/upgrade/TestOMStartFinalizeUpgradeRequestLegacy.java
new file mode 100644
index 00000000000..28451c6931f
--- /dev/null
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/upgrade/TestOMStartFinalizeUpgradeRequestLegacy.java
@@ -0,0 +1,63 @@
+/*
+ * 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.mockito.Mockito.doNothing;
+
+import java.io.IOException;
+import
org.apache.hadoop.hdds.protocol.proto.HddsProtos.UpgradeFinalizationStatus;
+import org.apache.hadoop.ozone.om.response.OMClientResponse;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
+import
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
+import org.apache.ratis.protocol.ClientId;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for OMStartFinalizeUpgradeRequestLegacy, the old CLI ({@code ozone
admin om finalizeupgrade}) initiate
+ * request. Shared initiate behavior is covered by {@link
TestOMStartFinalizeUpgradeRequestBase}; the case here
+ * asserts the {@code STARTING_FINALIZATION} response the old CLI requires
before it polls progress.
+ */
+public class TestOMStartFinalizeUpgradeRequestLegacy extends
TestOMStartFinalizeUpgradeRequestBase {
+
+ @Override
+ protected OMFinalizeUpgradeRequestBase newRequest() {
+ return new OMStartFinalizeUpgradeRequestLegacy(buildRequest());
+ }
+
+ @Test
+ public void testValidateAndUpdateCacheReturnsStartingFinalization() throws
IOException {
+ doNothing().when(scmContainerLocationProtocol).finalizeUpgrade();
+
+ OMClientResponse response = submitRequest();
+ OMResponse omResponse = response.getOMResponse();
+
+ // The old CLI requires STARTING_FINALIZATION back before it polls
progress.
+ assertEquals(UpgradeFinalizationStatus.Status.STARTING_FINALIZATION,
+ omResponse.getFinalizeUpgradeResponse().getStatus().getStatus());
+ }
+
+ private OzoneManagerProtocolProtos.OMRequest buildRequest() {
+ return OzoneManagerProtocolProtos.OMRequest.newBuilder()
+ .setCmdType(OzoneManagerProtocolProtos.Type.FinalizeUpgrade)
+ .setClientId(ClientId.randomId().toString())
+
.setFinalizeUpgradeRequest(OzoneManagerProtocolProtos.FinalizeUpgradeRequest.newBuilder()
+ .setUpgradeClientId("client-id"))
+ .build();
+ }
+}
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/upgrade/TestOMFinalizeUpgradeResponse.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/upgrade/TestOMCompleteFinalizeUpgradeResponse.java
similarity index 90%
rename from
hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/upgrade/TestOMFinalizeUpgradeResponse.java
rename to
hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/upgrade/TestOMCompleteFinalizeUpgradeResponse.java
index 15ad3c848b5..0546b1ac96c 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/upgrade/TestOMFinalizeUpgradeResponse.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/upgrade/TestOMCompleteFinalizeUpgradeResponse.java
@@ -34,9 +34,9 @@
import org.junit.jupiter.api.io.TempDir;
/**
- * Tests for the OMFinalizeUpgradeResponse class.
+ * Tests for the OMCompleteFinalizeUpgradeResponse class.
*/
-public class TestOMFinalizeUpgradeResponse {
+public class TestOMCompleteFinalizeUpgradeResponse {
@TempDir
private Path folder;
@@ -60,7 +60,8 @@ public void testFinalizationInProgressKeyRemoved() throws
IOException {
String value =
omMetadataManager.getMetaTable().get(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY);
assertEquals("ignored", value);
- OMFinalizeUpgradeResponse finalizeUpgradeResponse = new
OMFinalizeUpgradeResponse(createRequest(), 1);
+ OMCompleteFinalizeUpgradeResponse finalizeUpgradeResponse =
+ new OMCompleteFinalizeUpgradeResponse(createRequest(), 1);
finalizeUpgradeResponse.addToDBBatch(omMetadataManager, batchOperation);
omMetadataManager.getStore().commitBatchOperation(batchOperation);
@@ -72,7 +73,7 @@ public void testFinalizationInProgressKeyRemoved() throws
IOException {
private OzoneManagerProtocolProtos.OMResponse createRequest() {
return OzoneManagerProtocolProtos.OMResponse.newBuilder()
- .setCmdType(OzoneManagerProtocolProtos.Type.FinalizeUpgrade)
+ .setCmdType(OzoneManagerProtocolProtos.Type.CompleteFinalizeUpgrade)
.setStatus(OzoneManagerProtocolProtos.Status.OK)
.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
index b5564218513..b3c8b1af85d 100644
---
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
@@ -66,6 +66,21 @@ public void
testAddToDBBatchPersistsFinalizationInProgressKey() throws IOExcepti
"key should be persisted to the meta table after the response is
committed");
}
+ @Test
+ public void testAddToDBBatchSkipsPersistWhenFinalizationNotNeeded() throws
IOException {
+
assertNull(omMetadataManager.getMetaTable().get(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY),
+ "key should not exist before the response is applied");
+
+ // finalizationNeeded=false models initiating finalize on an
already-finalized cluster: the key must not be
+ // persisted, otherwise it would be orphaned since
OMUpgradeFinalizeService never clears it.
+ OMStartFinalizeUpgradeResponse response = new
OMStartFinalizeUpgradeResponse(buildOkResponse(), false);
+ response.addToDBBatch(omMetadataManager, batchOperation);
+ omMetadataManager.getStore().commitBatchOperation(batchOperation);
+
+
assertNull(omMetadataManager.getMetaTable().get(OzoneConsts.FINALIZATION_IN_PROGRESS_KEY),
+ "key must not be persisted when finalization is not needed");
+ }
+
private OzoneManagerProtocolProtos.OMResponse buildOkResponse() {
return OzoneManagerProtocolProtos.OMResponse.newBuilder()
.setCmdType(OzoneManagerProtocolProtos.Type.StartFinalizeUpgrade)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]