Skip to content

Commit a1f0606

Browse files
committed
[8.x] Add min. read-only index version compatible to DiscoveryNode (elastic#118744)
In a short future we'd like to use this information in methods like IndexMetadataVerifier#checkSupportedVersion and NodeJoineExecutor to allow opening indices in N-2 versions as read-only indices on ES V9.
1 parent 3c357ea commit a1f0606

File tree

14 files changed

+135
-7
lines changed

14 files changed

+135
-7
lines changed

docs/reference/indices/shard-stores.asciidoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ The API returns the following response:
173173
"roles": [...],
174174
"version": "8.10.0",
175175
"min_index_version": 7000099,
176+
"min_read_only_index_version": 7000099,
176177
"max_index_version": 8100099
177178
},
178179
"allocation_id": "2iNySv_OQVePRX-yaRH_lQ", <4>
@@ -193,6 +194,7 @@ The API returns the following response:
193194
// TESTRESPONSE[s/"roles": \[[^]]*\]/"roles": $body.$_path/]
194195
// TESTRESPONSE[s/"8.10.0"/\$node_version/]
195196
// TESTRESPONSE[s/"min_index_version": 7000099/"min_index_version": $body.$_path/]
197+
// TESTRESPONSE[s/"min_index_version": 7000099/"min_index_version": $body.$_path/]
196198
// TESTRESPONSE[s/"max_index_version": 8100099/"max_index_version": $body.$_path/]
197199

198200

