Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import java.util.TreeMap;

/**
* Versioning for datanode.
* Upgrade and downgrade version handling for SCM and Datanode.
*/
public enum HDDSVersion implements ComponentVersion {

Expand Down
4 changes: 3 additions & 1 deletion hadoop-hdds/docs/content/design/upgrade-dev-primer.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,15 @@ Class to add a new layout feature being brought in. Layout version is typically

**DataNode** uses [`org.apache.hadoop.ozone.container.upgrade.DatanodeVersionManager`](https://github.com/apache/ozone/blob/master/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/upgrade/DatanodeVersionManager.java) with upgrade actions via [`org.apache.hadoop.ozone.container.upgrade.DatanodeUpgradeActionProvider`](https://github.com/apache/ozone/blob/master/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/upgrade/DatanodeUpgradeActionProvider.java). Both SCM and DataNode expose apparent/software `ComponentVersion` and `isAllowed(ComponentVersion)` for gating (including legacy [`HDDSLayoutFeature`](https://github.com/apache/ozone/blob/master/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/upgrade/HDDSLayoutFeature.java) checks where still used).

**Recon** uses [`org.apache.hadoop.ozone.recon.upgrade.ReconVersionManager`](https://github.com/apache/ozone/blob/master/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/ReconVersionManager.java) for Derby SQL schema versioning, with versions defined in [`ReconVersion`](https://github.com/apache/ozone/blob/master/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/ReconVersion.java) and upgrade actions via [`ReconUpgradeActionProvider`](https://github.com/apache/ozone/blob/master/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/ReconUpgradeActionProvider.java). Apparent version is stored in `RECON_SCHEMA_VERSION`. Recon also runs [`ScmVersionManager`](https://github.com/apache/ozone/blob/master/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/upgrade/ScmVersionManager.java) for SCM-lite metadata and finalizes both tracks on startup.

## @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.

## @BelongsToLayoutVersion Annotation
Annotation to mark an OM request class that it belongs to a specific Layout Version. Until that version is available post finalize, this request will not be supported. A newer version of an existing OM request can be created (by inheritance or a fully new class) and marked with a newer layout version. Until finalizing this layout version, the older request class is used. Post finalizing, the newer version of the request class is used.

## Upgrade Action (UpgradeActionOm, UpgradeActionScm & UpgradeActionDatanode)
## Upgrade Action (UpgradeActionOm, UpgradeActionScm, UpgradeActionDatanode & UpgradeActionRecon)
Annotation to specify upgrade action run during finalization. Each layout feature can optionally define a single upgrade action that will be executed when the feature is finalized. This action should be idempotent and execute quickly. The action must complete for the feature to finish
finalizing, so if there is an error executing the action it will be retried. This partial failure should not leave the component inoperable.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ public void finalizeUpgrade() throws UpgradeException {

LOG.info("Version {} has been finalized.", newVersion);
}
LOG.info("Finalization is complete.");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public ScmVersionManager(SCMStorageConfig storage, OzoneStorageContainerManager
this(storage, upgradeActionArg, new ScmUpgradeActionProvider());
}

@VisibleForTesting
// Used by Recon's node manager to track Datanode versions without running SCM specific upgrade actions.
public ScmVersionManager(SCMStorageConfig storage,
OzoneStorageContainerManager upgradeActionArg,
ComponentUpgradeActionProvider<ScmUpgradeAction> upgradeActionProvider)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class SchemaVersionTableDefinition implements ReconSchemaDefinition {

public static final String SCHEMA_VERSION_TABLE_NAME = "RECON_SCHEMA_VERSION";
private final DataSource dataSource;
private int latestSLV;
private int softwareVersion;

@Inject
public SchemaVersionTableDefinition(DataSource dataSource) {
Expand All @@ -61,8 +61,7 @@ public void initializeSchema() throws SQLException {
createSchemaVersionTable(localDslContext);

if (isFreshInstall) {
// Fresh install: Set the SLV to the latest version
insertInitialSLV(localDslContext, latestSLV);
insertApparentVersion(localDslContext, softwareVersion);
}
}
}
Expand All @@ -80,27 +79,16 @@ private void createSchemaVersionTable(DSLContext dslContext) {
.execute();
}

/**
* Inserts the initial SLV into the Schema Version table.
*
* @param dslContext The DSLContext to use for the operation.
* @param slv The initial SLV value.
*/
private void insertInitialSLV(DSLContext dslContext, int slv) {
private void insertApparentVersion(DSLContext dslContext, int apparentVersion) {
dslContext.insertInto(DSL.table(SCHEMA_VERSION_TABLE_NAME))
.columns(DSL.field(name("version_number")),
DSL.field(name("applied_on")))
.values(slv, DSL.currentTimestamp())
.values(apparentVersion, DSL.currentTimestamp())
.execute();
LOG.info("Inserted initial SLV '{}' into SchemaVersion table.", slv);
LOG.info("Inserted initial apparent version '{}' into SchemaVersion table.", apparentVersion);
}

/**
* Set the latest SLV.
*
* @param slv The latest Software Layout Version.
*/
public void setLatestSLV(int slv) {
this.latestSLV = slv;
public void setSoftwareVersion(int version) {
this.softwareVersion = version;
}
}
6 changes: 6 additions & 0 deletions hadoop-ozone/recon/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,12 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.ozone</groupId>
<artifactId>hdds-server-framework</artifactId>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.ozone</groupId>
<artifactId>hdds-server-scm</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;
import org.apache.hadoop.ozone.recon.upgrade.ReconLayoutFeature;
import org.apache.hadoop.ozone.recon.upgrade.ReconVersion;
import org.apache.ozone.recon.schema.ReconSchemaDefinition;
import org.apache.ozone.recon.schema.SchemaVersionTableDefinition;
import org.slf4j.Logger;
Expand All @@ -44,17 +44,14 @@ public ReconSchemaManager(Set<ReconSchemaDefinition> reconSchemaDefinitions) {

@VisibleForTesting
public void createReconSchema() {
// Calculate the latest SLV from ReconLayoutFeature
int latestSLV = calculateLatestSLV();

try {
// Initialize the schema version table first
reconSchemaDefinitions.stream()
.filter(SchemaVersionTableDefinition.class::isInstance)
.findFirst()
.ifPresent(schemaDefinition -> {
SchemaVersionTableDefinition schemaVersionTable = (SchemaVersionTableDefinition) schemaDefinition;
schemaVersionTable.setLatestSLV(latestSLV);
schemaVersionTable.setSoftwareVersion(ReconVersion.SOFTWARE_VERSION.serialize());
try {
schemaVersionTable.initializeSchema();
} catch (SQLException e) {
Expand All @@ -77,13 +74,4 @@ public void createReconSchema() {
LOG.error("Error creating Recon schema.", e);
}
}

/**
* Calculate the latest SLV by iterating over ReconLayoutFeature.
*
* @return The latest SLV.
*/
private int calculateLatestSLV() {
return ReconLayoutFeature.determineSLV();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.sql.DataSource;
import org.apache.hadoop.hdds.cli.GenericCli;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.protocolPB.SCMSecurityProtocolClientSideTranslatorPB;
Expand All @@ -50,14 +49,16 @@
import org.apache.hadoop.ozone.recon.metrics.ReconTaskStatusMetrics;
import org.apache.hadoop.ozone.recon.scm.ReconSafeModeManager;
import org.apache.hadoop.ozone.recon.scm.ReconStorageConfig;
import org.apache.hadoop.ozone.recon.scm.ReconStorageContainerManagerFacade;
import org.apache.hadoop.ozone.recon.security.ReconCertificateClient;
import org.apache.hadoop.ozone.recon.spi.OzoneManagerServiceProvider;
import org.apache.hadoop.ozone.recon.spi.ReconContainerMetadataManager;
import org.apache.hadoop.ozone.recon.spi.ReconNamespaceSummaryManager;
import org.apache.hadoop.ozone.recon.spi.StorageContainerServiceProvider;
import org.apache.hadoop.ozone.recon.spi.impl.ReconDBProvider;
import org.apache.hadoop.ozone.recon.tasks.ReconTaskController;
import org.apache.hadoop.ozone.recon.upgrade.ReconLayoutVersionManager;
import org.apache.hadoop.ozone.recon.upgrade.ReconVersionManager;
import org.apache.hadoop.ozone.upgrade.UpgradeException;
import org.apache.hadoop.ozone.util.OzoneNetUtils;
import org.apache.hadoop.ozone.util.OzoneVersionInfo;
import org.apache.hadoop.ozone.util.ShutdownHookManager;
Expand All @@ -83,7 +84,7 @@ public class ReconServer extends GenericCli implements Callable<Void> {
private OzoneManagerServiceProvider ozoneManagerServiceProvider;
private ReconDBProvider reconDBProvider;
private ReconNamespaceSummaryManager reconNamespaceSummaryManager;
private OzoneStorageContainerManager reconStorageContainerManager;
private ReconStorageContainerManagerFacade reconStorageContainerManager;
private OzoneConfiguration configuration;
private ReconStorageConfig reconStorage;
private CertificateClient certClient;
Expand Down Expand Up @@ -163,33 +164,21 @@ public Void call() throws Exception {
httpServer = injector.getInstance(ReconHttpServer.class);
this.ozoneManagerServiceProvider =
injector.getInstance(OzoneManagerServiceProvider.class);
this.reconStorageContainerManager =
injector.getInstance(OzoneStorageContainerManager.class);
this.reconStorageContainerManager = injector.getInstance(ReconStorageContainerManagerFacade.class);

this.reconTaskStatusMetrics =
injector.getInstance(ReconTaskStatusMetrics.class);

LOG.info("Initializing support of Recon Features...");
FeatureProvider.initFeatureSupport(configuration);

finalizeUpgrade();

LOG.debug("Now starting all services of Recon...");
// Start all services
start();
isStarted = true;

LOG.info("Finalizing Layout Features.");
// Handle Recon Schema Versioning
ReconSchemaVersionTableManager versionTableManager =
injector.getInstance(ReconSchemaVersionTableManager.class);
DataSource dataSource = injector.getInstance(DataSource.class);

ReconLayoutVersionManager layoutVersionManager =
new ReconLayoutVersionManager(versionTableManager, reconContext, dataSource);
// Run the upgrade framework to finalize layout features if needed
layoutVersionManager.finalizeLayoutFeatures();

LOG.info("Recon schema versioning completed.");

// Register ReconTaskStatusMetrics after schema upgrade completes
// This ensures the RECON_TASK_STATUS table has all required columns
if (reconTaskStatusMetrics != null) {
Expand All @@ -214,6 +203,31 @@ public Void call() throws Exception {
return null;
}

private void finalizeUpgrade() {
LOG.info("Finalizing Recon versions.");
ReconContext reconContext = injector.getInstance(ReconContext.class);
ReconVersionManager reconVersionManager = injector.getInstance(ReconVersionManager.class);
try {
reconVersionManager.finalizeUpgrade();
} catch (UpgradeException e) {
LOG.error("Failed to finalize Recon versions.", e);
reconContext.updateErrors(ReconContext.ErrorCode.UPGRADE_FAILURE);
reconContext.updateHealthStatus(new AtomicBoolean(false));
throw new RuntimeException("Recon failed to finalize schema versions. Startup halted.", e);
}

try {
reconStorageContainerManager.finalizeScmVersionUpgrade();
} catch (UpgradeException e) {
LOG.error("Failed to finalize Recon SCM apparent version.", e);
reconContext.updateErrors(ReconContext.ErrorCode.UPGRADE_FAILURE);
reconContext.updateHealthStatus(new AtomicBoolean(false));
throw new RuntimeException("Recon failed to finalize SCM version. Startup halted.", e);
}

LOG.info("Recon upgrade finalization completed.");
}

private void updateAndLogReconHealthStatus() {
ReconContext reconContext = injector.getInstance(ReconContext.class);
assert reconContext != null;
Expand Down
Loading