From 82f381573616a646ca67e46c95793c7490fe00b8 Mon Sep 17 00:00:00 2001 From: Ethan Rose Date: Mon, 20 Apr 2026 16:45:27 -0400 Subject: [PATCH 1/7] HDDS-14496. Version managers, snapshot layout-version join points, and small cleanups - Add ComponentVersionManager / HDDSVersionManager / OMVersionManager and related upgrade framework pieces (no OM production wiring). - Move @DisallowedUntilLayoutVersion onto preExecute for snapshot move requests; minor DN/doc/repair/freon cleanups. - Include HDDS-side renames and SCM wiring updates that accompany the version-manager refactor (no functional change on the HDDS side). - Keep LayoutVersionManager + AbstractLayoutVersionManager implementing it until OM wiring PR (HDDS matches feature except those two files). - Include OM wire-compatibility/doc/deprecation proto tweaks, OMStorage apparent-version init alignment, finalize-upgrade response naming, and a comment clarification in OzoneManagerRequestHandler (no OM prod wiring). --- .../ComponentUpgradeActionProvider.java | 38 ++++ .../ozone/upgrade/UpgradeException.java | 8 +- .../ozone/upgrade/UpgradeFinalization.java | 9 +- .../common/helpers/DatanodeIdYaml.java | 2 +- .../statemachine/DatanodeStateMachine.java | 2 +- .../upgrade/DataNodeUpgradeFinalizer.java | 2 +- .../docs/content/design/upgrade-dev-primer.md | 10 +- .../hdds/upgrade/HDDSVersionManager.java | 38 ++-- .../apache/hadoop/ozone/common/Storage.java | 19 +- .../hadoop/ozone/common/StorageInfo.java | 25 +-- .../ozone/upgrade/BasicUpgradeFinalizer.java | 12 +- .../upgrade/ComponentVersionManager.java | 74 +++++--- .../hdds/upgrade/TestHDDSVersionManager.java | 22 ++- .../AbstractComponentVersionManagerTest.java | 64 +++---- .../upgrade/TestBasicUpgradeFinalizer.java | 6 +- .../hdds/scm/server/SCMStorageConfig.java | 2 +- .../scm/server/StorageContainerManager.java | 6 +- .../server/upgrade/SCMUpgradeFinalizer.java | 2 +- .../hdds/scm/node/TestSCMNodeManager.java | 6 +- ...TestScmStartupInvalidApparentVersion.java} | 67 +++---- .../datanode/schemaupgrade/UpgradeUtils.java | 2 +- .../hadoop/ozone/freon/DatanodeSimulator.java | 2 +- .../src/main/proto/OmClientProtocol.proto | 8 +- .../org/apache/hadoop/ozone/om/OMStorage.java | 6 +- .../OMSnapshotMoveDeletedKeysRequest.java | 5 + .../OMSnapshotMoveTableKeysRequest.java | 2 +- .../upgrade/OMFinalizeUpgradeResponse.java | 13 +- .../om/upgrade/OMUpgradeActionProvider.java | 80 +++++++++ .../ozone/om/upgrade/OMVersionManager.java | 109 ++++++++++-- .../OzoneManagerRequestHandler.java | 2 +- .../om/upgrade/OMVersionManagerTestUtils.java | 48 +++++ .../om/upgrade/TestOMVersionManager.java | 168 +++++++++++++++++- 32 files changed, 656 insertions(+), 203 deletions(-) create mode 100644 hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/upgrade/ComponentUpgradeActionProvider.java rename hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/upgrade/{TestScmStartupSlvLessThanMlv.java => TestScmStartupInvalidApparentVersion.java} (52%) create mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMUpgradeActionProvider.java create mode 100644 hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/OMVersionManagerTestUtils.java diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/upgrade/ComponentUpgradeActionProvider.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/upgrade/ComponentUpgradeActionProvider.java new file mode 100644 index 000000000000..bf2a8543d165 --- /dev/null +++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/upgrade/ComponentUpgradeActionProvider.java @@ -0,0 +1,38 @@ +/* + * 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.upgrade; + +import java.util.Map; +import org.apache.hadoop.hdds.ComponentVersion; + +/** + * Supplies upgrade actions keyed by {@link ComponentVersion}. Implementations typically perform classpath scanning or + * return a fixed map for tests. The component version manager decides when each action is invoked. + * + * @param concrete upgrade action type (for example OM-specific or HDDS-specific) + */ +@FunctionalInterface +public interface ComponentUpgradeActionProvider { + + /** + * Returns all upgrade actions from this provider, keyed by component version. + *

+ * Implementations must return a newly allocated map on each call; the caller may retain and use it directly. + */ + Map load(); +} diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/upgrade/UpgradeException.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/upgrade/UpgradeException.java index 20a7d02d178f..ebdd7d730037 100644 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/upgrade/UpgradeException.java +++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/upgrade/UpgradeException.java @@ -106,10 +106,8 @@ public String toString() { public enum ResultCodes { OK, INVALID_REQUEST, - UPDATE_LAYOUT_VERSION_FAILED, - LAYOUT_FEATURE_FINALIZATION_FAILED, - PREFINALIZE_ACTION_VALIDATION_FAILED, - FIRST_UPGRADE_START_ACTION_FAILED, - PREFINALIZE_VALIDATION_FAILED; + APPARENT_VERSION_UPDATE_FAILED, + UPGRADE_FINALIZATION_FAILED, + FINALIZE_UPGRADE_ACTION_FAILED, } } diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/upgrade/UpgradeFinalization.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/upgrade/UpgradeFinalization.java index 218a09b6edc5..846ff28bdb4f 100644 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/upgrade/UpgradeFinalization.java +++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/upgrade/UpgradeFinalization.java @@ -49,12 +49,19 @@ public final class UpgradeFinalization { ); /** - * Default message to provide when the service is in ALREADY_FINALIZED state. + * Returned from finalize upgrade commands when finalization is not required. */ public static final StatusAndMessages FINALIZED_MSG = new StatusAndMessages( Status.ALREADY_FINALIZED, Collections.emptyList() ); + /** + * Returned from progress/status queries when finalization is not required. + */ + public static final StatusAndMessages FINALIZATION_DONE_MSG = new StatusAndMessages( + Status.FINALIZATION_DONE, Collections.emptyList() + ); + /** * Represents the current state in which the service is with regards to * finalization after an upgrade. diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/DatanodeIdYaml.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/DatanodeIdYaml.java index 07bdedb4398e..d45623f36bb1 100644 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/DatanodeIdYaml.java +++ b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/DatanodeIdYaml.java @@ -261,7 +261,7 @@ private static DatanodeDetailsYaml getDatanodeDetailsYaml( HDDSLayoutFeature layoutFeature = f.getAnnotation(BelongsToHDDSLayoutVersion.class).value(); if (layoutFeature.layoutVersion() > - datanodeLayoutStorage.getLayoutVersion()) { + datanodeLayoutStorage.getApparentVersion()) { continue; } } diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/DatanodeStateMachine.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/DatanodeStateMachine.java index 2f53178e9bf9..5263b7b87a66 100644 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/DatanodeStateMachine.java +++ b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/DatanodeStateMachine.java @@ -168,7 +168,7 @@ public DatanodeStateMachine(HddsDatanodeService hddsDatanodeService, datanodeDetails.getUuidString()); layoutVersionManager = new HDDSLayoutVersionManager( - layoutStorage.getLayoutVersion()); + layoutStorage.getApparentVersion()); upgradeFinalizer = new DataNodeUpgradeFinalizer(layoutVersionManager); VersionedDatanodeFeatures.initialize(layoutVersionManager); diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/upgrade/DataNodeUpgradeFinalizer.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/upgrade/DataNodeUpgradeFinalizer.java index 769d556643cd..7fd352ac0f27 100644 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/upgrade/DataNodeUpgradeFinalizer.java +++ b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/upgrade/DataNodeUpgradeFinalizer.java @@ -47,7 +47,7 @@ public void finalizeLayoutFeature(LayoutFeature layoutFeature, String msg = String.format("Failed to finalize datanode layout feature " + "%s. It is not an HDDS Layout Feature.", layoutFeature); throw new UpgradeException(msg, - UpgradeException.ResultCodes.LAYOUT_FEATURE_FINALIZATION_FAILED); + UpgradeException.ResultCodes.UPGRADE_FINALIZATION_FAILED); } } } diff --git a/hadoop-hdds/docs/content/design/upgrade-dev-primer.md b/hadoop-hdds/docs/content/design/upgrade-dev-primer.md index 13f6f5a683d7..8934e412f8a5 100644 --- a/hadoop-hdds/docs/content/design/upgrade-dev-primer.md +++ b/hadoop-hdds/docs/content/design/upgrade-dev-primer.md @@ -36,13 +36,11 @@ Downgrade to a lower version is allowed from the pre-finalized state. This invol org.apache.hadoop.hdds.upgrade.HDDSLayoutFeature Class to add a new layout feature being brought in. Layout version is typically 1 + last layout feature in that catalog. -## LayoutVersionManager - org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager - org.apache.hadoop.hdds.upgrade.HDDSLayoutVersionManager -Every component carries an instance of this interface, which provides APIs to get runtime layout version, and if a feature is allowed based on that or not. +## Version management (OM vs HDDS) -The LayoutVersionManager interface carries an API that can be used to check if a feature is allowed in the current layout version. - org.apache.hadoop.ozone.upgrade.LayoutVersionManager#isAllowed(org.apache.hadoop.ozone.upgrade.LayoutFeature) +**Ozone Manager** uses [`org.apache.hadoop.ozone.om.upgrade.OMVersionManager`](https://github.com/apache/ozone/blob/master/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMVersionManager.java) ([`org.apache.hadoop.ozone.upgrade.ComponentVersionManager`](https://github.com/apache/ozone/blob/master/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/ComponentVersionManager.java)), with upgrade actions discovered via [`org.apache.hadoop.ozone.om.upgrade.OMUpgradeActionProvider`](https://github.com/apache/ozone/blob/master/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMUpgradeActionProvider.java). It exposes apparent/software `ComponentVersion` and `isAllowed(ComponentVersion)` for gating. + +**SCM / DataNode** continue to use [`org.apache.hadoop.hdds.upgrade.HDDSLayoutVersionManager`](https://github.com/apache/ozone/blob/master/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/upgrade/HDDSLayoutVersionManager.java) ([`org.apache.hadoop.ozone.upgrade.AbstractLayoutVersionManager`](https://github.com/apache/ozone/blob/master/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/AbstractLayoutVersionManager.java)), which provides metadata/software layout integers and `isAllowed(LayoutFeature)`. ## @DisallowedUntilLayoutVersion Annotation Method level annotation used to "disallow" an API if current layout version does not include the associated layout feature. Currently it is added only to the OM module, but can easily be moved down to a common module based on need on the HDDS layer. diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/upgrade/HDDSVersionManager.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/upgrade/HDDSVersionManager.java index ad6bad1c7029..9498859067ca 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/upgrade/HDDSVersionManager.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/upgrade/HDDSVersionManager.java @@ -20,29 +20,45 @@ import java.io.IOException; import org.apache.hadoop.hdds.ComponentVersion; import org.apache.hadoop.hdds.HDDSVersion; +import org.apache.hadoop.ozone.common.Storage; import org.apache.hadoop.ozone.upgrade.ComponentVersionManager; +import org.apache.hadoop.ozone.upgrade.UpgradeException; /** * Component version manager for HDDS (Datanodes and SCM). */ public class HDDSVersionManager extends ComponentVersionManager { - public HDDSVersionManager(int serializedApparentVersion) throws IOException { - super(computeApparentVersion(serializedApparentVersion), HDDSVersion.SOFTWARE_VERSION); + public HDDSVersionManager(Storage storage) throws IOException { + super(storage, computeApparentVersion(storage.getApparentVersion()), HDDSVersion.SOFTWARE_VERSION); } /** - * If the apparent version stored on the disk is >= 100, it indicates the component has been finalized for the - * ZDU feature, and the apparent version corresponds to a version in {@link HDDSVersion}. - * If the apparent version stored on the disk is < 100, it indicates the component is not yet finalized for the - * ZDU feature, and the apparent version corresponds to a version in {@link HDDSLayoutFeature}. + * If the apparent version stored on the disk is >= {@link HDDSVersion#ZDU} serialized, the apparent version is + * resolved via {@link HDDSVersion#deserialize(int)}. Values with no matching {@link HDDSVersion} fail startup with + * the persisted integer in the exception message. + * If the value is below that threshold, the apparent version is resolved as a {@link HDDSLayoutFeature}. Integers in + * the gap between the largest {@link HDDSLayoutFeature} and ZDU are not valid legacy layout values; startup fails + * with the persisted integer in the exception message. */ - private static ComponentVersion computeApparentVersion(int serializedApparentVersion) { - if (serializedApparentVersion < HDDSVersion.ZDU.serialize()) { - return HDDSLayoutFeature.deserialize(serializedApparentVersion); + private static ComponentVersion computeApparentVersion(int serializedApparentVersion) throws IOException { + if (serializedApparentVersion >= HDDSVersion.ZDU.serialize()) { + HDDSVersion fromHdds = HDDSVersion.deserialize(serializedApparentVersion); + if (fromHdds != HDDSVersion.FUTURE_VERSION) { + return fromHdds; + } } else { - return HDDSVersion.deserialize(serializedApparentVersion); + ComponentVersion fromLayout = HDDSLayoutFeature.deserialize(serializedApparentVersion); + if (fromLayout != null) { + return fromLayout; + } } + throw new IOException("Initialization failed. Disk contains unknown apparent version " + serializedApparentVersion + + " for software version " + HDDSVersion.SOFTWARE_VERSION + ". Make sure this component was not downgraded" + + " after finalization"); } - // TODO HDDS-14826: Register upgrade actions based on annotations + @Override + protected void runUpgradeAction(ComponentVersion componentVersion) throws UpgradeException { + // TODO HDDS-14826: Register upgrade actions based on annotations + } } diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/common/Storage.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/common/Storage.java index ae357d8d7519..4b0c49b02445 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/common/Storage.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/common/Storage.java @@ -124,20 +124,12 @@ public void setClusterId(String clusterId) throws IOException { } } - public int getLayoutVersion() { - return storageInfo.getLayoutVersion(); + public int getApparentVersion() { + return storageInfo.getApparentVersion(); } - public void setLayoutVersion(int version) { - storageInfo.setLayoutVersion(version); - } - - public void setFirstUpgradeActionLayoutVersion(int version) { - storageInfo.setFirstUpgradeActionLayoutVersion(version); - } - - public int getFirstUpgradeActionLayoutVersion() { - return storageInfo.getFirstUpgradeActionLayoutVersion(); + public void setApparentVersion(int version) { + storageInfo.setApparentVersion(version); } /** @@ -288,8 +280,7 @@ public void persistCurrentState() throws IOException { storageInfo.writeTo(getVersionFile()); } - protected static int getInitLayoutVersion(OzoneConfiguration conf, - String configKey, + protected static int getInitApparentVersion(OzoneConfiguration conf, String configKey, IntSupplier defaultLvSupplier) { int lV = conf.getInt(configKey, OZONE_INIT_DEFAULT_LAYOUT_VERSION_DEFAULT); if (lV == OZONE_INIT_DEFAULT_LAYOUT_VERSION_DEFAULT) { diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/common/StorageInfo.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/common/StorageInfo.java index 7a74258936fe..624b1affde7d 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/common/StorageInfo.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/common/StorageInfo.java @@ -61,9 +61,6 @@ public class StorageInfo { */ private static final String LAYOUT_VERSION = "layoutVersion"; - private static final String FIRST_UPGRADE_ACTION_LAYOUT_VERSION = - "firstUpgradeActionLayoutVersion"; - private static final int INVALID_LAYOUT_VERSION = -1; /** @@ -93,7 +90,7 @@ public StorageInfo(NodeType type, File propertiesFile) verifyNodeType(type); verifyClusterId(); verifyCreationTime(); - verifyLayoutVersion(); + verifyApparentVersion(); } public NodeType getNodeType() { @@ -112,7 +109,7 @@ public Long getCreationTime() { return null; } - public int getLayoutVersion() { + public int getApparentVersion() { String layout = properties.getProperty(LAYOUT_VERSION); if (layout != null) { return Integer.parseInt(layout); @@ -120,7 +117,7 @@ public int getLayoutVersion() { return 0; } - private void verifyLayoutVersion() { + private void verifyApparentVersion() { String layout = getProperty(LAYOUT_VERSION); if (layout == null) { LOG.warn("Found " + STORAGE_FILE_VERSION + " file without any layout " + @@ -129,20 +126,6 @@ private void verifyLayoutVersion() { } } - public int getFirstUpgradeActionLayoutVersion() { - String upgradingTo = - properties.getProperty(FIRST_UPGRADE_ACTION_LAYOUT_VERSION); - if (upgradingTo != null) { - return Integer.parseInt(upgradingTo); - } - return INVALID_LAYOUT_VERSION; - } - - public void setFirstUpgradeActionLayoutVersion(int layoutVersion) { - properties.setProperty( - FIRST_UPGRADE_ACTION_LAYOUT_VERSION, Integer.toString(layoutVersion)); - } - public String getProperty(String key) { return properties.getProperty(key); } @@ -159,7 +142,7 @@ public void setClusterId(String clusterId) { properties.setProperty(CLUSTER_ID, clusterId); } - public void setLayoutVersion(int version) { + public void setApparentVersion(int version) { properties.setProperty(LAYOUT_VERSION, Integer.toString(version)); } diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/BasicUpgradeFinalizer.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/BasicUpgradeFinalizer.java index fda69ff872f0..8d0a31a8a4ac 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/BasicUpgradeFinalizer.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/BasicUpgradeFinalizer.java @@ -17,9 +17,9 @@ package org.apache.hadoop.ozone.upgrade; +import static org.apache.hadoop.ozone.upgrade.UpgradeException.ResultCodes.APPARENT_VERSION_UPDATE_FAILED; import static org.apache.hadoop.ozone.upgrade.UpgradeException.ResultCodes.INVALID_REQUEST; -import static org.apache.hadoop.ozone.upgrade.UpgradeException.ResultCodes.LAYOUT_FEATURE_FINALIZATION_FAILED; -import static org.apache.hadoop.ozone.upgrade.UpgradeException.ResultCodes.UPDATE_LAYOUT_VERSION_FAILED; +import static org.apache.hadoop.ozone.upgrade.UpgradeException.ResultCodes.UPGRADE_FINALIZATION_FAILED; import static org.apache.hadoop.ozone.upgrade.UpgradeFinalization.FINALIZATION_IN_PROGRESS_MSG; import static org.apache.hadoop.ozone.upgrade.UpgradeFinalization.FINALIZATION_REQUIRED_MSG; import static org.apache.hadoop.ozone.upgrade.UpgradeFinalization.FINALIZED_MSG; @@ -291,11 +291,11 @@ protected void updateLayoutVersionInVersionFile(LayoutFeature feature, } private int currentStoredLayoutVersion(Storage config) { - return config.getLayoutVersion(); + return config.getApparentVersion(); } private void updateStorageLayoutVersion(int version, Storage config) { - config.setLayoutVersion(version); + config.setApparentVersion(version); } private void persistStorage(Storage config) throws IOException { @@ -326,13 +326,13 @@ protected void logAndEmit(String msg) { protected void logFinalizationFailureAndThrow(Exception e, String feature) throws UpgradeException { String msg = "Error during finalization of " + feature + "."; - logAndThrow(e, msg, LAYOUT_FEATURE_FINALIZATION_FAILED); + logAndThrow(e, msg, UPGRADE_FINALIZATION_FAILED); } private void logLayoutVersionUpdateFailureAndThrow(IOException e) throws UpgradeException { String msg = "Updating the LayoutVersion in the VERSION file failed."; - logAndThrow(e, msg, UPDATE_LAYOUT_VERSION_FAILED); + logAndThrow(e, msg, APPARENT_VERSION_UPDATE_FAILED); } private void logAndThrow(Exception e, String msg, ResultCodes resultCode) diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/ComponentVersionManager.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/ComponentVersionManager.java index 11bf4a3f2281..b2f6c7e6c615 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/ComponentVersionManager.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/ComponentVersionManager.java @@ -17,11 +17,15 @@ package org.apache.hadoop.ozone.upgrade; +import static org.apache.hadoop.ozone.upgrade.UpgradeException.ResultCodes.APPARENT_VERSION_UPDATE_FAILED; + +import com.google.common.annotations.VisibleForTesting; import java.io.Closeable; import java.io.IOException; import java.util.Iterator; import java.util.NoSuchElementException; import org.apache.hadoop.hdds.ComponentVersion; +import org.apache.hadoop.ozone.common.Storage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,22 +55,16 @@ public abstract class ComponentVersionManager implements Closeable { // Software version will never change. private final ComponentVersion softwareVersion; private final ComponentVersionManagerMetrics metrics; + private final Storage storage; - private static final Logger LOG = - LoggerFactory.getLogger(ComponentVersionManager.class); + private static final Logger LOG = LoggerFactory.getLogger(ComponentVersionManager.class); - protected ComponentVersionManager(ComponentVersion apparentVersion, ComponentVersion softwareVersion) - throws IOException { + protected ComponentVersionManager(Storage storage, ComponentVersion apparentVersion, + ComponentVersion softwareVersion) { + this.storage = storage; this.apparentVersion = apparentVersion; this.softwareVersion = softwareVersion; - if (!apparentVersion.isSupportedBy(softwareVersion)) { - throw new IOException( - "Cannot initialize ComponentVersionManager. Apparent version " - + apparentVersion + " is larger than software version " - + softwareVersion); - } - LOG.info("Initializing version manager with apparent version {} and software version {}", apparentVersion, softwareVersion); this.metrics = ComponentVersionManagerMetrics.create(this); @@ -88,11 +86,30 @@ public boolean needsFinalization() { return !apparentVersion.equals(softwareVersion); } + /** + * Test-only accessor for the {@link Storage} instance supplied to the constructor. + */ + @VisibleForTesting + protected Storage getStorageForTesting() { + return storage; + } + + public void finalizeUpgrade() throws UpgradeException { + for (ComponentVersion version : getUnfinalizedVersions()) { + validateForFinalization(version); + runUpgradeAction(version); + persistApparentVersion(version); + + LOG.info("Version {} has been finalized.", version); + } + LOG.info("Finalization is complete."); + } + /** * @return An Iterable of all versions after the current apparent version which still need to be finalized. If this * component is already finalized, the Iterable will be empty. */ - public Iterable getUnfinalizedVersions() { + private Iterable getUnfinalizedVersions() { return () -> new Iterator() { private ComponentVersion currentVersion = apparentVersion; @@ -118,7 +135,7 @@ public ComponentVersion next() { * * @param newApparentVersion The version to mark as finalized. */ - public void markFinalized(ComponentVersion newApparentVersion) { + private void validateForFinalization(ComponentVersion newApparentVersion) { String versionMsg = "Software version: " + softwareVersion + ", apparent version: " + apparentVersion + ", provided version: " + newApparentVersion @@ -131,19 +148,34 @@ public void markFinalized(ComponentVersion newApparentVersion) { ComponentVersion nextVersion = apparentVersion.nextVersion(); if (nextVersion == null) { throw new IllegalArgumentException("Attempt to finalize when no future versions exist." + versionMsg); - } else if (nextVersion.equals(newApparentVersion)) { - apparentVersion = newApparentVersion; - LOG.info("Version {} has been finalized.", apparentVersion); - if (!needsFinalization()) { - LOG.info("Finalization is complete."); - } - } else { + } else if (newApparentVersion != nextVersion) { throw new IllegalArgumentException( - "Finalize attempt on a version that is newer than the next feature to be finalized. " + versionMsg); + "Finalize attempt on a version that is not the next feature to be finalized. " + versionMsg); } } } + private void persistApparentVersion(ComponentVersion version) throws UpgradeException { + int prevVersion = storage.getApparentVersion(); + + storage.setApparentVersion(version.serialize()); + try { + storage.persistCurrentState(); + } catch (IOException e) { + storage.setApparentVersion(prevVersion); + logAndThrow(e, "Updating version in the VERSION file from " + prevVersion + " to " + version + + " failed.", APPARENT_VERSION_UPDATE_FAILED); + } + apparentVersion = version; + } + + protected void logAndThrow(Exception e, String msg, UpgradeException.ResultCodes resultCode) throws UpgradeException { + LOG.error(msg, e); + throw new UpgradeException(msg, e, resultCode); + } + + protected abstract void runUpgradeAction(ComponentVersion componentVersion) throws UpgradeException; + @Override public void close() { metrics.unRegister(); diff --git a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/upgrade/TestHDDSVersionManager.java b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/upgrade/TestHDDSVersionManager.java index 1e76ff91be39..77a3720a25b2 100644 --- a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/upgrade/TestHDDSVersionManager.java +++ b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/upgrade/TestHDDSVersionManager.java @@ -17,6 +17,8 @@ package org.apache.hadoop.hdds.upgrade; +import static org.mockito.Mockito.when; + import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -24,12 +26,17 @@ import java.util.stream.Stream; import org.apache.hadoop.hdds.ComponentVersion; import org.apache.hadoop.hdds.HDDSVersion; +import org.apache.hadoop.ozone.common.Storage; import org.apache.hadoop.ozone.upgrade.AbstractComponentVersionManagerTest; import org.apache.hadoop.ozone.upgrade.ComponentVersionManager; +import org.apache.ozone.test.tag.Unhealthy; +import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mockito; /** - * Tests for {@link HDDSVersionManager}. + * Tests for {@link HDDSVersionManager} using on-disk {@link Storage} under a JUnit temp directory. */ class TestHDDSVersionManager extends AbstractComponentVersionManagerTest { @@ -52,9 +59,20 @@ public static Stream preFinalizedVersionArgs() { .map(Arguments::of); } + @ParameterizedTest + @MethodSource("preFinalizedVersionArgs") + @Override + @Unhealthy + public void testFinalizationFromEarlierVersions(ComponentVersion apparentVersion) { + // TODO Once HDDSVersionManager implementation is finished, this override can be removed to enable the test in the + // parent class. + } + @Override protected ComponentVersionManager createManager(int serializedApparentVersion) throws IOException { - return new HDDSVersionManager(serializedApparentVersion); + Storage mockStorage = Mockito.mock(Storage.class); + when(mockStorage.getApparentVersion()).thenReturn(serializedApparentVersion); + return new HDDSVersionManager(mockStorage); } @Override diff --git a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/ozone/upgrade/AbstractComponentVersionManagerTest.java b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/ozone/upgrade/AbstractComponentVersionManagerTest.java index 0bf439326cac..b5a38623faf6 100644 --- a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/ozone/upgrade/AbstractComponentVersionManagerTest.java +++ b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/ozone/upgrade/AbstractComponentVersionManagerTest.java @@ -23,27 +23,33 @@ import static org.junit.jupiter.api.Assertions.assertFalse; 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.when; import java.io.IOException; -import java.util.Iterator; import java.util.List; -import java.util.NoSuchElementException; import org.apache.hadoop.hdds.ComponentVersion; import org.apache.hadoop.metrics2.MetricsRecordBuilder; import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; +import org.apache.hadoop.ozone.common.Storage; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.Mockito; /** * Shared tests for concrete {@link ComponentVersionManager} implementations. + * + *

Each subclass {@linkplain #createManager(int) builds} the version manager with a real {@link Storage} + * instance rooted under a JUnit temporary directory (see for example {@code TestOMStorage} in ozone-manager). + * Assertions use {@link ComponentVersionManager#getStorageForTesting()} and {@link Storage#getApparentVersion()} + * to confirm what was persisted, instead of Mockito interaction verification. */ public abstract class AbstractComponentVersionManagerTest { + /** + * Creates a new manager for {@code serializedApparentVersion}. The implementation must initialize real + * {@link Storage} on disk with that apparent version (and return a manager whose + * {@link ComponentVersionManager#getStorageForTesting()} is that instance). + */ protected abstract ComponentVersionManager createManager(int serializedApparentVersion) throws IOException; protected abstract List allVersionsInOrder(); @@ -71,65 +77,49 @@ public void testApparentVersionBehindSoftwareVersion() { } @ParameterizedTest - // Child classes must implement this as a static method to provide the versions to start finalization from. @MethodSource("preFinalizedVersionArgs") public void testFinalizationFromEarlierVersions(ComponentVersion apparentVersion) throws Exception { List allVersions = allVersionsInOrder(); int apparentVersionIndex = allVersions.indexOf(apparentVersion); assertTrue(apparentVersionIndex >= 0, "Apparent version " + apparentVersion + " must exist"); - Iterator expectedVersions = allVersions.subList(apparentVersionIndex + 1, allVersions.size()) - .iterator(); + List expectedChain = allVersions.subList(apparentVersionIndex + 1, allVersions.size()); try (ComponentVersionManager versionManager = createManager(apparentVersion.serialize())) { assertApparentVersion(versionManager, apparentVersion); - for (ComponentVersion versionToFinalize : versionManager.getUnfinalizedVersions()) { + if (!expectedChain.isEmpty()) { assertTrue(versionManager.needsFinalization()); - assertFalse(versionManager.isAllowed(versionToFinalize), - "Unfinalized version " + versionToFinalize + " should not be allowed by apparent version " - + versionManager.getApparentVersion()); - assertTrue(expectedVersions.hasNext()); - assertEquals(expectedVersions.next(), versionToFinalize); - - versionManager.markFinalized(versionToFinalize); - assertApparentVersion(versionManager, versionToFinalize); + for (ComponentVersion v : expectedChain) { + assertFalse(versionManager.isAllowed(v), + "Version " + v + " should not be allowed before finalization"); + } } - assertFalse(expectedVersions.hasNext()); - assertThrows(NoSuchElementException.class, expectedVersions::next); - } - } + versionManager.finalizeUpgrade(); - @Test - public void testFinalizationFromSoftwareVersionNoOp() throws Exception { - try (ComponentVersionManager versionManager = createManager(expectedSoftwareVersion().serialize())) { assertApparentVersion(versionManager, expectedSoftwareVersion()); assertFalse(versionManager.needsFinalization()); - assertFalse(versionManager.getUnfinalizedVersions().iterator().hasNext()); - - versionManager.markFinalized(expectedSoftwareVersion()); - assertApparentVersion(versionManager, expectedSoftwareVersion()); - assertFalse(versionManager.needsFinalization()); - assertFalse(versionManager.getUnfinalizedVersions().iterator().hasNext()); + Storage storage = versionManager.getStorageForTesting(); + assertEquals(expectedSoftwareVersion().serialize(), storage.getApparentVersion(), + "Storage apparent version should match software version after finalization"); } } @Test - public void testFinalizationOfNonExistentVersion() throws Exception { + public void testFinalizationFromSoftwareVersionNoOp() throws Exception { try (ComponentVersionManager versionManager = createManager(expectedSoftwareVersion().serialize())) { assertApparentVersion(versionManager, expectedSoftwareVersion()); assertFalse(versionManager.needsFinalization()); - assertFalse(versionManager.getUnfinalizedVersions().iterator().hasNext()); - ComponentVersion mockVersion = Mockito.mock(ComponentVersion.class); - when(mockVersion.isSupportedBy(any())).thenReturn(false); + Storage storage = versionManager.getStorageForTesting(); + int apparentOnStorageBefore = storage.getApparentVersion(); + versionManager.finalizeUpgrade(); - assertThrows(IllegalArgumentException.class, () -> versionManager.markFinalized(mockVersion)); - // The failed finalization call should not have changed the version manager's state. assertApparentVersion(versionManager, expectedSoftwareVersion()); assertFalse(versionManager.needsFinalization()); - assertFalse(versionManager.getUnfinalizedVersions().iterator().hasNext()); + assertEquals(apparentOnStorageBefore, storage.getApparentVersion(), + "No-op finalize should not change the persisted apparent version"); } } diff --git a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/ozone/upgrade/TestBasicUpgradeFinalizer.java b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/ozone/upgrade/TestBasicUpgradeFinalizer.java index 00ac2411fe11..29cac62fbb20 100644 --- a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/ozone/upgrade/TestBasicUpgradeFinalizer.java +++ b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/ozone/upgrade/TestBasicUpgradeFinalizer.java @@ -95,6 +95,8 @@ public void testAlreadyFinalizedDoesNotTriggerNewFinalization() StatusAndMessages res = finalizer.finalize("test-client-1", mockObj); + // TODO this test class will be removed with BasicUpgradeFinalizer when all components are migrated to the new + // version framework. assertEquals(ALREADY_FINALIZED, res.status()); assertFalse(finalizer.preCalled || finalizer.finalizeCalled || finalizer.postCalled); @@ -222,12 +224,12 @@ public void finalizeLayoutFeature(LayoutFeature lf, Object service) super.finalizeLayoutFeature(lf, lf.action(), mockStorage); - inOrder.verify(mockStorage).setLayoutVersion(eq(lf.layoutVersion())); + inOrder.verify(mockStorage).setApparentVersion(eq(lf.layoutVersion())); try { inOrder.verify(mockStorage).persistCurrentState(); } catch (IOException ex) { throw new UpgradeException(ex, - UpgradeException.ResultCodes.LAYOUT_FEATURE_FINALIZATION_FAILED); + UpgradeException.ResultCodes.UPGRADE_FINALIZATION_FAILED); } finalizeCalled = true; } diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMStorageConfig.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMStorageConfig.java index 9bb8809055e8..d41537fed0fb 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMStorageConfig.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMStorageConfig.java @@ -48,7 +48,7 @@ public class SCMStorageConfig extends Storage { */ public SCMStorageConfig(OzoneConfiguration conf) throws IOException { super(NodeType.SCM, ServerUtils.getScmDbDir(conf), STORAGE_DIR, - getInitLayoutVersion(conf, TESTING_INIT_LAYOUT_VERSION_KEY, + getInitApparentVersion(conf, TESTING_INIT_LAYOUT_VERSION_KEY, HDDSLayoutVersionManager::maxLayoutVersion)); } diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java index 543190140e9f..b9f2d799827d 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java @@ -696,7 +696,7 @@ private void initializeSystemManagers(OzoneConfiguration conf, } scmLayoutVersionManager = new HDDSLayoutVersionManager( - scmStorageConfig.getLayoutVersion()); + scmStorageConfig.getApparentVersion()); VersionedDatanodeFeatures.initialize(scmLayoutVersionManager); UpgradeFinalizationExecutor @@ -1320,7 +1320,7 @@ public static boolean scmInit(OzoneConfiguration conf, LOG.info("SCM initialization succeeded. Current cluster id for sd={}" + "; cid={}; layoutVersion={}; scmId={}", scmStorageConfig.getStorageDir(), scmStorageConfig.getClusterID(), - scmStorageConfig.getLayoutVersion(), scmStorageConfig.getScmId()); + scmStorageConfig.getApparentVersion(), scmStorageConfig.getScmId()); return true; } catch (IOException ioe) { LOG.error("Could not initialize SCM version file", ioe); @@ -1354,7 +1354,7 @@ public static boolean scmInit(OzoneConfiguration conf, LOG.info("SCM already initialized. Reusing existing cluster id for sd={}" + ";cid={}; layoutVersion={}; HAEnabled={}", scmStorageConfig.getStorageDir(), scmStorageConfig.getClusterID(), - scmStorageConfig.getLayoutVersion(), scmStorageConfig.isSCMHAEnabled()); + scmStorageConfig.getApparentVersion(), scmStorageConfig.isSCMHAEnabled()); return true; } } diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/upgrade/SCMUpgradeFinalizer.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/upgrade/SCMUpgradeFinalizer.java index 93f2c7dace88..410e18cb35f3 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/upgrade/SCMUpgradeFinalizer.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/upgrade/SCMUpgradeFinalizer.java @@ -70,7 +70,7 @@ public void finalizeLayoutFeatures(Iterable features, SCMUpgradeF LOG.info("No layout features to finalize."); } } catch (IOException ex) { - throw new UpgradeException(ex, UpgradeException.ResultCodes.LAYOUT_FEATURE_FINALIZATION_FAILED); + throw new UpgradeException(ex, UpgradeException.ResultCodes.UPGRADE_FINALIZATION_FAILED); } } diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestSCMNodeManager.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestSCMNodeManager.java index a93fbd4aa99b..06c8e0b32b4a 100644 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestSCMNodeManager.java +++ b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestSCMNodeManager.java @@ -753,7 +753,7 @@ public void testProcessLayoutVersionReportHigherMlv() when(scmStorageConfig.getClusterID()).thenReturn("xyz111"); EventPublisher eventPublisher = mock(EventPublisher.class); HDDSLayoutVersionManager lvm = - new HDDSLayoutVersionManager(scmStorageConfig.getLayoutVersion()); + new HDDSLayoutVersionManager(scmStorageConfig.getApparentVersion()); SCMContext nodeManagerContext = SCMContext.emptyContext(); SCMNodeManager nodeManager = new SCMNodeManager(conf, scmStorageConfig, eventPublisher, new NetworkTopologyImpl(conf), @@ -832,7 +832,7 @@ public void testProcessCommandQueueReport() when(scmStorageConfig.getClusterID()).thenReturn("xyz111"); EventPublisher eventPublisher = mock(EventPublisher.class); HDDSLayoutVersionManager lvm = - new HDDSLayoutVersionManager(scmStorageConfig.getLayoutVersion()); + new HDDSLayoutVersionManager(scmStorageConfig.getApparentVersion()); createNodeManager(getConf()); SCMNodeManager nodeManager = new SCMNodeManager(conf, scmStorageConfig, eventPublisher, new NetworkTopologyImpl(conf), @@ -2024,7 +2024,7 @@ public void testNodeOperationalStateChange( SCMStorageConfig scmStorageConfig = mock(SCMStorageConfig.class); when(scmStorageConfig.getClusterID()).thenReturn("xyz111"); EventPublisher eventPublisher = mock(EventPublisher.class); - HDDSLayoutVersionManager lvm = new HDDSLayoutVersionManager(scmStorageConfig.getLayoutVersion()); + HDDSLayoutVersionManager lvm = new HDDSLayoutVersionManager(scmStorageConfig.getApparentVersion()); createNodeManager(getConf()); SCMNodeManager nodeManager = new SCMNodeManager(conf, scmStorageConfig, eventPublisher, new NetworkTopologyImpl(conf), diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/upgrade/TestScmStartupSlvLessThanMlv.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/upgrade/TestScmStartupInvalidApparentVersion.java similarity index 52% rename from hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/upgrade/TestScmStartupSlvLessThanMlv.java rename to hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/upgrade/TestScmStartupInvalidApparentVersion.java index 25de21766947..cb78e35968be 100644 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/upgrade/TestScmStartupSlvLessThanMlv.java +++ b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/upgrade/TestScmStartupInvalidApparentVersion.java @@ -17,6 +17,7 @@ package org.apache.hadoop.hdds.scm.upgrade; +import static org.apache.hadoop.hdds.HDDSVersion.SOFTWARE_VERSION; import static org.apache.hadoop.ozone.OzoneConsts.SCM_HA; import static org.apache.hadoop.ozone.OzoneConsts.SCM_ID; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -33,61 +34,61 @@ import org.apache.hadoop.hdds.scm.ScmConfigKeys; import org.apache.hadoop.hdds.scm.server.StorageContainerManager; import org.apache.hadoop.hdds.upgrade.HDDSLayoutFeature; -import org.apache.hadoop.ozone.upgrade.LayoutFeature; +import org.apache.hadoop.hdds.upgrade.HDDSLayoutVersionManager; import org.apache.hadoop.ozone.upgrade.UpgradeTestUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** - * Tests that SCM will throw an exception on creation when it reads in a - * VERSION file indicating a metadata layout version larger than its - * software layout version. + * Ensures SCM does not start when the VERSION file records an apparent version (still persisted as the layout-version + * integer) that is not supported by the layout version manager for this build + * ({@link HDDSLayoutVersionManager} / {@link HDDSLayoutFeature}). */ -public class TestScmStartupSlvLessThanMlv { +public class TestScmStartupInvalidApparentVersion { + + @TempDir + private Path folder; + + @Test + public void testStartupFailsWhenApparentVersionBetweenLastLayoutFeatureAndZdu() throws Exception { + assertStartupFailsWithComponentVersionMessage( + HDDSLayoutFeature.STORAGE_SPACE_DISTRIBUTION.layoutVersion() + 1); + } @Test - public void testStartupSlvLessThanMlv(@TempDir Path tempDir) + public void testStartupFailsWhenApparentVersionBeyondLastKnownComponentVersion() throws Exception { + assertStartupFailsWithComponentVersionMessage(SOFTWARE_VERSION.serialize() + 1); + } + + private void assertStartupFailsWithComponentVersionMessage(int serializedApparentVersion) throws Exception { - // Add subdirectories under the temporary folder where the version file - // will be placed. - File scmSubdir = tempDir.resolve("scm").resolve("current").toFile(); + File scmSubdir = folder.resolve("scm").resolve("current").toFile(); assertTrue(scmSubdir.mkdirs()); - // Create Ratis directories to simulate a realistic downgrade scenario - // where SCM was previously running with a newer version - File ratisDir = tempDir.resolve("scm.ratis").toFile(); - File snapshotDir = tempDir.resolve("scm.ratis.snapshot").toFile(); + File ratisDir = folder.resolve("scm.ratis").toFile(); + File snapshotDir = folder.resolve("scm.ratis.snapshot").toFile(); assertTrue(ratisDir.mkdirs()); assertTrue(snapshotDir.mkdirs()); OzoneConfiguration conf = new OzoneConfiguration(); - conf.set(ScmConfigKeys.OZONE_SCM_DB_DIRS, - tempDir.toAbsolutePath().toString()); - conf.set(HddsConfigKeys.OZONE_METADATA_DIRS, - tempDir.toAbsolutePath().toString()); + conf.set(ScmConfigKeys.OZONE_SCM_DB_DIRS, folder.toAbsolutePath().toString()); + conf.set(HddsConfigKeys.OZONE_METADATA_DIRS, folder.toAbsolutePath().toString()); - // Set metadata layout version larger then software layout version. - int largestSlv = 0; - for (LayoutFeature f: HDDSLayoutFeature.values()) { - largestSlv = Math.max(largestSlv, f.layoutVersion()); - } - int mlv = largestSlv + 1; + int softwareLayoutVersion = HDDSLayoutVersionManager.maxLayoutVersion(); Properties properties = new Properties(); properties.setProperty(SCM_ID, "scm"); properties.setProperty(SCM_HA, "true"); - // Create version file with MLV > SLV, which should fail the SCM - // construction. - UpgradeTestUtils.createVersionFile(scmSubdir, HddsProtos.NodeType.SCM, mlv, - properties); + UpgradeTestUtils.createVersionFile(scmSubdir, HddsProtos.NodeType.SCM, serializedApparentVersion, properties); + // TODO update this message when SCM migrated to using HDDSVersionManager. + String expectedMessage = String.format( + "Cannot initialize VersionManager. Metadata layout version (%s) > software layout version (%s)", + serializedApparentVersion, softwareLayoutVersion); - Throwable t = assertThrows(IOException.class, - () -> new StorageContainerManager(conf)); - String expectedMessage = String.format("Cannot initialize VersionManager." + - " Metadata layout version (%s) > software layout version (%s)", - mlv, largestSlv); - assertEquals(expectedMessage, t.getMessage()); + IOException ioException = + assertThrows(IOException.class, () -> new StorageContainerManager(conf)); + assertEquals(expectedMessage, ioException.getMessage()); } } diff --git a/hadoop-ozone/cli-repair/src/main/java/org/apache/hadoop/ozone/repair/datanode/schemaupgrade/UpgradeUtils.java b/hadoop-ozone/cli-repair/src/main/java/org/apache/hadoop/ozone/repair/datanode/schemaupgrade/UpgradeUtils.java index e447f1011543..b609aa0a00e8 100644 --- a/hadoop-ozone/cli-repair/src/main/java/org/apache/hadoop/ozone/repair/datanode/schemaupgrade/UpgradeUtils.java +++ b/hadoop-ozone/cli-repair/src/main/java/org/apache/hadoop/ozone/repair/datanode/schemaupgrade/UpgradeUtils.java @@ -98,7 +98,7 @@ public static Pair getLayoutFeature( DatanodeLayoutStorage layoutStorage = new DatanodeLayoutStorage(conf, dnDetail.getUuidString()); HDDSLayoutVersionManager layoutVersionManager = - new HDDSLayoutVersionManager(layoutStorage.getLayoutVersion()); + new HDDSLayoutVersionManager(layoutStorage.getApparentVersion()); final int metadataLayoutVersion = layoutVersionManager.getMetadataLayoutVersion(); diff --git a/hadoop-ozone/freon/src/main/java/org/apache/hadoop/ozone/freon/DatanodeSimulator.java b/hadoop-ozone/freon/src/main/java/org/apache/hadoop/ozone/freon/DatanodeSimulator.java index bee91d466594..91a02f368020 100644 --- a/hadoop-ozone/freon/src/main/java/org/apache/hadoop/ozone/freon/DatanodeSimulator.java +++ b/hadoop-ozone/freon/src/main/java/org/apache/hadoop/ozone/freon/DatanodeSimulator.java @@ -445,7 +445,7 @@ private LayoutVersionProto createLayoutInfo() throws IOException { UUID.randomUUID().toString()); HDDSLayoutVersionManager layoutVersionManager = - new HDDSLayoutVersionManager(layoutStorage.getLayoutVersion()); + new HDDSLayoutVersionManager(layoutStorage.getApparentVersion()); return LayoutVersionProto.newBuilder() .setMetadataLayoutVersion( diff --git a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto index bdb3cc3cee35..ff2d72c7f6dd 100644 --- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto +++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto @@ -1599,17 +1599,19 @@ message RangerBGSyncResponse { } message FinalizeUpgradeRequest { + // Ignored by OM; retained for wire compatibility. required string upgradeClientId = 1; } message FinalizeUpgradeResponse { - required hadoop.hdds.UpgradeFinalizationStatus status = 1; + required hadoop.hdds.UpgradeFinalizationStatus status = 1; } message FinalizeUpgradeProgressRequest { + // Ignored by OM; retained for wire compatibility. required string upgradeClientId = 1; - optional bool takeover = 2; - optional bool readonly = 3; + optional bool takeover = 2 [deprecated = true]; + optional bool readonly = 3 [deprecated = true]; } message FinalizeUpgradeProgressResponse { diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java index 1c1a4d1f9830..8c97ee4232e3 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java @@ -25,8 +25,8 @@ import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeType; import org.apache.hadoop.hdds.server.ServerUtils; +import org.apache.hadoop.ozone.OzoneManagerVersion; import org.apache.hadoop.ozone.common.Storage; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; /** * Ozone Manager VERSION file representation. @@ -91,8 +91,8 @@ public class OMStorage extends Storage { */ public OMStorage(OzoneConfiguration conf) throws IOException { super(NodeType.OM, getOmDbDir(conf), STORAGE_DIR, - getInitLayoutVersion(conf, TESTING_INIT_LAYOUT_VERSION_KEY, - OMLayoutVersionManager::maxLayoutVersion)); + getInitApparentVersion(conf, TESTING_INIT_LAYOUT_VERSION_KEY, + () -> OzoneManagerVersion.SOFTWARE_VERSION.serialize())); } /** diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveDeletedKeysRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveDeletedKeysRequest.java index 73a2a89b22b2..95fa38c51ec8 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveDeletedKeysRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveDeletedKeysRequest.java @@ -52,6 +52,11 @@ public OMSnapshotMoveDeletedKeysRequest(OMRequest omRequest) { @Override @DisallowedUntilLayoutVersion(FILESYSTEM_SNAPSHOT) + public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { + return super.preExecute(ozoneManager); + } + + @Override public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, ExecutionContext context) { OmMetadataManagerImpl omMetadataManager = (OmMetadataManagerImpl) ozoneManager.getMetadataManager(); diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveTableKeysRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveTableKeysRequest.java index fef5dc76c4de..2f8a81f5ce67 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveTableKeysRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveTableKeysRequest.java @@ -73,6 +73,7 @@ public OMSnapshotMoveTableKeysRequest(OMRequest omRequest) { } @Override + @DisallowedUntilLayoutVersion(FILESYSTEM_SNAPSHOT) public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { OmMetadataManagerImpl omMetadataManager = (OmMetadataManagerImpl) ozoneManager.getMetadataManager(); SnapshotChainManager snapshotChainManager = omMetadataManager.getSnapshotChainManager(); @@ -186,7 +187,6 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { } @Override - @DisallowedUntilLayoutVersion(FILESYSTEM_SNAPSHOT) public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, ExecutionContext context) { OmSnapshotInternalMetrics omSnapshotIntMetrics = ozoneManager.getOmSnapshotIntMetrics(); 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/OMFinalizeUpgradeResponse.java index 49bb6fc86587..7bb188af03c5 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/OMFinalizeUpgradeResponse.java @@ -36,23 +36,24 @@ public class OMFinalizeUpgradeResponse extends OMClientResponse { private static final Logger LOG = LoggerFactory.getLogger(OMFinalizeUpgradeResponse.class); - private int layoutVersionToWrite = -1; + private int serializedApparentVersion = -1; public OMFinalizeUpgradeResponse( OzoneManagerProtocolProtos.OMResponse omResponse, - int layoutVersionToWrite) { + int serializedApparentVersion) { super(omResponse); - this.layoutVersionToWrite = layoutVersionToWrite; + this.serializedApparentVersion = serializedApparentVersion; } @Override protected void addToDBBatch(OMMetadataManager omMetadataManager, BatchOperation batchOperation) throws IOException { - if (layoutVersionToWrite != -1) { - LOG.info("Layout version to persist to DB : {}", layoutVersionToWrite); + if (serializedApparentVersion != -1) { + LOG.info("Serialized apparent component version to persist to DB : {}", + serializedApparentVersion); omMetadataManager.getMetaTable().putWithBatch(batchOperation, LAYOUT_VERSION_KEY, - String.valueOf(layoutVersionToWrite)); + String.valueOf(serializedApparentVersion)); } } } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMUpgradeActionProvider.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMUpgradeActionProvider.java new file mode 100644 index 000000000000..26516a172364 --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMUpgradeActionProvider.java @@ -0,0 +1,80 @@ +/* + * 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.upgrade; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import org.apache.hadoop.hdds.ComponentVersion; +import org.apache.hadoop.ozone.upgrade.ComponentUpgradeActionProvider; +import org.reflections.Reflections; +import org.reflections.scanners.SubTypesScanner; +import org.reflections.scanners.TypeAnnotationsScanner; +import org.reflections.util.ConfigurationBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Loads {@link OmUpgradeAction} implementations annotated with {@link UpgradeActionOm} from + * {@link #OM_UPGRADE_CLASS_PACKAGE} only. + */ +public final class OMUpgradeActionProvider implements ComponentUpgradeActionProvider { + + private static final Logger LOG = LoggerFactory.getLogger(OMUpgradeActionProvider.class); + + /** + * Package scanned for {@link UpgradeActionOm}-annotated classes (production OM upgrade actions). + */ + public static final String OM_UPGRADE_CLASS_PACKAGE = "org.apache.hadoop.ozone.om.upgrade"; + + public OMUpgradeActionProvider() { + } + + @Override + public Map load() { + Map upgradeActions = new HashMap<>(); + + Reflections reflections = new Reflections(new ConfigurationBuilder() + .forPackages(OM_UPGRADE_CLASS_PACKAGE) + .setScanners(new TypeAnnotationsScanner(), new SubTypesScanner()) + .setExpandSuperTypes(false) + .setParallel(true)); + Set> typesAnnotatedWith = reflections.getTypesAnnotatedWith(UpgradeActionOm.class); + + typesAnnotatedWith.forEach(actionClass -> { + if (OmUpgradeAction.class.isAssignableFrom(actionClass)) { + try { + OmUpgradeAction action = (OmUpgradeAction) actionClass.getDeclaredConstructor().newInstance(); + UpgradeActionOm annotation = actionClass.getAnnotation(UpgradeActionOm.class); + OMLayoutFeature feature = annotation.feature(); + LOG.info("Registering Upgrade Action : {}", action.name()); + upgradeActions.put(feature, action); + } catch (Exception e) { + LOG.error("Cannot instantiate Upgrade Action class {}", + actionClass.getSimpleName(), e); + } + } else { + LOG.warn("Found upgrade action class not of type " + + "org.apache.hadoop.ozone.om.upgrade.OmUpgradeAction : {}", + actionClass.getName()); + } + }); + + return upgradeActions; + } +} diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMVersionManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMVersionManager.java index f250928b2a97..fcda84149a01 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMVersionManager.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMVersionManager.java @@ -17,32 +17,117 @@ package org.apache.hadoop.ozone.om.upgrade; +import static org.apache.hadoop.ozone.OzoneConsts.LAYOUT_VERSION_KEY; + +import com.google.common.annotations.VisibleForTesting; import java.io.IOException; +import java.util.Map; import org.apache.hadoop.hdds.ComponentVersion; import org.apache.hadoop.ozone.OzoneManagerVersion; +import org.apache.hadoop.ozone.om.OMMetadataManager; +import org.apache.hadoop.ozone.om.OMStorage; +import org.apache.hadoop.ozone.om.OzoneManager; +import org.apache.hadoop.ozone.upgrade.ComponentUpgradeActionProvider; import org.apache.hadoop.ozone.upgrade.ComponentVersionManager; +import org.apache.hadoop.ozone.upgrade.UpgradeException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Component version manager for Ozone Manager. */ public class OMVersionManager extends ComponentVersionManager { - public OMVersionManager(int serializedApparentVersion) throws IOException { - super(computeApparentVersion(serializedApparentVersion), OzoneManagerVersion.SOFTWARE_VERSION); + + private static final Logger LOG = LoggerFactory.getLogger(OMVersionManager.class); + + private final Map upgradeActions; + + // The OM may not be fully initialized when the version manager is constructed. This field is just provided as an + // argument for upgrade actions when they are run. + private final OzoneManager upgradeActionArg; + + public OMVersionManager(OMStorage storage, OzoneManager upgradeActionArg) throws IOException { + this(storage, upgradeActionArg, new OMUpgradeActionProvider()); + } + + public OMVersionManager(OMStorage storage, OzoneManager upgradeActionArg, + ComponentUpgradeActionProvider upgradeActionProvider) throws IOException { + super(storage, computeApparentVersion(storage.getApparentVersion()), OzoneManagerVersion.SOFTWARE_VERSION); + this.upgradeActionArg = upgradeActionArg; + upgradeActions = upgradeActionProvider.load(); + } + + public void validateDBVersion(OMMetadataManager metadataManager) throws IOException { + ComponentVersion dbVersion = getApparentVersionInDB(metadataManager); + ComponentVersion apparentVersion = getApparentVersion(); + + if (!apparentVersion.equals(dbVersion)) { + LOG.info("Version file has different apparent version ({}) than OM DB ({}). That is expected if this " + + "OM has never been finalized to a newer version.", apparentVersion, dbVersion); + } + } + + public void finalizeFromSnapshotIfRequired(OMMetadataManager metadataManager) throws IOException { + ComponentVersion apparentVersionInDB = getApparentVersionInDB(metadataManager); + if (apparentVersionInDB != null && !isAllowed(apparentVersionInDB)) { + LOG.info("New OM snapshot received with higher apparent version {}. " + + "Attempting to finalize current OM to that version.", apparentVersionInDB); + finalizeUpgrade(); + updateApparentVersionInDB(metadataManager); + } + } + + @VisibleForTesting + public Map getUpgradeActionsForTesting() { + return upgradeActions; + } + + @Override + protected void runUpgradeAction(ComponentVersion componentVersion) throws UpgradeException { + OmUpgradeAction action = upgradeActions.get(componentVersion); + if (action == null) { + return; + } + try { + action.execute(upgradeActionArg); + } catch (Exception e) { + logAndThrow(e, "OM upgrade action for version " + componentVersion + " failed.", + UpgradeException.ResultCodes.FINALIZE_UPGRADE_ACTION_FAILED); + } + } + + private static ComponentVersion getApparentVersionInDB(OMMetadataManager metadataManager) throws IOException { + String apparentVersion = metadataManager.getMetaTable().get(LAYOUT_VERSION_KEY); + return (apparentVersion == null) ? null : computeApparentVersion(Integer.parseInt(apparentVersion)); + } + + private void updateApparentVersionInDB(OMMetadataManager metadataManager) throws IOException { + metadataManager.getMetaTable().put(LAYOUT_VERSION_KEY, String.valueOf(getApparentVersion().serialize())); } /** - * If the apparent version stored on the disk is >= 100, it indicates the component has been finalized for the - * ZDU feature, and the apparent version corresponds to a version in {@link OzoneManagerVersion}. - * If the apparent version stored on the disk is < 100, it indicates the component is not yet finalized for the - * ZDU feature, and the apparent version corresponds to a version in {@link OMLayoutFeature}. + * Maps a serialized apparent version to a {@link ComponentVersion}. + * If the value is >= {@link OzoneManagerVersion#ZDU} serialized, the OM has been finalized for ZDU and the + * apparent version is resolved via {@link OzoneManagerVersion#deserialize(int)}. Values with no matching + * {@link OzoneManagerVersion} fail startup with the persisted integer in the exception message. + * If the value is below that threshold, the apparent version is resolved as an {@link OMLayoutFeature}. Integers in + * the gap between the largest {@link OMLayoutFeature} and ZDU are not valid legacy layout values; startup fails with + * the persisted integer in the exception message. */ - private static ComponentVersion computeApparentVersion(int serializedApparentVersion) { - if (serializedApparentVersion < OzoneManagerVersion.ZDU.serialize()) { - return OMLayoutFeature.deserialize(serializedApparentVersion); + private static ComponentVersion computeApparentVersion(int serializedApparentVersion) throws IOException { + if (serializedApparentVersion >= OzoneManagerVersion.ZDU.serialize()) { + OzoneManagerVersion fromOm = OzoneManagerVersion.deserialize(serializedApparentVersion); + if (fromOm != OzoneManagerVersion.FUTURE_VERSION) { + return fromOm; + } } else { - return OzoneManagerVersion.deserialize(serializedApparentVersion); + ComponentVersion fromLayout = OMLayoutFeature.deserialize(serializedApparentVersion); + if (fromLayout != null) { + return fromLayout; + } } + throw new IOException("Initialization failed. Disk contains unknown apparent version " + serializedApparentVersion + + " for software version " + OzoneManagerVersion.SOFTWARE_VERSION + ". Make sure OM was not downgraded after" + + " finalization"); } - - // TODO HDDS-14826: Register upgrade actions based on annotations } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java index bea7785bfbc2..87d3d83002cb 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java @@ -507,7 +507,7 @@ public void validateRequest(OMRequest omRequest) throws OMException { OMException.ResultCodes.INVALID_REQUEST); } - // Layout version should have been set up the leader while serializing + // Apparent version should have been set up the leader while serializing // the request, and hence cannot be null. This version is used by each // node to identify which request handler version to use. if (omRequest.getLayoutVersion() == null) { diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/OMVersionManagerTestUtils.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/OMVersionManagerTestUtils.java new file mode 100644 index 000000000000..d2549431274e --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/OMVersionManagerTestUtils.java @@ -0,0 +1,48 @@ +/* + * 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.upgrade; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.hadoop.hdds.ComponentVersion; +import org.apache.hadoop.ozone.OzoneManagerVersion; + +/** + * Mockito helpers for {@link OMVersionManager} in unit tests. + */ +public final class OMVersionManagerTestUtils { + + private OMVersionManagerTestUtils() { + } + + /** + * Mock with apparent and software version both {@link OzoneManagerVersion#SOFTWARE_VERSION}, + * {@link OMVersionManager#needsFinalization()} false, and {@link OMVersionManager#isAllowed(ComponentVersion)} + * true for any argument. + */ + public static OMVersionManager mockFinalizedOmVersionManager() { + OMVersionManager ovm = mock(OMVersionManager.class); + when(ovm.getApparentVersion()).thenReturn(OzoneManagerVersion.SOFTWARE_VERSION); + when(ovm.getSoftwareVersion()).thenReturn(OzoneManagerVersion.SOFTWARE_VERSION); + when(ovm.needsFinalization()).thenReturn(false); + when(ovm.isAllowed(any(ComponentVersion.class))).thenReturn(true); + return ovm; + } +} diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMVersionManager.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMVersionManager.java index eed52733acbb..9e89a7780dee 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMVersionManager.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMVersionManager.java @@ -17,34 +17,83 @@ package org.apache.hadoop.ozone.om.upgrade; +import static org.apache.hadoop.ozone.OzoneManagerVersion.SOFTWARE_VERSION; +import static org.apache.hadoop.ozone.OzoneManagerVersion.ZDU; +import static org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature.DELEGATION_TOKEN_SYMMETRIC_SIGN; +import static org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature.ERASURE_CODED_STORAGE_SUPPORT; +import static org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature.HBASE_SUPPORT; +import static org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature.INITIAL_VERSION; +import static org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature.QUOTA; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +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.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; import org.apache.hadoop.hdds.ComponentVersion; +import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.ozone.OzoneManagerVersion; +import org.apache.hadoop.ozone.om.OMConfigKeys; +import org.apache.hadoop.ozone.om.OMStorage; +import org.apache.hadoop.ozone.om.OzoneManager; import org.apache.hadoop.ozone.upgrade.AbstractComponentVersionManagerTest; -import org.apache.hadoop.ozone.upgrade.ComponentVersionManager; +import org.apache.hadoop.ozone.upgrade.ComponentUpgradeActionProvider; +import org.apache.hadoop.ozone.upgrade.UpgradeException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.provider.Arguments; +import org.mockito.Mockito; /** - * Tests for {@link OMVersionManager}. + * Tests for {@link OMVersionManager}. Shared abstract tests use an empty upgrade-action map; action behavior is + * covered with map-based providers and a required classpath discovery test. */ class TestOMVersionManager extends AbstractComponentVersionManagerTest { private static final List ALL_VERSIONS; + private OzoneConfiguration conf; + + @TempDir + private Path tempFolder; + static { ALL_VERSIONS = new ArrayList<>(Arrays.asList(OMLayoutFeature.values())); for (OzoneManagerVersion version : OzoneManagerVersion.values()) { // Add all defined versions after and including ZDU to get the complete version list. - if (OzoneManagerVersion.ZDU.isSupportedBy(version) && version != OzoneManagerVersion.FUTURE_VERSION) { + if (ZDU.isSupportedBy(version) && version != OzoneManagerVersion.FUTURE_VERSION) { ALL_VERSIONS.add(version); } } } + @BeforeEach + public void init() { + conf = new OzoneConfiguration(); + } + public static Stream preFinalizedVersionArgs() { return ALL_VERSIONS.stream() .limit(ALL_VERSIONS.size() - 1) @@ -52,8 +101,17 @@ public static Stream preFinalizedVersionArgs() { } @Override - protected ComponentVersionManager createManager(int serializedApparentVersion) throws IOException { - return new OMVersionManager(serializedApparentVersion); + protected OMVersionManager createManager(int serializedApparentVersion) throws IOException { + // By default create a version manager which does not have any upgrade actions to run. Production upgrade actions + // may not be able to run in a test environment during finalization. + return createManager(serializedApparentVersion, HashMap::new); + } + + private OMVersionManager createManager(int serializedApparentVersion, + ComponentUpgradeActionProvider actions) throws IOException { + OMStorage storage = newOmStorage(serializedApparentVersion); + OzoneManager mockOM = Mockito.mock(OzoneManager.class); + return new OMVersionManager(storage, mockOM, actions); } @Override @@ -65,4 +123,104 @@ protected List allVersionsInOrder() { protected ComponentVersion expectedSoftwareVersion() { return OzoneManagerVersion.SOFTWARE_VERSION; } + + @Test + public void testClasspathScanDiscoversUpgradeActions() throws Exception { + // Regardless of whether OM is finalized, the same set of upgrade actions should be loaded. + try (OMVersionManager versionManager = createManager(INITIAL_VERSION.serialize(), new OMUpgradeActionProvider())) { + assertTrue(versionManager.needsFinalization()); + OmUpgradeAction quotaAction = versionManager.getUpgradeActionsForTesting().get(QUOTA); + assertInstanceOf(QuotaRepairUpgradeAction.class, quotaAction); + } + + try (OMVersionManager versionManager = createManager(SOFTWARE_VERSION.serialize(), new OMUpgradeActionProvider())) { + assertFalse(versionManager.needsFinalization()); + OmUpgradeAction quotaAction = versionManager.getUpgradeActionsForTesting().get(QUOTA); + assertInstanceOf(QuotaRepairUpgradeAction.class, quotaAction); + } + } + + @Test + public void testFinalizeRunsSuppliedUpgradeAction() throws Exception { + OmUpgradeAction mockECAction = mock(OmUpgradeAction.class); + OmUpgradeAction mockZDUAction = mock(OmUpgradeAction.class); + + ComponentUpgradeActionProvider provider = () -> { + Map m = new HashMap<>(); + m.put(ERASURE_CODED_STORAGE_SUPPORT, mockECAction); + m.put(ZDU, mockZDUAction); + return m; + }; + + try (OMVersionManager versionManager = createManager(QUOTA.serialize(), provider)) { + versionManager.finalizeUpgrade(); + assertEquals(OzoneManagerVersion.SOFTWARE_VERSION, versionManager.getApparentVersion()); + + // QUOTA was added after EC, so the EC upgrade action should not run when we finalize from this version. + verify(mockECAction, never()).execute(any()); + verify(mockZDUAction, atLeastOnce()).execute(any()); + assertOmApparentVersionOnDisk(conf, OzoneManagerVersion.SOFTWARE_VERSION.serialize()); + } + } + + @Test + public void testUpgradeActionFailureAbortsFinalize() throws Exception { + ComponentUpgradeActionProvider provider = () -> { + Map m = new HashMap<>(); + m.put(DELEGATION_TOKEN_SYMMETRIC_SIGN, o -> { + throw new IOException("expected test failure"); + }); + return m; + }; + + try (OMVersionManager versionManager = createManager(QUOTA.serialize(), provider)) { + UpgradeException thrown = + assertThrows(UpgradeException.class, versionManager::finalizeUpgrade); + assertEquals(UpgradeException.ResultCodes.FINALIZE_UPGRADE_ACTION_FAILED, thrown.getResult()); + // HBase is the version before symmetric encrypted delegation tokens, which has failed. + assertEquals(HBASE_SUPPORT, versionManager.getApparentVersion()); + assertOmApparentVersionOnDisk(conf, HBASE_SUPPORT.serialize()); + } + } + + @Test + public void testPersistFailureRollsBack() throws Exception { + // Create a mock storage instance that throws when persisting version updates. + OMStorage storage = mock(OMStorage.class); + AtomicInteger persistedApparentVersion = new AtomicInteger(INITIAL_VERSION.serialize()); + when(storage.getApparentVersion()).thenAnswer(invocation -> persistedApparentVersion.get()); + doAnswer(invocation -> { + persistedApparentVersion.set(invocation.getArgument(0)); + return null; + }).when(storage).setApparentVersion(anyInt()); + doThrow(new IOException("persist failed")).when(storage).persistCurrentState(); + + OzoneManager mockOM = Mockito.mock(OzoneManager.class); + try (OMVersionManager versionManager = new OMVersionManager(storage, mockOM, HashMap::new)) { + assertEquals(INITIAL_VERSION, versionManager.getApparentVersion()); + UpgradeException thrown = assertThrows(UpgradeException.class, versionManager::finalizeUpgrade); + assertEquals(UpgradeException.ResultCodes.APPARENT_VERSION_UPDATE_FAILED, thrown.getResult()); + assertEquals(INITIAL_VERSION, versionManager.getApparentVersion()); + assertEquals(INITIAL_VERSION.serialize(), storage.getApparentVersion()); + } + } + + private OMStorage newOmStorage(int apparentVersion) + throws IOException { + // Reinitialize the configuration to point to a new unique storage location. + Path dbDir = Files.createDirectory(new File(tempFolder.toFile(), UUID.randomUUID().toString()).toPath()); + conf.set(OMConfigKeys.OZONE_OM_DB_DIRS, dbDir.toString()); + OMStorage storage = new OMStorage(conf); + storage.setClusterId("test-cluster"); + storage.setApparentVersion(apparentVersion); + storage.setOmId(UUID.randomUUID().toString()); + storage.initialize(); + storage.persistCurrentState(); + return storage; + } + + private static void assertOmApparentVersionOnDisk(OzoneConfiguration conf, int expected) throws IOException { + OMStorage reloaded = new OMStorage(conf); + assertEquals(expected, reloaded.getApparentVersion()); + } } From c48683e4cbc961596b1f274e7b72eb30af434e6b Mon Sep 17 00:00:00 2001 From: Ethan Rose Date: Mon, 20 Apr 2026 16:50:57 -0400 Subject: [PATCH 2/7] HDDS-14496. OMStorage: add getLayoutVersion() delegating to getApparentVersion() for PR1 compile Made-with: Cursor --- .../src/main/java/org/apache/hadoop/ozone/om/OMStorage.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java index 8c97ee4232e3..4ef24efd6710 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java @@ -95,6 +95,11 @@ public OMStorage(OzoneConfiguration conf) throws IOException { () -> OzoneManagerVersion.SOFTWARE_VERSION.serialize())); } + /** Same as {@link #getApparentVersion()}; for callers still using layout-version naming. */ + public int getLayoutVersion() { + return getApparentVersion(); + } + /** * Sets the certificate serial id to be stored in the VERSION file * representation. From e550ff79d91b69cb1ed56039bf14d745dc5032b4 Mon Sep 17 00:00:00 2001 From: Ethan Rose Date: Mon, 20 Apr 2026 16:56:44 -0400 Subject: [PATCH 3/7] HDDS-14496. Storage: add getLayoutVersion() delegating to getApparentVersion() for PR1 compile Made-with: Cursor --- .../main/java/org/apache/hadoop/ozone/common/Storage.java | 5 +++++ .../src/main/java/org/apache/hadoop/ozone/om/OMStorage.java | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/common/Storage.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/common/Storage.java index 4b0c49b02445..ff69e81fc255 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/common/Storage.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/common/Storage.java @@ -132,6 +132,11 @@ public void setApparentVersion(int version) { storageInfo.setApparentVersion(version); } + /** Same as {@link #getApparentVersion()}; for callers still using layout-version naming. */ + public int getLayoutVersion() { + return getApparentVersion(); + } + /** * Retrieves the storageInfo instance to read/write the common * version file properties. diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java index 4ef24efd6710..8c97ee4232e3 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java @@ -95,11 +95,6 @@ public OMStorage(OzoneConfiguration conf) throws IOException { () -> OzoneManagerVersion.SOFTWARE_VERSION.serialize())); } - /** Same as {@link #getApparentVersion()}; for callers still using layout-version naming. */ - public int getLayoutVersion() { - return getApparentVersion(); - } - /** * Sets the certificate serial id to be stored in the VERSION file * representation. From 308a86b25385d437b0c6aa94a854188bc8e47e70 Mon Sep 17 00:00:00 2001 From: Ethan Rose Date: Mon, 20 Apr 2026 17:11:11 -0400 Subject: [PATCH 4/7] HDDS-14496. Use getApparentVersion/setApparentVersion instead of Storage#getLayoutVersion Made-with: Cursor --- .../main/java/org/apache/hadoop/ozone/common/Storage.java | 5 ----- .../main/java/org/apache/hadoop/ozone/om/OzoneManager.java | 6 +++--- .../test/java/org/apache/hadoop/ozone/om/TestOMStorage.java | 2 +- .../hadoop/ozone/om/upgrade/TestOMUpgradeFinalizer.java | 4 ++-- .../ozone/recon/scm/ReconStorageContainerManagerFacade.java | 2 +- .../apache/hadoop/ozone/recon/scm/TestReconNodeManager.java | 2 +- 6 files changed, 8 insertions(+), 13 deletions(-) diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/common/Storage.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/common/Storage.java index ff69e81fc255..4b0c49b02445 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/common/Storage.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/common/Storage.java @@ -132,11 +132,6 @@ public void setApparentVersion(int version) { storageInfo.setApparentVersion(version); } - /** Same as {@link #getApparentVersion()}; for callers still using layout-version naming. */ - public int getLayoutVersion() { - return getApparentVersion(); - } - /** * Retrieves the storageInfo instance to read/write the common * version file properties. 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 08634010e44e..b427729df931 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 @@ -532,7 +532,7 @@ private OzoneManager(OzoneConfiguration conf, StartupOption startupOption) reconfigurationHandler.setReconfigurationCompleteCallback(reconfigurationHandler.defaultLoggingCallback()); - versionManager = new OMLayoutVersionManager(omStorage.getLayoutVersion()); + versionManager = new OMLayoutVersionManager(omStorage.getApparentVersion()); upgradeFinalizer = new OMUpgradeFinalizer(versionManager); replicationConfigValidator = conf.getObject(ReplicationConfigValidator.class); @@ -1545,13 +1545,13 @@ public static boolean omInit(OzoneConfiguration conf) throws IOException, "OM initialization succeeded.Current cluster id for sd=" + omStorage.getStorageDir() + ";cid=" + omStorage .getClusterID() + ";layoutVersion=" + omStorage - .getLayoutVersion()); + .getApparentVersion()); } else { System.out.println( "OM already initialized.Reusing existing cluster id for sd=" + omStorage.getStorageDir() + ";cid=" + omStorage .getClusterID() + ";layoutVersion=" + omStorage - .getLayoutVersion()); + .getApparentVersion()); } } catch (IOException ioe) { LOG.error("Could not initialize OM version file", ioe); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestOMStorage.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestOMStorage.java index 12b88c11e673..ce85249c1a7a 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestOMStorage.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestOMStorage.java @@ -282,7 +282,7 @@ private void setupAPersistedVersionFileWithNodeId( OzoneConfiguration conf, String nodeId) throws IOException { OMStorage storage = new OMStorage(conf); storage.setClusterId("clusterId"); - storage.setLayoutVersion(OMLayoutVersionManager.maxLayoutVersion()); + storage.setApparentVersion(OMLayoutVersionManager.maxLayoutVersion()); storage.setOmId(OM_ID_STR); if (nodeId != null) { storage.setOmNodeId(nodeId); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMUpgradeFinalizer.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMUpgradeFinalizer.java index 27d6c8f3a7a5..21935dcb09d8 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMUpgradeFinalizer.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMUpgradeFinalizer.java @@ -262,9 +262,9 @@ private OzoneManager mockOzoneManager(int initialLayoutVersion) { (Answer) inv -> { storedLayoutVersion = inv.getArgument(0, Integer.class); return null; - }).when(st).setLayoutVersion(anyInt()); + }).when(st).setApparentVersion(anyInt()); - lenient().when(st.getLayoutVersion()) + lenient().when(st.getApparentVersion()) .thenAnswer((Answer) ignore -> storedLayoutVersion); when(mock.getOmStorage()).thenReturn(st); diff --git a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/scm/ReconStorageContainerManagerFacade.java b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/scm/ReconStorageContainerManagerFacade.java index 57067c421344..2db9fc153b57 100644 --- a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/scm/ReconStorageContainerManagerFacade.java +++ b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/scm/ReconStorageContainerManagerFacade.java @@ -218,7 +218,7 @@ public ReconStorageContainerManagerFacade(OzoneConfiguration conf, this.dbStore = DBStoreBuilder.createDBStore(ozoneConfiguration, ReconSCMDBDefinition.get()); HDDSLayoutVersionManager scmLayoutVersionManager = - new HDDSLayoutVersionManager(scmStorageConfig.getLayoutVersion()); + new HDDSLayoutVersionManager(scmStorageConfig.getApparentVersion()); this.scmhaManager = SCMHAManagerStub.getInstance( true, new SCMDBTransactionBufferImpl()); this.sequenceIdGen = new SequenceIdGenerator( diff --git a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/scm/TestReconNodeManager.java b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/scm/TestReconNodeManager.java index e0eb2f020ccb..8aa49a991741 100644 --- a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/scm/TestReconNodeManager.java +++ b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/scm/TestReconNodeManager.java @@ -82,7 +82,7 @@ public void setUp() throws Exception { ReconUtils reconUtils = new ReconUtils(); ReconStorageConfig reconStorageConfig = new ReconStorageConfig(conf, reconUtils); versionManager = new HDDSLayoutVersionManager( - reconStorageConfig.getLayoutVersion()); + reconStorageConfig.getApparentVersion()); store = DBStoreBuilder.createDBStore(conf, ReconSCMDBDefinition.get()); reconContext = new ReconContext(conf, reconUtils); } From 3a37bd57a5a0708912a17d93d42787f5a5411190 Mon Sep 17 00:00:00 2001 From: Ethan Rose Date: Mon, 20 Apr 2026 17:36:10 -0400 Subject: [PATCH 5/7] HDDS-14496. OMStorage: keep max layout version default until OM wiring PR Made-with: Cursor --- .../src/main/java/org/apache/hadoop/ozone/om/OMStorage.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java index 8c97ee4232e3..518ae6231144 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java @@ -25,8 +25,8 @@ import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeType; import org.apache.hadoop.hdds.server.ServerUtils; -import org.apache.hadoop.ozone.OzoneManagerVersion; import org.apache.hadoop.ozone.common.Storage; +import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; /** * Ozone Manager VERSION file representation. @@ -92,7 +92,7 @@ public class OMStorage extends Storage { public OMStorage(OzoneConfiguration conf) throws IOException { super(NodeType.OM, getOmDbDir(conf), STORAGE_DIR, getInitApparentVersion(conf, TESTING_INIT_LAYOUT_VERSION_KEY, - () -> OzoneManagerVersion.SOFTWARE_VERSION.serialize())); + OMLayoutVersionManager::maxLayoutVersion)); } /** From 695c4dada2bdf38808416045798ca099eae6d033 Mon Sep 17 00:00:00 2001 From: Ethan Rose Date: Mon, 20 Apr 2026 17:54:59 -0400 Subject: [PATCH 6/7] HDDS-14496. Move snapshot DisallowedUntilLayoutVersion fix to OM wiring PR Made-with: Cursor --- .../request/snapshot/OMSnapshotMoveDeletedKeysRequest.java | 5 ----- .../om/request/snapshot/OMSnapshotMoveTableKeysRequest.java | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveDeletedKeysRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveDeletedKeysRequest.java index 95fa38c51ec8..73a2a89b22b2 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveDeletedKeysRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveDeletedKeysRequest.java @@ -52,11 +52,6 @@ public OMSnapshotMoveDeletedKeysRequest(OMRequest omRequest) { @Override @DisallowedUntilLayoutVersion(FILESYSTEM_SNAPSHOT) - public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { - return super.preExecute(ozoneManager); - } - - @Override public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, ExecutionContext context) { OmMetadataManagerImpl omMetadataManager = (OmMetadataManagerImpl) ozoneManager.getMetadataManager(); diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveTableKeysRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveTableKeysRequest.java index 2f8a81f5ce67..fef5dc76c4de 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveTableKeysRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveTableKeysRequest.java @@ -73,7 +73,6 @@ public OMSnapshotMoveTableKeysRequest(OMRequest omRequest) { } @Override - @DisallowedUntilLayoutVersion(FILESYSTEM_SNAPSHOT) public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { OmMetadataManagerImpl omMetadataManager = (OmMetadataManagerImpl) ozoneManager.getMetadataManager(); SnapshotChainManager snapshotChainManager = omMetadataManager.getSnapshotChainManager(); @@ -187,6 +186,7 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { } @Override + @DisallowedUntilLayoutVersion(FILESYSTEM_SNAPSHOT) public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, ExecutionContext context) { OmSnapshotInternalMetrics omSnapshotIntMetrics = ozoneManager.getOmSnapshotIntMetrics(); From 9753136665f527ec3f64454ed2d55cb726a4ac14 Mon Sep 17 00:00:00 2001 From: Ethan Rose Date: Mon, 20 Apr 2026 17:54:59 -0400 Subject: [PATCH 7/7] HDDS-14496. Wire OM to OMVersionManager and remove layout-version manager path --- .../upgrade/AbstractLayoutVersionManager.java | 7 +- .../ozone/upgrade/LayoutVersionManager.java | 69 ----- .../ozone/om/TestOMBucketLayoutUpgrade.java | 14 +- .../ozone/om/TestOMUpgradeFinalization.java | 9 +- ... TestOmStartupInvalidApparentVersion.java} | 52 ++-- .../org/apache/hadoop/ozone/om/OMStorage.java | 4 +- .../apache/hadoop/ozone/om/OzoneManager.java | 97 ++----- .../ozone/om/request/OMClientRequest.java | 6 +- .../OMSnapshotMoveDeletedKeysRequest.java | 5 + .../OMSnapshotMoveTableKeysRequest.java | 2 +- .../upgrade/OMFinalizeUpgradeRequest.java | 6 +- .../request/validation/ValidationContext.java | 18 +- .../request/validation/VersionExtractor.java | 6 +- .../snapshot/OmSnapshotLocalDataManager.java | 10 +- .../RequireSnapshotFeatureStateAspect.java | 2 +- .../om/upgrade/OMLayoutFeatureAspect.java | 41 +-- .../om/upgrade/OMLayoutVersionManager.java | 149 ---------- .../ozone/om/upgrade/OMUpgradeFinalizer.java | 42 --- .../apache/hadoop/ozone/om/TestOMStorage.java | 4 +- .../TestOMClientRequestWithUserInfo.java | 7 +- .../om/request/bucket/TestBucketRequest.java | 8 +- .../file/TestOMDirectoryCreateRequest.java | 10 +- .../TestOMDirectoryCreateRequestWithFSO.java | 10 +- .../om/request/key/TestOMKeyRequest.java | 9 +- .../s3/multipart/TestS3MultipartRequest.java | 8 +- .../s3/security/TestS3GetSecretRequest.java | 9 +- .../s3/tenant/TestOMTenantCreateRequest.java | 10 +- .../s3/tenant/TestOMTenantDeleteRequest.java | 10 +- .../TestSetRangerServiceVersionRequest.java | 7 +- .../TestOMGetDelegationTokenRequest.java | 7 +- .../validation/TestRequestValidations.java | 10 +- .../validation/TestVersionExtractor.java | 8 +- .../request/volume/TestOMVolumeRequest.java | 8 +- .../TestOmSnapshotLocalDataManager.java | 15 +- .../TestSnapshotRequestAndResponse.java | 9 +- .../defrag/TestSnapshotDefragService.java | 9 +- .../ozone/om/upgrade/OMLayoutFeatureUtil.java | 66 ----- .../om/upgrade/TestOMLayoutFeatureAspect.java | 32 +- .../upgrade/TestOMLayoutVersionManager.java | 124 -------- .../om/upgrade/TestOMUpgradeFinalizer.java | 274 ------------------ ...TestOzoneDelegationTokenSecretManager.java | 7 +- 41 files changed, 208 insertions(+), 992 deletions(-) delete mode 100644 hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/LayoutVersionManager.java rename hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/{TestOmStartupSlvLessThanMlv.java => TestOmStartupInvalidApparentVersion.java} (58%) delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMLayoutVersionManager.java delete mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMUpgradeFinalizer.java delete mode 100644 hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/OMLayoutFeatureUtil.java delete mode 100644 hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMLayoutVersionManager.java delete mode 100644 hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMUpgradeFinalizer.java diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/AbstractLayoutVersionManager.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/AbstractLayoutVersionManager.java index 73aa6c077236..6baf0b7ee8a2 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/AbstractLayoutVersionManager.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/AbstractLayoutVersionManager.java @@ -38,7 +38,7 @@ */ @SuppressWarnings("visibilitymodifier") public abstract class AbstractLayoutVersionManager - implements LayoutVersionManager, LayoutVersionManagerMXBean { + implements LayoutVersionManagerMXBean { private static final Logger LOG = LoggerFactory.getLogger(AbstractLayoutVersionManager.class); @@ -164,7 +164,6 @@ public int getSoftwareLayoutVersion() { return softwareLayoutVersion; } - @Override public boolean needsFinalization() { lock.readLock().lock(); try { @@ -174,7 +173,6 @@ public boolean needsFinalization() { } } - @Override public boolean isAllowed(LayoutFeature layoutFeature) { lock.readLock().lock(); try { @@ -184,12 +182,10 @@ public boolean isAllowed(LayoutFeature layoutFeature) { } } - @Override public LayoutFeature getFeature(int layoutVersion) { return features.get(layoutVersion); } - @Override public Iterable unfinalizedFeatures() { lock.readLock().lock(); try { @@ -201,7 +197,6 @@ public Iterable unfinalizedFeatures() { } } - @Override public void close() { if (mBean != null) { MBeans.unregister(mBean); diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/LayoutVersionManager.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/LayoutVersionManager.java deleted file mode 100644 index ee2d145071c5..000000000000 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/LayoutVersionManager.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.upgrade; - -/** - * Read Only interface to an Ozone component's Version Manager. - */ -public interface LayoutVersionManager { - - /** - * Get the Current Metadata Layout Version. - * @return MLV - */ - int getMetadataLayoutVersion(); - - /** - * Get the Current Software Layout Version. - * @return SLV - */ - int getSoftwareLayoutVersion(); - - /** - * Does it need finalization? - * @return true/false - */ - boolean needsFinalization(); - - /** - * Is allowed feature? - * @param layoutFeature feature object - * @return true/false. - */ - boolean isAllowed(LayoutFeature layoutFeature); - - /** - * Get Feature given its layout version. - * @param layoutVersion Version number of the feature. - * @return LayoutFeature instance. - */ - LayoutFeature getFeature(int layoutVersion); - - Iterable unfinalizedFeatures(); - - /** - * Generic API for returning a registered handler for a given type. - * @param type String type - */ - default Object getHandler(String type) { - return null; - } - - void close(); - -} diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMBucketLayoutUpgrade.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMBucketLayoutUpgrade.java index 58b9bdc21725..6282046c9999 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMBucketLayoutUpgrade.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMBucketLayoutUpgrade.java @@ -21,7 +21,6 @@ import static org.apache.hadoop.ozone.om.OMUpgradeTestUtils.waitForFinalization; import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.NOT_SUPPORTED_OPERATION_PRIOR_FINALIZATION; import static org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature.INITIAL_VERSION; -import static org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager.maxLayoutVersion; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -31,10 +30,12 @@ import java.util.Set; import java.util.UUID; import org.apache.commons.lang3.RandomStringUtils; +import org.apache.hadoop.hdds.ComponentVersion; import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.hdds.utils.IOUtils; import org.apache.hadoop.ozone.MiniOzoneCluster; import org.apache.hadoop.ozone.MiniOzoneHAClusterImpl; +import org.apache.hadoop.ozone.OzoneManagerVersion; import org.apache.hadoop.ozone.client.OzoneClient; import org.apache.hadoop.ozone.om.exceptions.OMException; import org.apache.hadoop.ozone.om.helpers.BucketLayout; @@ -79,7 +80,7 @@ class TestOMBucketLayoutUpgrade { private MiniOzoneHAClusterImpl cluster; private OzoneManager ozoneManager; private static final String VOLUME_NAME = "vol-" + UUID.randomUUID(); - private final int fromLayoutVersion = INITIAL_VERSION.layoutVersion(); + private final ComponentVersion fromVersion = INITIAL_VERSION; private OzoneManagerProtocol omClient; private OzoneClient client; @@ -87,7 +88,7 @@ class TestOMBucketLayoutUpgrade { @BeforeAll void setup() throws Exception { OzoneConfiguration conf = new OzoneConfiguration(); - conf.setInt(OMStorage.TESTING_INIT_LAYOUT_VERSION_KEY, fromLayoutVersion); + conf.setInt(OMStorage.TESTING_INIT_LAYOUT_VERSION_KEY, fromVersion.serialize()); String omServiceId = UUID.randomUUID().toString(); MiniOzoneHAClusterImpl.Builder builder = MiniOzoneCluster.newHABuilder(conf); builder.setOMServiceId(omServiceId) @@ -120,8 +121,8 @@ void shutdown() { @Test @Order(PRE_UPGRADE) void omLayoutBeforeUpgrade() throws IOException { - assertEquals(fromLayoutVersion, - ozoneManager.getVersionManager().getMetadataLayoutVersion()); + assertEquals(fromVersion, + ozoneManager.getVersionManager().getApparentVersion()); assertNull(ozoneManager.getMetadataManager().getMetaTable() .get(LAYOUT_VERSION_KEY)); } @@ -157,7 +158,8 @@ void finalizeUpgrade() throws Exception { waitForFinalization(omClient); - final String expectedVersion = String.valueOf(maxLayoutVersion()); + final String expectedVersion = + String.valueOf(OzoneManagerVersion.SOFTWARE_VERSION.serialize()); LambdaTestUtils.await(30000, 3000, () -> expectedVersion.equals( ozoneManager.getMetadataManager().getMetaTable() diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMUpgradeFinalization.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMUpgradeFinalization.java index be0f99099770..3efe5a0d91d1 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMUpgradeFinalization.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOMUpgradeFinalization.java @@ -21,7 +21,6 @@ import static org.apache.hadoop.ozone.om.OMUpgradeTestUtils.assertClusterPrepared; import static org.apache.hadoop.ozone.om.OMUpgradeTestUtils.waitForFinalization; import static org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature.INITIAL_VERSION; -import static org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager.maxLayoutVersion; import static org.apache.ozone.test.GenericTestUtils.waitFor; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -34,6 +33,7 @@ import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.ozone.MiniOzoneCluster; import org.apache.hadoop.ozone.MiniOzoneHAClusterImpl; +import org.apache.hadoop.ozone.OzoneManagerVersion; import org.apache.hadoop.ozone.audit.AuditEventStatus; import org.apache.hadoop.ozone.audit.AuditLogTestUtils; import org.apache.hadoop.ozone.audit.OMAction; @@ -110,12 +110,13 @@ void testOMUpgradeFinalizationWithOneOMDown() throws Exception { waitFor(() -> !omStateMachine.getLifeCycle().getCurrentState() .isPausingOrPaused(), 1000, 60000); - assertEquals(maxLayoutVersion(), - downedOM.getVersionManager().getMetadataLayoutVersion()); + int expectedSerialized = OzoneManagerVersion.SOFTWARE_VERSION.serialize(); + assertEquals(expectedSerialized, + downedOM.getVersionManager().getApparentVersion().serialize()); String lvString = downedOM.getMetadataManager().getMetaTable() .get(LAYOUT_VERSION_KEY); assertNotNull(lvString); - assertEquals(maxLayoutVersion(), Integer.parseInt(lvString)); + assertEquals(expectedSerialized, Integer.parseInt(lvString)); } } } diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOmStartupSlvLessThanMlv.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOmStartupInvalidApparentVersion.java similarity index 58% rename from hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOmStartupSlvLessThanMlv.java rename to hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOmStartupInvalidApparentVersion.java index 78ec2713334c..bd4aad16a882 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOmStartupSlvLessThanMlv.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/TestOmStartupInvalidApparentVersion.java @@ -17,10 +17,12 @@ package org.apache.hadoop.ozone.om; +import static org.apache.hadoop.ozone.OzoneManagerVersion.SOFTWARE_VERSION; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.File; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -28,53 +30,53 @@ import org.apache.hadoop.hdds.protocol.proto.HddsProtos; import org.apache.hadoop.ozone.MiniOzoneCluster; import org.apache.hadoop.ozone.MiniOzoneClusterImpl; -import org.apache.hadoop.ozone.om.exceptions.OMException; import org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature; -import org.apache.hadoop.ozone.upgrade.LayoutFeature; import org.apache.hadoop.ozone.upgrade.UpgradeTestUtils; import org.apache.ozone.test.GenericTestUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; /** - * Test that the ozone manager will not start when it loads a VERSION file - * indicating a metadata layout version larger than its software layout version. + * Ensures OM does not start when the VERSION file records an apparent version newer than the software version + * baked into this process ({@link org.apache.hadoop.ozone.OzoneManagerVersion#SOFTWARE_VERSION}). */ -public class TestOmStartupSlvLessThanMlv { +public class TestOmStartupInvalidApparentVersion { @TempDir private Path folder; @Test - public void testStartupSlvLessThanMlv() throws Exception { - // Add subdirectories under the temporary folder where the version file - // will be placed. + public void testStartupFailsWhenApparentVersionBetweenLastLayoutFeatureAndZdu() + throws Exception { + assertStartupFailsWithComponentVersionMessage(OMLayoutFeature.SNAPSHOT_DEFRAG.layoutVersion() + 1); + } + + @Test + public void testStartupFailsWhenApparentVersionBeyondLastKnownComponentVersion() + throws Exception { + assertStartupFailsWithComponentVersionMessage(SOFTWARE_VERSION.serialize() + 1); + } + + private void assertStartupFailsWithComponentVersionMessage(int serializedApparentVersion) + throws Exception { String subDir = folder.toAbsolutePath() + "/om/current"; File omSubdir = Files.createDirectories(Paths.get(subDir)).toFile(); OzoneConfiguration conf = new OzoneConfiguration(); - conf.set(OMConfigKeys.OZONE_OM_DB_DIRS, - folder.toAbsolutePath().toString()); - - // Set metadata layout version larger than software layout version. - int largestSlv = 0; - for (LayoutFeature f: OMLayoutFeature.values()) { - largestSlv = Math.max(largestSlv, f.layoutVersion()); - } - int mlv = largestSlv + 1; + conf.set(OMConfigKeys.OZONE_OM_DB_DIRS, folder.toAbsolutePath().toString()); - // Create version file with MLV > SLV, which should fail the cluster build. - UpgradeTestUtils.createVersionFile(omSubdir, HddsProtos.NodeType.OM, mlv); + UpgradeTestUtils.createVersionFile(omSubdir, HddsProtos.NodeType.OM, serializedApparentVersion); MiniOzoneCluster.Builder clusterBuilder = MiniOzoneCluster.newBuilder(conf); + String expectedMessage = + "Initialization failed. Disk contains unknown apparent version " + serializedApparentVersion + + " for software version " + SOFTWARE_VERSION + ". Make sure OM was not downgraded after" + + " finalization"; + GenericTestUtils.withLogDisabled(MiniOzoneClusterImpl.class, () -> { - OMException omException = assertThrows(OMException.class, - clusterBuilder::build); - String expectedMessage = String.format("Cannot initialize " + - "VersionManager. Metadata layout version (%s) > software layout" + - " version (%s)", mlv, mlv - 1); - assertEquals(expectedMessage, omException.getMessage()); + IOException ioException = assertThrows(IOException.class, clusterBuilder::build); + assertEquals(expectedMessage, ioException.getMessage()); }); } } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java index 518ae6231144..8c97ee4232e3 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMStorage.java @@ -25,8 +25,8 @@ import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeType; import org.apache.hadoop.hdds.server.ServerUtils; +import org.apache.hadoop.ozone.OzoneManagerVersion; import org.apache.hadoop.ozone.common.Storage; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; /** * Ozone Manager VERSION file representation. @@ -92,7 +92,7 @@ public class OMStorage extends Storage { public OMStorage(OzoneConfiguration conf) throws IOException { super(NodeType.OM, getOmDbDir(conf), STORAGE_DIR, getInitApparentVersion(conf, TESTING_INIT_LAYOUT_VERSION_KEY, - OMLayoutVersionManager::maxLayoutVersion)); + () -> OzoneManagerVersion.SOFTWARE_VERSION.serialize())); } /** 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 b427729df931..f8310902017a 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 @@ -41,7 +41,6 @@ import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_SCM_BLOCK_SIZE_DEFAULT; import static org.apache.hadoop.ozone.OzoneConsts.DB_TRANSIENT_MARKER; import static org.apache.hadoop.ozone.OzoneConsts.DEFAULT_OM_UPDATE_ID; -import static org.apache.hadoop.ozone.OzoneConsts.LAYOUT_VERSION_KEY; import static org.apache.hadoop.ozone.OzoneConsts.OM_DB_NAME; import static org.apache.hadoop.ozone.OzoneConsts.OM_KEY_PREFIX; import static org.apache.hadoop.ozone.OzoneConsts.OM_METRICS_FILE; @@ -101,6 +100,10 @@ import static org.apache.hadoop.ozone.protocol.proto.OzoneManagerInterServiceProtocolProtos.OzoneManagerInterService; import static org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OzoneManagerService; import static org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.PrepareStatusResponse.PrepareStatus; +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; @@ -287,8 +290,7 @@ import org.apache.hadoop.ozone.om.service.QuotaRepairTask; import org.apache.hadoop.ozone.om.snapshot.defrag.SnapshotDefragService; import org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; -import org.apache.hadoop.ozone.om.upgrade.OMUpgradeFinalizer; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerAdminProtocolProtos.OzoneManagerAdminService; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.DBUpdatesRequest; @@ -320,7 +322,6 @@ import org.apache.hadoop.ozone.snapshot.SnapshotDiffResponse; import org.apache.hadoop.ozone.storage.proto.OzoneManagerStorageProtos.PersistedUserVolumeInfo; import org.apache.hadoop.ozone.upgrade.UpgradeFinalization.StatusAndMessages; -import org.apache.hadoop.ozone.upgrade.UpgradeFinalizer; import org.apache.hadoop.ozone.util.OzoneNetUtils; import org.apache.hadoop.ozone.util.OzoneVersionInfo; import org.apache.hadoop.ozone.util.ShutdownHookManager; @@ -399,7 +400,6 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl private BucketManager bucketManager; private KeyManager keyManager; private PrefixManagerImpl prefixManager; - private final UpgradeFinalizer upgradeFinalizer; private ExecutorService edekCacheLoader = null; /** @@ -449,7 +449,7 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl private List ratisReporterList = null; private KeyProviderCryptoExtension kmsProvider; - private final OMLayoutVersionManager versionManager; + private final OMVersionManager versionManager; private final ReplicationConfigValidator replicationConfigValidator; @@ -532,8 +532,6 @@ private OzoneManager(OzoneConfiguration conf, StartupOption startupOption) reconfigurationHandler.setReconfigurationCompleteCallback(reconfigurationHandler.defaultLoggingCallback()); - versionManager = new OMLayoutVersionManager(omStorage.getApparentVersion()); - upgradeFinalizer = new OMUpgradeFinalizer(versionManager); replicationConfigValidator = conf.getObject(ReplicationConfigValidator.class); @@ -561,6 +559,8 @@ private OzoneManager(OzoneConfiguration conf, StartupOption startupOption) } omMetaDir = OMStorage.getOmDbDir(configuration); + versionManager = new OMVersionManager(omStorage, this); + this.isSpnegoEnabled = conf.get(OZONE_OM_HTTP_AUTH_TYPE, "simple") .equals("kerberos"); this.isOmGrpcServerEnabled = conf.getBoolean( @@ -916,6 +916,7 @@ private void instantiateServices(boolean withNewSnapshot) throws IOException { OmMetadataManagerImpl metadataManagerImpl = new OmMetadataManagerImpl(configuration, this); this.metadataManager = metadataManagerImpl; + versionManager.validateDBVersion(metadataManager); LOG.info("S3 Multi-Tenancy is {}", isS3MultiTenancyEnabled ? "enabled" : "disabled"); if (isS3MultiTenancyEnabled) { @@ -1002,23 +1003,7 @@ public void close() { updateActiveSnapshotMetrics(); if (withNewSnapshot) { - Integer layoutVersionInDB = getLayoutVersionInDB(); - if (layoutVersionInDB != null && - versionManager.getMetadataLayoutVersion() < layoutVersionInDB) { - LOG.info("New OM snapshot received with higher layout version {}. " + - "Attempting to finalize current OM to that version.", - layoutVersionInDB); - upgradeFinalizer.finalizeAndWaitForCompletion( - "om-ratis-snapshot", this, - config.getRatisBasedFinalizationTimeout()); - if (versionManager.getMetadataLayoutVersion() < layoutVersionInDB) { - throw new IOException("Unable to finalize OM to the desired layout " + - "version " + layoutVersionInDB + " present in the snapshot DB."); - } else { - updateLayoutVersionInDB(versionManager, metadataManager); - } - } - + versionManager.finalizeFromSnapshotIfRequired(metadataManager); instantiatePrepareStateAfterSnapshot(); } else { // Prepare state depends on the transaction ID of metadataManager after a @@ -1544,13 +1529,13 @@ public static boolean omInit(OzoneConfiguration conf) throws IOException, System.out.println( "OM initialization succeeded.Current cluster id for sd=" + omStorage.getStorageDir() + ";cid=" + omStorage - .getClusterID() + ";layoutVersion=" + omStorage + .getClusterID() + ";apparentVersion=" + omStorage .getApparentVersion()); } else { System.out.println( "OM already initialized.Reusing existing cluster id for sd=" + omStorage.getStorageDir() + ";cid=" + omStorage - .getClusterID() + ";layoutVersion=" + omStorage + .getClusterID() + ";apparentVersion=" + omStorage .getApparentVersion()); } } catch (IOException ioe) { @@ -1825,15 +1810,6 @@ public void start() throws IOException { omRatisServer.start(); } - Integer layoutVersionInDB = getLayoutVersionInDB(); - if (layoutVersionInDB == null || - versionManager.getMetadataLayoutVersion() != layoutVersionInDB) { - LOG.info("Version File has different layout " + - "version ({}) than OM DB ({}). That is expected if this " + - "OM has never been finalized to a newer layout version.", - versionManager.getMetadataLayoutVersion(), layoutVersionInDB); - } - metrics.setNumVolumes(metadataManager .countEstimatedRowsInTable(metadataManager.getVolumeTable())); metrics.setNumBuckets(metadataManager @@ -2338,17 +2314,6 @@ public long getObjectIdFromTxId(long trxnId) { trxnId); } - /** - * - * @return Gets the stored layout version from the DB meta table. - * @throws IOException on Error. - */ - private Integer getLayoutVersionInDB() throws IOException { - String layoutVersion = - metadataManager.getMetaTable().get(LAYOUT_VERSION_KEY); - return (layoutVersion == null) ? null : Integer.parseInt(layoutVersion); - } - public TransactionInfo getTransactionInfo() { return omTransactionInfo.get(); } @@ -3597,20 +3562,27 @@ public boolean triggerSnapshotDefrag(boolean noWait) throws IOException { } @Override - public StatusAndMessages finalizeUpgrade(String upgradeClientID) + public StatusAndMessages finalizeUpgrade(String unusedUpgradeClientId) throws IOException { - return upgradeFinalizer.finalize(upgradeClientID, this); + if (!versionManager.needsFinalization()) { + return FINALIZED_MSG; + } + versionManager.finalizeUpgrade(); + // OM clients currently require STARTING_MSG to be returned when this method succeeds. + // TODO This will be removed when OM learns to finalize from SCM. + + return STARTING_MSG; } @Override public StatusAndMessages queryUpgradeFinalizationProgress( - String upgradeClientID, boolean takeover, boolean readonly - ) throws IOException { - if (readonly) { - return new StatusAndMessages(upgradeFinalizer.getStatus(), - Collections.emptyList()); + String unusedUpgradeClientId, boolean unusedTakeover, boolean unusedReadonly) + throws IOException { + if (versionManager.needsFinalization()) { + return FINALIZATION_REQUIRED_MSG; + } else { + return FINALIZATION_DONE_MSG; } - return upgradeFinalizer.reportStatus(upgradeClientID, takeover); } /** @@ -4876,7 +4848,7 @@ private OmVolumeArgs createS3VolumeContext(String s3Volume, return omVolumeArgs.build(); } - public OMLayoutVersionManager getVersionManager() { + public OMVersionManager getVersionManager() { return versionManager; } @@ -5045,19 +5017,6 @@ public Map getObjectTagging(final OmKeyArgs args) } } - /** - * Write down Layout version of a finalized feature to DB on finalization. - * @param lvm OMLayoutVersionManager - * @param omMetadataManager omMetadataManager instance - * @throws IOException on Error. - */ - private void updateLayoutVersionInDB(OMLayoutVersionManager lvm, - OMMetadataManager omMetadataManager) - throws IOException { - omMetadataManager.getMetaTable().put(LAYOUT_VERSION_KEY, - String.valueOf(lvm.getMetadataLayoutVersion())); - } - private BucketLayout getBucketLayout() { return BucketLayout.DEFAULT; } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/OMClientRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/OMClientRequest.java index fdb1f30a7cb2..c61992821ab6 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/OMClientRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/OMClientRequest.java @@ -112,12 +112,12 @@ public OMClientRequest(OMRequest omRequest) { */ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { - LayoutVersion layoutVersion = LayoutVersion.newBuilder() - .setVersion(ozoneManager.getVersionManager().getMetadataLayoutVersion()) + LayoutVersion apparentVersion = LayoutVersion.newBuilder() + .setVersion(ozoneManager.getVersionManager().getApparentVersion().serialize()) .build(); omRequest = getOmRequest().toBuilder() .setUserInfo(getUserIfNotExists(ozoneManager)) - .setLayoutVersion(layoutVersion).build(); + .setLayoutVersion(apparentVersion).build(); return omRequest; } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveDeletedKeysRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveDeletedKeysRequest.java index 73a2a89b22b2..95fa38c51ec8 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveDeletedKeysRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveDeletedKeysRequest.java @@ -52,6 +52,11 @@ public OMSnapshotMoveDeletedKeysRequest(OMRequest omRequest) { @Override @DisallowedUntilLayoutVersion(FILESYSTEM_SNAPSHOT) + public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { + return super.preExecute(ozoneManager); + } + + @Override public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, ExecutionContext context) { OmMetadataManagerImpl omMetadataManager = (OmMetadataManagerImpl) ozoneManager.getMetadataManager(); diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveTableKeysRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveTableKeysRequest.java index fef5dc76c4de..2f8a81f5ce67 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveTableKeysRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotMoveTableKeysRequest.java @@ -73,6 +73,7 @@ public OMSnapshotMoveTableKeysRequest(OMRequest omRequest) { } @Override + @DisallowedUntilLayoutVersion(FILESYSTEM_SNAPSHOT) public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { OmMetadataManagerImpl omMetadataManager = (OmMetadataManagerImpl) ozoneManager.getMetadataManager(); SnapshotChainManager snapshotChainManager = omMetadataManager.getSnapshotChainManager(); @@ -186,7 +187,6 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { } @Override - @DisallowedUntilLayoutVersion(FILESYSTEM_SNAPSHOT) public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, ExecutionContext context) { OmSnapshotInternalMetrics omSnapshotIntMetrics = ozoneManager.getOmSnapshotIntMetrics(); 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/OMFinalizeUpgradeRequest.java index b37d1ee6d1dc..07ae3423e054 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/OMFinalizeUpgradeRequest.java @@ -79,9 +79,7 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, Execut FinalizeUpgradeRequest request = getOmRequest().getFinalizeUpgradeRequest(); - String upgradeClientID = request.getUpgradeClientId(); - StatusAndMessages omStatus = ozoneManager.finalizeUpgrade(upgradeClientID); @@ -93,7 +91,7 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, Execut .build(); OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager(); - int lV = ozoneManager.getVersionManager().getMetadataLayoutVersion(); + int lV = ozoneManager.getVersionManager().getApparentVersion().serialize(); omMetadataManager.getMetaTable().addCacheEntry( new CacheKey<>(LAYOUT_VERSION_KEY), CacheValue.get(context.getIndex(), String.valueOf(lV))); @@ -104,7 +102,7 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, Execut .build(); responseBuilder.setFinalizeUpgradeResponse(omResponse); response = new OMFinalizeUpgradeResponse(responseBuilder.build(), - ozoneManager.getVersionManager().getMetadataLayoutVersion()); + ozoneManager.getVersionManager().getApparentVersion().serialize()); LOG.trace("Returning response: {}", response); } catch (IOException e) { exception = e; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/ValidationContext.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/ValidationContext.java index ad3c938b1e08..74e574a9456c 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/ValidationContext.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/ValidationContext.java @@ -22,7 +22,7 @@ import org.apache.hadoop.ozone.om.OMMetadataManager; import org.apache.hadoop.ozone.om.OzoneManagerUtils; import org.apache.hadoop.ozone.om.helpers.BucketLayout; -import org.apache.hadoop.ozone.upgrade.LayoutVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; /** * A context that contains useful information for request validator instances. @@ -31,13 +31,11 @@ public interface ValidationContext { /** - * Gets the {@link LayoutVersionManager} of the service, so that a pre - * finalization validation can check if the layout version it belongs to - * is finalized already or not. + * Gets the OM component version manager for pre-finalization checks and feature gating. * - * @return the {@link LayoutVersionManager} of the service + * @return the {@link OMVersionManager} of the service */ - LayoutVersionManager versionManager(); + OMVersionManager versionManager(); /** * Gets the {@link BucketLayout} of the given bucket. In case of a link bucket @@ -51,16 +49,16 @@ BucketLayout getBucketLayout(String volumeName, String bucketName) /** * Creates a context object based on the given parameters. * - * @param versionManager the {@link LayoutVersionManager} of the service + * @param omVersionManager the {@link OMVersionManager} of the service * @return the {@link ValidationContext} specified by the parameters. */ - static ValidationContext of(LayoutVersionManager versionManager, + static ValidationContext of(OMVersionManager omVersionManager, OMMetadataManager omMetadataManager) { return new ValidationContext() { @Override - public LayoutVersionManager versionManager() { - return versionManager; + public OMVersionManager versionManager() { + return omVersionManager; } @Override diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/VersionExtractor.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/VersionExtractor.java index 4b9a8de52660..9471d425fac1 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/VersionExtractor.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/VersionExtractor.java @@ -21,20 +21,18 @@ import org.apache.hadoop.hdds.ComponentVersion; import org.apache.hadoop.ozone.ClientVersion; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; -import org.apache.hadoop.ozone.upgrade.LayoutVersionManager; /** * Class to extract version out of OM request. */ public enum VersionExtractor { /** - * Extracts current metadata layout version. + * Extracts current apparent component version (legacy layout or {@link org.apache.hadoop.ozone.OzoneManagerVersion}). */ LAYOUT_VERSION_EXTRACTOR { @Override public ComponentVersion extractVersion(OMRequest req, ValidationContext ctx) { - LayoutVersionManager layoutVersionManager = ctx.versionManager(); - return ctx.versionManager().getFeature(layoutVersionManager.getMetadataLayoutVersion()); + return ctx.versionManager().getApparentVersion(); } @Override diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/OmSnapshotLocalDataManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/OmSnapshotLocalDataManager.java index cec65701c808..66773e80ee88 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/OmSnapshotLocalDataManager.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/OmSnapshotLocalDataManager.java @@ -70,7 +70,7 @@ import org.apache.hadoop.ozone.om.helpers.SnapshotInfo; import org.apache.hadoop.ozone.om.lock.HierarchicalResourceLockManager; import org.apache.hadoop.ozone.om.lock.HierarchicalResourceLockManager.HierarchicalResourceLock; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; import org.apache.hadoop.ozone.util.ObjectSerializer; import org.apache.hadoop.ozone.util.YamlSerializer; import org.apache.ratis.util.function.CheckedFunction; @@ -119,7 +119,7 @@ public class OmSnapshotLocalDataManager implements AutoCloseable { private volatile boolean closed; public OmSnapshotLocalDataManager(OMMetadataManager omMetadataManager, - SnapshotChainManager snapshotChainManager, OMLayoutVersionManager omLayoutVersionManager, + SnapshotChainManager snapshotChainManager, OMVersionManager omVersionManager, CheckedFunction defaultSnapProvider, OzoneConfiguration configuration) throws IOException { this.localDataGraph = GraphBuilder.directed().build(); @@ -134,7 +134,7 @@ public void computeAndSetChecksum(Yaml yaml, OmSnapshotLocalData data) throws IO }; this.versionNodeMap = new ConcurrentHashMap<>(); this.internalLock = new ReentrantReadWriteLock(); - init(configuration, snapshotChainManager, omLayoutVersionManager, defaultSnapProvider); + init(configuration, snapshotChainManager, omVersionManager, defaultSnapProvider); } public Map getVersionNodeMapUnmodifiable() { @@ -342,14 +342,14 @@ Map getSnapshotToBeCheckedForOrphans() { } private void init(OzoneConfiguration configuration, SnapshotChainManager chainManager, - OMLayoutVersionManager layoutVersionManager, + OMVersionManager omVersionManager, CheckedFunction defaultSnapProvider) throws IOException { this.locks = omMetadataManager.getHierarchicalLockManager(); this.snapshotToBeCheckedForOrphans = new ConcurrentHashMap<>(); RDBStore store = (RDBStore) omMetadataManager.getStore(); String checkpointPrefix = store.getDbLocation().getName(); File snapshotDir = new File(store.getSnapshotsParentDir()); - boolean upgradeNeeded = !layoutVersionManager.isAllowed(SNAPSHOT_DEFRAG); + boolean upgradeNeeded = !omVersionManager.isAllowed(SNAPSHOT_DEFRAG); if (upgradeNeeded) { addMissingSnapshotYamlFiles(defaultSnapProvider); } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/RequireSnapshotFeatureStateAspect.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/RequireSnapshotFeatureStateAspect.java index 4166fe2e827f..48688bfdbbc7 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/RequireSnapshotFeatureStateAspect.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/RequireSnapshotFeatureStateAspect.java @@ -36,7 +36,7 @@ /** * 'Aspect' for checking whether snapshot feature is enabled. * All methods annotated with the specific annotation will have pre-processing - * done here to check layout version compatibility. + * done here to check snapshot feature / component version compatibility. * Note: Append class to * hadoop-ozone/ozone-manager/src/main/resources/META-INF/aop.xml * if the annotation doesn't seem to take affect on other classes' methods. diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMLayoutFeatureAspect.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMLayoutFeatureAspect.java index 20edda53823f..aeedb72d4ce6 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMLayoutFeatureAspect.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMLayoutFeatureAspect.java @@ -20,20 +20,16 @@ import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.NOT_SUPPORTED_OPERATION_PRIOR_FINALIZATION; import java.io.IOException; -import java.lang.reflect.Method; import org.apache.hadoop.ozone.om.OzoneManager; import org.apache.hadoop.ozone.om.exceptions.OMException; import org.apache.hadoop.ozone.om.request.OMClientRequest; import org.apache.hadoop.ozone.protocolPB.OzoneManagerRequestHandler; import org.apache.hadoop.ozone.upgrade.LayoutFeature; -import org.apache.hadoop.ozone.upgrade.LayoutVersionManager; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * 'Aspect' for OM Layout Feature API. All methods annotated with the @@ -43,50 +39,41 @@ @Aspect public class OMLayoutFeatureAspect { - public static final String GET_VERSION_MANAGER_METHOD_NAME = - "getOmVersionManager"; - private static final Logger LOG = LoggerFactory - .getLogger(OMLayoutFeatureAspect.class); - @Before("@annotation(DisallowedUntilLayoutVersion) && execution(* *(..))") public void checkLayoutFeature(JoinPoint joinPoint) throws IOException { LayoutFeature layoutFeature = ((MethodSignature) joinPoint.getSignature()) .getMethod().getAnnotation(DisallowedUntilLayoutVersion.class) .value(); - LayoutVersionManager lvm; + OMVersionManager versionManager = null; final Object[] args = joinPoint.getArgs(); if (joinPoint.getTarget() instanceof OzoneManagerRequestHandler) { OzoneManager ozoneManager = ((OzoneManagerRequestHandler) joinPoint.getTarget()).getOzoneManager(); - lvm = ozoneManager.getVersionManager(); + versionManager = ozoneManager.getVersionManager(); } else if (joinPoint.getTarget() instanceof OMClientRequest && joinPoint.toShortString().endsWith(".preExecute(..))")) { // Get OzoneManager instance from preExecute first argument OzoneManager ozoneManager = (OzoneManager) args[0]; - lvm = ozoneManager.getVersionManager(); + versionManager = ozoneManager.getVersionManager(); } else { - try { - Method method = joinPoint.getTarget().getClass() - .getMethod(GET_VERSION_MANAGER_METHOD_NAME); - lvm = (LayoutVersionManager) method.invoke(joinPoint.getTarget()); - } catch (Exception ex) { - lvm = new OMLayoutVersionManager(); - } + throw new IOException( + "Unable to resolve OMVersionManager for layout validation; " + + "expected OzoneManagerRequestHandler or OMClientRequest.preExecute: " + + joinPoint.toShortString()); } - checkIsAllowed(joinPoint.getSignature().toShortString(), lvm, layoutFeature); + // Throws an exception that must be propagated if the request is not allowed. + checkIsAllowed(joinPoint.getSignature().toShortString(), versionManager, layoutFeature); } private void checkIsAllowed(String operationName, - LayoutVersionManager lvm, + OMVersionManager omVersionManager, LayoutFeature layoutFeature) throws OMException { - if (!lvm.isAllowed(layoutFeature)) { + if (!omVersionManager.isAllowed(layoutFeature)) { throw new OMException(String.format("Operation %s cannot be invoked " + - "before finalization. It belongs to the layout feature %s, " + - "whose layout version is %d. Current Layout version is %d", + "before finalization. It belongs to version %s. Current apparent version is %s", operationName, - layoutFeature.toString(), - layoutFeature.layoutVersion(), - lvm.getMetadataLayoutVersion()), + layoutFeature, + omVersionManager.getApparentVersion()), NOT_SUPPORTED_OPERATION_PRIOR_FINALIZATION); } } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMLayoutVersionManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMLayoutVersionManager.java deleted file mode 100644 index 5da5919af17c..000000000000 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMLayoutVersionManager.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * 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.upgrade; - -import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.NOT_SUPPORTED_OPERATION; - -import com.google.common.annotations.VisibleForTesting; -import java.io.IOException; -import java.lang.reflect.Modifier; -import java.util.HashSet; -import java.util.Set; -import org.apache.hadoop.ozone.om.exceptions.OMException; -import org.apache.hadoop.ozone.om.request.OMClientRequest; -import org.apache.hadoop.ozone.upgrade.AbstractLayoutVersionManager; -import org.reflections.Reflections; -import org.reflections.scanners.SubTypesScanner; -import org.reflections.scanners.TypeAnnotationsScanner; -import org.reflections.util.ClasspathHelper; -import org.reflections.util.ConfigurationBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Class to manage layout versions and features for Ozone Manager. - */ -public final class OMLayoutVersionManager - extends AbstractLayoutVersionManager { - - private static final Logger LOG = - LoggerFactory.getLogger(OMLayoutVersionManager.class); - - public static final String OM_CLASS_PACKAGE = - "org.apache.hadoop.ozone.om"; - public static final String OM_REQUEST_CLASS_PACKAGE = - OM_CLASS_PACKAGE + ".request"; - public static final String OM_UPGRADE_CLASS_PACKAGE = - OM_CLASS_PACKAGE + ".upgrade"; - - public OMLayoutVersionManager(int layoutVersion) throws OMException { - init(layoutVersion); - } - - public OMLayoutVersionManager() throws IOException { - OMLayoutFeature[] features = OMLayoutFeature.values(); - init(features[features.length - 1].layoutVersion(), features); - } - - /** - * Initialize the OM Layout Features and current Layout Version. - * @throws OMException on error. - */ - private void init(int layoutVersion) throws OMException { - try { - init(layoutVersion, OMLayoutFeature.values()); - } catch (IOException e) { - throw new OMException( - String.format("Cannot initialize VersionManager. Metadata " + - "layout version (%d) > software layout version (%d)", - getMetadataLayoutVersion(), getSoftwareLayoutVersion()), - e, - NOT_SUPPORTED_OPERATION); - } - registerUpgradeActions(OM_UPGRADE_CLASS_PACKAGE); - } - - /** - * Scan classpath and register all actions to layout features. - */ - @VisibleForTesting - protected void registerUpgradeActions(String packageName) { - Reflections reflections = new Reflections(new ConfigurationBuilder() - .forPackages(packageName) - .setScanners(new TypeAnnotationsScanner(), new SubTypesScanner()) - .setExpandSuperTypes(false) - .setParallel(true)); - Set> typesAnnotatedWith = - reflections.getTypesAnnotatedWith(UpgradeActionOm.class); - typesAnnotatedWith.forEach(actionClass -> { - if (OmUpgradeAction.class.isAssignableFrom(actionClass)) { - try { - OmUpgradeAction action = (OmUpgradeAction) actionClass.newInstance(); - UpgradeActionOm annotation = - actionClass.getAnnotation(UpgradeActionOm.class); - OMLayoutFeature feature = annotation.feature(); - if (feature.layoutVersion() > getMetadataLayoutVersion()) { - LOG.info("Registering Upgrade Action : {}", action.name()); - feature.addAction(action); - } else { - LOG.info("Skipping Upgrade Action {} since it has been finalized" + - ".", action.name()); - } - } catch (Exception e) { - LOG.error("Cannot instantiate Upgrade Action class {}", - actionClass.getSimpleName(), e); - } - } else { - LOG.warn("Found upgrade action class not of type " + - "org.apache.hadoop.ozone.om.upgrade.OmUpgradeAction : {}", - actionClass.getName()); - } - }); - } - - @VisibleForTesting - public static Set> getRequestClasses( - String packageName) { - Reflections reflections = new Reflections(new ConfigurationBuilder() - .setUrls(ClasspathHelper.forPackage(packageName)) - .setScanners(new SubTypesScanner()) - .setExpandSuperTypes(false) - .setParallel(true)); - Set> validRequests = new HashSet<>(); - - Set> subTypes = - reflections.getSubTypesOf(OMClientRequest.class); - for (Class requestClass : subTypes) { - if (!Modifier.isAbstract(requestClass.getModifiers())) { - validRequests.add(requestClass); - } - } - return validRequests; - } - - @Override - public void finalized(OMLayoutFeature layoutFeature) { - super.finalized(layoutFeature); - } - - public static int maxLayoutVersion() { - OMLayoutFeature[] features = OMLayoutFeature.values(); - return features[features.length - 1].layoutVersion(); - } - -} diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMUpgradeFinalizer.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMUpgradeFinalizer.java deleted file mode 100644 index 20bf57d93f35..000000000000 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMUpgradeFinalizer.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.upgrade; - -import org.apache.hadoop.ozone.om.OzoneManager; -import org.apache.hadoop.ozone.upgrade.BasicUpgradeFinalizer; -import org.apache.hadoop.ozone.upgrade.LayoutFeature; -import org.apache.hadoop.ozone.upgrade.UpgradeException; - -/** - * UpgradeFinalizer implementation for the Ozone Manager service. - */ -public class OMUpgradeFinalizer extends BasicUpgradeFinalizer { - - public OMUpgradeFinalizer(OMLayoutVersionManager versionManager) { - super(versionManager); - } - - @Override - public void finalizeLayoutFeature(LayoutFeature layoutFeature, - OzoneManager om) throws UpgradeException { - super.finalizeLayoutFeature(layoutFeature, - layoutFeature.action(), - om.getOmStorage()); - } -} diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestOMStorage.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestOMStorage.java index ce85249c1a7a..31f931b8a141 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestOMStorage.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestOMStorage.java @@ -39,7 +39,7 @@ import java.util.UUID; import org.apache.hadoop.hdds.HddsConfigKeys; import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; +import org.apache.hadoop.ozone.OzoneManagerVersion; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -282,7 +282,7 @@ private void setupAPersistedVersionFileWithNodeId( OzoneConfiguration conf, String nodeId) throws IOException { OMStorage storage = new OMStorage(conf); storage.setClusterId("clusterId"); - storage.setApparentVersion(OMLayoutVersionManager.maxLayoutVersion()); + storage.setApparentVersion(OzoneManagerVersion.SOFTWARE_VERSION.serialize()); storage.setOmId(OM_ID_STR); if (nodeId != null) { storage.setOmNodeId(nodeId); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMClientRequestWithUserInfo.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMClientRequestWithUserInfo.java index 145ffe9854fe..1375693dcd63 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMClientRequestWithUserInfo.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMClientRequestWithUserInfo.java @@ -44,7 +44,8 @@ import org.apache.hadoop.ozone.om.helpers.BucketLayout; import org.apache.hadoop.ozone.om.request.bucket.OMBucketCreateRequest; import org.apache.hadoop.ozone.om.request.key.OMKeyCommitRequest; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManagerTestUtils; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.BucketInfo; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; @@ -85,9 +86,7 @@ public void setup() throws Exception { when(omConfig.isFileSystemPathEnabled()).thenReturn(false); when(ozoneManager.getConfig()).thenReturn(omConfig); - // Mock version manager to avoid NPE in preExecute - OMLayoutVersionManager versionManager = mock(OMLayoutVersionManager.class); - when(versionManager.getMetadataLayoutVersion()).thenReturn(0); + OMVersionManager versionManager = OMVersionManagerTestUtils.mockFinalizedOmVersionManager(); when(ozoneManager.getVersionManager()).thenReturn(versionManager); inetAddress = InetAddress.getByName("127.0.0.1"); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestBucketRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestBucketRequest.java index 018e60633a50..355c64739e23 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestBucketRequest.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestBucketRequest.java @@ -37,7 +37,8 @@ import org.apache.hadoop.ozone.om.OzoneManager; import org.apache.hadoop.ozone.om.ResolvedBucket; import org.apache.hadoop.ozone.om.helpers.BucketLayout; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManagerTestUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.io.TempDir; @@ -75,9 +76,8 @@ public void setup() throws Exception { setupReplicationConfigValidation(ozoneManager, ozoneConfiguration); - OMLayoutVersionManager lvm = mock(OMLayoutVersionManager.class); - when(lvm.getMetadataLayoutVersion()).thenReturn(0); - when(ozoneManager.getVersionManager()).thenReturn(lvm); + OMVersionManager versionManager = OMVersionManagerTestUtils.mockFinalizedOmVersionManager(); + when(ozoneManager.getVersionManager()).thenReturn(versionManager); auditLogger = mock(AuditLogger.class); when(ozoneManager.getAuditLogger()).thenReturn(auditLogger); doNothing().when(auditLogger).logWrite(any(AuditMessage.class)); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/file/TestOMDirectoryCreateRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/file/TestOMDirectoryCreateRequest.java index 04351d3f8299..bfc69b0b3a4c 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/file/TestOMDirectoryCreateRequest.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/file/TestOMDirectoryCreateRequest.java @@ -63,12 +63,12 @@ import org.apache.hadoop.ozone.om.request.OMClientRequest; import org.apache.hadoop.ozone.om.request.OMRequestTestUtils; import org.apache.hadoop.ozone.om.response.OMClientResponse; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManagerTestUtils; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CreateDirectoryRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyArgs; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; -import org.apache.hadoop.ozone.upgrade.LayoutFeature; import org.apache.hadoop.security.UserGroupInformation; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -110,10 +110,8 @@ public void setup() throws Exception { .thenReturn(new ResolvedBucket("", "", "", "", "", BucketLayout.DEFAULT)); - OMLayoutVersionManager lvm = mock(OMLayoutVersionManager.class); - when(lvm.getMetadataLayoutVersion()).thenReturn(0); - when(lvm.isAllowed(any(LayoutFeature.class))).thenReturn(true); - when(ozoneManager.getVersionManager()).thenReturn(lvm); + OMVersionManager versionManager = OMVersionManagerTestUtils.mockFinalizedOmVersionManager(); + when(ozoneManager.getVersionManager()).thenReturn(versionManager); } @AfterEach diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/file/TestOMDirectoryCreateRequestWithFSO.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/file/TestOMDirectoryCreateRequestWithFSO.java index fd125563825d..ea4241aa9666 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/file/TestOMDirectoryCreateRequestWithFSO.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/file/TestOMDirectoryCreateRequestWithFSO.java @@ -63,12 +63,12 @@ import org.apache.hadoop.ozone.om.request.OMClientRequest; import org.apache.hadoop.ozone.om.request.OMRequestTestUtils; import org.apache.hadoop.ozone.om.response.OMClientResponse; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManagerTestUtils; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CreateDirectoryRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyArgs; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; -import org.apache.hadoop.ozone.upgrade.LayoutFeature; import org.apache.hadoop.security.UserGroupInformation; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -111,10 +111,8 @@ public void setup() throws Exception { .thenReturn(new ResolvedBucket("", "", "", "", "", BucketLayout.DEFAULT)); - OMLayoutVersionManager lvm = mock(OMLayoutVersionManager.class); - when(lvm.getMetadataLayoutVersion()).thenReturn(0); - when(lvm.isAllowed(any(LayoutFeature.class))).thenReturn(true); - when(ozoneManager.getVersionManager()).thenReturn(lvm); + OMVersionManager versionManager = OMVersionManagerTestUtils.mockFinalizedOmVersionManager(); + when(ozoneManager.getVersionManager()).thenReturn(versionManager); } @AfterEach diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyRequest.java index 8643802723ec..7fc22047400c 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyRequest.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyRequest.java @@ -83,11 +83,11 @@ import org.apache.hadoop.ozone.om.request.snapshot.OMSnapshotCreateRequest; import org.apache.hadoop.ozone.om.request.snapshot.TestOMSnapshotCreateRequest; import org.apache.hadoop.ozone.om.response.snapshot.OMSnapshotCreateResponse; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManagerTestUtils; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyArgs; import org.apache.hadoop.ozone.security.acl.OzoneNativeAuthorizer; -import org.apache.hadoop.ozone.upgrade.LayoutFeature; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.util.Time; import org.apache.ozone.test.GenericTestUtils; @@ -155,9 +155,8 @@ public void setup() throws Exception { when(ozoneManager.getMetadataManager()).thenReturn(omMetadataManager); when(ozoneManager.getConfiguration()).thenReturn(ozoneConfiguration); when(ozoneManager.getConfig()).thenReturn(ozoneConfiguration.getObject(OmConfig.class)); - OMLayoutVersionManager lvm = mock(OMLayoutVersionManager.class); - when(lvm.isAllowed(any(LayoutFeature.class))).thenReturn(true); - when(ozoneManager.getVersionManager()).thenReturn(lvm); + OMVersionManager versionManager = OMVersionManagerTestUtils.mockFinalizedOmVersionManager(); + when(ozoneManager.getVersionManager()).thenReturn(versionManager); when(ozoneManager.isFilesystemSnapshotEnabled()).thenReturn(true); auditLogger = mock(AuditLogger.class); when(ozoneManager.getAuditLogger()).thenReturn(auditLogger); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/multipart/TestS3MultipartRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/multipart/TestS3MultipartRequest.java index 38749f6812a6..5ffce24c3990 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/multipart/TestS3MultipartRequest.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/multipart/TestS3MultipartRequest.java @@ -49,7 +49,8 @@ import org.apache.hadoop.ozone.om.helpers.KeyValueUtil; import org.apache.hadoop.ozone.om.request.OMClientRequest; import org.apache.hadoop.ozone.om.request.OMRequestTestUtils; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManagerTestUtils; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyArgs; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyLocation; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; @@ -108,9 +109,8 @@ public void setup() throws Exception { args.getVolumeName(), args.getBucketName(), "owner", BucketLayout.DEFAULT); }); - OMLayoutVersionManager lvm = mock(OMLayoutVersionManager.class); - when(lvm.getMetadataLayoutVersion()).thenReturn(0); - when(ozoneManager.getVersionManager()).thenReturn(lvm); + OMVersionManager versionManager = OMVersionManagerTestUtils.mockFinalizedOmVersionManager(); + when(ozoneManager.getVersionManager()).thenReturn(versionManager); when(ozoneManager.getConfiguration()).thenReturn(ozoneConfiguration); when(ozoneManager.getConfig()).thenReturn(ozoneConfiguration.getObject(OmConfig.class)); } diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/security/TestS3GetSecretRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/security/TestS3GetSecretRequest.java index 78ccef961f38..8feb283baee9 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/security/TestS3GetSecretRequest.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/security/TestS3GetSecretRequest.java @@ -71,7 +71,8 @@ import org.apache.hadoop.ozone.om.response.s3.tenant.OMTenantAssignUserAccessIdResponse; import org.apache.hadoop.ozone.om.response.s3.tenant.OMTenantCreateResponse; import org.apache.hadoop.ozone.om.s3.S3SecretCacheProvider; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManagerTestUtils; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CreateTenantRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetS3SecretRequest; @@ -444,10 +445,8 @@ public void testGetSecretWithTenant() throws IOException { when(omMultiTenantManager.isTenantAdmin(ugiAlice, TENANT_ID, false)) .thenReturn(true); - // Init LayoutVersionManager to prevent NPE in checkLayoutFeature - final OMLayoutVersionManager lvm = - new OMLayoutVersionManager(OMLayoutVersionManager.maxLayoutVersion()); - when(ozoneManager.getVersionManager()).thenReturn(lvm); + OMVersionManager versionManager = OMVersionManagerTestUtils.mockFinalizedOmVersionManager(); + when(ozoneManager.getVersionManager()).thenReturn(versionManager); // 1. CreateTenantRequest: Create tenant "finance". long txLogIndex = 1; diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/tenant/TestOMTenantCreateRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/tenant/TestOMTenantCreateRequest.java index 713bf6b621d9..0633c000ed4f 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/tenant/TestOMTenantCreateRequest.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/tenant/TestOMTenantCreateRequest.java @@ -46,14 +46,14 @@ import org.apache.hadoop.ozone.om.multitenant.AuthorizerLock; import org.apache.hadoop.ozone.om.request.OMRequestTestUtils; import org.apache.hadoop.ozone.om.response.OMClientResponse; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManagerTestUtils; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CreateTenantRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Status; import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer; import org.apache.hadoop.ozone.security.acl.OzoneObj; -import org.apache.hadoop.ozone.upgrade.LayoutFeature; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -81,10 +81,8 @@ public void setup() throws Exception { when(ozoneManager.getMetrics()).thenReturn(omMetrics); when(ozoneManager.getMetadataManager()).thenReturn(omMetadataManager); when(ozoneManager.getMaxUserVolumeCount()).thenReturn(10L); - OMLayoutVersionManager lvm = mock(OMLayoutVersionManager.class); - when(lvm.getMetadataLayoutVersion()).thenReturn(0); - when(lvm.isAllowed(any(LayoutFeature.class))).thenReturn(true); - when(ozoneManager.getVersionManager()).thenReturn(lvm); + OMVersionManager versionManager = OMVersionManagerTestUtils.mockFinalizedOmVersionManager(); + when(ozoneManager.getVersionManager()).thenReturn(versionManager); AuditLogger auditLogger = mock(AuditLogger.class); when(ozoneManager.getAuditLogger()).thenReturn(auditLogger); doNothing().when(auditLogger).logWrite(any(AuditMessage.class)); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/tenant/TestOMTenantDeleteRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/tenant/TestOMTenantDeleteRequest.java index 15a0660a6863..697ce44c43cd 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/tenant/TestOMTenantDeleteRequest.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/tenant/TestOMTenantDeleteRequest.java @@ -45,11 +45,11 @@ import org.apache.hadoop.ozone.om.multitenant.OzoneTenant; import org.apache.hadoop.ozone.om.multitenant.Tenant; import org.apache.hadoop.ozone.om.request.OMRequestTestUtils; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; +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.ozone.security.acl.IAccessAuthorizer; import org.apache.hadoop.ozone.security.acl.OzoneObj; -import org.apache.hadoop.ozone.upgrade.LayoutFeature; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -79,10 +79,8 @@ public void setup() throws Exception { when(ozoneManager.getMetrics()).thenReturn(omMetrics); when(ozoneManager.getMetadataManager()).thenReturn(omMetadataManager); - OMLayoutVersionManager lvm = mock(OMLayoutVersionManager.class); - when(lvm.getMetadataLayoutVersion()).thenReturn(0); - when(lvm.isAllowed(any(LayoutFeature.class))).thenReturn(true); - when(ozoneManager.getVersionManager()).thenReturn(lvm); + OMVersionManager versionManager = OMVersionManagerTestUtils.mockFinalizedOmVersionManager(); + when(ozoneManager.getVersionManager()).thenReturn(versionManager); AuditLogger auditLogger = mock(AuditLogger.class); when(ozoneManager.getAuditLogger()).thenReturn(auditLogger); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/tenant/TestSetRangerServiceVersionRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/tenant/TestSetRangerServiceVersionRequest.java index f9c9f0879935..d75597fb4aee 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/tenant/TestSetRangerServiceVersionRequest.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/tenant/TestSetRangerServiceVersionRequest.java @@ -33,7 +33,8 @@ import org.apache.hadoop.ozone.om.OzoneManager; import org.apache.hadoop.ozone.om.response.OMClientResponse; import org.apache.hadoop.ozone.om.response.s3.tenant.OMSetRangerServiceVersionResponse; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; +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.ozone.protocol.proto.OzoneManagerProtocolProtos.SetRangerServiceVersionRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type; @@ -55,8 +56,8 @@ public class TestSetRangerServiceVersionRequest { @BeforeEach public void setUp() throws Exception { ozoneManager = mock(OzoneManager.class); - when(ozoneManager.getVersionManager()) - .thenReturn(new OMLayoutVersionManager(1)); + OMVersionManager versionManager = OMVersionManagerTestUtils.mockFinalizedOmVersionManager(); + when(ozoneManager.getVersionManager()).thenReturn(versionManager); final OzoneConfiguration conf = new OzoneConfiguration(); conf.set(OMConfigKeys.OZONE_OM_DB_DIRS, diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/security/TestOMGetDelegationTokenRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/security/TestOMGetDelegationTokenRequest.java index 750a29af6c54..1986526114b8 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/security/TestOMGetDelegationTokenRequest.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/security/TestOMGetDelegationTokenRequest.java @@ -37,7 +37,8 @@ import org.apache.hadoop.ozone.audit.AuditLogger; import org.apache.hadoop.ozone.audit.AuditLoggerType; import org.apache.hadoop.ozone.om.response.OMClientResponse; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; +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.ozone.protocol.proto.OzoneManagerProtocolProtos.Status; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type; @@ -69,8 +70,8 @@ public void setupGetDelegationToken() throws IOException { when(ozoneManager.getDelegationTokenMgr()).thenReturn(secretManager); when(ozoneManager.getAuditLogger()).thenReturn(new AuditLogger( AuditLoggerType.OMLOGGER)); - when(ozoneManager.getVersionManager()).thenReturn( - new OMLayoutVersionManager()); + OMVersionManager versionManager = OMVersionManagerTestUtils.mockFinalizedOmVersionManager(); + when(ozoneManager.getVersionManager()).thenReturn(versionManager); setupToken(); setupRequest(); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestRequestValidations.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestRequestValidations.java index 75420d0474e2..54c75c0ba346 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestRequestValidations.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestRequestValidations.java @@ -40,10 +40,10 @@ import org.apache.hadoop.ozone.om.helpers.OmBucketInfo; import org.apache.hadoop.ozone.om.request.validation.testvalidatorset1.GeneralValidatorsForTesting; import org.apache.hadoop.ozone.om.request.validation.testvalidatorset1.GeneralValidatorsForTesting.ValidationListener; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type; -import org.apache.hadoop.ozone.upgrade.LayoutVersionManager; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -330,14 +330,14 @@ private OMResponse aResponse(Type type) { .build(); } - private LayoutVersionManager aFinalizedVersionManager() { - LayoutVersionManager vm = mock(LayoutVersionManager.class); + private OMVersionManager aFinalizedVersionManager() { + OMVersionManager vm = mock(OMVersionManager.class); when(vm.needsFinalization()).thenReturn(false); return vm; } - private LayoutVersionManager anUnfinalizedVersionManager() { - LayoutVersionManager vm = mock(LayoutVersionManager.class); + private OMVersionManager anUnfinalizedVersionManager() { + OMVersionManager vm = mock(OMVersionManager.class); when(vm.needsFinalization()).thenReturn(true); return vm; } diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestVersionExtractor.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestVersionExtractor.java index bb842083484f..b4c5c3282889 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestVersionExtractor.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestVersionExtractor.java @@ -28,9 +28,8 @@ import org.apache.hadoop.ozone.ClientVersion; import org.apache.hadoop.ozone.om.exceptions.OMException; import org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; -import org.apache.hadoop.ozone.upgrade.LayoutVersionManager; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -42,8 +41,9 @@ class TestVersionExtractor { @EnumSource(OMLayoutFeature.class) void testLayoutVersionExtractor(OMLayoutFeature layoutVersionValue) throws OMException { ValidationContext context = mock(ValidationContext.class); - LayoutVersionManager layoutVersionManager = new OMLayoutVersionManager(layoutVersionValue.serialize()); - when(context.versionManager()).thenReturn(layoutVersionManager); + OMVersionManager omVm = mock(OMVersionManager.class); + when(omVm.getApparentVersion()).thenReturn(layoutVersionValue); + when(context.versionManager()).thenReturn(omVm); ComponentVersion version = VersionExtractor.LAYOUT_VERSION_EXTRACTOR.extractVersion(null, context); assertEquals(layoutVersionValue, version); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/TestOMVolumeRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/TestOMVolumeRequest.java index 36c6034207c0..c46791a247d1 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/TestOMVolumeRequest.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/TestOMVolumeRequest.java @@ -35,7 +35,8 @@ import org.apache.hadoop.ozone.om.OmConfig; import org.apache.hadoop.ozone.om.OmMetadataManagerImpl; import org.apache.hadoop.ozone.om.OzoneManager; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManagerTestUtils; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CreateVolumeRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; @@ -70,9 +71,8 @@ public void setup() throws Exception { when(ozoneManager.getMetrics()).thenReturn(omMetrics); when(ozoneManager.getMetadataManager()).thenReturn(omMetadataManager); when(ozoneManager.getMaxUserVolumeCount()).thenReturn(10L); - OMLayoutVersionManager lvm = mock(OMLayoutVersionManager.class); - when(lvm.getMetadataLayoutVersion()).thenReturn(0); - when(ozoneManager.getVersionManager()).thenReturn(lvm); + OMVersionManager versionManager = OMVersionManagerTestUtils.mockFinalizedOmVersionManager(); + when(ozoneManager.getVersionManager()).thenReturn(versionManager); auditLogger = mock(AuditLogger.class); when(ozoneManager.getAuditLogger()).thenReturn(auditLogger); doNothing().when(auditLogger).logWrite(any(AuditMessage.class)); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshotLocalDataManager.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshotLocalDataManager.java index 7cacfd2bc9e6..806201ab75d5 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshotLocalDataManager.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestOmSnapshotLocalDataManager.java @@ -89,8 +89,8 @@ import org.apache.hadoop.ozone.om.snapshot.OmSnapshotLocalDataManager.ReadableOmSnapshotLocalDataProvider; import org.apache.hadoop.ozone.om.snapshot.OmSnapshotLocalDataManager.WritableOmSnapshotLocalDataProvider; import org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; -import org.apache.hadoop.ozone.upgrade.LayoutFeature; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManagerTestUtils; import org.apache.hadoop.ozone.util.YamlSerializer; import org.apache.ozone.rocksdb.util.SstFileInfo; import org.apache.ratis.util.function.CheckedFunction; @@ -137,8 +137,7 @@ public class TestOmSnapshotLocalDataManager { @TempDir private Path tempDir; - @Mock - private OMLayoutVersionManager layoutVersionManager; + private OMVersionManager omVersionManager; private OmSnapshotLocalDataManager localDataManager; private AutoCloseable mocks; @@ -175,7 +174,8 @@ public static void teardownClass() { @BeforeEach public void setUp() throws IOException { mocks = MockitoAnnotations.openMocks(this); - + omVersionManager = OMVersionManagerTestUtils.mockFinalizedOmVersionManager(); + // Setup mock behavior when(omMetadataManager.getStore()).thenReturn(rdbStore); when(omMetadataManager.getHierarchicalLockManager()).thenReturn(lockManager); @@ -193,7 +193,6 @@ public void setUp() throws IOException { purgedSnapshotIdMap.clear(); snapshotUtilMock.when(() -> OmSnapshotManager.isSnapshotPurged(any(), any(), any(), any())) .thenAnswer(i -> purgedSnapshotIdMap.getOrDefault(i.getArgument(2), false)); - when(layoutVersionManager.isAllowed(any(LayoutFeature.class))).thenReturn(true); conf.setInt(OZONE_OM_SNAPSHOT_LOCAL_DATA_MANAGER_SERVICE_INTERVAL, -1); } @@ -262,7 +261,7 @@ private void mockLockManager() throws IOException { private OmSnapshotLocalDataManager getNewOmSnapshotLocalDataManager( CheckedFunction provider) throws IOException { - return new OmSnapshotLocalDataManager(omMetadataManager, null, layoutVersionManager, provider, conf); + return new OmSnapshotLocalDataManager(omMetadataManager, null, omVersionManager, provider, conf); } private OmSnapshotLocalDataManager getNewOmSnapshotLocalDataManager() throws IOException { @@ -997,7 +996,7 @@ public void testInitWithMissingYamlFiles(boolean needsUpgrade) throws IOExceptio table.put("snap3", createMockSnapshotInfo(snap3, null, SNAPSHOT_ACTIVE)); table.put("snap2", createMockSnapshotInfo(snap2, snap3, SNAPSHOT_DELETED)); table.put("snap1", createMockSnapshotInfo(snap1, snap2, SNAPSHOT_ACTIVE)); - when(layoutVersionManager.isAllowed(eq(OMLayoutFeature.SNAPSHOT_DEFRAG))).thenReturn(!needsUpgrade); + when(omVersionManager.isAllowed(eq(OMLayoutFeature.SNAPSHOT_DEFRAG))).thenReturn(!needsUpgrade); localDataManager = getNewOmSnapshotLocalDataManager(mockedProvider); if (needsUpgrade) { assertEquals(ImmutableSet.of(snap1, snap2, snap3), localDataManager.getVersionNodeMapUnmodifiable().keySet()); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotRequestAndResponse.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotRequestAndResponse.java index 3653a324a975..749e9d24e559 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotRequestAndResponse.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotRequestAndResponse.java @@ -65,10 +65,10 @@ import org.apache.hadoop.ozone.om.request.snapshot.OMSnapshotCreateRequest; import org.apache.hadoop.ozone.om.request.snapshot.TestOMSnapshotCreateRequest; import org.apache.hadoop.ozone.om.response.snapshot.OMSnapshotCreateResponse; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManagerTestUtils; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer; -import org.apache.hadoop.ozone.upgrade.LayoutFeature; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.io.TempDir; @@ -166,9 +166,8 @@ public void baseSetup() throws Exception { IAccessAuthorizer accessAuthorizer = mock(IAccessAuthorizer.class); when(ozoneManager.getAccessAuthorizer()).thenReturn(accessAuthorizer); when(accessAuthorizer.isNative()).thenReturn(false); - OMLayoutVersionManager lvm = mock(OMLayoutVersionManager.class); - when(lvm.isAllowed(any(LayoutFeature.class))).thenReturn(true); - when(ozoneManager.getVersionManager()).thenReturn(lvm); + OMVersionManager versionManager = OMVersionManagerTestUtils.mockFinalizedOmVersionManager(); + when(ozoneManager.getVersionManager()).thenReturn(versionManager); AuditLogger auditLogger = mock(AuditLogger.class); when(ozoneManager.getAuditLogger()).thenReturn(auditLogger); doNothing().when(auditLogger).logWrite(any(AuditMessage.class)); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java index 00c1b73398ad..136d18c31890 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java @@ -105,8 +105,8 @@ import org.apache.hadoop.ozone.om.snapshot.SnapshotUtils; import org.apache.hadoop.ozone.om.snapshot.diff.delta.CompositeDeltaDiffComputer; import org.apache.hadoop.ozone.om.snapshot.diff.delta.DeltaFileComputer; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; -import org.apache.hadoop.ozone.upgrade.LayoutFeature; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManagerTestUtils; import org.apache.hadoop.ozone.util.ClosableIterator; import org.apache.ozone.rocksdb.util.SstFileInfo; import org.apache.ratis.util.function.UncheckedAutoCloseableSupplier; @@ -145,9 +145,6 @@ public class TestSnapshotDefragService { @Mock private IOzoneManagerLock omLock; - @Mock - private OMLayoutVersionManager versionManager; - private DeltaFileComputer deltaFileComputer; @TempDir @@ -162,6 +159,7 @@ public class TestSnapshotDefragService { public void setup() throws IOException { mocks = MockitoAnnotations.openMocks(this); configuration = new OzoneConfiguration(); + OMVersionManager versionManager = OMVersionManagerTestUtils.mockFinalizedOmVersionManager(); // Setup basic mocks when(ozoneManager.getOmSnapshotManager()).thenReturn(omSnapshotManager); @@ -174,7 +172,6 @@ public void setup() throws IOException { when(omSnapshotManager.getSnapshotLocalDataManager()).thenReturn(snapshotLocalDataManager); when(metadataManager.getLock()).thenReturn(omLock); when(metadataManager.getSnapshotParentDir()).thenReturn(tempDir); - when(versionManager.isAllowed(any(LayoutFeature.class))).thenReturn(true); try (MockedConstruction compositeDeltaDiffComputer = mockConstruction(CompositeDeltaDiffComputer.class)) { // Initialize service diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/OMLayoutFeatureUtil.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/OMLayoutFeatureUtil.java deleted file mode 100644 index f9e7f364c0ae..000000000000 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/OMLayoutFeatureUtil.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.upgrade; - -import static org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature.INITIAL_VERSION; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.io.IOException; -import org.apache.hadoop.ozone.upgrade.LayoutFeature; -import org.apache.hadoop.ozone.upgrade.LayoutVersionManager; - -/** - * Test util class. To be removed. - */ -public class OMLayoutFeatureUtil { - - /** - * This is an example of an "API" that uses a new Layout feature (EC) that is - * not yet supported by the current layout version. The following can be - * "disallowed" by just adding the following annotation, thereby keeping the - * method logic and upgrade logic separate. - */ - @DisallowedUntilLayoutVersion(INITIAL_VERSION) - public String ecMethod() { - // Blah Blah EC Blah.... - return "ec"; - } - - /** - * This is an example of an "API" that is - * supported by the current layout version. - */ - public String basicMethod() { - // Blah Blah Basic Blah.... - return "basic"; - } - - // A method named 'getOmVersionManager' needed for the Aspect to get - // instance of the layout version manager. - public LayoutVersionManager getOmVersionManager() throws IOException { - LayoutVersionManager mockLvm = mock(LayoutVersionManager.class); - when(mockLvm.isAllowed(any(LayoutFeature.class))) - .thenReturn(false) - .thenReturn(true); - return mockLvm; - } - -} - diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMLayoutFeatureAspect.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMLayoutFeatureAspect.java index a49df70bb0ad..f3a389fa089d 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMLayoutFeatureAspect.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMLayoutFeatureAspect.java @@ -25,10 +25,11 @@ import java.io.IOException; import java.nio.file.Path; +import org.apache.hadoop.hdds.ComponentVersion; import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.ozone.om.OzoneManager; import org.apache.hadoop.ozone.om.exceptions.OMException; -import org.apache.hadoop.ozone.upgrade.LayoutFeature; +import org.apache.hadoop.ozone.om.request.snapshot.OMSnapshotCreateRequest; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.reflect.MethodSignature; import org.junit.jupiter.api.BeforeEach; @@ -53,22 +54,31 @@ public void setUp() throws IOException { } /** - * This unit test invokes the above 2 layout feature APIs. The first one - * should fail, and the second one should pass. - * @throws Exception + * Exercises {@link OMLayoutFeatureAspect#checkLayoutFeature} for an + * {@link org.apache.hadoop.ozone.om.request.OMClientRequest#preExecute} join + * point using the real {@link OMSnapshotCreateRequest#preExecute} metadata + * (including {@link DisallowedUntilLayoutVersion}). */ @Test public void testDisallowedUntilLayoutVersion() throws Throwable { - OMLayoutFeatureUtil testObj = new OMLayoutFeatureUtil(); + OzoneManager om = mock(OzoneManager.class); + OMVersionManager ovm = mock(OMVersionManager.class); + when(ovm.isAllowed(any(ComponentVersion.class))).thenReturn(false); + when(om.getVersionManager()).thenReturn(ovm); + + OMSnapshotCreateRequest request = mock(OMSnapshotCreateRequest.class); OMLayoutFeatureAspect aspect = new OMLayoutFeatureAspect(); JoinPoint joinPoint = mock(JoinPoint.class); - when(joinPoint.getTarget()).thenReturn(testObj); + when(joinPoint.getTarget()).thenReturn(request); + when(joinPoint.getArgs()).thenReturn(new Object[]{om}); + when(joinPoint.toShortString()) + .thenReturn("OMSnapshotCreateRequest.preExecute(..))"); MethodSignature methodSignature = mock(MethodSignature.class); when(methodSignature.getMethod()) - .thenReturn(OMLayoutFeatureUtil.class.getMethod("ecMethod")); - when(methodSignature.toShortString()).thenReturn("ecMethod"); + .thenReturn( + OMSnapshotCreateRequest.class.getMethod("preExecute", OzoneManager.class)); when(joinPoint.getSignature()).thenReturn(methodSignature); OMException omException = assertThrows(OMException.class, @@ -81,9 +91,9 @@ public void testDisallowedUntilLayoutVersion() throws Throwable { public void testPreExecuteLayoutCheck() { OzoneManager om = mock(OzoneManager.class); - OMLayoutVersionManager lvm = mock(OMLayoutVersionManager.class); - when(lvm.isAllowed(any(LayoutFeature.class))).thenReturn(false); - when(om.getVersionManager()).thenReturn(lvm); + OMVersionManager ovm = mock(OMVersionManager.class); + when(ovm.isAllowed(any(ComponentVersion.class))).thenReturn(false); + when(om.getVersionManager()).thenReturn(ovm); MockOmRequest mockOmRequest = new MockOmRequest(); OMLayoutFeatureAspect aspect = new OMLayoutFeatureAspect(); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMLayoutVersionManager.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMLayoutVersionManager.java deleted file mode 100644 index 2c2044e9d04f..000000000000 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMLayoutVersionManager.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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.upgrade; - -import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.NOT_SUPPORTED_OPERATION; -import static org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature.INITIAL_VERSION; -import static org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager.OM_UPGRADE_CLASS_PACKAGE; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.doCallRealMethod; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Optional; -import org.apache.hadoop.ozone.om.OzoneManager; -import org.apache.hadoop.ozone.om.exceptions.OMException; -import org.apache.hadoop.ozone.om.request.OMClientRequest; -import org.junit.jupiter.api.Test; - -/** - * Test OM layout version management. - */ -public class TestOMLayoutVersionManager { - - @Test - public void testOMLayoutVersionManager() throws IOException { - OMLayoutVersionManager omVersionManager = - new OMLayoutVersionManager(); - - // Initial Version is always allowed. - assertTrue(omVersionManager.isAllowed(INITIAL_VERSION)); - assertThat(INITIAL_VERSION.layoutVersion()) - .isLessThanOrEqualTo(omVersionManager.getMetadataLayoutVersion()); - } - - @Test - public void testOMLayoutVersionManagerInitError() { - int lV = OMLayoutFeature.values()[OMLayoutFeature.values().length - 1] - .layoutVersion() + 1; - OMException ome = assertThrows(OMException.class, () -> new OMLayoutVersionManager(lV)); - assertEquals(NOT_SUPPORTED_OPERATION, ome.getResult()); - } - - @Test - - /* - * The OMLayoutFeatureAspect relies on the fact that the OM client - * request handler class has a preExecute method with first argument as - * 'OzoneManager'. If that is not true, please fix - * OMLayoutFeatureAspect#beforeRequestApplyTxn. - */ - public void testOmClientRequestPreExecuteIsCompatibleWithAspect() { - Method[] methods = OMClientRequest.class.getMethods(); - - Optional preExecuteMethod = Arrays.stream(methods) - .filter(m -> m.getName().equals("preExecute")) - .findFirst(); - - assertTrue(preExecuteMethod.isPresent()); - assertThat(preExecuteMethod.get().getParameterCount()).isGreaterThanOrEqualTo(1); - assertEquals(OzoneManager.class, - preExecuteMethod.get().getParameterTypes()[0]); - } - - @Test - public void testOmUpgradeActionsRegistered() throws Exception { - OMLayoutVersionManager lvm = new OMLayoutVersionManager(); // MLV >= 0 - assertFalse(lvm.needsFinalization()); - - // INITIAL_VERSION is finalized, hence should not register. - Optional action = - INITIAL_VERSION.action(); - assertFalse(action.isPresent()); - - lvm = mock(OMLayoutVersionManager.class); - when(lvm.getMetadataLayoutVersion()).thenReturn(-1); - doCallRealMethod().when(lvm).registerUpgradeActions(anyString()); - lvm.registerUpgradeActions(OM_UPGRADE_CLASS_PACKAGE); - - action = INITIAL_VERSION.action(); - assertTrue(action.isPresent()); - assertEquals(MockOmUpgradeAction.class, action.get().getClass()); - OzoneManager omMock = mock(OzoneManager.class); - action.get().execute(omMock); - verify(omMock, times(1)).getVersion(); - } - - /** - * Mock OM upgrade action class. - */ - @UpgradeActionOm(feature = - INITIAL_VERSION) - public static class MockOmUpgradeAction implements OmUpgradeAction { - - @Override - public void execute(OzoneManager arg) { - arg.getVersion(); - } - } -} diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMUpgradeFinalizer.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMUpgradeFinalizer.java deleted file mode 100644 index 21935dcb09d8..000000000000 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMUpgradeFinalizer.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * 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.upgrade; - -import static org.apache.hadoop.ozone.upgrade.UpgradeException.ResultCodes.LAYOUT_FEATURE_FINALIZATION_FAILED; -import static org.apache.hadoop.ozone.upgrade.UpgradeFinalization.Status.ALREADY_FINALIZED; -import static org.apache.hadoop.ozone.upgrade.UpgradeFinalization.Status.FINALIZATION_DONE; -import static org.apache.hadoop.ozone.upgrade.UpgradeFinalization.Status.FINALIZATION_REQUIRED; -import static org.apache.hadoop.ozone.upgrade.UpgradeFinalization.Status.STARTING_FINALIZATION; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.lenient; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; -import org.apache.hadoop.ozone.om.OMStorage; -import org.apache.hadoop.ozone.om.OzoneManager; -import org.apache.hadoop.ozone.upgrade.LayoutFeature; -import org.apache.hadoop.ozone.upgrade.UpgradeException; -import org.apache.hadoop.ozone.upgrade.UpgradeFinalization; -import org.apache.hadoop.ozone.upgrade.UpgradeFinalization.StatusAndMessages; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.mockito.stubbing.Answer; -import org.mockito.verification.VerificationMode; - -/** - * {@link OMUpgradeFinalizer} tests. - */ -@ExtendWith(MockitoExtension.class) -public class TestOMUpgradeFinalizer { - - private static final String CLIENT_ID = "clientID"; - private static final String OTHER_CLIENT_ID = "otherClientID"; - - @Mock - private OMLayoutVersionManager versionManager; - - private int storedLayoutVersion = 0; - - @Test - public void testEmitsFinalizedStatusIfAlreadyFinalized() throws Exception { - - when(versionManager.getUpgradeState()).thenReturn(ALREADY_FINALIZED); - OMUpgradeFinalizer finalizer = new OMUpgradeFinalizer(versionManager); - StatusAndMessages ret = finalizer.finalize(CLIENT_ID, null); - - assertEquals(ALREADY_FINALIZED, ret.status()); - } - - @Test - public void testEmitsStartingStatusOnFinalization() throws Exception { - Iterable lfs = mockFeatures(3, "feature-3", "feature-4"); - setupVersionManagerMockToFinalize(lfs); - - OMUpgradeFinalizer finalizer = new OMUpgradeFinalizer(versionManager); - StatusAndMessages ret = finalizer.finalize(CLIENT_ID, mockOzoneManager(2)); - - assertEquals(STARTING_FINALIZATION, ret.status()); - } - - /* - * This test ensures that whenever finalize() is called, we finish all - * finalization step, and getting the report gives back a FINALIZATION_DONE - * status. This has to be revisited as soon as we change the behaviour to - * post the finalization steps to the state machine from bg thread one by one. - * This also means that FINALIZATION_IN_PROGRESS status related tests - * has to be added at the same time. - */ - @Test - public void testReportStatusResultsInFinalizationDone() - throws Exception { - Iterable lfs = mockFeatures(3, "feature-3", "feature-4"); - setupVersionManagerMockToFinalize(lfs); - - OMUpgradeFinalizer finalizer = new OMUpgradeFinalizer(versionManager); - finalizer.finalize(CLIENT_ID, mockOzoneManager(2)); - - - if (finalizer.isFinalizationDone()) { - when(versionManager.getUpgradeState()).thenReturn(FINALIZATION_DONE); - } - StatusAndMessages ret = finalizer.reportStatus(CLIENT_ID, false); - - assertEquals(UpgradeFinalization.Status.FINALIZATION_DONE, ret.status()); - } - - @Test - public void testReportStatusAllowsTakeover() - throws Exception { - Iterable lfs = mockFeatures(3, "feature-3", "feature-4"); - setupVersionManagerMockToFinalize(lfs); - - OMUpgradeFinalizer finalizer = new OMUpgradeFinalizer(versionManager); - finalizer.finalize(CLIENT_ID, mockOzoneManager(2)); - - if (finalizer.isFinalizationDone()) { - when(versionManager.getUpgradeState()).thenReturn(FINALIZATION_DONE); - } - StatusAndMessages ret = finalizer.reportStatus(OTHER_CLIENT_ID, true); - - assertEquals(UpgradeFinalization.Status.FINALIZATION_DONE, ret.status()); - } - - @Test - public void testReportStatusFailsFromNewClientIfRequestIsNotATakeover() - throws Exception { - Iterable lfs = mockFeatures(3, "feature-3", "feature-4"); - setupVersionManagerMockToFinalize(lfs); - - OMUpgradeFinalizer finalizer = new OMUpgradeFinalizer(versionManager); - finalizer.finalize(CLIENT_ID, mockOzoneManager(2)); - - Throwable exception = assertThrows( - UpgradeException.class, () -> { - finalizer.reportStatus(OTHER_CLIENT_ID, false); - }); - assertThat(exception.getMessage()).contains("Unknown client"); - } - - @Test - public void testFinalizationWithUpgradeAction() throws Exception { - Optional action = Optional.of(om -> om.getVersion()); - OzoneManager om = mockOzoneManager(0); - Iterable lfs = mockFeatures("feature-1", "feature-2"); - when(lfs.iterator().next().action()).thenReturn(action); - setupVersionManagerMockToFinalize(lfs); - - OMUpgradeFinalizer finalizer = new OMUpgradeFinalizer(versionManager); - finalizer.finalize(CLIENT_ID, om); - - Iterator it = lfs.iterator(); - OMLayoutFeature f = it.next(); - - // the first feature has an upgrade action, and the action execution is - // checked by verifying on om.getVersion - verify(om.getOmStorage(), once()) - .setLayoutVersion(f.layoutVersion()); - verify(om, once()).getVersion(); - - // The second feature has a NOOP, but should update the layout version. - f = it.next(); - verify(om.getOmStorage(), once()) - .setLayoutVersion(f.layoutVersion()); - - if (finalizer.isFinalizationDone()) { - when(versionManager.getUpgradeState()).thenReturn(FINALIZATION_DONE); - } - StatusAndMessages status = finalizer.reportStatus(CLIENT_ID, false); - assertEquals(FINALIZATION_DONE, status.status()); - assertFalse(status.msgs().isEmpty()); - } - - @Test - public void testFinalizationWithFailingUpgradeAction() throws Exception { - Optional action = Optional.of( - ignore -> { - throw new IOException("Fail."); - } - ); - - OzoneManager om = mockOzoneManager(0); - Iterable lfs = mockFeatures("feature-1", "feature-2"); - when(lfs.iterator().next().action()).thenReturn(action); - setupVersionManagerMockToFinalize(lfs); - - OMUpgradeFinalizer finalizer = new OMUpgradeFinalizer(versionManager); - UpgradeException e = assertThrows(UpgradeException.class, () -> finalizer.finalize(CLIENT_ID, om)); - assertThat(e.getMessage()).contains(lfs.iterator().next().toString()); - assertEquals(e.getResult(), LAYOUT_FEATURE_FINALIZATION_FAILED); - if (finalizer.isFinalizationDone()) { - when(versionManager.getUpgradeState()).thenReturn(FINALIZATION_DONE); - } - - // Verify that we have never updated the layout version. - Iterator it = lfs.iterator(); - OMLayoutFeature f = it.next(); - verify(om.getOmStorage(), never()) - .setLayoutVersion(f.layoutVersion()); - - // Verify that we never got to the second feature. - f = it.next(); - verify(om.getOmStorage(), never()) - .setLayoutVersion(f.layoutVersion()); - - StatusAndMessages status = finalizer.reportStatus(CLIENT_ID, false); - assertEquals(FINALIZATION_DONE, status.status()); - assertFalse(status.msgs().isEmpty()); - } - - private VerificationMode once() { - return times(1); - } - - private void setupVersionManagerMockToFinalize( - Iterable lfs - ) { - when(versionManager.getUpgradeState()).thenReturn(FINALIZATION_REQUIRED); - when(versionManager.needsFinalization()).thenReturn(true); - List lfIter = new ArrayList<>(); - lfs.forEach(lfIter::add); - when(versionManager.unfinalizedFeatures()).thenReturn(lfIter); - } - - private OMLayoutFeature mockFeature(String name, int version) { - OMLayoutFeature f = mock(OMLayoutFeature.class); - lenient().when(f.toString()).thenReturn(name); - when(f.layoutVersion()).thenReturn(version); - return f; - } - - private Iterable mockFeatures(String... names) { - return mockFeatures(1, names); - } - - private Iterable mockFeatures( - int startFromLV, String... names - ) { - int i = startFromLV; - List ret = new ArrayList<>(); - for (String name : names) { - ret.add(mockFeature(name, i)); - i++; - } - return ret; - } - - private OzoneManager mockOzoneManager(int initialLayoutVersion) { - OzoneManager mock = mock(OzoneManager.class); - OMStorage st = mock(OMStorage.class); - storedLayoutVersion = initialLayoutVersion; - - lenient().doAnswer( - (Answer) inv -> { - storedLayoutVersion = inv.getArgument(0, Integer.class); - return null; - }).when(st).setApparentVersion(anyInt()); - - lenient().when(st.getApparentVersion()) - .thenAnswer((Answer) ignore -> storedLayoutVersion); - - when(mock.getOmStorage()).thenReturn(st); - - return mock; - } -} diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/TestOzoneDelegationTokenSecretManager.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/TestOzoneDelegationTokenSecretManager.java index 941167191193..184c8f9983db 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/TestOzoneDelegationTokenSecretManager.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/security/TestOzoneDelegationTokenSecretManager.java @@ -66,8 +66,8 @@ import org.apache.hadoop.ozone.om.exceptions.OMLeaderNotReadyException; import org.apache.hadoop.ozone.om.exceptions.OMNotLeaderException; import org.apache.hadoop.ozone.om.helpers.S3SecretValue; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; -import org.apache.hadoop.ozone.upgrade.LayoutFeature; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManager; +import org.apache.hadoop.ozone.om.upgrade.OMVersionManagerTestUtils; import org.apache.hadoop.security.AccessControlException; import org.apache.hadoop.security.ssl.KeyStoreTestUtil; import org.apache.hadoop.security.token.SecretManager; @@ -121,8 +121,7 @@ public void setUp() throws Exception { om = mock(OzoneManager.class); OMMetadataManager metadataManager = new OmMetadataManagerImpl(conf, om); when(om.getMetadataManager()).thenReturn(metadataManager); - OMLayoutVersionManager versionManager = mock(OMLayoutVersionManager.class); - when(versionManager.isAllowed(any(LayoutFeature.class))).thenReturn(true); + OMVersionManager versionManager = OMVersionManagerTestUtils.mockFinalizedOmVersionManager(); when(om.getVersionManager()).thenReturn(versionManager); s3SecretManager = new S3SecretLockedManager( new S3SecretManagerImpl(new S3SecretStoreMap(s3Secrets),