server/src/main/java/org/elasticsearch/TransportVersions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ static TransportVersion def(int id) {
147147
public static final TransportVersion SEMANTIC_QUERY_LENIENT = def(8_807_00_0);
148148
public static final TransportVersion ESQL_QUERY_BUILDER_IN_SEARCH_FUNCTIONS = def(8_808_00_0);
149149
public static final TransportVersion EQL_ALLOW_PARTIAL_SEARCH_RESULTS = def(8_809_00_0);
150+
public static final TransportVersion NODE_VERSION_INFORMATION_WITH_MIN_READ_ONLY_INDEX_VERSION = def(8_810_00_0);
150151

151152
/*
152153
* STOP! READ THIS FIRST! No, really,

server/src/main/java/org/elasticsearch/cluster/node/DiscoveryNode.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import java.util.SortedSet;
3939
import java.util.TreeSet;
4040

41+
import static org.elasticsearch.TransportVersions.NODE_VERSION_INFORMATION_WITH_MIN_READ_ONLY_INDEX_VERSION;
4142
import static org.elasticsearch.node.NodeRoleSettings.NODE_ROLES_SETTING;
4243

4344
/**
@@ -339,7 +340,16 @@ public DiscoveryNode(StreamInput in) throws IOException {
339340
}
340341
this.roles = Collections.unmodifiableSortedSet(roles);
341342
if (in.getTransportVersion().onOrAfter(TransportVersions.V_8_10_X)) {
342-
versionInfo = new VersionInformation(Version.readVersion(in), IndexVersion.readVersion(in), IndexVersion.readVersion(in));
343+
Version version = Version.readVersion(in);
344+
IndexVersion minIndexVersion = IndexVersion.readVersion(in);
345+
IndexVersion minReadOnlyIndexVersion;
346+
if (in.getTransportVersion().onOrAfter(NODE_VERSION_INFORMATION_WITH_MIN_READ_ONLY_INDEX_VERSION)) {
347+
minReadOnlyIndexVersion = IndexVersion.readVersion(in);
348+
} else {
349+
minReadOnlyIndexVersion = minIndexVersion;
350+
}
351+
IndexVersion maxIndexVersion = IndexVersion.readVersion(in);
352+
versionInfo = new VersionInformation(version, minIndexVersion, minReadOnlyIndexVersion, maxIndexVersion);
343353
} else {
344354
versionInfo = inferVersionInformation(Version.readVersion(in));
345355
}
@@ -378,6 +388,9 @@ public void writeTo(StreamOutput out) throws IOException {
378388
if (out.getTransportVersion().onOrAfter(TransportVersions.V_8_10_X)) {
379389
Version.writeVersion(versionInfo.nodeVersion(), out);
380390
IndexVersion.writeVersion(versionInfo.minIndexVersion(), out);
391+
if (out.getTransportVersion().onOrAfter(NODE_VERSION_INFORMATION_WITH_MIN_READ_ONLY_INDEX_VERSION)) {
392+
IndexVersion.writeVersion(versionInfo.minReadOnlyIndexVersion(), out);
393+
}
381394
IndexVersion.writeVersion(versionInfo.maxIndexVersion(), out);
382395
} else {
383396
Version.writeVersion(versionInfo.nodeVersion(), out);
@@ -504,6 +517,10 @@ public IndexVersion getMinIndexVersion() {
504517
return versionInfo.minIndexVersion();
505518
}
506519

520+
public IndexVersion getMinReadOnlyIndexVersion() {
521+
return versionInfo.minReadOnlyIndexVersion();
522+
}
523+
507524
public IndexVersion getMaxIndexVersion() {
508525
return versionInfo.maxIndexVersion();
509526
}
@@ -603,6 +620,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
603620
builder.endArray();
604621
builder.field("version", versionInfo.nodeVersion());
605622
builder.field("min_index_version", versionInfo.minIndexVersion());
623+
builder.field("min_read_only_index_version", versionInfo.minReadOnlyIndexVersion());
606624
builder.field("max_index_version", versionInfo.maxIndexVersion());
607625
builder.endObject();
608626
return builder;

server/src/main/java/org/elasticsearch/cluster/node/DiscoveryNodes.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public class DiscoveryNodes implements Iterable<DiscoveryNode>, SimpleDiffable<D
7070
private final Version minNodeVersion;
7171
private final IndexVersion maxDataNodeCompatibleIndexVersion;
7272
private final IndexVersion minSupportedIndexVersion;
73+
private final IndexVersion minReadOnlySupportedIndexVersion;
7374

7475
private final Map<String, Set<String>> tiersToNodeIds;
7576

@@ -86,6 +87,7 @@ private DiscoveryNodes(
8687
Version minNodeVersion,
8788
IndexVersion maxDataNodeCompatibleIndexVersion,
8889
IndexVersion minSupportedIndexVersion,
90+
IndexVersion minReadOnlySupportedIndexVersion,
8991
Map<String, Set<String>> tiersToNodeIds
9092
) {
9193
this.nodeLeftGeneration = nodeLeftGeneration;
@@ -103,6 +105,8 @@ private DiscoveryNodes(
103105
this.maxNodeVersion = maxNodeVersion;
104106
this.maxDataNodeCompatibleIndexVersion = maxDataNodeCompatibleIndexVersion;
105107
this.minSupportedIndexVersion = minSupportedIndexVersion;
108+
this.minReadOnlySupportedIndexVersion = minReadOnlySupportedIndexVersion;
109+
assert minReadOnlySupportedIndexVersion.onOrBefore(minSupportedIndexVersion);
106110
assert (localNodeId == null) == (localNode == null);
107111
this.tiersToNodeIds = tiersToNodeIds;
108112
}
@@ -122,6 +126,7 @@ public DiscoveryNodes withMasterNodeId(@Nullable String masterNodeId) {
122126
minNodeVersion,
123127
maxDataNodeCompatibleIndexVersion,
124128
minSupportedIndexVersion,
129+
minReadOnlySupportedIndexVersion,
125130
tiersToNodeIds
126131
);
127132
}
@@ -382,6 +387,13 @@ public IndexVersion getMinSupportedIndexVersion() {
382387
return minSupportedIndexVersion;
383388
}
384389

390+
/**
391+
* Returns the minimum index version for read-only indices supported by all nodes in the cluster
392+
*/
393+
public IndexVersion getMinReadOnlySupportedIndexVersion() {
394+
return minReadOnlySupportedIndexVersion;
395+
}
396+
385397
/**
386398
* Return the node-left generation, which is the number of times the cluster membership has been updated by removing one or more nodes.
387399
* <p>
@@ -841,6 +853,7 @@ public DiscoveryNodes build() {
841853
Version minNonClientNodeVersion = null;
842854
IndexVersion maxDataNodeCompatibleIndexVersion = null;
843855
IndexVersion minSupportedIndexVersion = null;
856+
IndexVersion minReadOnlySupportedIndexVersion = null;
844857
for (Map.Entry<String, DiscoveryNode> nodeEntry : nodes.entrySet()) {
845858
DiscoveryNode discoNode = nodeEntry.getValue();
846859
Version version = discoNode.getVersion();
@@ -851,6 +864,7 @@ public DiscoveryNodes build() {
851864
minNodeVersion = min(minNodeVersion, version);
852865
maxNodeVersion = max(maxNodeVersion, version);
853866
minSupportedIndexVersion = max(minSupportedIndexVersion, discoNode.getMinIndexVersion());
867+
minReadOnlySupportedIndexVersion = max(minReadOnlySupportedIndexVersion, discoNode.getMinReadOnlyIndexVersion());
854868
}
855869

856870
final long newNodeLeftGeneration;
@@ -884,6 +898,7 @@ public DiscoveryNodes build() {
884898
Objects.requireNonNullElse(minNodeVersion, Version.CURRENT.minimumCompatibilityVersion()),
885899
Objects.requireNonNullElse(maxDataNodeCompatibleIndexVersion, IndexVersion.current()),
886900
Objects.requireNonNullElse(minSupportedIndexVersion, IndexVersions.MINIMUM_COMPATIBLE),
901+
Objects.requireNonNullElse(minReadOnlySupportedIndexVersion, IndexVersions.MINIMUM_READONLY_COMPATIBLE),
887902
computeTiersToNodesMap(dataNodes)
888903
);
889904
}

server/src/main/java/org/elasticsearch/cluster/node/VersionInformation.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,22 @@
1717

1818
/**
1919
* Represents the versions of various aspects of an Elasticsearch node.
20-
* @param nodeVersion The node {@link Version}
21-
* @param minIndexVersion The minimum {@link IndexVersion} supported by this node
22-
* @param maxIndexVersion The maximum {@link IndexVersion} supported by this node
20+
* @param nodeVersion The node {@link Version}
21+
* @param minIndexVersion The minimum {@link IndexVersion} supported by this node
22+
* @param minReadOnlyIndexVersion The minimum {@link IndexVersion} for read-only indices supported by this node
23+
* @param maxIndexVersion The maximum {@link IndexVersion} supported by this node
2324
*/
24-
public record VersionInformation(Version nodeVersion, IndexVersion minIndexVersion, IndexVersion maxIndexVersion) {
25+
public record VersionInformation(
26+
Version nodeVersion,
27+
IndexVersion minIndexVersion,
28+
IndexVersion minReadOnlyIndexVersion,
29+
IndexVersion maxIndexVersion
30+
) {
2531

2632
public static final VersionInformation CURRENT = new VersionInformation(
2733
Version.CURRENT,
2834
IndexVersions.MINIMUM_COMPATIBLE,
35+
IndexVersions.MINIMUM_READONLY_COMPATIBLE,
2936
IndexVersion.current()
3037
);
3138

@@ -45,9 +52,16 @@ public static VersionInformation inferVersions(Version nodeVersion) {
4552
}
4653
}
4754

55+
@Deprecated
56+
public VersionInformation(Version version, IndexVersion minIndexVersion, IndexVersion maxIndexVersion) {
57+
this(version, minIndexVersion, minIndexVersion, maxIndexVersion);
58+
}
59+
4860
public VersionInformation {
4961
Objects.requireNonNull(nodeVersion);
5062
Objects.requireNonNull(minIndexVersion);
63+
Objects.requireNonNull(minReadOnlyIndexVersion);
5164
Objects.requireNonNull(maxIndexVersion);
65+
assert minReadOnlyIndexVersion.onOrBefore(minIndexVersion) : minReadOnlyIndexVersion + " > " + minIndexVersion;
5266
}
5367
}

server/src/main/java/org/elasticsearch/discovery/HandshakingTransportAddressConnector.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ private void openProbeConnection(ActionListener<Transport.Connection> listener)
110110
new VersionInformation(
111111
Version.CURRENT.minimumCompatibilityVersion(),
112112
IndexVersions.MINIMUM_COMPATIBLE,
113+
IndexVersions.MINIMUM_READONLY_COMPATIBLE,
113114
IndexVersion.current()
114115
)
115116
),

