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

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


The following commit(s) were added to refs/heads/HDDS-14496-zdu by this push:
     new 21b69d28856 HDDS-15716. Replace layout version protos with new 
version-named protos in the DN–SCM protocol (#10817)
21b69d28856 is described below

commit 21b69d28856b992958ee183793556fabd50a28cf
Author: Zita Dombi <[email protected]>
AuthorDate: Mon Jul 27 17:21:42 2026 +0200

    HDDS-15716. Replace layout version protos with new version-named protos in 
the DN–SCM protocol (#10817)
---
 .../FinalizeVersionCommandHandler.java             | 27 ++++---
 .../states/endpoint/HeartbeatEndpointTask.java     | 10 +--
 .../states/endpoint/RegisterEndpointTask.java      | 10 +--
 .../ozone/container/upgrade/UpgradeUtils.java      | 19 ++---
 .../protocol/StorageContainerDatanodeProtocol.java |  6 +-
 .../protocol/StorageContainerNodeProtocol.java     |  6 +-
 .../protocol/commands/FinalizeVersionCommand.java  | 38 ++++-----
 ...inerDatanodeProtocolClientSideTranslatorPB.java | 10 +--
 ...inerDatanodeProtocolServerSideTranslatorPB.java | 15 +---
 .../hadoop/ozone/container/common/ScmTestMock.java |  4 +-
 .../TestFinalizeVersionCommandHandler.java         | 91 ++++++++++++++++++++++
 .../proto/ScmServerDatanodeHeartbeatProtocol.proto | 34 +++++++-
 .../apache/hadoop/hdds/scm/node/DatanodeInfo.java  | 16 ++--
 .../apache/hadoop/hdds/scm/node/NodeManager.java   |  8 +-
 .../hadoop/hdds/scm/node/NodeStateManager.java     | 30 +++----
 .../hadoop/hdds/scm/node/SCMNodeManager.java       | 35 +++++----
 .../scm/server/SCMDatanodeHeartbeatDispatcher.java | 29 +------
 .../hdds/scm/server/SCMDatanodeProtocolServer.java | 14 ++--
 .../hadoop/hdds/scm/container/MockNodeManager.java | 12 +--
 .../hdds/scm/container/SimpleMockNodeManager.java  |  6 +-
 .../hadoop/hdds/scm/node/TestNodeStateManager.java | 12 +--
 .../hadoop/hdds/scm/node/TestSCMNodeManager.java   | 47 ++++++-----
 .../server/TestSCMDatanodeHeartbeatDispatcher.java | 27 +++++++
 .../hadoop/ozone/recon/scm/ReconNodeManager.java   | 16 ++--
 .../hadoop/ozone/recon/api/TestEndpoints.java      |  8 +-
 .../ozone/recon/scm/TestReconNodeManager.java      | 16 ++--
 .../ozone/freon/DatanodeSimulationState.java       |  6 +-
 .../hadoop/ozone/freon/DatanodeSimulator.java      | 22 +++---
 .../hadoop/ozone/freon/SCMThroughputBenchmark.java |  2 +-
 29 files changed, 351 insertions(+), 225 deletions(-)

diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/FinalizeVersionCommandHandler.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/FinalizeVersionCommandHandler.java
index a9df014b9ec..c6839867500 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/FinalizeVersionCommandHandler.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/FinalizeVersionCommandHandler.java
@@ -18,7 +18,7 @@
 package org.apache.hadoop.ozone.container.common.statemachine.commandhandler;
 
 import java.util.concurrent.atomic.AtomicLong;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.FinalizeNewLayoutVersionCommandProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.FinalizeNewDatanodeVersionCommandProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto;
 import org.apache.hadoop.metrics2.lib.MetricsRegistry;
 import org.apache.hadoop.metrics2.lib.MutableRate;
@@ -30,6 +30,7 @@
 import org.apache.hadoop.ozone.protocol.commands.SCMCommand;
 import org.apache.hadoop.ozone.upgrade.UpgradeException;
 import org.apache.hadoop.util.Time;
+import org.apache.ratis.util.ExitUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -51,7 +52,7 @@ public FinalizeVersionCommandHandler() {
     MetricsRegistry registry = new MetricsRegistry(
         FinalizeVersionCommandHandler.class.getSimpleName());
     this.opsLatencyMs =
-        registry.newRate(SCMCommandProto.Type.finalizeNewLayoutVersionCommand 
+ "Ms");
+        
registry.newRate(SCMCommandProto.Type.finalizeNewDatanodeVersionCommand + "Ms");
   }
 
   /**
@@ -69,14 +70,22 @@ public void handle(SCMCommand<?> command, OzoneContainer 
ozoneContainer,
     invocationCount.incrementAndGet();
     final long startTime = Time.monotonicNow();
     DatanodeStateMachine dsm = context.getParent();
-    final FinalizeNewLayoutVersionCommandProto finalizeCommand =
+    final FinalizeNewDatanodeVersionCommandProto finalizeCommand =
         ((FinalizeVersionCommand) command).getProto();
     try {
-      if (finalizeCommand.getFinalizeNewLayoutVersion()) {
-        if (dsm.getVersionManager().needsFinalization()) {
-          LOG.info("Finalize upgrade called.");
-          dsm.getVersionManager().finalizeUpgrade();
-        }
+      int dnSoftwareVersion = 
dsm.getVersionManager().getSoftwareVersion().serialize();
+      int expectedSoftwareVersion = 
finalizeCommand.getExpectedSoftwareVersion();
+      if (dnSoftwareVersion != expectedSoftwareVersion) {
+        // Version mismatch should not happen here: the datanode is rejected
+        // at registration and SCM only finalizes after its own version checks.
+        // Crash defensively rather than finalize on an unexpected version.
+        String msg = String.format("Datanode software version %d does not 
match the software version %d expected by " +
+            "SCM. Terminating the datanode.", dnSoftwareVersion, 
expectedSoftwareVersion);
+        ExitUtils.terminate(1, msg, LOG);
+      }
+      if (dsm.getVersionManager().needsFinalization()) {
+        LOG.info("Finalize upgrade called.");
+        dsm.getVersionManager().finalizeUpgrade();
       }
     } catch (UpgradeException e) {
       LOG.error("Exception during finalization.", e);
@@ -93,7 +102,7 @@ public void handle(SCMCommand<?> command, OzoneContainer 
ozoneContainer,
    */
   @Override
   public SCMCommandProto.Type getCommandType() {
-    return SCMCommandProto.Type.finalizeNewLayoutVersionCommand;
+    return SCMCommandProto.Type.finalizeNewDatanodeVersionCommand;
   }
 
   /**
diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/HeartbeatEndpointTask.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/HeartbeatEndpointTask.java
index e35192daa09..61fb248ef20 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/HeartbeatEndpointTask.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/HeartbeatEndpointTask.java
@@ -37,7 +37,7 @@
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.CommandQueueReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerAction;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerActionsProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineAction;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineActionsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto;
@@ -128,13 +128,13 @@ public EndpointStateMachine.EndPointStates call() throws 
Exception {
     try {
       Preconditions.checkState(this.datanodeDetailsProto != null);
 
-      LayoutVersionProto versionInfo = toVersionProto(
+      DatanodeVersionProto versionInfo = toVersionProto(
           versionManager.getApparentVersion(),
           versionManager.getSoftwareVersion());
 
       requestBuilder = SCMHeartbeatRequestProto.newBuilder()
           .setDatanodeDetails(datanodeDetailsProto)
-          .setDataNodeLayoutVersion(versionInfo);
+          .setDatanodeVersion(versionInfo);
       addReports(requestBuilder);
       addContainerActions(requestBuilder);
       addPipelineActions(requestBuilder);
@@ -363,9 +363,9 @@ private void processResponse(SCMHeartbeatResponseProto 
response,
         processCommonCommand(commandResponseProto,
             setNodeOperationalStateCommand);
         break;
-      case finalizeNewLayoutVersionCommand:
+      case finalizeNewDatanodeVersionCommand:
         FinalizeVersionCommand finalizeVersionCommand =
-            
FinalizeVersionCommand.getFromProtobuf(commandResponseProto.getFinalizeNewLayoutVersionCommandProto());
+            
FinalizeVersionCommand.getFromProtobuf(commandResponseProto.getFinalizeNewDatanodeVersionCommandProto());
         if (LOG.isDebugEnabled()) {
           LOG.debug("Received SCM finalize command {}", 
finalizeVersionCommand.getId());
         }
diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/RegisterEndpointTask.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/RegisterEndpointTask.java
index cc946694257..08bff1a422d 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/RegisterEndpointTask.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/endpoint/RegisterEndpointTask.java
@@ -27,7 +27,7 @@
 import org.apache.hadoop.hdds.conf.ConfigurationSource;
 import org.apache.hadoop.hdds.protocol.DatanodeDetails;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReportsProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMRegisteredResponseProto;
@@ -108,10 +108,10 @@ public EndpointStateMachine.EndPointStates call() throws 
Exception {
 
       if (rpcEndPoint.getState()
           .equals(EndpointStateMachine.EndPointStates.REGISTER)) {
-        LayoutVersionProto layoutInfo = LayoutVersionProto.newBuilder()
-            .setMetadataLayoutVersion(
+        DatanodeVersionProto versionInfo = DatanodeVersionProto.newBuilder()
+            .setApparentVersion(
                 versionManager.getApparentVersion().serialize())
-            .setSoftwareLayoutVersion(
+            .setSoftwareVersion(
                 versionManager.getSoftwareVersion().serialize())
             .build();
         ContainerReportsProto containerReport =
@@ -122,7 +122,7 @@ public EndpointStateMachine.EndPointStates call() throws 
Exception {
         // TODO : Add responses to the command Queue.
         SCMRegisteredResponseProto response = rpcEndPoint.getEndPoint()
             .register(datanodeDetails.getExtendedProtoBufMessage(),
-            nodeReport, containerReport, pipelineReportsProto, layoutInfo);
+            nodeReport, containerReport, pipelineReportsProto, versionInfo);
         Preconditions.assertEquals(datanodeDetails.getUuidString(), 
response.getDatanodeUUID(), "datanodeID");
         Preconditions.assertTrue(!StringUtils.isBlank(response.getClusterID()),
             "Invalid cluster ID in the response.");
diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/upgrade/UpgradeUtils.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/upgrade/UpgradeUtils.java
index 29024891ee4..4901afb7aae 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/upgrade/UpgradeUtils.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/upgrade/UpgradeUtils.java
@@ -19,7 +19,7 @@
 
 import org.apache.hadoop.hdds.ComponentVersion;
 import org.apache.hadoop.hdds.HDDSVersion;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 
 /**
  * Util methods for upgrade.
@@ -29,17 +29,18 @@ public final class UpgradeUtils {
   private UpgradeUtils() {
   }
 
-  public static LayoutVersionProto defaultVersionProto() {
+  public static DatanodeVersionProto defaultVersionProto() {
     int softwareVersion = HDDSVersion.SOFTWARE_VERSION.serialize();
-    return LayoutVersionProto.newBuilder()
-        .setMetadataLayoutVersion(softwareVersion)
-        .setSoftwareLayoutVersion(softwareVersion).build();
+    return DatanodeVersionProto.newBuilder()
+        .setApparentVersion(softwareVersion)
+        .setSoftwareVersion(softwareVersion).build();
   }
 
-  public static LayoutVersionProto toVersionProto(ComponentVersion 
apparentVersion, ComponentVersion softwareVersion) {
-    return LayoutVersionProto.newBuilder()
-        .setMetadataLayoutVersion(apparentVersion.serialize())
-        .setSoftwareLayoutVersion(softwareVersion.serialize())
+  public static DatanodeVersionProto toVersionProto(ComponentVersion 
apparentVersion,
+                                                    ComponentVersion 
softwareVersion) {
+    return DatanodeVersionProto.newBuilder()
+        .setApparentVersion(apparentVersion.serialize())
+        .setSoftwareVersion(softwareVersion.serialize())
         .build();
   }
 }
diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/StorageContainerDatanodeProtocol.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/StorageContainerDatanodeProtocol.java
index a9342621372..1d75ef3208e 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/StorageContainerDatanodeProtocol.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/StorageContainerDatanodeProtocol.java
@@ -22,7 +22,7 @@
 import org.apache.hadoop.hdds.annotation.InterfaceAudience;
 import 
org.apache.hadoop.hdds.protocol.proto.HddsProtos.ExtendedDatanodeDetailsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReportsProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMHeartbeatRequestProto;
@@ -69,7 +69,7 @@ SCMHeartbeatResponseProto 
sendHeartbeat(SCMHeartbeatRequestProto heartbeat)
    * @param extendedDatanodeDetailsProto - extended Datanode Details.
    * @param nodeReport - Node Report.
    * @param containerReportsRequestProto - Container Reports.
-   * @param layoutInfo - Layout Version Information.
+   * @param versionInfo - Datanode Version Information.
    * @return SCM Command.
    */
   SCMRegisteredResponseProto register(
@@ -77,6 +77,6 @@ SCMRegisteredResponseProto register(
       NodeReportProto nodeReport,
       ContainerReportsProto containerReportsRequestProto,
       PipelineReportsProto pipelineReports,
-      LayoutVersionProto layoutInfo) throws IOException;
+      DatanodeVersionProto versionInfo) throws IOException;
 
 }
diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/StorageContainerNodeProtocol.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/StorageContainerNodeProtocol.java
index 210c87e99bf..ec728dbf2c2 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/StorageContainerNodeProtocol.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/StorageContainerNodeProtocol.java
@@ -21,7 +21,7 @@
 import org.apache.hadoop.hdds.annotation.InterfaceAudience;
 import org.apache.hadoop.hdds.protocol.DatanodeDetails;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.CommandQueueReportProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMVersionRequestProto;
@@ -52,13 +52,13 @@ public interface StorageContainerNodeProtocol {
    * @param datanodeDetails DatanodeDetails
    * @param nodeReport NodeReportProto
    * @param pipelineReport PipelineReportsProto
-   * @param layoutVersionInfo LayoutVersionProto
+   * @param versionInfo DatanodeVersionProto
    * @return  SCMRegisteredResponseProto
    */
   RegisteredCommand register(DatanodeDetails datanodeDetails,
                              NodeReportProto nodeReport,
                              PipelineReportsProto pipelineReport,
-                             LayoutVersionProto layoutVersionInfo);
+                             DatanodeVersionProto versionInfo);
 
   /**
    * Send heartbeat to indicate the datanode is alive and doing well.
diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/FinalizeVersionCommand.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/FinalizeVersionCommand.java
index 181a6f6b1a6..38c5030ce63 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/FinalizeVersionCommand.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocol/commands/FinalizeVersionCommand.java
@@ -18,32 +18,25 @@
 package org.apache.hadoop.ozone.protocol.commands;
 
 import java.util.Objects;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.FinalizeNewLayoutVersionCommandProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.FinalizeNewDatanodeVersionCommandProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto;
 
 /**
  * Asks DataNode to finalize new upgrade version.
  */
 public class FinalizeVersionCommand
-    extends SCMCommand<FinalizeNewLayoutVersionCommandProto> {
+    extends SCMCommand<FinalizeNewDatanodeVersionCommandProto> {
 
-  private boolean finalizeUpgrade = false;
-  private LayoutVersionProto versionInfo;
+  private final int expectedSoftwareVersion;
 
-  public FinalizeVersionCommand(boolean finalizeNewLayoutVersion,
-                                LayoutVersionProto versionInfo,
-                                long id) {
+  public FinalizeVersionCommand(int expectedSoftwareVersion, long id) {
     super(id);
-    finalizeUpgrade = finalizeNewLayoutVersion;
-    this.versionInfo = versionInfo;
+    this.expectedSoftwareVersion = expectedSoftwareVersion;
   }
 
-  public FinalizeVersionCommand(boolean finalizeNewLayoutVersion,
-                                LayoutVersionProto versionInfo) {
+  public FinalizeVersionCommand(int expectedSoftwareVersion) {
     super();
-    finalizeUpgrade = finalizeNewLayoutVersion;
-    this.versionInfo = versionInfo;
+    this.expectedSoftwareVersion = expectedSoftwareVersion;
   }
 
   /**
@@ -53,24 +46,22 @@ public FinalizeVersionCommand(boolean 
finalizeNewLayoutVersion,
    */
   @Override
   public SCMCommandProto.Type getType() {
-    return SCMCommandProto.Type.finalizeNewLayoutVersionCommand;
+    return SCMCommandProto.Type.finalizeNewDatanodeVersionCommand;
   }
 
   @Override
-  public FinalizeNewLayoutVersionCommandProto getProto() {
-    return FinalizeNewLayoutVersionCommandProto.newBuilder()
-        .setFinalizeNewLayoutVersion(finalizeUpgrade)
+  public FinalizeNewDatanodeVersionCommandProto getProto() {
+    return FinalizeNewDatanodeVersionCommandProto.newBuilder()
+        .setExpectedSoftwareVersion(expectedSoftwareVersion)
         .setCmdId(getId())
-        .setDataNodeLayoutVersion(versionInfo)
         .build();
   }
 
   public static FinalizeVersionCommand getFromProtobuf(
-      FinalizeNewLayoutVersionCommandProto finalizeProto) {
+      FinalizeNewDatanodeVersionCommandProto finalizeProto) {
     Objects.requireNonNull(finalizeProto, "finalizeProto == null");
     return new FinalizeVersionCommand(
-        finalizeProto.getFinalizeNewLayoutVersion(),
-        finalizeProto.getDataNodeLayoutVersion(), finalizeProto.getCmdId());
+        finalizeProto.getExpectedSoftwareVersion(), finalizeProto.getCmdId());
   }
 
   @Override
@@ -81,8 +72,7 @@ public String toString() {
         .append(", encodedToken: \"").append(getEncodedToken()).append('"')
         .append(", term: ").append(getTerm())
         .append(", deadlineMsSinceEpoch: ").append(getDeadline())
-        .append(", finalizeUpgrade: ").append(finalizeUpgrade)
-        .append(", versionInfo: ").append(versionInfo);
+        .append(", expectedSoftwareVersion: ").append(expectedSoftwareVersion);
     return sb.toString();
   }
 }
diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolClientSideTranslatorPB.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolClientSideTranslatorPB.java
index 328b2b2e6ac..2e21d7bc2bb 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolClientSideTranslatorPB.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolClientSideTranslatorPB.java
@@ -24,7 +24,7 @@
 import java.util.function.Consumer;
 import 
org.apache.hadoop.hdds.protocol.proto.HddsProtos.ExtendedDatanodeDetailsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReportsProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMDatanodeRequest;
@@ -144,7 +144,7 @@ public SCMHeartbeatResponseProto sendHeartbeat(
    * @param extendedDatanodeDetailsProto - extended Datanode Details
    * @param nodeReport - Node Report.
    * @param containerReportsRequestProto - Container Reports.
-   * @param layoutInfo - Layout Version Information.
+   * @param versionInfo - Datanode Version Information.
    * @return SCM Command.
    */
   @Override
@@ -153,7 +153,7 @@ public SCMRegisteredResponseProto register(
       NodeReportProto nodeReport,
       ContainerReportsProto containerReportsRequestProto,
       PipelineReportsProto pipelineReportsProto,
-      LayoutVersionProto layoutInfo)
+      DatanodeVersionProto versionInfo)
       throws IOException {
     SCMRegisterRequestProto.Builder req =
         SCMRegisterRequestProto.newBuilder();
@@ -161,8 +161,8 @@ public SCMRegisteredResponseProto register(
     req.setContainerReport(containerReportsRequestProto);
     req.setPipelineReports(pipelineReportsProto);
     req.setNodeReport(nodeReport);
-    if (layoutInfo != null) {
-      req.setDataNodeLayoutVersion(layoutInfo);
+    if (versionInfo != null) {
+      req.setDatanodeVersion(versionInfo);
     }
     return submitRequest(Type.Register,
         (builder) -> builder.setRegisterRequest(req))
diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolServerSideTranslatorPB.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolServerSideTranslatorPB.java
index 3f91c277bf7..0adc824aabd 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolServerSideTranslatorPB.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/protocolPB/StorageContainerDatanodeProtocolServerSideTranslatorPB.java
@@ -17,15 +17,12 @@
 
 package org.apache.hadoop.ozone.protocolPB;
 
-import static org.apache.hadoop.hdds.upgrade.HDDSLayoutFeature.INITIAL_VERSION;
-import static 
org.apache.hadoop.ozone.container.upgrade.UpgradeUtils.toVersionProto;
-
 import com.google.protobuf.RpcController;
 import com.google.protobuf.ServiceException;
 import java.io.IOException;
 import java.util.concurrent.TimeoutException;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReportsProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMDatanodeRequest;
@@ -71,14 +68,8 @@ public SCMRegisteredResponseProto register(
         .getContainerReport();
     NodeReportProto dnNodeReport = request.getNodeReport();
     PipelineReportsProto pipelineReport = request.getPipelineReports();
-    LayoutVersionProto versionInfo = null;
-    if (request.hasDataNodeLayoutVersion()) {
-      versionInfo = request.getDataNodeLayoutVersion();
-    } else {
-      // Backward compatibility to make sure old Datanodes can still talk to
-      // SCM.
-      versionInfo = toVersionProto(INITIAL_VERSION, INITIAL_VERSION);
-    }
+    // Datanodes which do not report a version will not be allowed to register.
+    DatanodeVersionProto versionInfo = request.hasDatanodeVersion() ? 
request.getDatanodeVersion() : null;
     return impl.register(request.getExtendedDatanodeDetails(), dnNodeReport,
         containerRequestProto, pipelineReport, versionInfo);
   }
diff --git 
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/ScmTestMock.java
 
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/ScmTestMock.java
index 902b0ab2168..ad95e737822 100644
--- 
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/ScmTestMock.java
+++ 
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/ScmTestMock.java
@@ -34,7 +34,7 @@
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.CommandStatusReportsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReplicaProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReportsProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto;
@@ -227,7 +227,7 @@ private void sleepIfNeeded() {
       NodeReportProto nodeReport,
       ContainerReportsProto containerReportsRequestProto,
       PipelineReportsProto pipelineReportsProto,
-      LayoutVersionProto layoutInfo)
+      DatanodeVersionProto versionInfo)
       throws IOException {
     rpcCount.incrementAndGet();
     DatanodeDetailsProto datanodeDetailsProto =
diff --git 
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/TestFinalizeVersionCommandHandler.java
 
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/TestFinalizeVersionCommandHandler.java
new file mode 100644
index 00000000000..82ccb8dc49c
--- /dev/null
+++ 
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/TestFinalizeVersionCommandHandler.java
@@ -0,0 +1,91 @@
+/*
+ * 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.container.common.statemachine.commandhandler;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+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 org.apache.hadoop.hdds.ComponentVersion;
+import 
org.apache.hadoop.ozone.container.common.statemachine.DatanodeStateMachine;
+import 
org.apache.hadoop.ozone.container.common.statemachine.SCMConnectionManager;
+import org.apache.hadoop.ozone.container.common.statemachine.StateContext;
+import org.apache.hadoop.ozone.container.ozoneimpl.OzoneContainer;
+import org.apache.hadoop.ozone.container.upgrade.DatanodeVersionManager;
+import org.apache.hadoop.ozone.protocol.commands.FinalizeVersionCommand;
+import org.apache.hadoop.ozone.upgrade.UpgradeException;
+import org.apache.ratis.util.ExitUtils;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for {@link FinalizeVersionCommandHandler}.
+ */
+public class TestFinalizeVersionCommandHandler {
+
+  private static final int DN_SOFTWARE_VERSION = 3;
+
+  @AfterEach
+  public void reset() {
+    ExitUtils.clear();
+  }
+
+  private StateContext mockContext(DatanodeVersionManager versionManager) {
+    ComponentVersion softwareVersion = mock(ComponentVersion.class);
+    when(softwareVersion.serialize()).thenReturn(DN_SOFTWARE_VERSION);
+    when(versionManager.getSoftwareVersion()).thenReturn(softwareVersion);
+
+    DatanodeStateMachine dsm = mock(DatanodeStateMachine.class);
+    when(dsm.getVersionManager()).thenReturn(versionManager);
+    StateContext context = mock(StateContext.class);
+    when(context.getParent()).thenReturn(dsm);
+    return context;
+  }
+
+  @Test
+  public void testFinalizesWhenExpectedVersionMatches() throws 
UpgradeException {
+    DatanodeVersionManager versionManager = mock(DatanodeVersionManager.class);
+    when(versionManager.needsFinalization()).thenReturn(true);
+    StateContext context = mockContext(versionManager);
+
+    new FinalizeVersionCommandHandler().handle(
+        new FinalizeVersionCommand(DN_SOFTWARE_VERSION), 
mock(OzoneContainer.class),
+        context, mock(SCMConnectionManager.class));
+
+    verify(versionManager, times(1)).finalizeUpgrade();
+  }
+
+  @Test
+  public void testTerminatesWhenExpectedVersionMismatches() throws 
UpgradeException {
+    ExitUtils.disableSystemExit();
+    DatanodeVersionManager versionManager = mock(DatanodeVersionManager.class);
+    StateContext context = mockContext(versionManager);
+
+    ExitUtils.ExitException ex = assertThrows(ExitUtils.ExitException.class, 
() ->
+        new FinalizeVersionCommandHandler().handle(
+            new FinalizeVersionCommand(DN_SOFTWARE_VERSION + 1), 
mock(OzoneContainer.class),
+            context, mock(SCMConnectionManager.class)));
+
+    assertEquals(1, ex.getStatus());
+    verify(versionManager, never()).finalizeUpgrade();
+  }
+}
diff --git 
a/hadoop-hdds/interface-server/src/main/proto/ScmServerDatanodeHeartbeatProtocol.proto
 
b/hadoop-hdds/interface-server/src/main/proto/ScmServerDatanodeHeartbeatProtocol.proto
index 3d08f39992c..4d9bb74a04f 100644
--- 
a/hadoop-hdds/interface-server/src/main/proto/ScmServerDatanodeHeartbeatProtocol.proto
+++ 
b/hadoop-hdds/interface-server/src/main/proto/ScmServerDatanodeHeartbeatProtocol.proto
@@ -75,6 +75,10 @@ enum Status {
 }
 
 /**
+ * Deprecated, please use DatanodeVersionProto instead. The field names
+ * metadataLayoutVersion and softwareLayoutVersion have been replaced by
+ * apparentVersion and softwareVersion respectively.
+ *
  * DataNode will advertise its current layout version through
  * heartbeat as well as registration mechanism.
  */
@@ -83,6 +87,14 @@ message LayoutVersionProto {
    required uint32 softwareLayoutVersion = 2;
 }
 
+/**
+ * Used by Datanodes to report their versions to SCM.
+ */
+message DatanodeVersionProto {
+   optional uint32 apparentVersion = 1;
+   optional uint32 softwareVersion = 2;
+}
+
 /**
  * Request for version info of the software stack on the server.
  */
@@ -102,7 +114,8 @@ message SCMRegisterRequestProto {
   required NodeReportProto nodeReport = 2;
   required ContainerReportsProto containerReport = 3;
   required PipelineReportsProto pipelineReports = 4;
-  optional LayoutVersionProto dataNodeLayoutVersion = 5;
+  optional LayoutVersionProto dataNodeLayoutVersion = 5 [deprecated = true];
+  optional DatanodeVersionProto datanodeVersion = 6;
 }
 
 /**
@@ -137,8 +150,9 @@ message SCMHeartbeatRequestProto {
   optional ContainerActionsProto containerActions = 6;
   optional PipelineActionsProto pipelineActions = 7;
   optional PipelineReportsProto pipelineReports = 8;
-  optional LayoutVersionProto dataNodeLayoutVersion = 9;
+  optional LayoutVersionProto dataNodeLayoutVersion = 9 [deprecated = true];
   optional CommandQueueReportProto commandQueueReport = 10;
+  optional DatanodeVersionProto datanodeVersion = 11;
 }
 
 message CommandQueueReportProto {
@@ -324,10 +338,11 @@ message SCMCommandProto {
     createPipelineCommand = 6;
     closePipelineCommand = 7;
     setNodeOperationalStateCommand = 8;
-    finalizeNewLayoutVersionCommand = 9;
+    finalizeNewLayoutVersionCommand = 9 [deprecated = true];
     refreshVolumeUsageInfo = 10;
     reconstructECContainersCommand = 11;
     reconcileContainerCommand = 12;
+    finalizeNewDatanodeVersionCommand = 13;
   }
   // TODO: once we start using protoc 3.x, refactor this message using "oneof"
   required Type commandType = 1;
@@ -340,10 +355,11 @@ message SCMCommandProto {
   optional ClosePipelineCommandProto closePipelineCommandProto = 8;
   optional SetNodeOperationalStateCommandProto 
setNodeOperationalStateCommandProto = 9;
   optional FinalizeNewLayoutVersionCommandProto
-  finalizeNewLayoutVersionCommandProto = 10;
+  finalizeNewLayoutVersionCommandProto = 10 [deprecated = true];
   optional RefreshVolumeUsageCommandProto refreshVolumeUsageCommandProto = 11;
   optional ReconstructECContainersCommandProto 
reconstructECContainersCommandProto = 12;
   optional ReconcileContainerCommandProto reconcileContainerCommandProto = 13;
+  optional FinalizeNewDatanodeVersionCommandProto 
finalizeNewDatanodeVersionCommandProto = 14;
 
   // If running upon Ratis, holds term of underlying RaftServer iff current
   // SCM is a leader. If running without Ratis, holds SCMContext.INVALID_TERM.
@@ -497,6 +513,8 @@ message ProcessCRLCommandProto {
 }
 
 /**
+ * Deprecated, please use FinalizeNewDatanodeVersionCommandProto instead.
+ *
  * This command asks the DataNode to finalize a new layout version.
  */
 message FinalizeNewLayoutVersionCommandProto {
@@ -505,6 +523,14 @@ message FinalizeNewLayoutVersionCommandProto {
   required int64 cmdId = 3;
 }
 
+/**
+ * This command asks the Datanode to finalize a new datanode version.
+ */
+message FinalizeNewDatanodeVersionCommandProto {
+  optional uint32 expectedSoftwareVersion = 1;
+  optional int64 cmdId = 2;
+}
+
 /**
 This command asks the datanode to reconcile its copy of a container with its 
peer datanodes that also have a copy of
 the container.
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/DatanodeInfo.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/DatanodeInfo.java
index 54e996ec3bf..160f788c90c 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/DatanodeInfo.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/DatanodeInfo.java
@@ -27,7 +27,7 @@
 import org.apache.hadoop.hdds.ComponentVersion;
 import org.apache.hadoop.hdds.protocol.DatanodeDetails;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.CommandQueueReportProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.MetadataStorageReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.StorageReportProto;
@@ -68,17 +68,17 @@ public class DatanodeInfo extends DatanodeDetails {
    * Constructs DatanodeInfo from DatanodeDetails.
    *
    * @param datanodeDetails Details about the datanode
-   * @param versionInfo Details about the LayoutVersionProto
+   * @param versionInfo Details about the DatanodeVersionProto
    */
   public DatanodeInfo(DatanodeDetails datanodeDetails, NodeStatus nodeStatus,
-       LayoutVersionProto versionInfo, long containerRollIntervalMs) {
+       DatanodeVersionProto versionInfo, long containerRollIntervalMs) {
     super(datanodeDetails);
     this.lock = new ReentrantReadWriteLock();
     this.lastHeartbeatTime = Time.monotonicNow();
     this.lastKnownSoftwareVersion =
-        
HDDSVersionUtils.deserializeHDDSVersionOrLayoutVersion(versionInfo.getSoftwareLayoutVersion());
+        
HDDSVersionUtils.deserializeHDDSVersionOrLayoutVersion(versionInfo.getSoftwareVersion());
     this.lastKnownApparentVersion =
-        
HDDSVersionUtils.deserializeHDDSVersionOrLayoutVersion(versionInfo.getMetadataLayoutVersion());
+        
HDDSVersionUtils.deserializeHDDSVersionOrLayoutVersion(versionInfo.getApparentVersion());
     this.storageReports = Collections.emptyList();
     this.nodeStatus = nodeStatus;
     this.metadataStorageReports = Collections.emptyList();
@@ -112,16 +112,16 @@ public void updateLastHeartbeatTime(long 
milliSecondsSinceEpoch) {
   /**
    * Updates the last known apparent and software versions for this datanode.
    */
-  public void updateLastKnownVersions(LayoutVersionProto version) {
+  public void updateLastKnownVersions(DatanodeVersionProto version) {
     if (version == null) {
       return;
     }
     try {
       lock.writeLock().lock();
       lastKnownSoftwareVersion =
-          
HDDSVersionUtils.deserializeHDDSVersionOrLayoutVersion(version.getSoftwareLayoutVersion());
+          
HDDSVersionUtils.deserializeHDDSVersionOrLayoutVersion(version.getSoftwareVersion());
       lastKnownApparentVersion =
-          
HDDSVersionUtils.deserializeHDDSVersionOrLayoutVersion(version.getMetadataLayoutVersion());
+          
HDDSVersionUtils.deserializeHDDSVersionOrLayoutVersion(version.getApparentVersion());
     } finally {
       lock.writeLock().unlock();
     }
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeManager.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeManager.java
index a3afe1f2506..3f232cb8a51 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeManager.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeManager.java
@@ -32,7 +32,7 @@
 import org.apache.hadoop.hdds.protocol.DatanodeID;
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeOperationalState;
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto;
@@ -388,13 +388,13 @@ void processNodeReport(DatanodeDetails datanodeDetails,
                          NodeReportProto nodeReport);
 
   /**
-   * Process Node LayoutVersion report.
+   * Process Node version report.
    *
    * @param datanodeDetails
-   * @param layoutReport
+   * @param versionReport
    */
   void processVersionReport(DatanodeDetails datanodeDetails,
-                            LayoutVersionProto layoutReport);
+                            DatanodeVersionProto versionReport);
 
   /**
    * Get the number of commands of the given type queued on the datanode at the
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeStateManager.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeStateManager.java
index e23d3f33c10..266fb0f2d94 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeStateManager.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/NodeStateManager.java
@@ -44,7 +44,7 @@
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeOperationalState;
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import org.apache.hadoop.hdds.scm.ScmConfigKeys;
 import org.apache.hadoop.hdds.scm.container.ContainerID;
 import org.apache.hadoop.hdds.scm.events.SCMEvents;
@@ -232,24 +232,24 @@ private void initializeStateMachines() {
    * Adds a new node to the state manager.
    *
    * @param datanodeDetails DatanodeDetails
-   * @param layoutInfo LayoutVersionProto
+   * @param versionInfo DatanodeVersionProto
    *
    * @throws NodeAlreadyExistsException if the node is already present
    */
   public void addNode(DatanodeDetails datanodeDetails,
-      LayoutVersionProto layoutInfo) throws NodeAlreadyExistsException {
-    nodeStateMap.addNode(newDatanodeInfo(datanodeDetails, layoutInfo));
+      DatanodeVersionProto versionInfo) throws NodeAlreadyExistsException {
+    nodeStateMap.addNode(newDatanodeInfo(datanodeDetails, versionInfo));
     try {
-      updateLastKnownVersionInfo(datanodeDetails, layoutInfo);
+      updateLastKnownVersionInfo(datanodeDetails, versionInfo);
     } catch (NodeNotFoundException ex) {
       throw new IllegalStateException("Inconsistent NodeStateMap! Datanode "
           + datanodeDetails.getID() + " was added but not found in map: " + 
nodeStateMap);
     }
   }
 
-  private DatanodeInfo newDatanodeInfo(DatanodeDetails datanode, 
LayoutVersionProto layout) {
+  private DatanodeInfo newDatanodeInfo(DatanodeDetails datanode, 
DatanodeVersionProto versionInfo) {
     final NodeStatus status = newNodeStatus(datanode);
-    return new DatanodeInfo(datanode, status, layout, containerRollIntervalMs);
+    return new DatanodeInfo(datanode, status, versionInfo, 
containerRollIntervalMs);
   }
 
   /**
@@ -318,33 +318,33 @@ public void updateLastHeartbeatTime(DatanodeDetails 
datanodeDetails)
   }
 
   /**
-   * Updates the last known layout version of the node.
+   * Updates the last known version of the node.
    * @param datanodeDetails DataNode Details
-   * @param layoutInfo DataNode Layout Information
+   * @param versionInfo DataNode Version Information
    *
    * @throws NodeNotFoundException if the node is not present
    */
   public void updateLastKnownVersionInfo(DatanodeDetails datanodeDetails,
-      LayoutVersionProto layoutInfo) throws NodeNotFoundException {
+      DatanodeVersionProto versionInfo) throws NodeNotFoundException {
     nodeStateMap.getNodeInfo(datanodeDetails.getID())
-        .updateLastKnownVersions(layoutInfo);
+        .updateLastKnownVersions(versionInfo);
   }
 
   /**
    * Update node.
    *
    * @param datanodeDetails the datanode details
-   * @param layoutInfo the layoutInfo
+   * @param versionInfo the datanode version information
    * @throws NodeNotFoundException the node not found exception
    */
   public void updateNode(DatanodeDetails datanodeDetails,
-                         LayoutVersionProto layoutInfo)
+                         DatanodeVersionProto versionInfo)
           throws NodeNotFoundException {
-    final DatanodeInfo newInfo = newDatanodeInfo(datanodeDetails, layoutInfo);
+    final DatanodeInfo newInfo = newDatanodeInfo(datanodeDetails, versionInfo);
     final DatanodeInfo oldInfo = nodeStateMap.updateNode(newInfo);
     LOG.info("Updated datanode {} {} to {} {}",
         oldInfo, oldInfo.getNodeStatus(), newInfo, newInfo.getNodeStatus());
-    updateLastKnownVersionInfo(datanodeDetails, layoutInfo);
+    updateLastKnownVersionInfo(datanodeDetails, versionInfo);
   }
 
   /**
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeManager.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeManager.java
index 3bcb7fa7f17..9f4f5353a77 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeManager.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeManager.java
@@ -60,7 +60,7 @@
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState;
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos.StorageTypeProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.CommandQueueReportProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.MetadataStorageReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
@@ -381,9 +381,9 @@ public RegisteredCommand register(
       DatanodeDetails datanodeDetails, NodeReportProto nodeReport,
       PipelineReportsProto pipelineReportsProto) {
     return register(datanodeDetails, nodeReport, pipelineReportsProto,
-        LayoutVersionProto.newBuilder()
-            
.setMetadataLayoutVersion(versionManager.getApparentVersion().serialize())
-            
.setSoftwareLayoutVersion(versionManager.getSoftwareVersion().serialize())
+        DatanodeVersionProto.newBuilder()
+            
.setApparentVersion(versionManager.getApparentVersion().serialize())
+            
.setSoftwareVersion(versionManager.getSoftwareVersion().serialize())
             .build());
   }
 
@@ -403,7 +403,7 @@ public RegisteredCommand register(
   public RegisteredCommand register(
       DatanodeDetails datanodeDetails, NodeReportProto nodeReport,
       PipelineReportsProto pipelineReportsProto,
-      LayoutVersionProto dnVersionInfo) {
+      DatanodeVersionProto dnVersionInfo) {
     if (shouldFenceDatanode(datanodeDetails, dnVersionInfo)) {
       return RegisteredCommand.newBuilder()
           .setErrorCode(ErrorCode.errorNodeNotPermitted)
@@ -726,14 +726,14 @@ public void processNodeReport(DatanodeDetails 
datanodeDetails,
   }
 
   /**
-   * Process Layout Version report.
+   * Process version report.
    *
    * @param datanodeDetails
    * @param versionReport
    */
   @Override
   public void processVersionReport(DatanodeDetails datanodeDetails,
-                                   LayoutVersionProto versionReport) {
+                                   DatanodeVersionProto versionReport) {
     if (LOG.isDebugEnabled()) {
       LOG.debug("Processing version report from [datanode={}]",
           datanodeDetails.getHostName());
@@ -757,11 +757,11 @@ public void processVersionReport(DatanodeDetails 
datanodeDetails,
   }
 
   protected void sendFinalizeToDatanodeIfNeeded(DatanodeDetails 
datanodeDetails,
-      LayoutVersionProto versionReport) {
+      DatanodeVersionProto versionReport) {
     ComponentVersion dnSoftwareVersion = 
HDDSVersionUtils.deserializeHDDSVersionOrLayoutVersion(
-        versionReport.getSoftwareLayoutVersion());
+        versionReport.getSoftwareVersion());
     ComponentVersion dnApparentVersion = 
HDDSVersionUtils.deserializeHDDSVersionOrLayoutVersion(
-        versionReport.getMetadataLayoutVersion());
+        versionReport.getApparentVersion());
     ComponentVersion scmSoftwareVersion = versionManager.getSoftwareVersion();
     ComponentVersion scmApparentVersion = versionManager.getApparentVersion();
 
@@ -795,10 +795,7 @@ protected void 
sendFinalizeToDatanodeIfNeeded(DatanodeDetails datanodeDetails,
         "apparent version {}", datanodeDetails, dnApparentVersion, 
scmApparentVersion);
 
     FinalizeVersionCommand finalizeCmd =
-        new FinalizeVersionCommand(true,
-            LayoutVersionProto.newBuilder()
-                .setSoftwareLayoutVersion(dnSoftwareVersion.serialize())
-                
.setMetadataLayoutVersion(dnSoftwareVersion.serialize()).build());
+        new FinalizeVersionCommand(scmSoftwareVersion.serialize());
     try {
       finalizeCmd.setTerm(scmContext.getTermOfLeader());
       // Send Finalize command to the data node. It's OK to send Finalize 
command multiple times.
@@ -2041,11 +2038,15 @@ public void removeNode(DatanodeDetails datanodeDetails) 
throws NodeNotFoundExcep
     }
   }
 
-  protected boolean shouldFenceDatanode(DatanodeDetails dnDetails, 
LayoutVersionProto versionReport) {
+  protected boolean shouldFenceDatanode(DatanodeDetails dnDetails, 
DatanodeVersionProto versionReport) {
+    if (versionReport == null || !versionReport.hasSoftwareVersion() || 
!versionReport.hasApparentVersion()) {
+      LOG.error("Datanode {} did not report its version. Not allowing it to 
join the cluster.", dnDetails);
+      return true;
+    }
     ComponentVersion dnSoftwareVersion = 
HDDSVersionUtils.deserializeHDDSVersionOrLayoutVersion(
-        versionReport.getSoftwareLayoutVersion());
+        versionReport.getSoftwareVersion());
     ComponentVersion dnApparentVersion = 
HDDSVersionUtils.deserializeHDDSVersionOrLayoutVersion(
-        versionReport.getMetadataLayoutVersion());
+        versionReport.getApparentVersion());
     return shouldFenceDatanode(dnDetails, dnSoftwareVersion, 
dnApparentVersion);
   }
 
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeHeartbeatDispatcher.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeHeartbeatDispatcher.java
index efb7a5b8116..e8cf61ba1e8 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeHeartbeatDispatcher.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeHeartbeatDispatcher.java
@@ -24,8 +24,6 @@
 import static org.apache.hadoop.hdds.scm.events.SCMEvents.NODE_REPORT;
 import static org.apache.hadoop.hdds.scm.events.SCMEvents.PIPELINE_ACTIONS;
 import static org.apache.hadoop.hdds.scm.events.SCMEvents.PIPELINE_REPORT;
-import static org.apache.hadoop.hdds.upgrade.HDDSLayoutFeature.INITIAL_VERSION;
-import static 
org.apache.hadoop.ozone.container.upgrade.UpgradeUtils.toVersionProto;
 
 import com.google.protobuf.Message;
 import java.util.List;
@@ -38,7 +36,6 @@
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerActionsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReportsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.IncrementalContainerReportProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineActionsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
@@ -97,18 +94,12 @@ public List<SCMCommand<?>> 
dispatch(SCMHeartbeatRequestProto heartbeat) {
 
     } else {
 
-      LayoutVersionProto versionInfo = null;
-      if (!heartbeat.hasDataNodeLayoutVersion()) {
-        // Backward compatibility to make sure old Datanodes can still talk to
-        // SCM.
-        versionInfo = toVersionProto(INITIAL_VERSION, INITIAL_VERSION);
-      } else {
-        versionInfo = heartbeat.getDataNodeLayoutVersion();
+      // Process the last known version reported by the datanode only when 
attached.
+      if (heartbeat.hasDatanodeVersion()) {
+        LOG.debug("Processing DataNode version report.");
+        nodeManager.processVersionReport(datanodeDetails, 
heartbeat.getDatanodeVersion());
       }
 
-      LOG.debug("Processing DataNode Layout Report.");
-      nodeManager.processVersionReport(datanodeDetails, versionInfo);
-
       CommandQueueReportProto commandQueueReport = null;
       if (heartbeat.hasCommandQueueReport()) {
         commandQueueReport = heartbeat.getCommandQueueReport();
@@ -250,18 +241,6 @@ public Map<SCMCommandProto.Type, Integer> 
getCommandsToBeSent() {
     }
   }
 
-  /**
-   * Layout report event payload with origin.
-   */
-  public static class LayoutReportFromDatanode
-      extends ReportFromDatanode<LayoutVersionProto> {
-
-    public LayoutReportFromDatanode(DatanodeDetails datanodeDetails,
-                                  LayoutVersionProto report) {
-      super(datanodeDetails, report);
-    }
-  }
-
   /**
    * Container report payload base reference.
    */
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeProtocolServer.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeProtocolServer.java
index f1c4c78168f..7ca8adccb28 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeProtocolServer.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeProtocolServer.java
@@ -22,7 +22,7 @@
 import static 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type.createPipelineCommand;
 import static 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type.deleteBlocksCommand;
 import static 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type.deleteContainerCommand;
-import static 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type.finalizeNewLayoutVersionCommand;
+import static 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type.finalizeNewDatanodeVersionCommand;
 import static 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type.reconcileContainerCommand;
 import static 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type.reconstructECContainersCommand;
 import static 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type.refreshVolumeUsageInfo;
@@ -58,7 +58,7 @@
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReportsProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ReconstructECContainersCommandProto;
@@ -230,7 +230,7 @@ public SCMRegisteredResponseProto register(
       NodeReportProto nodeReport,
       ContainerReportsProto containerReportsProto,
       PipelineReportsProto pipelineReportsProto,
-      LayoutVersionProto layoutInfo)
+      DatanodeVersionProto versionInfo)
       throws IOException {
     DatanodeDetails datanodeDetails = DatanodeDetails
         .getFromProtoBuf(extendedDatanodeDetailsProto);
@@ -241,7 +241,7 @@ public SCMRegisteredResponseProto register(
     // TODO : Return the list of Nodes that forms the SCM HA.
     RegisteredCommand registeredCommand = scm.getScmNodeManager()
         .register(datanodeDetails, nodeReport, pipelineReportsProto,
-            layoutInfo);
+            versionInfo);
     if (registeredCommand.getError()
         == SCMRegisteredResponseProto.ErrorCode.success) {
       eventPublisher.fireEvent(CONTAINER_REPORT,
@@ -419,10 +419,10 @@ public static SCMCommandProto 
getCommandResponse(SCMCommand<?> cmd,
             .setSetNodeOperationalStateCommandProto(
                 ((SetNodeOperationalStateCommand)cmd).getProto())
             .build();
-    case finalizeNewLayoutVersionCommand:
+    case finalizeNewDatanodeVersionCommand:
       return builder
-            .setCommandType(finalizeNewLayoutVersionCommand)
-            .setFinalizeNewLayoutVersionCommandProto(
+            .setCommandType(finalizeNewDatanodeVersionCommand)
+            .setFinalizeNewDatanodeVersionCommandProto(
                 ((FinalizeVersionCommand)cmd).getProto())
             .build();
     case refreshVolumeUsageInfo:
diff --git 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/MockNodeManager.java
 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/MockNodeManager.java
index 4cb0eda9515..8111abb6e9b 100644
--- 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/MockNodeManager.java
+++ 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/MockNodeManager.java
@@ -44,7 +44,7 @@
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeOperationalState;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.CommandQueueReportProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.MetadataStorageReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
@@ -650,14 +650,14 @@ public void processNodeReport(DatanodeDetails dnUuid,
   }
 
   /**
-   * Empty implementation for processLayoutVersionReport.
+   * Empty implementation for processVersionReport.
    *
    * @param dnUuid
-   * @param layoutReport
+   * @param versionReport
    */
   @Override
   public void processVersionReport(DatanodeDetails dnUuid,
-                                   LayoutVersionProto layoutReport) {
+                                   DatanodeVersionProto versionReport) {
     // do nothing
   }
 
@@ -793,9 +793,9 @@ public VersionResponse getVersion(SCMVersionRequestProto 
versionRequest) {
   public RegisteredCommand register(DatanodeDetails datanodeDetails,
                                     NodeReportProto nodeReport,
                                     PipelineReportsProto pipelineReportsProto,
-                                    LayoutVersionProto layoutInfo) {
+                                    DatanodeVersionProto versionInfo) {
     final DatanodeInfo info = new DatanodeInfo(datanodeDetails,
-        NodeStatus.inServiceHealthy(), layoutInfo, 
HddsTestUtils.ROLL_INTERVAL_MS_DEFAULT);
+        NodeStatus.inServiceHealthy(), versionInfo, 
HddsTestUtils.ROLL_INTERVAL_MS_DEFAULT);
     try {
       node2ContainerMap.addNode(info);
       addEntryTodnsToUuidMap(datanodeDetails.getIpAddress(),
diff --git 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/SimpleMockNodeManager.java
 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/SimpleMockNodeManager.java
index aa2f1ef94bc..aea96de4e70 100644
--- 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/SimpleMockNodeManager.java
+++ 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/SimpleMockNodeManager.java
@@ -30,7 +30,7 @@
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeOperationalState;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.CommandQueueReportProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto;
@@ -308,7 +308,7 @@ public void processNodeReport(DatanodeDetails 
datanodeDetails,
 
   @Override
   public void processVersionReport(DatanodeDetails datanodeDetails,
-                                   LayoutVersionProto layoutReport) {
+                                   DatanodeVersionProto versionReport) {
   }
 
   /**
@@ -436,7 +436,7 @@ public VersionResponse getVersion(
   public RegisteredCommand register(DatanodeDetails datanodeDetails,
                                     NodeReportProto nodeReport,
                                     PipelineReportsProto pipelineReport,
-                                    LayoutVersionProto layoutreport) {
+                                    DatanodeVersionProto versionReport) {
     return null;
   }
 
diff --git 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestNodeStateManager.java
 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestNodeStateManager.java
index 48b1b813f44..4578e4529df 100644
--- 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestNodeStateManager.java
+++ 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestNodeStateManager.java
@@ -296,8 +296,8 @@ public void testUpdateNode() throws 
NodeAlreadyExistsException,
     UUID dnUuid = UUID.randomUUID();
     String ipAddress = "1.2.3.4";
     String hostName = "test-host";
-    StorageContainerDatanodeProtocolProtos.LayoutVersionProto
-            layoutVersionProto =
+    StorageContainerDatanodeProtocolProtos.DatanodeVersionProto
+            datanodeVersionProto =
             UpgradeUtils.toVersionProto(HDDSLayoutFeature.INITIAL_VERSION, 
HDDSLayoutFeature.INITIAL_VERSION);
     DatanodeDetails dn = DatanodeDetails.newBuilder()
             .setUuid(dnUuid)
@@ -305,19 +305,19 @@ public void testUpdateNode() throws 
NodeAlreadyExistsException,
             .setHostName(hostName)
             
.setPersistedOpState(HddsProtos.NodeOperationalState.IN_MAINTENANCE)
             .build();
-    nsm.addNode(dn, layoutVersionProto);
+    nsm.addNode(dn, datanodeVersionProto);
 
     String newIpAddress = "2.3.4.5";
     String newHostName = "new-host";
-    StorageContainerDatanodeProtocolProtos.LayoutVersionProto
-            newLayoutVersionProto = UpgradeUtils.defaultVersionProto();
+    StorageContainerDatanodeProtocolProtos.DatanodeVersionProto
+            newDatanodeVersionProto = UpgradeUtils.defaultVersionProto();
     DatanodeDetails newDn = DatanodeDetails.newBuilder()
             .setUuid(dnUuid)
             .setIpAddress(newIpAddress)
             .setHostName(newHostName)
             .setPersistedOpState(HddsProtos.NodeOperationalState.IN_SERVICE)
             .build();
-    nsm.updateNode(newDn, newLayoutVersionProto);
+    nsm.updateNode(newDn, newDatanodeVersionProto);
 
     DatanodeInfo updatedDn = nsm.getNode(dn);
     assertEquals(newIpAddress, updatedDn.getIpAddress());
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 b7b7c8bdf8e..2a253746727 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
@@ -26,7 +26,7 @@
 import static 
org.apache.hadoop.hdds.protocol.MockDatanodeDetails.createDatanodeDetails;
 import static 
org.apache.hadoop.hdds.protocol.MockDatanodeDetails.randomDatanodeDetails;
 import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState.STALE;
-import static 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type.finalizeNewLayoutVersionCommand;
+import static 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type.finalizeNewDatanodeVersionCommand;
 import static 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMRegisteredResponseProto.ErrorCode.errorNodeNotPermitted;
 import static 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMRegisteredResponseProto.ErrorCode.success;
 import static 
org.apache.hadoop.hdds.scm.HddsTestUtils.getRandomPipelineReports;
@@ -78,7 +78,7 @@
 import org.apache.hadoop.hdds.protocol.MockDatanodeDetails;
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.CommandQueueReportProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.MetadataStorageReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto;
@@ -266,7 +266,7 @@ private DatanodeDetails registerWithCapacity(SCMNodeManager 
nodeManager) {
    * @return The created {@link DatanodeDetails}.
    */
   private DatanodeDetails registerWithCapacity(SCMNodeManager nodeManager,
-      LayoutVersionProto layout, ErrorCode expectedResult) {
+      DatanodeVersionProto versionInfo, ErrorCode expectedResult) {
     DatanodeDetails details = MockDatanodeDetails.randomDatanodeDetails();
 
     StorageReportProto storageReport =
@@ -280,7 +280,7 @@ private DatanodeDetails registerWithCapacity(SCMNodeManager 
nodeManager,
         MockDatanodeDetails.randomDatanodeDetails(),
         HddsTestUtils.createNodeReport(Arrays.asList(storageReport),
             Arrays.asList(metadataStorageReport)),
-        getRandomPipelineReports(), layout);
+        getRandomPipelineReports(), versionInfo);
 
     assertEquals(expectedResult, cmd.getError());
     return cmd.getDatanode();
@@ -630,9 +630,9 @@ public void 
testDatanodeFinalizedCounterTracksVersionReports()
       // Report a pre-finalized datanode.
       int softwareVersion = HDDSVersion.SOFTWARE_VERSION.serialize();
       nodeManager.processVersionReport(node,
-          LayoutVersionProto.newBuilder()
-              
.setMetadataLayoutVersion(HDDSLayoutFeature.INITIAL_VERSION.serialize())
-              .setSoftwareLayoutVersion(softwareVersion)
+          DatanodeVersionProto.newBuilder()
+              
.setApparentVersion(HDDSLayoutFeature.INITIAL_VERSION.serialize())
+              .setSoftwareVersion(softwareVersion)
               .build());
       assertEquals(0, nodeManager.getDatanodeFinalizationCounts()
               .getNumFinalizedDatanodes(),
@@ -640,9 +640,9 @@ public void 
testDatanodeFinalizedCounterTracksVersionReports()
 
       // Report a finalized datanode.
       nodeManager.processVersionReport(node,
-          LayoutVersionProto.newBuilder()
-              .setMetadataLayoutVersion(softwareVersion)
-              .setSoftwareLayoutVersion(softwareVersion)
+          DatanodeVersionProto.newBuilder()
+              .setApparentVersion(softwareVersion)
+              .setSoftwareVersion(softwareVersion)
               .build());
       assertEquals(1, nodeManager.getDatanodeFinalizationCounts()
               .getNumFinalizedDatanodes(),
@@ -661,7 +661,7 @@ public void 
testDatanodeFinalizedCounterTracksRegistrationAndRemoveNode()
           "Finalized registration should increment finalized count");
 
 
-      LayoutVersionProto preFinalizedVersionProto =
+      DatanodeVersionProto preFinalizedVersionProto =
           toVersionProto(HDDSLayoutFeature.SCM_HA, 
HDDSVersion.SOFTWARE_VERSION);
       DatanodeDetails nonFinalizedNode =
           registerWithCapacity(nodeManager, preFinalizedVersionProto, success);
@@ -740,9 +740,16 @@ private static Stream<Arguments> 
scmDatanodeVersionCombinations() {
             errorNodeNotPermitted, false),
         // Newer DN rejected, even though its apparent version matches SCM.
         Arguments.of(HDDSLayoutFeature.INITIAL_VERSION,
-            LayoutVersionProto.newBuilder()
-                
.setMetadataLayoutVersion(HDDSLayoutFeature.INITIAL_VERSION.serialize())
-                
.setSoftwareLayoutVersion(HDDSVersion.SOFTWARE_VERSION.serialize() + 1).build(),
+            DatanodeVersionProto.newBuilder()
+                
.setApparentVersion(HDDSLayoutFeature.INITIAL_VERSION.serialize())
+                .setSoftwareVersion(HDDSVersion.SOFTWARE_VERSION.serialize() + 
1).build(),
+            errorNodeNotPermitted, false),
+        // DN that does not report any version is rejected.
+        Arguments.of(HDDSLayoutFeature.INITIAL_VERSION, null, 
errorNodeNotPermitted, false),
+        // DN that reports an incomplete version is rejected.
+        Arguments.of(HDDSLayoutFeature.INITIAL_VERSION,
+            DatanodeVersionProto.newBuilder()
+                
.setSoftwareVersion(HDDSVersion.SOFTWARE_VERSION.serialize()).build(),
             errorNodeNotPermitted, false),
 
         /* SCM FINALIZED */
@@ -761,16 +768,16 @@ private static Stream<Arguments> 
scmDatanodeVersionCombinations() {
             success, false),
         // Newer DN rejected, even though its apparent version matches SCM.
         Arguments.of(HDDSVersion.SOFTWARE_VERSION,
-            LayoutVersionProto.newBuilder()
-                
.setMetadataLayoutVersion(HDDSVersion.SOFTWARE_VERSION.serialize())
-                
.setSoftwareLayoutVersion(HDDSVersion.SOFTWARE_VERSION.serialize() + 1).build(),
+            DatanodeVersionProto.newBuilder()
+                .setApparentVersion(HDDSVersion.SOFTWARE_VERSION.serialize())
+                .setSoftwareVersion(HDDSVersion.SOFTWARE_VERSION.serialize() + 
1).build(),
             errorNodeNotPermitted, false)
     );
   }
 
   @ParameterizedTest
   @MethodSource("scmDatanodeVersionCombinations")
-  public void testDatanodeFencingOnRegister(ComponentVersion scmApparent, 
LayoutVersionProto dnVersionProto,
+  public void testDatanodeFencingOnRegister(ComponentVersion scmApparent, 
DatanodeVersionProto dnVersionProto,
       ErrorCode expectedResult, boolean expectFinalizeCmd) throws IOException {
     OzoneConfiguration conf = new OzoneConfiguration();
     SCMStorageConfig scmStorageConfig = mock(SCMStorageConfig.class);
@@ -795,7 +802,7 @@ public void testDatanodeFencingOnRegister(ComponentVersion 
scmApparent, LayoutVe
         if (expectFinalizeCmd) {
           verify(eventPublisher, times(1)).fireEvent(eq(DATANODE_COMMAND), 
captor.capture());
           assertEquals(node.getID(), captor.getValue().getDatanodeId());
-          assertEquals(finalizeNewLayoutVersionCommand, 
captor.getValue().getCommand().getType());
+          assertEquals(finalizeNewDatanodeVersionCommand, 
captor.getValue().getCommand().getType());
         } else {
           verify(eventPublisher, times(0)).fireEvent(eq(DATANODE_COMMAND), 
captor.capture());
         }
@@ -901,7 +908,7 @@ scmStorageConfig, eventPublisher, new 
NetworkTopologyImpl(conf),
     DatanodeDetails node1 = MockDatanodeDetails.randomDatanodeDetails();
     StorageReportProto storageReport = HddsTestUtils.createStorageReport(
         node1.getID(), node1.getNetworkFullPath(), Long.MAX_VALUE);
-    LayoutVersionProto preFinalizedDNVersion =
+    DatanodeVersionProto preFinalizedDNVersion =
         toVersionProto(HDDSLayoutFeature.INITIAL_VERSION, 
HDDSVersion.SOFTWARE_VERSION);
     nodeManager.register(node1,
         
HddsTestUtils.createNodeReport(Collections.singletonList(storageReport), 
emptyList()),
diff --git 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMDatanodeHeartbeatDispatcher.java
 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMDatanodeHeartbeatDispatcher.java
index e1e515f80ce..9750bbfc50d 100644
--- 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMDatanodeHeartbeatDispatcher.java
+++ 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMDatanodeHeartbeatDispatcher.java
@@ -35,6 +35,7 @@
 import org.apache.hadoop.hdds.protocol.DatanodeID;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.CommandStatusReportsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReportsProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMHeartbeatRequestProto;
 import org.apache.hadoop.hdds.scm.node.NodeManager;
@@ -139,6 +140,32 @@ public <PAYLOAD, EVENT extends Event<PAYLOAD>> void 
fireEvent(
 
   }
 
+  @Test
+  public void testVersionReportProcessedOnlyWhenPresent() throws IOException {
+    NodeManager mockNodeManager = mock(NodeManager.class);
+    when(mockNodeManager.isNodeRegistered(any())).thenReturn(true);
+
+    SCMDatanodeHeartbeatDispatcher dispatcher =
+        new SCMDatanodeHeartbeatDispatcher(mockNodeManager, 
mock(EventPublisher.class));
+
+    DatanodeDetails datanodeDetails = randomDatanodeDetails();
+
+    // Heartbeat without a version report: SCM should not process a version.
+    dispatcher.dispatch(SCMHeartbeatRequestProto.newBuilder()
+        .setDatanodeDetails(datanodeDetails.getProtoBufMessage())
+        .build());
+    verify(mockNodeManager, times(0)).processVersionReport(any(), any());
+
+    // Heartbeat with a version report: SCM should process it.
+    DatanodeVersionProto version = DatanodeVersionProto.newBuilder()
+        .setApparentVersion(1).setSoftwareVersion(1).build();
+    dispatcher.dispatch(SCMHeartbeatRequestProto.newBuilder()
+        .setDatanodeDetails(datanodeDetails.getProtoBufMessage())
+        .setDatanodeVersion(version)
+        .build());
+    verify(mockNodeManager, times(1)).processVersionReport(any(), any());
+  }
+
   /**
    * Asserts scm informs datanodes to re-register on a restart.
    *
diff --git 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/scm/ReconNodeManager.java
 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/scm/ReconNodeManager.java
index 143dcef2f0a..dafc3c5148b 100644
--- 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/scm/ReconNodeManager.java
+++ 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/scm/ReconNodeManager.java
@@ -36,7 +36,7 @@
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.CommandQueueReportProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto.Type;
@@ -211,7 +211,7 @@ public void refreshAllHealthyDnUsageInfo() {
   public RegisteredCommand register(
       DatanodeDetails datanodeDetails, NodeReportProto nodeReport,
       PipelineReportsProto pipelineReportsProto,
-      LayoutVersionProto dnVersionInfo) {
+      DatanodeVersionProto dnVersionInfo) {
     if (isNodeRegistered(datanodeDetails)) {
       try {
         nodeDB.put(datanodeDetails.getID(), datanodeDetails);
@@ -297,7 +297,7 @@ public void removeNode(DatanodeDetails datanodeDetails) 
throws NodeNotFoundExcep
 
   @Override
   protected void sendFinalizeToDatanodeIfNeeded(DatanodeDetails 
datanodeDetails,
-      LayoutVersionProto versionReport) {
+      DatanodeVersionProto versionReport) {
     // Recon will not send finalize commands to datanodes.
   }
 
@@ -308,11 +308,15 @@ protected void 
sendFinalizeToDatanodeIfNeeded(DatanodeDetails datanodeDetails,
    * it has finalized, unlike SCM.
    */
   @Override
-  protected boolean shouldFenceDatanode(DatanodeDetails dnDetails, 
LayoutVersionProto versionReport) {
+  protected boolean shouldFenceDatanode(DatanodeDetails dnDetails, 
DatanodeVersionProto versionReport) {
+    if (versionReport == null || !versionReport.hasSoftwareVersion() || 
!versionReport.hasApparentVersion()) {
+      LOG.error("Datanode {} did not report its version. Not allowing it to 
join the cluster.", dnDetails);
+      return true;
+    }
     ComponentVersion dnSoftwareVersion = 
HDDSVersionUtils.deserializeHDDSVersionOrLayoutVersion(
-        versionReport.getSoftwareLayoutVersion());
+        versionReport.getSoftwareVersion());
     ComponentVersion dnApparentVersion = 
HDDSVersionUtils.deserializeHDDSVersionOrLayoutVersion(
-        versionReport.getMetadataLayoutVersion());
+        versionReport.getApparentVersion());
     ComponentVersion reconSoftwareVersion = 
versionManager.getSoftwareVersion();
     ComponentVersion reconApparentVersion = 
versionManager.getApparentVersion();
 
diff --git 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestEndpoints.java
 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestEndpoints.java
index f44d16d02ac..d4e73ca32b3 100644
--- 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestEndpoints.java
+++ 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestEndpoints.java
@@ -82,7 +82,7 @@
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos.StorageTypeProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReplicaProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReportsProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReport;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
@@ -428,7 +428,7 @@ public void setUp() throws Exception {
         NodeReportProto.newBuilder()
             .addStorageReport(storageReportProto3)
             .addStorageReport(storageReportProto4).build();
-    LayoutVersionProto layoutInfo = defaultVersionProto();
+    DatanodeVersionProto versionInfo = defaultVersionProto();
 
     DatanodeDetailsProto datanodeDetailsProto3 =
         DatanodeDetailsProto.newBuilder()
@@ -467,7 +467,7 @@ public void setUp() throws Exception {
     assertDoesNotThrow(() -> {
       reconScm.getDatanodeProtocolServer()
           .register(extendedDatanodeDetailsProto, nodeReportProto,
-              containerReportsProto, pipelineReportsProto, layoutInfo);
+              containerReportsProto, pipelineReportsProto, versionInfo);
       reconScm.getDatanodeProtocolServer()
           .register(extendedDatanodeDetailsProto2, nodeReportProto2,
               ContainerReportsProto.newBuilder().build(),
@@ -1277,7 +1277,7 @@ private void 
waitAndCheckConditionAfterHeartbeat(Callable<Boolean> check)
             .setContainerReport(containerReportsProto)
             .setDatanodeDetails(extendedDatanodeDetailsProto
                 .getDatanodeDetails())
-            .setDataNodeLayoutVersion(defaultVersionProto())
+            .setDatanodeVersion(defaultVersionProto())
             .build();
     reconScm.getDatanodeProtocolServer().sendHeartbeat(heartbeatRequestProto);
     LambdaTestUtils.await(30000, 1000, check);
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 df3938b7aa7..b8dfa05c338 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
@@ -50,7 +50,7 @@
 import org.apache.hadoop.hdds.protocol.DatanodeID;
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMRegisteredResponseProto.ErrorCode;
 import org.apache.hadoop.hdds.scm.net.NetworkTopology;
@@ -271,9 +271,9 @@ private static Stream<Arguments> 
reconDatanodeVersionCombinations() {
             errorNodeNotPermitted),
         // Newer SW DN rejected
         Arguments.of(HDDSLayoutFeature.INITIAL_VERSION,
-            LayoutVersionProto.newBuilder()
-                
.setMetadataLayoutVersion(HDDSLayoutFeature.INITIAL_VERSION.serialize())
-                
.setSoftwareLayoutVersion(HDDSVersion.SOFTWARE_VERSION.serialize() + 1).build(),
+            DatanodeVersionProto.newBuilder()
+                
.setApparentVersion(HDDSLayoutFeature.INITIAL_VERSION.serialize())
+                .setSoftwareVersion(HDDSVersion.SOFTWARE_VERSION.serialize() + 
1).build(),
             errorNodeNotPermitted),
 
         /* RECON FINALIZED */
@@ -292,9 +292,9 @@ private static Stream<Arguments> 
reconDatanodeVersionCombinations() {
             success),
         // Newer SW DN rejected
         Arguments.of(HDDSVersion.SOFTWARE_VERSION,
-            LayoutVersionProto.newBuilder()
-                
.setMetadataLayoutVersion(HDDSVersion.SOFTWARE_VERSION.serialize())
-                
.setSoftwareLayoutVersion(HDDSVersion.SOFTWARE_VERSION.serialize() + 1).build(),
+            DatanodeVersionProto.newBuilder()
+                .setApparentVersion(HDDSVersion.SOFTWARE_VERSION.serialize())
+                .setSoftwareVersion(HDDSVersion.SOFTWARE_VERSION.serialize() + 
1).build(),
             errorNodeNotPermitted)
     );
   }
@@ -302,7 +302,7 @@ private static Stream<Arguments> 
reconDatanodeVersionCombinations() {
   @ParameterizedTest
   @MethodSource("reconDatanodeVersionCombinations")
   public void testDatanodeFencingOnRegister(ComponentVersion reconApparent,
-      LayoutVersionProto dnVersionProto, ErrorCode expectedResult) throws 
IOException {
+      DatanodeVersionProto dnVersionProto, ErrorCode expectedResult) throws 
IOException {
     ReconStorageConfig scmStorageConfig = new ReconStorageConfig(conf, new 
ReconUtils());
     EventQueue eventQueue = new EventQueue();
     NetworkTopology clusterMap = new NetworkTopologyImpl(conf);
diff --git 
a/hadoop-ozone/vapor/src/main/java/org/apache/hadoop/ozone/freon/DatanodeSimulationState.java
 
b/hadoop-ozone/vapor/src/main/java/org/apache/hadoop/ozone/freon/DatanodeSimulationState.java
index b9809677855..6b02a5e8c20 100644
--- 
a/hadoop-ozone/vapor/src/main/java/org/apache/hadoop/ozone/freon/DatanodeSimulationState.java
+++ 
b/hadoop-ozone/vapor/src/main/java/org/apache/hadoop/ozone/freon/DatanodeSimulationState.java
@@ -41,8 +41,8 @@
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReplicaProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReportsProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.IncrementalContainerReportProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMHeartbeatRequestProto;
@@ -126,12 +126,12 @@ public synchronized void ackHeartbeatResponse(
   }
 
   public synchronized SCMHeartbeatRequestProto heartbeatRequest(
-      InetSocketAddress endpoint, LayoutVersionProto layoutInfo)
+      InetSocketAddress endpoint, DatanodeVersionProto versionInfo)
       throws IOException {
     SCMHeartbeatRequestProto.Builder builder =
         SCMHeartbeatRequestProto.newBuilder()
             .setDatanodeDetails(datanodeDetails.getProtoBufMessage())
-            .setDataNodeLayoutVersion(layoutInfo)
+            .setDatanodeVersion(versionInfo)
             .setNodeReport(createNodeReport())
             .setPipelineReports(createPipelineReport());
 
diff --git 
a/hadoop-ozone/vapor/src/main/java/org/apache/hadoop/ozone/freon/DatanodeSimulator.java
 
b/hadoop-ozone/vapor/src/main/java/org/apache/hadoop/ozone/freon/DatanodeSimulator.java
index 4939557f07d..4e46d68d8a0 100644
--- 
a/hadoop-ozone/vapor/src/main/java/org/apache/hadoop/ozone/freon/DatanodeSimulator.java
+++ 
b/hadoop-ozone/vapor/src/main/java/org/apache/hadoop/ozone/freon/DatanodeSimulator.java
@@ -59,7 +59,7 @@
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor;
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReportsProto;
-import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
+import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DatanodeVersionProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
 import 
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto;
@@ -135,7 +135,7 @@ public class DatanodeSimulator implements Callable<Void>, 
VaporSubcommand {
   private Map<DatanodeID, DatanodeSimulationState> datanodesMap;
 
   private ScheduledExecutorService heartbeatScheduler;
-  private LayoutVersionProto layoutInfo;
+  private DatanodeVersionProto versionInfo;
 
   @CommandLine.ParentCommand
   private Freon freonCommand;
@@ -396,7 +396,7 @@ private void heartbeat(InetSocketAddress endpoint,
                          DatanodeSimulationState dn) {
     try {
       SCMHeartbeatRequestProto heartbeat = dn.heartbeatRequest(endpoint,
-          layoutInfo);
+          versionInfo);
       SCMHeartbeatResponseProto response = client.sendHeartbeat(heartbeat);
       dn.ackHeartbeatResponse(response);
 
@@ -415,7 +415,7 @@ private void heartbeat(InetSocketAddress endpoint,
         client.register(
             dn.getDatanodeDetails().getExtendedProtoBufMessage(),
             dn.createNodeReport(), dn.createFullContainerReport(),
-            dn.createPipelineReport(), this.layoutInfo);
+            dn.createPipelineReport(), this.versionInfo);
       }
     } catch (Exception e) {
       LOGGER.info("Error sending heartbeat for {}: {}",
@@ -439,19 +439,19 @@ private void init() throws IOException {
 
     scmContainerClient = HAUtils.getScmContainerClient(conf);
 
-    this.layoutInfo = createLayoutInfo();
+    this.versionInfo = createVersionInfo();
   }
 
-  private LayoutVersionProto createLayoutInfo() throws IOException {
+  private DatanodeVersionProto createVersionInfo() throws IOException {
     DatanodeStorage layoutStorage = new DatanodeStorage(conf,
         UUID.randomUUID().toString());
 
     DatanodeVersionManager versionManager = new 
DatanodeVersionManager(layoutStorage, null);
 
-    return LayoutVersionProto.newBuilder()
-        .setMetadataLayoutVersion(
+    return DatanodeVersionProto.newBuilder()
+        .setApparentVersion(
             versionManager.getApparentVersion().serialize())
-        .setSoftwareLayoutVersion(
+        .setSoftwareVersion(
             versionManager.getSoftwareVersion().serialize())
         .build();
   }
@@ -492,7 +492,7 @@ private boolean registerDataNode(DatanodeSimulationState dn)
         SCMRegisteredResponseProto response =
             client.register(
                 dn.getDatanodeDetails().getExtendedProtoBufMessage(),
-                nodeReport, containerReports, pipelineReports, 
this.layoutInfo);
+                nodeReport, containerReports, pipelineReports, 
this.versionInfo);
         if (response.hasHostname() && response.hasIpAddress()) {
           dn.getDatanodeDetails().setHostName(response.getHostname());
           dn.getDatanodeDetails().setIpAddress(response.getIpAddress());
@@ -512,7 +512,7 @@ private boolean registerDataNode(DatanodeSimulationState dn)
 
     try {
       
reconClient.register(dn.getDatanodeDetails().getExtendedProtoBufMessage(),
-          nodeReport, containerReports, pipelineReports, this.layoutInfo);
+          nodeReport, containerReports, pipelineReports, this.versionInfo);
     } catch (IOException e) {
       LOGGER.error("Error register datanode to Recon", e);
     }
diff --git 
a/hadoop-ozone/vapor/src/main/java/org/apache/hadoop/ozone/freon/SCMThroughputBenchmark.java
 
b/hadoop-ozone/vapor/src/main/java/org/apache/hadoop/ozone/freon/SCMThroughputBenchmark.java
index 11d3babe39f..127c305e57b 100644
--- 
a/hadoop-ozone/vapor/src/main/java/org/apache/hadoop/ozone/freon/SCMThroughputBenchmark.java
+++ 
b/hadoop-ozone/vapor/src/main/java/org/apache/hadoop/ozone/freon/SCMThroughputBenchmark.java
@@ -816,7 +816,7 @@ public void sendHeartbeat() throws IOException, 
TimeoutException {
           .newBuilder()
           .setDatanodeDetails(datanodeDetails.getProtoBufMessage())
           .setContainerReport(containerReport)
-          .setDataNodeLayoutVersion(UpgradeUtils.defaultVersionProto())
+          .setDatanodeVersion(UpgradeUtils.defaultVersionProto())
           .build();
       datanodeScmClient.sendHeartbeat(heartbeatRequest);
       // scm commands are ignored


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


Reply via email to