This is an automated email from the ASF dual-hosted git repository.
sodonnel pushed a commit to branch HDDS-14496-zdu
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/HDDS-14496-zdu by this push:
new 79728a163a3 HDDS-16154. Datanode should assign
DatanodeDetails#currentVersion based on its apparent version (#11006)
79728a163a3 is described below
commit 79728a163a308cec2009f65e6ca201d4953b69f0
Author: Ethan Rose <[email protected]>
AuthorDate: Fri Aug 21 05:49:10 2026 -0400
HDDS-16154. Datanode should assign DatanodeDetails#currentVersion based on
its apparent version (#11006)
---
.../hadoop/hdds/protocol/DatanodeDetails.java | 5 +-
.../hadoop/hdds/protocol/TestDatanodeDetails.java | 20 ++--
.../apache/hadoop/ozone/HddsDatanodeService.java | 11 +--
.../container/common/helpers/DatanodeIdYaml.java | 17 +---
.../states/datanode/RunningDatanodeState.java | 2 -
.../states/endpoint/HeartbeatEndpointTask.java | 53 ++---------
.../states/endpoint/RegisterEndpointTask.java | 38 +-------
.../container/upgrade/DatanodeVersionManager.java | 10 ++
.../common/helpers/TestContainerUtils.java | 20 +++-
.../states/endpoint/TestHeartbeatEndpointTask.java | 104 +++++++++++++++++++--
.../upgrade/TestDatanodeVersionManager.java | 23 ++++-
.../ozone/upgrade/ComponentVersionManager.java | 8 ++
.../hdds/scm/server/upgrade/ScmVersionManager.java | 10 ++
.../scm/server/upgrade/TestScmVersionManager.java | 23 ++++-
.../ozone/container/common/TestEndPoint.java | 38 +++++---
.../client/rpc/TestBlockDataStreamOutput.java | 13 ++-
.../hadoop/ozone/om/upgrade/OMVersionManager.java | 10 ++
.../ozone/om/upgrade/TestOMVersionManager.java | 20 ++++
.../ozone/recon/upgrade/ReconVersionManager.java | 9 ++
.../recon/upgrade/TestReconVersionManager.java | 12 +++
20 files changed, 298 insertions(+), 148 deletions(-)
diff --git
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/protocol/DatanodeDetails.java
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/protocol/DatanodeDetails.java
index 27da3567310..66856efcb4e 100644
---
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/protocol/DatanodeDetails.java
+++
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/protocol/DatanodeDetails.java
@@ -88,7 +88,7 @@ public class DatanodeDetails extends NodeImpl implements
Comparable<DatanodeDeta
private volatile HddsProtos.NodeOperationalState persistedOpState;
private volatile long persistedOpStateExpiryEpochSec;
private HDDSVersion initialVersion;
- private HDDSVersion currentVersion;
+ private volatile HDDSVersion currentVersion;
private DatanodeDetails(Builder b) {
super(b.hostName, b.networkLocation, NetConstants.NODE_COST_DEFAULT);
@@ -464,9 +464,6 @@ public static DatanodeDetails.Builder newBuilder(
}
if (datanodeDetailsProto.hasCurrentVersion()) {
builder.setCurrentVersion(HDDSVersion.deserialize(datanodeDetailsProto.getCurrentVersion()));
- } else {
- // fallback to version 1 if not present
- builder.setCurrentVersion(HDDSVersion.SEPARATE_RATIS_PORTS_AVAILABLE);
}
return builder;
}
diff --git
a/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/protocol/TestDatanodeDetails.java
b/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/protocol/TestDatanodeDetails.java
index 6af228d52d3..2df255aae1d 100644
---
a/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/protocol/TestDatanodeDetails.java
+++
b/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/protocol/TestDatanodeDetails.java
@@ -69,23 +69,21 @@ void testRequiredPortsProto() {
@Test
public void testNewBuilderCurrentVersion() {
- // test that if the current version is not set (Ozone 1.4.0 and earlier),
- // it falls back to SEPARATE_RATIS_PORTS_AVAILABLE
+ // When the current version proto field is absent, the builder default
(DEFAULT_VERSION) applies.
DatanodeDetails dn = MockDatanodeDetails.randomDatanodeDetails();
Set<Port.Name> requiredPorts = Stream.of(Port.Name.STANDALONE,
Port.Name.RATIS)
.collect(Collectors.toSet());
- HddsProtos.DatanodeDetailsProto.Builder protoBuilder =
- dn.toProtoBuilder(DEFAULT_VERSION, requiredPorts);
+ HddsProtos.DatanodeDetailsProto.Builder protoBuilder =
dn.toProtoBuilder(ClientVersion.CURRENT, requiredPorts);
protoBuilder.clearCurrentVersion();
DatanodeDetails dn2 =
DatanodeDetails.newBuilder(protoBuilder.build()).build();
- assertEquals(HDDSVersion.SEPARATE_RATIS_PORTS_AVAILABLE,
- dn2.getCurrentVersion());
+ assertEquals(HDDSVersion.DEFAULT_VERSION, dn2.getCurrentVersion());
- // test that if the current version is set, it is used
- protoBuilder = dn.toProtoBuilder(DEFAULT_VERSION, requiredPorts);
-
protoBuilder.setCurrentVersion(HDDSVersion.COMBINED_PUTBLOCK_WRITECHUNK_RPC.serialize());
- DatanodeDetails dn3 =
DatanodeDetails.newBuilder(protoBuilder.build()).build();
- assertEquals(HDDSVersion.COMBINED_PUTBLOCK_WRITECHUNK_RPC,
dn3.getCurrentVersion());
+ // When the proto field is present, it round-trips correctly.
+ protoBuilder = dn.toProtoBuilder(ClientVersion.CURRENT, requiredPorts);
+ DatanodeDetails dn3 = DatanodeDetails.newBuilder(
+
protoBuilder.setCurrentVersion(HDDSVersion.SOFTWARE_VERSION.serialize()).build())
+ .build();
+ assertEquals(HDDSVersion.SOFTWARE_VERSION, dn3.getCurrentVersion());
}
public static void assertPorts(HddsProtos.DatanodeDetailsProto dn,
diff --git
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/HddsDatanodeService.java
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/HddsDatanodeService.java
index 274de843b9b..8e482457516 100644
---
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/HddsDatanodeService.java
+++
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/HddsDatanodeService.java
@@ -122,6 +122,7 @@ public class HddsDatanodeService extends GenericCli
implements Callable<Void>, S
HddsDatanodeService.class);
public static final String TESTING_DATANODE_VERSION_INITIAL =
"testing.hdds.datanode.version.initial";
+ // TODO(HDDS-16044): TESTING_DATANODE_VERSION_CURRENT is unused until
SCM-side version setting lands.
public static final String TESTING_DATANODE_VERSION_CURRENT =
"testing.hdds.datanode.version.current";
private OzoneConfiguration conf;
@@ -478,8 +479,6 @@ private DatanodeDetails initializeDatanodeDetails()
details =
DatanodeDetails.newBuilder().setID(DatanodeID.randomID()).build();
details.setInitialVersion(getInitialVersion());
}
- // Current version is always overridden to the latest
- details.setCurrentVersion(getCurrentVersion());
return details;
}
@@ -840,12 +839,4 @@ private HDDSVersion getInitialVersion() {
return HDDSVersion.deserialize(
conf.getInt(TESTING_DATANODE_VERSION_INITIAL,
HDDSVersion.SOFTWARE_VERSION.serialize()));
}
-
- /**
- * Returns the current version of the datanode.
- */
- private HDDSVersion getCurrentVersion() {
- return HDDSVersion.deserialize(
- conf.getInt(TESTING_DATANODE_VERSION_CURRENT,
HDDSVersion.SOFTWARE_VERSION.serialize()));
- }
}
diff --git
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/DatanodeIdYaml.java
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/DatanodeIdYaml.java
index 00d232adc18..f74f3b0d8fd 100644
---
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/DatanodeIdYaml.java
+++
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/DatanodeIdYaml.java
@@ -110,8 +110,7 @@ public static DatanodeDetails readDatanodeIdFile(File path)
}
}
-
builder.setInitialVersion(HDDSVersion.deserialize(datanodeDetailsYaml.getInitialVersion()))
-
.setCurrentVersion(HDDSVersion.deserialize(datanodeDetailsYaml.getCurrentVersion()));
+
builder.setInitialVersion(HDDSVersion.deserialize(datanodeDetailsYaml.getInitialVersion()));
datanodeDetails = builder.build();
}
@@ -131,7 +130,6 @@ public static class DatanodeDetailsYaml {
private long persistedOpStateExpiryEpochSec = 0;
private Map<String, Integer> portDetails;
private int initialVersion;
- private int currentVersion;
public DatanodeDetailsYaml() {
// Needed for snake-yaml introspection.
@@ -142,7 +140,7 @@ private DatanodeDetailsYaml(String uuid, String ipAddress,
String hostName, String certSerialId,
String persistedOpState, long persistedOpStateExpiryEpochSec,
Map<String, Integer> portDetails,
- int initialVersion, int currentVersion) {
+ int initialVersion) {
this.uuid = uuid;
this.ipAddress = ipAddress;
this.hostName = hostName;
@@ -151,7 +149,6 @@ private DatanodeDetailsYaml(String uuid, String ipAddress,
this.persistedOpStateExpiryEpochSec = persistedOpStateExpiryEpochSec;
this.portDetails = portDetails;
this.initialVersion = initialVersion;
- this.currentVersion = currentVersion;
}
public String getUuid() {
@@ -218,12 +215,9 @@ public void setInitialVersion(int version) {
this.initialVersion = version;
}
- public int getCurrentVersion() {
- return currentVersion;
- }
-
public void setCurrentVersion(int version) {
- this.currentVersion = version;
+ // Setter retained so SnakeYAML can bind existing datanode.id files
+ // that contain this key without throwing on unknown properties.
}
@Override
@@ -249,7 +243,6 @@ private static DatanodeDetailsYaml getDatanodeDetailsYaml(
persistedOpString,
datanodeDetails.getPersistedOpStateExpiryEpochSec(),
VersionedDatanodeFeatures.DatanodePorts.getPortsToPersist(datanodeDetails,
conf),
- datanodeDetails.getInitialVersion().serialize(),
- datanodeDetails.getCurrentVersion().serialize());
+ datanodeDetails.getInitialVersion().serialize());
}
}
diff --git
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/datanode/RunningDatanodeState.java
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/datanode/RunningDatanodeState.java
index 6b8ea712a93..9dcf81603d1 100644
---
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/datanode/RunningDatanodeState.java
+++
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/states/datanode/RunningDatanodeState.java
@@ -150,14 +150,12 @@ private Callable<EndPointStates> buildEndPointTask(
.setConfig(conf)
.setEndpointStateMachine(endpoint)
.setContext(context)
- .setDatanodeDetails(context.getParent().getDatanodeDetails())
.setOzoneContainer(context.getParent().getContainer())
.build();
case HEARTBEAT:
return HeartbeatEndpointTask.newBuilder()
.setConfig(conf)
.setEndpointStateMachine(endpoint)
- .setDatanodeDetails(context.getParent().getDatanodeDetails())
.setContext(context)
.build();
default:
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 61fb248ef20..e7bed34a6f7 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
@@ -72,7 +72,7 @@ public class HeartbeatEndpointTask
implements Callable<EndpointStateMachine.EndPointStates> {
private static final Logger LOG =
LoggerFactory.getLogger(HeartbeatEndpointTask.class);
private final EndpointStateMachine rpcEndpoint;
- private DatanodeDetailsProto datanodeDetailsProto;
+ private final DatanodeDetails datanodeDetails;
private StateContext context;
private int maxContainerActionsPerHB;
private int maxPipelineActionsPerHB;
@@ -93,28 +93,10 @@ public HeartbeatEndpointTask(EndpointStateMachine
rpcEndpoint,
HDDS_CONTAINER_ACTION_MAX_LIMIT_DEFAULT);
this.maxPipelineActionsPerHB = conf.getInt(HDDS_PIPELINE_ACTION_MAX_LIMIT,
HDDS_PIPELINE_ACTION_MAX_LIMIT_DEFAULT);
+ this.datanodeDetails = context.getParent().getDatanodeDetails();
this.versionManager = context.getParent().getVersionManager();
}
- /**
- * Get the container Node ID proto.
- *
- * @return ContainerNodeIDProto
- */
- public DatanodeDetailsProto getDatanodeDetailsProto() {
- return datanodeDetailsProto;
- }
-
- /**
- * Set container node ID proto.
- *
- * @param datanodeDetailsProto - the node id.
- */
- public void setDatanodeDetailsProto(DatanodeDetailsProto
- datanodeDetailsProto) {
- this.datanodeDetailsProto = datanodeDetailsProto;
- }
-
/**
* Computes a result, or throws an exception if unable to do so.
*
@@ -126,12 +108,13 @@ public EndpointStateMachine.EndPointStates call() throws
Exception {
rpcEndpoint.lock();
SCMHeartbeatRequestProto.Builder requestBuilder = null;
try {
- Preconditions.checkState(this.datanodeDetailsProto != null);
-
DatanodeVersionProto versionInfo = toVersionProto(
versionManager.getApparentVersion(),
versionManager.getSoftwareVersion());
+ datanodeDetails.setCurrentVersion(versionManager.getVersionForClient());
+ DatanodeDetailsProto datanodeDetailsProto =
datanodeDetails.getProtoBufMessage();
+
requestBuilder = SCMHeartbeatRequestProto.newBuilder()
.setDatanodeDetails(datanodeDetailsProto)
.setDatanodeVersion(versionInfo);
@@ -265,9 +248,9 @@ public static Builder newBuilder() {
* @param response - SCMHeartbeat response.
*/
private void processResponse(SCMHeartbeatResponseProto response,
- final DatanodeDetailsProto datanodeDetails) {
+ final DatanodeDetailsProto datanodeDetailsProto) {
Preconditions.checkState(response.getDatanodeUUID()
- .equalsIgnoreCase(datanodeDetails.getUuid()),
+ .equalsIgnoreCase(datanodeDetailsProto.getUuid()),
"Unexpected datanode ID in the response.");
if (response.hasTerm()) {
context.updateTermOfLeaderSCM(response.getTerm());
@@ -433,7 +416,6 @@ private void processReregisterCommand() {
public static class Builder {
private EndpointStateMachine endPointStateMachine;
private ConfigurationSource conf;
- private DatanodeDetails datanodeDetails;
private StateContext context;
/**
@@ -464,17 +446,6 @@ public Builder setConfig(ConfigurationSource config) {
return this;
}
- /**
- * Sets the NodeID.
- *
- * @param dnDetails - NodeID proto
- * @return Builder
- */
- public Builder setDatanodeDetails(DatanodeDetails dnDetails) {
- this.datanodeDetails = dnDetails;
- return this;
- }
-
/**
* Sets the context.
* @param stateContext - State context.
@@ -498,16 +469,8 @@ public HeartbeatEndpointTask build() {
" construct HeartbeatEndpointTask task");
}
- if (datanodeDetails == null) {
- LOG.error("No datanode specified.");
- throw new IllegalArgumentException("A valid Node ID is needed to " +
- "construct HeartbeatEndpointTask task");
- }
-
- HeartbeatEndpointTask task = new HeartbeatEndpointTask(this
+ return new HeartbeatEndpointTask(this
.endPointStateMachine, this.conf, this.context);
- task.setDatanodeDetailsProto(datanodeDetails.getProtoBufMessage());
- return task;
}
}
}
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 08bff1a422d..31ff3821882 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
@@ -47,7 +47,7 @@ public final class RegisterEndpointTask implements
static final Logger LOG =
LoggerFactory.getLogger(RegisterEndpointTask.class);
private final EndpointStateMachine rpcEndPoint;
- private DatanodeDetails datanodeDetails;
+ private final DatanodeDetails datanodeDetails;
private final OzoneContainer datanodeContainerManager;
private StateContext stateContext;
private final DatanodeVersionManager versionManager;
@@ -66,6 +66,7 @@ public RegisterEndpointTask(EndpointStateMachine rpcEndPoint,
this.rpcEndPoint = rpcEndPoint;
this.datanodeContainerManager = ozoneContainer;
this.stateContext = context;
+ this.datanodeDetails = context.getParent().getDatanodeDetails();
this.versionManager = context.getParent().getVersionManager();
}
@@ -78,16 +79,6 @@ public DatanodeDetails getDatanodeDetails() {
return datanodeDetails;
}
- /**
- * Set the contiainerNodeID Proto.
- *
- * @param datanodeDetails - Container Node ID.
- */
- public void setDatanodeDetails(
- DatanodeDetails datanodeDetails) {
- this.datanodeDetails = datanodeDetails;
- }
-
/**
* Computes a result, or throws an exception if unable to do so.
*
@@ -119,6 +110,7 @@ public EndpointStateMachine.EndPointStates call() throws
Exception {
NodeReportProto nodeReport = datanodeContainerManager.getNodeReport();
PipelineReportsProto pipelineReportsProto =
datanodeContainerManager.getPipelineReport();
+
datanodeDetails.setCurrentVersion(versionManager.getVersionForClient());
// TODO : Add responses to the command Queue.
SCMRegisteredResponseProto response = rpcEndPoint.getEndPoint()
.register(datanodeDetails.getExtendedProtoBufMessage(),
@@ -177,7 +169,6 @@ public static Builder newBuilder() {
public static class Builder {
private EndpointStateMachine endPointStateMachine;
private ConfigurationSource conf;
- private DatanodeDetails datanodeDetails;
private OzoneContainer container;
private StateContext context;
@@ -209,17 +200,6 @@ public Builder setConfig(ConfigurationSource config) {
return this;
}
- /**
- * Sets the NodeID.
- *
- * @param dnDetails - NodeID proto
- * @return Builder
- */
- public Builder setDatanodeDetails(DatanodeDetails dnDetails) {
- this.datanodeDetails = dnDetails;
- return this;
- }
-
/**
* Sets the ozonecontainer.
* @param ozoneContainer
@@ -249,12 +229,6 @@ public RegisterEndpointTask build() {
+ "task");
}
- if (datanodeDetails == null) {
- LOG.error("No datanode specified.");
- throw new IllegalArgumentException("A valid Node ID is needed to " +
- "construct RegisterEndpoint task");
- }
-
if (container == null) {
LOG.error("Container is not specified");
throw new IllegalArgumentException("Container is not specified to " +
@@ -267,10 +241,8 @@ public RegisterEndpointTask build() {
"construct RegisterEndpoint task");
}
- RegisterEndpointTask task = new RegisterEndpointTask(this
- .endPointStateMachine, this.container, this.context);
- task.setDatanodeDetails(datanodeDetails);
- return task;
+ return new RegisterEndpointTask(this.endPointStateMachine,
+ this.container, this.context);
}
}
}
diff --git
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/upgrade/DatanodeVersionManager.java
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/upgrade/DatanodeVersionManager.java
index a4a762ffa27..b925a4b8759 100644
---
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/upgrade/DatanodeVersionManager.java
+++
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/upgrade/DatanodeVersionManager.java
@@ -65,6 +65,16 @@ public int getPersistedApparentVersion() {
return storage.getApparentVersion();
}
+ @Override
+ public HDDSVersion getVersionForClient() {
+ ComponentVersion apparentVersion = getApparentVersion();
+ // Once ZDU is finalized, the apparent version should always belong to the
HDDSVersion enum.
+ if (isAllowed(HDDSVersion.ZDU) && apparentVersion instanceof HDDSVersion) {
+ return (HDDSVersion) apparentVersion;
+ }
+ return HDDSVersion.values()[HDDSVersion.ZDU.ordinal() - 1];
+ }
+
@VisibleForTesting
public Map<ComponentVersion, DatanodeUpgradeAction>
getUpgradeActionsForTesting() {
return upgradeActions;
diff --git
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/helpers/TestContainerUtils.java
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/helpers/TestContainerUtils.java
index 9735c5eeb13..0feb3c03fb8 100644
---
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/helpers/TestContainerUtils.java
+++
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/helpers/TestContainerUtils.java
@@ -24,6 +24,7 @@
import static
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Type.ReadChunk;
import static
org.apache.hadoop.hdds.scm.protocolPB.ContainerCommandResponseBuilders.getReadChunkResponse;
import static
org.apache.hadoop.ozone.container.ContainerTestHelper.getDummyCommandRequestProto;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -112,6 +113,10 @@ public void testTarName() throws IOException {
public void testDatanodeIDPersistent(@TempDir File tempDir) throws Exception
{
// Generate IDs for testing
DatanodeDetails id1 = randomDatanodeDetails();
+ // `randomDatanodeDetails()` populates the current version to
SOFTWARE_VERSION by default.
+ // Datanodes do not populate this value when persisting the proto, only
when sending it over the wire,
+ // so override the setter to the default value to match what Datanodes
actually persist internally.
+ id1.setCurrentVersion(HDDSVersion.DEFAULT_VERSION);
try (MockedStatic<InetAddress> mockedStaticInetAddress =
mockStatic(InetAddress.class)) {
InetAddress mockedInetAddress = mock(InetAddress.class);
mockedStaticInetAddress.when(() ->
InetAddress.getByName(id1.getHostName()))
@@ -204,7 +209,20 @@ private void assertWriteRead(@TempDir File tempDir,
DatanodeDetails read = ContainerUtils.readDatanodeDetailsFrom(file, conf);
assertDetailsEquals(details, read);
- assertEquals(details.getCurrentVersion(), read.getCurrentVersion());
+ // currentVersion is updated by SCM for clients to consume. When unset for
cases like persisting to the datanode,
+ // it should return DEFAULT_VERSION. This is an in-memory placeholder
which is not written to the file.
+ assertEquals(HDDSVersion.DEFAULT_VERSION, read.getCurrentVersion());
+ }
+
+ @Test
+ public void writtenYamlOmitsCurrentVersion(@TempDir File tempDir) throws
IOException {
+ DatanodeDetails details = randomDatanodeDetails();
+ details.setCurrentVersion(HDDSVersion.SOFTWARE_VERSION);
+ File file = new File(tempDir, "no-current-version.id");
+ ContainerUtils.writeDatanodeDetailsTo(details, file, conf);
+
+ String yaml = new String(Files.readAllBytes(file.toPath()), UTF_8);
+ assertThat(yaml).doesNotContain("currentVersion");
}
private void assertWriteReadWithChangedIpAddress(@TempDir File tempDir,
diff --git
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/states/endpoint/TestHeartbeatEndpointTask.java
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/states/endpoint/TestHeartbeatEndpointTask.java
index 4c49b634aa1..1dd6fd02ad0 100644
---
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/states/endpoint/TestHeartbeatEndpointTask.java
+++
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/states/endpoint/TestHeartbeatEndpointTask.java
@@ -50,6 +50,7 @@
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMHeartbeatRequestProto;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMHeartbeatResponseProto;
import org.apache.hadoop.hdds.scm.net.HostAndPort;
+import org.apache.hadoop.hdds.upgrade.HDDSLayoutFeature;
import org.apache.hadoop.hdfs.util.EnumCounters;
import
org.apache.hadoop.ozone.container.common.statemachine.DatanodeStateMachine;
import
org.apache.hadoop.ozone.container.common.statemachine.DatanodeStateMachine.DatanodeStates;
@@ -395,6 +396,94 @@ public void testheartbeatWithAllReports() throws Exception
{
}
}
+ @Test
+ public void testDatanodeCurrentVersionPassThrough() throws Exception {
+ OzoneConfiguration conf = new OzoneConfiguration();
+ DatanodeStateMachine datanodeStateMachine = mockDatanodeStateMachine();
+ StateContext context = new StateContext(conf, DatanodeStates.RUNNING,
+ datanodeStateMachine, "");
+
+ // Set the expected versions to return.
+ DatanodeVersionManager versionManager =
datanodeStateMachine.getVersionManager();
+ when(versionManager.getVersionForClient())
+ .thenReturn(HDDSVersion.DEFAULT_VERSION)
+ .thenReturn(HDDSVersion.ZDU)
+ .thenReturn(HDDSVersion.SOFTWARE_VERSION);
+
+ when(datanodeStateMachine.getQueuedCommandCount())
+ .thenReturn(new EnumCounters<>(SCMCommandProto.Type.class));
+
+ StorageContainerDatanodeProtocolClientSideTranslatorPB scm =
+ mock(StorageContainerDatanodeProtocolClientSideTranslatorPB.class);
+ ArgumentCaptor<SCMHeartbeatRequestProto> argument = ArgumentCaptor
+ .forClass(SCMHeartbeatRequestProto.class);
+ when(scm.sendHeartbeat(argument.capture()))
+ .thenAnswer(invocation ->
+ SCMHeartbeatResponseProto.newBuilder()
+ .setDatanodeUUID(
+ ((SCMHeartbeatRequestProto)invocation.getArgument(0))
+ .getDatanodeDetails().getUuid())
+ .build());
+
+ HeartbeatEndpointTask endpointTask = getHeartbeatEndpointTask(
+ conf, context, scm);
+
+ // Assert the expected versions were returned.
+ endpointTask.call();
+ assertEquals(HDDSVersion.DEFAULT_VERSION.serialize(),
+ argument.getValue().getDatanodeDetails().getCurrentVersion());
+ endpointTask.call();
+ assertEquals(HDDSVersion.ZDU.serialize(),
+ argument.getValue().getDatanodeDetails().getCurrentVersion());
+ endpointTask.call();
+ assertEquals(HDDSVersion.SOFTWARE_VERSION.serialize(),
+ argument.getValue().getDatanodeDetails().getCurrentVersion());
+ }
+
+ @Test
+ public void testDatanodeApparentVersionPassThrough() throws Exception {
+ OzoneConfiguration conf = new OzoneConfiguration();
+ DatanodeStateMachine datanodeStateMachine = mockDatanodeStateMachine();
+ StateContext context = new StateContext(conf, DatanodeStates.RUNNING,
+ datanodeStateMachine, "");
+
+ // Set the expected versions to return.
+ DatanodeVersionManager versionManager =
datanodeStateMachine.getVersionManager();
+ when(versionManager.getApparentVersion())
+ .thenReturn(HDDSLayoutFeature.INITIAL_VERSION)
+ .thenReturn(HDDSVersion.ZDU)
+ .thenReturn(HDDSVersion.SOFTWARE_VERSION);
+
+ when(datanodeStateMachine.getQueuedCommandCount())
+ .thenReturn(new EnumCounters<>(SCMCommandProto.Type.class));
+
+ StorageContainerDatanodeProtocolClientSideTranslatorPB scm =
+ mock(StorageContainerDatanodeProtocolClientSideTranslatorPB.class);
+ ArgumentCaptor<SCMHeartbeatRequestProto> argument = ArgumentCaptor
+ .forClass(SCMHeartbeatRequestProto.class);
+ when(scm.sendHeartbeat(argument.capture()))
+ .thenAnswer(invocation ->
+ SCMHeartbeatResponseProto.newBuilder()
+ .setDatanodeUUID(
+ ((SCMHeartbeatRequestProto)invocation.getArgument(0))
+ .getDatanodeDetails().getUuid())
+ .build());
+
+ HeartbeatEndpointTask endpointTask = getHeartbeatEndpointTask(
+ conf, context, scm);
+
+ // Assert the expected versions were returned.
+ endpointTask.call();
+ assertEquals(HDDSLayoutFeature.INITIAL_VERSION.serialize(),
+ argument.getValue().getDatanodeVersion().getApparentVersion());
+ endpointTask.call();
+ assertEquals(HDDSVersion.ZDU.serialize(),
+ argument.getValue().getDatanodeVersion().getApparentVersion());
+ endpointTask.call();
+ assertEquals(HDDSVersion.SOFTWARE_VERSION.serialize(),
+ argument.getValue().getDatanodeVersion().getApparentVersion());
+ }
+
/**
* Creates HeartbeatEndpointTask with the given conf, context and
* StorageContainerManager client side proxy.
@@ -409,28 +498,29 @@ private HeartbeatEndpointTask getHeartbeatEndpointTask(
ConfigurationSource conf,
StateContext context,
StorageContainerDatanodeProtocolClientSideTranslatorPB proxy) {
- DatanodeDetails datanodeDetails = DatanodeDetails.newBuilder()
- .setUuid(UUID.randomUUID())
- .setHostName("localhost")
- .setIpAddress("127.0.0.1")
- .build();
EndpointStateMachine endpointStateMachine =
mock(EndpointStateMachine.class);
when(endpointStateMachine.getEndPoint()).thenReturn(proxy);
when(endpointStateMachine.getAddress())
.thenReturn(TEST_SCM_ENDPOINT);
return HeartbeatEndpointTask.newBuilder()
.setConfig(conf)
- .setDatanodeDetails(datanodeDetails)
.setContext(context)
.setEndpointStateMachine(endpointStateMachine)
.build();
}
-
+
private DatanodeStateMachine mockDatanodeStateMachine() {
+ DatanodeDetails datanodeDetails = DatanodeDetails.newBuilder()
+ .setUuid(UUID.randomUUID())
+ .setHostName("localhost")
+ .setIpAddress("127.0.0.1")
+ .build();
DatanodeVersionManager versionManager = mock(DatanodeVersionManager.class);
when(versionManager.getSoftwareVersion()).thenReturn(HDDSVersion.SOFTWARE_VERSION);
when(versionManager.getApparentVersion()).thenReturn(HDDSVersion.SOFTWARE_VERSION);
+
when(versionManager.getVersionForClient()).thenReturn(HDDSVersion.SOFTWARE_VERSION);
DatanodeStateMachine mockDSM = mock(DatanodeStateMachine.class);
+ when(mockDSM.getDatanodeDetails()).thenReturn(datanodeDetails);
when(mockDSM.getVersionManager()).thenReturn(versionManager);
return mockDSM;
}
diff --git
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/upgrade/TestDatanodeVersionManager.java
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/upgrade/TestDatanodeVersionManager.java
index 572b7baa679..a01dba245be 100644
---
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/upgrade/TestDatanodeVersionManager.java
+++
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/upgrade/TestDatanodeVersionManager.java
@@ -59,7 +59,6 @@
import
org.apache.hadoop.ozone.container.common.statemachine.DatanodeStateMachine;
import org.apache.hadoop.ozone.upgrade.AbstractComponentVersionManagerTest;
import org.apache.hadoop.ozone.upgrade.ComponentUpgradeActionProvider;
-import org.apache.hadoop.ozone.upgrade.ComponentVersionManager;
import org.apache.hadoop.ozone.upgrade.UpgradeException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -102,7 +101,7 @@ public static Stream<Arguments> preFinalizedVersionArgs() {
}
@Override
- protected ComponentVersionManager createManager(int
serializedApparentVersion) throws IOException {
+ protected DatanodeVersionManager createManager(int
serializedApparentVersion) throws IOException {
return createManager(serializedApparentVersion, HashMap::new);
}
@@ -224,6 +223,26 @@ public void testPersistFailureRollsBack() throws Exception
{
}
}
+ @Test
+ public void testGetVersionForClientWhenFinalized() throws Exception {
+ // Apparent version >= ZDU (finalized) reports the apparent version itself.
+ try (DatanodeVersionManager versionManager =
createManager(HDDSVersion.ZDU.serialize())) {
+ assertEquals(HDDSVersion.ZDU, versionManager.getVersionForClient());
+ }
+
+ try (DatanodeVersionManager versionManager =
createManager(HDDSVersion.SOFTWARE_VERSION.serialize())) {
+ assertEquals(HDDSVersion.SOFTWARE_VERSION,
versionManager.getVersionForClient());
+ }
+ }
+
+ @Test
+ public void testGetVersionForClientWhenPreZdu() throws Exception {
+ // A pre-ZDU apparent version clamps to the last pre-ZDU wire version.
+ try (DatanodeVersionManager versionManager =
createManager(INITIAL_VERSION.serialize())) {
+ assertEquals(HDDSVersion.STREAM_BLOCK_SUPPORT,
versionManager.getVersionForClient());
+ }
+ }
+
private static void assertDatanodeApparentVersionOnDisk(OzoneConfiguration
conf, int expected)
throws IOException {
DatanodeStorage reloaded = new DatanodeStorage(conf,
UUID.randomUUID().toString());
diff --git
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/ComponentVersionManager.java
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/ComponentVersionManager.java
index 516158f76c6..5aaa48aec1a 100644
---
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/ComponentVersionManager.java
+++
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/ozone/upgrade/ComponentVersionManager.java
@@ -101,6 +101,14 @@ public void finalizeUpgrade() throws UpgradeException {
}
}
+ /**
+ * Returns the version that the server should advertise to the client for
new client/oldserver compatibility.
+ * If ZDU is finalized, we can use the same apparent version for both client
and disk compatibility.
+ * If the server is not yet finalized for ZDU, we must continue to use the
separate component version system for
+ * clients and layout feature versioning system for internal apparent
version.
+ */
+ public abstract ComponentVersion getVersionForClient();
+
/**
* @return An Iterable of all versions after the current apparent version
which still need to be finalized. If this
* component is already finalized, the Iterable will be empty.
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/upgrade/ScmVersionManager.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/upgrade/ScmVersionManager.java
index c5a44fb249d..3f79bd0ddcb 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/upgrade/ScmVersionManager.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/upgrade/ScmVersionManager.java
@@ -72,6 +72,16 @@ public Map<ComponentVersion, ScmUpgradeAction>
getUpgradeActionsForTesting() {
return upgradeActions;
}
+ @Override
+ public HDDSVersion getVersionForClient() {
+ ComponentVersion apparentVersion = getApparentVersion();
+ // Once ZDU is finalized, the apparent version should always belong to the
HDDSVersion enum.
+ if (isAllowed(HDDSVersion.ZDU) && apparentVersion instanceof HDDSVersion) {
+ return (HDDSVersion) apparentVersion;
+ }
+ return HDDSVersion.values()[HDDSVersion.ZDU.ordinal() - 1];
+ }
+
@Override
protected void runUpgradeAction(ComponentVersion version) throws
UpgradeException {
ScmUpgradeAction action = upgradeActions.get(version);
diff --git
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/upgrade/TestScmVersionManager.java
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/upgrade/TestScmVersionManager.java
index 5c32cd8f71b..bb8c0ddde95 100644
---
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/upgrade/TestScmVersionManager.java
+++
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/upgrade/TestScmVersionManager.java
@@ -58,7 +58,6 @@
import org.apache.hadoop.hdds.upgrade.ScmUpgradeActionProvider;
import org.apache.hadoop.ozone.upgrade.AbstractComponentVersionManagerTest;
import org.apache.hadoop.ozone.upgrade.ComponentUpgradeActionProvider;
-import org.apache.hadoop.ozone.upgrade.ComponentVersionManager;
import org.apache.hadoop.ozone.upgrade.UpgradeException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -100,7 +99,7 @@ public static Stream<Arguments> preFinalizedVersionArgs() {
}
@Override
- protected ComponentVersionManager createManager(int
serializedApparentVersion) throws IOException {
+ protected ScmVersionManager createManager(int serializedApparentVersion)
throws IOException {
return createManager(serializedApparentVersion, HashMap::new);
}
@@ -221,6 +220,26 @@ public void testPersistFailureRollsBack() throws Exception
{
}
}
+ @Test
+ public void testGetVersionForClientWhenFinalized() throws Exception {
+ // Apparent version >= ZDU (finalized) reports the apparent version itself.
+ try (ScmVersionManager versionManager =
createManager(HDDSVersion.ZDU.serialize())) {
+ assertEquals(HDDSVersion.ZDU, versionManager.getVersionForClient());
+ }
+
+ try (ScmVersionManager versionManager =
createManager(HDDSVersion.SOFTWARE_VERSION.serialize())) {
+ assertEquals(HDDSVersion.SOFTWARE_VERSION,
versionManager.getVersionForClient());
+ }
+ }
+
+ @Test
+ public void testGetVersionForClientWhenPreZdu() throws Exception {
+ // A pre-ZDU apparent version clamps to the last pre-ZDU wire version.
+ try (ScmVersionManager versionManager =
createManager(INITIAL_VERSION.serialize())) {
+ assertEquals(HDDSVersion.STREAM_BLOCK_SUPPORT,
versionManager.getVersionForClient());
+ }
+ }
+
private static void assertScmApparentVersionOnDisk(OzoneConfiguration conf,
int expected)
throws IOException {
SCMStorageConfig reloaded = new SCMStorageConfig(conf);
diff --git
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/common/TestEndPoint.java
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/common/TestEndPoint.java
index 2b76ac820ff..caf36cf7743 100644
---
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/common/TestEndPoint.java
+++
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/ozone/container/common/TestEndPoint.java
@@ -42,7 +42,6 @@
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.protocol.DatanodeDetails;
import org.apache.hadoop.hdds.protocol.DatanodeID;
-import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.CloseContainerCommandProto;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.CommandStatus.Status;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DeleteBlocksCommandProto;
@@ -438,17 +437,16 @@ private RegisterEndpointTask
getRegisterEndpointTask(boolean clearDatanodeDetail
.thenReturn(HDDSVersion.SOFTWARE_VERSION);
when(versionManager.getSoftwareVersion())
.thenReturn(HDDSVersion.SOFTWARE_VERSION);
+ when(versionManager.getVersionForClient())
+ .thenReturn(HDDSVersion.SOFTWARE_VERSION);
DatanodeStateMachine dn = mock(DatanodeStateMachine.class);
when(dn.getVersionManager()).thenReturn(versionManager);
- StateContext context = mock(StateContext.class);
- when(context.getParent()).thenReturn(dn);
- RegisterEndpointTask endpointTask =
- new RegisterEndpointTask(rpcEndPoint, ozoneContainer, context);
if (!clearDatanodeDetails) {
- DatanodeDetails datanodeDetails = randomDatanodeDetails();
- endpointTask.setDatanodeDetails(datanodeDetails);
+ when(dn.getDatanodeDetails()).thenReturn(randomDatanodeDetails());
}
- return endpointTask;
+ StateContext context = mock(StateContext.class);
+ when(context.getParent()).thenReturn(dn);
+ return new RegisterEndpointTask(rpcEndPoint, ozoneContainer, context);
}
private EndpointStateMachine registerTaskHelper(InetSocketAddress scmAddress,
@@ -471,6 +469,26 @@ public void testRegisterTask() throws Exception {
}
}
+ @Test
+ public void testRegisterAssignsCurrentVersionFromVersionManager()
+ throws Exception {
+ OzoneConfiguration conf = SCMTestUtils.getConf(tempDir);
+ try (EndpointStateMachine rpcEndPoint =
+ createEndpoint(conf, serverAddress, 1000)) {
+ rpcEndPoint.setState(EndpointStateMachine.EndPointStates.REGISTER);
+ RegisterEndpointTask endpointTask =
+ getRegisterEndpointTask(false, conf, rpcEndPoint);
+ // Simulate stale version on the persisted datanode details. The task
+ // should overwrite it with the version manager's current value, matching
+ // the heartbeat behavior.
+ endpointTask.getDatanodeDetails()
+ .setCurrentVersion(HDDSVersion.DEFAULT_VERSION);
+ endpointTask.call();
+ assertEquals(HDDSVersion.SOFTWARE_VERSION,
+ endpointTask.getDatanodeDetails().getCurrentVersion());
+ }
+ }
+
@Test
public void testRegisterToInvalidEndpoint() throws Exception {
InetSocketAddress address = SCMTestUtils.getReuseableAddress();
@@ -619,8 +637,6 @@ private StateContext heartbeatTaskHelper(
randomDatanodeDetails(), conf);
EndpointStateMachine rpcEndPoint =
createEndpoint(conf, scmAddress, rpcTimeout)) {
- HddsProtos.DatanodeDetailsProto datanodeDetailsProto =
- randomDatanodeDetails().getProtoBufMessage();
rpcEndPoint.setState(EndpointStateMachine.EndPointStates.HEARTBEAT);
final StateContext stateContext =
@@ -629,9 +645,7 @@ private StateContext heartbeatTaskHelper(
HeartbeatEndpointTask endpointTask =
new HeartbeatEndpointTask(rpcEndPoint, conf, stateContext);
- endpointTask.setDatanodeDetailsProto(datanodeDetailsProto);
endpointTask.call();
- assertNotNull(endpointTask.getDatanodeDetailsProto());
assertEquals(EndpointStateMachine.EndPointStates.HEARTBEAT,
rpcEndPoint.getState());
return stateContext;
diff --git
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestBlockDataStreamOutput.java
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestBlockDataStreamOutput.java
index 97958c324e5..c915c393014 100644
---
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestBlockDataStreamOutput.java
+++
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestBlockDataStreamOutput.java
@@ -63,6 +63,7 @@
import org.apache.hadoop.ozone.container.ContainerTestHelper;
import org.apache.hadoop.ozone.container.TestHelper;
import org.apache.ozone.test.tag.Flaky;
+import org.apache.ozone.test.tag.Unhealthy;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.TestInstance;
@@ -333,17 +334,17 @@ public void testTotalAckDataLength(boolean flushDelay)
throws Exception {
}
}
+ @Unhealthy("Requires HDDS-16044 to finish implementing datanode version
passing to client.")
@ParameterizedTest
@MethodSource("clientParameters")
public void testDatanodeVersion(boolean flushDelay) throws Exception {
OzoneClientConfig config = newClientConfig(cluster.getConf(), flushDelay);
try (OzoneClient client = newClient(cluster.getConf(), config)) {
- // Each datanode advertises its own (older) currentVersion internally.
+ // Verify all DNs internally have versions set correctly
List<HddsDatanodeService> dns = cluster.getHddsDatanodes();
for (HddsDatanodeService dn : dns) {
DatanodeDetails details = dn.getDatanodeDetails();
- assertEquals(DN_OLD_VERSION,
- details.getCurrentVersion());
+ assertEquals(DN_OLD_VERSION, details.getCurrentVersion());
}
String keyName = getKeyName();
@@ -351,12 +352,10 @@ public void testDatanodeVersion(boolean flushDelay)
throws Exception {
KeyDataStreamOutput keyDataStreamOutput = (KeyDataStreamOutput)
key.getByteBufStreamOutput();
BlockDataStreamOutputEntry stream =
keyDataStreamOutput.getStreamEntries().get(0);
- // The cluster is finalized for ZDU, so the pipeline SCM returns on
block allocation
- // stamps each member's currentVersion with the lowest apparent version
across the
- // pipeline, which here is the software version the datanodes have
finalized to.
+ // Now check 3 DNs in a random pipeline returns the correct DN versions
List<DatanodeDetails> streamDnDetails = stream.getPipeline().getNodes();
for (DatanodeDetails details : streamDnDetails) {
- assertEquals(HDDSVersion.SOFTWARE_VERSION,
details.getCurrentVersion());
+ assertEquals(DN_OLD_VERSION, details.getCurrentVersion());
}
}
}
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMVersionManager.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMVersionManager.java
index f03e14819d6..65a94196a41 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMVersionManager.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMVersionManager.java
@@ -88,6 +88,16 @@ protected ComponentVersion computeApparentVersion(int
serializedApparentVersion)
return computeApparentVersionInternal(serializedApparentVersion);
}
+ @Override
+ public OzoneManagerVersion getVersionForClient() {
+ ComponentVersion apparentVersion = getApparentVersion();
+ // Once ZDU is finalized, the apparent version should always belong to the
OzoneManagerVersion enum.
+ if (isAllowed(OzoneManagerVersion.ZDU) && apparentVersion instanceof
OzoneManagerVersion) {
+ return (OzoneManagerVersion) apparentVersion;
+ }
+ return OzoneManagerVersion.values()[OzoneManagerVersion.ZDU.ordinal() - 1];
+ }
+
/**
* Maps a serialized apparent version to a {@link ComponentVersion}.
* If the value is >= {@link OzoneManagerVersion#ZDU} serialized, the OM
has been finalized for ZDU and the
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMVersionManager.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMVersionManager.java
index 5a927fa3614..434f23b010d 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMVersionManager.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/upgrade/TestOMVersionManager.java
@@ -213,6 +213,26 @@ public void testPersistFailureRollsBack() throws Exception
{
}
}
+ @Test
+ public void testGetVersionForClientWhenFinalized() throws Exception {
+ // Apparent version >= ZDU (finalized) reports the apparent version itself.
+ try (OMVersionManager versionManager = createManager(ZDU.serialize())) {
+ assertEquals(ZDU, versionManager.getVersionForClient());
+ }
+
+ try (OMVersionManager versionManager =
createManager(SOFTWARE_VERSION.serialize())) {
+ assertEquals(SOFTWARE_VERSION, versionManager.getVersionForClient());
+ }
+ }
+
+ @Test
+ public void testGetVersionForClientWhenPreZdu() throws Exception {
+ // A pre-ZDU apparent version clamps to the last pre-ZDU client version.
+ try (OMVersionManager versionManager =
createManager(INITIAL_VERSION.serialize())) {
+ assertEquals(OzoneManagerVersion.S3_BUCKET_TAGGING_API,
versionManager.getVersionForClient());
+ }
+ }
+
private OMStorage newOmStorage(int apparentVersion)
throws IOException {
// Reinitialize the configuration to point to a new unique storage
location.
diff --git
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/ReconVersionManager.java
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/ReconVersionManager.java
index eeffc03e443..03b8cc0cc72 100644
---
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/ReconVersionManager.java
+++
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/ReconVersionManager.java
@@ -135,6 +135,15 @@ public int getPersistedApparentVersion() {
}
}
+ /**
+ * Recon never used separate layout features and component versions, so its
apparent version can always be used for
+ * both network and disk compatibility.
+ */
+ @Override
+ public ReconVersion getVersionForClient() {
+ return (ReconVersion) getApparentVersion();
+ }
+
@Override
protected void runUpgradeAction(ComponentVersion version) throws
UpgradeException {
ReconUpgradeAction action = upgradeActions.get(version);
diff --git
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/upgrade/TestReconVersionManager.java
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/upgrade/TestReconVersionManager.java
index 24033063e31..c32c713e22a 100644
---
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/upgrade/TestReconVersionManager.java
+++
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/upgrade/TestReconVersionManager.java
@@ -214,6 +214,18 @@ public void testUpgradeActionFailureAbortsFinalize()
throws Exception {
}
}
+ @Test
+ public void testGetVersionForClientReturnsApparentVersion() throws Exception
{
+ // Recon has no separate ZDU/layout-feature split, so the client version
is always the apparent version.
+ try (ComponentVersionManager versionManager =
createManager(ReconVersion.SOFTWARE_VERSION.serialize())) {
+ assertEquals(ReconVersion.SOFTWARE_VERSION,
versionManager.getVersionForClient());
+ }
+
+ try (ComponentVersionManager versionManager =
createManager(ReconVersion.INITIAL_VERSION.serialize())) {
+ assertEquals(ReconVersion.INITIAL_VERSION,
versionManager.getVersionForClient());
+ }
+ }
+
@Override
@Test
public void testPersistFailureRollsBack() throws Exception {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]