server/src/main/java/org/elasticsearch/index/IndexVersions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ private static IndexVersion def(int id, Version luceneVersion) {
178178
*/
179179

180180
public static final IndexVersion MINIMUM_COMPATIBLE = V_7_0_0;
181+
public static final IndexVersion MINIMUM_READONLY_COMPATIBLE = MINIMUM_COMPATIBLE;
181182

182183
static final NavigableMap<Integer, IndexVersion> VERSION_IDS = getAllVersionIds(IndexVersions.class);
183184
static final IndexVersion LATEST_DEFINED;

server/src/main/java/org/elasticsearch/transport/ProxyConnectionStrategy.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ public void onFailure(Exception e) {
304304
new VersionInformation(
305305
Version.CURRENT.minimumCompatibilityVersion(),
306306
IndexVersions.MINIMUM_COMPATIBLE,
307+
IndexVersions.MINIMUM_READONLY_COMPATIBLE,
307308
IndexVersion.current()
308309
)
309310
);

server/src/main/java/org/elasticsearch/transport/SniffConnectionStrategy.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,7 @@ private static DiscoveryNode resolveSeedNode(String clusterAlias, String address
505505
var seedVersion = new VersionInformation(
506506
Version.CURRENT.minimumCompatibilityVersion(),
507507
IndexVersions.MINIMUM_COMPATIBLE,
508+
IndexVersions.MINIMUM_READONLY_COMPATIBLE,
508509
IndexVersion.current()
509510
);
510511
if (proxyAddress == null || proxyAddress.isEmpty()) {

server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ public void testToXContentWithDeprecatedClusterState() {
128128
],
129129
"version": "%s",
130130
"min_index_version": %s,
131+
"min_read_only_index_version": %s,
131132
"max_index_version": %s
132133
}
133134
},
@@ -219,6 +220,7 @@ public void testToXContentWithDeprecatedClusterState() {
219220
clusterState.getNodes().get("node0").getEphemeralId(),
220221
Version.CURRENT,
221222
IndexVersions.MINIMUM_COMPATIBLE,
223+
IndexVersions.MINIMUM_READONLY_COMPATIBLE,
222224
IndexVersion.current(),
223225
IndexVersion.current(),
224226
IndexVersion.current()

server/src/test/java/org/elasticsearch/cluster/ClusterStateTests.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ public void testToXContent() throws IOException {
213213
],
214214
"version": "%s",
215215
"min_index_version":%s,
216+
"min_read_only_index_version":%s,
216217
"max_index_version":%s
217218
}
218219
},
@@ -389,6 +390,7 @@ public void testToXContent() throws IOException {
389390
ephemeralId,
390391
Version.CURRENT,
391392
IndexVersions.MINIMUM_COMPATIBLE,
393+
IndexVersions.MINIMUM_READONLY_COMPATIBLE,
392394
IndexVersion.current(),
393395
TransportVersion.current(),
394396
IndexVersion.current(),
@@ -488,6 +490,7 @@ public void testToXContent_FlatSettingTrue_ReduceMappingFalse() throws IOExcepti
488490
],
489491
"version" : "%s",
490492
"min_index_version" : %s,
493+
"min_read_only_index_version" : %s,
491494
"max_index_version" : %s
492495
}
493496
},
@@ -663,6 +666,7 @@ public void testToXContent_FlatSettingTrue_ReduceMappingFalse() throws IOExcepti
663666
ephemeralId,
664667
Version.CURRENT,
665668
IndexVersions.MINIMUM_COMPATIBLE,
669+
IndexVersions.MINIMUM_READONLY_COMPATIBLE,
666670
IndexVersion.current(),
667671
TransportVersion.current(),
668672
IndexVersion.current(),
@@ -762,6 +766,7 @@ public void testToXContent_FlatSettingFalse_ReduceMappingTrue() throws IOExcepti
762766
],
763767
"version" : "%s",
764768
"min_index_version" : %s,
769+
"min_read_only_index_version" : %s,
765770
"max_index_version" : %s
766771
}
767772
},
@@ -943,6 +948,7 @@ public void testToXContent_FlatSettingFalse_ReduceMappingTrue() throws IOExcepti
943948
ephemeralId,
944949
Version.CURRENT,
945950
IndexVersions.MINIMUM_COMPATIBLE,
951+
IndexVersions.MINIMUM_READONLY_COMPATIBLE,
946952
IndexVersion.current(),
947953
TransportVersion.current(),
948954
IndexVersion.current(),

server/src/test/java/org/elasticsearch/cluster/node/DiscoveryNodeTests.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import static java.util.Collections.emptySet;
3232
import static org.elasticsearch.test.NodeRoles.nonRemoteClusterClientNode;
3333
import static org.elasticsearch.test.NodeRoles.remoteClusterClientNode;
34+
import static org.elasticsearch.test.TransportVersionUtils.getPreviousVersion;
35+
import static org.elasticsearch.test.TransportVersionUtils.randomVersionBetween;
3436
import static org.hamcrest.Matchers.allOf;
3537
import static org.hamcrest.Matchers.containsString;
3638
import static org.hamcrest.Matchers.equalTo;
@@ -221,13 +223,15 @@ public void testDiscoveryNodeToXContent() {
221223
],
222224
"version" : "%s",
223225
"min_index_version" : %s,
226+
"min_read_only_index_version" : %s,
224227
"max_index_version" : %s
225228
}
226229
}""",
227230
transportAddress,
228231
withExternalId ? "test-external-id" : "test-name",
229232
Version.CURRENT,
230233
IndexVersions.MINIMUM_COMPATIBLE,
234+
IndexVersions.MINIMUM_READONLY_COMPATIBLE,
231235
IndexVersion.current()
232236
)
233237
)
@@ -250,4 +254,61 @@ public void testDiscoveryNodeToString() {
250254
assertThat(toString, containsString("{" + node.getVersion() + "}"));
251255
assertThat(toString, containsString("{test-attr=val}"));// attributes
252256
}
257+
258+
public void testDiscoveryNodeMinReadOnlyVersionSerialization() throws Exception {
259+
var node = DiscoveryNodeUtils.create("_id", buildNewFakeTransportAddress(), Version.CURRENT);
260+
261+
{
262+
try (var out = new BytesStreamOutput()) {
263+
out.setTransportVersion(TransportVersion.current());
264+
node.writeTo(out);
265+
266+
try (var in = StreamInput.wrap(out.bytes().array())) {
267+
in.setTransportVersion(TransportVersion.current());
268+
269+
var deserialized = new DiscoveryNode(in);
270+
assertThat(deserialized.getId(), equalTo(node.getId()));
271+
assertThat(deserialized.getAddress(), equalTo(node.getAddress()));
272+
assertThat(deserialized.getMinIndexVersion(), equalTo(node.getMinIndexVersion()));
273+
assertThat(deserialized.getMaxIndexVersion(), equalTo(node.getMaxIndexVersion()));
274+
assertThat(deserialized.getMinReadOnlyIndexVersion(), equalTo(node.getMinReadOnlyIndexVersion()));
275+
assertThat(deserialized.getVersionInformation(), equalTo(node.getVersionInformation()));
276+
}
277+
}
278+
}
279+
280+
{
281+
var oldVersion = randomVersionBetween(
282+
random(),
283+
TransportVersions.MINIMUM_COMPATIBLE,
284+
getPreviousVersion(TransportVersions.NODE_VERSION_INFORMATION_WITH_MIN_READ_ONLY_INDEX_VERSION)
285+
);
286+
try (var out = new BytesStreamOutput()) {
287+
out.setTransportVersion(oldVersion);
288+
node.writeTo(out);
289+
290+
try (var in = StreamInput.wrap(out.bytes().array())) {
291+
in.setTransportVersion(oldVersion);
292+
293+
var deserialized = new DiscoveryNode(in);
294+
assertThat(deserialized.getId(), equalTo(node.getId()));
295+
assertThat(deserialized.getAddress(), equalTo(node.getAddress()));
296+
assertThat(deserialized.getMinIndexVersion(), equalTo(node.getMinIndexVersion()));
297+
assertThat(deserialized.getMaxIndexVersion(), equalTo(node.getMaxIndexVersion()));
298+
assertThat(deserialized.getMinReadOnlyIndexVersion(), equalTo(node.getMinIndexVersion()));
299+
assertThat(
300+
deserialized.getVersionInformation(),
301+
equalTo(
302+
new VersionInformation(
303+
node.getVersion(),
304+
node.getMinIndexVersion(),
305+
node.getMinIndexVersion(),
306+
node.getMaxIndexVersion()
307+
)
308+
)
309+
);
310+
}
311+
}
312+
}
313+
}
253314
}

0 commit comments

Comments
 (0)