Skip to content

Commit 04917e1

Browse files
authored
Add deprecation warning to TransportHandshaker (#123188)
This PR adds a deprecation warning log to the TransportHandshaker when connecting with nodes < v8.18.
1 parent 7e24885 commit 04917e1

File tree

3 files changed

+90
-14
lines changed

3 files changed

+90
-14
lines changed

docs/changelog/123188.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
pr: 123188
2+
summary: Add deprecation warning to `TransportHandshaker`
3+
area: Infra/Core
4+
type: deprecation
5+
issues: []
6+
deprecation:
7+
title: Deprecate ability to connect to nodes of versions 8.17 and earlier
8+
area: REST API
9+
details: >
10+
Versions 9.0.0 and later of {es} will not support communication with nodes of versions earlier than 8.18.0,
11+
so the ability to connect to nodes of earlier versions is deprecated in this version. This applies both to
12+
communication within a cluster and communication across clusters (e.g. for <<modules-cross-cluster-search,{ccs}>> or
13+
<<xpack-ccr,{ccr}>>).
14+
15+
{es} will report in its <<deprecation-logging, deprecation logging>> each time it opens a connection to a node that
16+
will not be supported from version 9.0.0 onwards. You must upgrade all your clusters to version 8.18.0 or later
17+
before upgrading any of your clusters to 9.0.0 or later.
18+
impact: >
19+
Upgrade all of your clusters to at least 8.18.0 before upgrading any of them to 9.0.0 or later.

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

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,17 @@
1111

1212
import org.elasticsearch.Build;
1313
import org.elasticsearch.TransportVersion;
14+
import org.elasticsearch.TransportVersions;
1415
import org.elasticsearch.action.ActionListener;
1516
import org.elasticsearch.cluster.node.DiscoveryNode;
1617
import org.elasticsearch.common.bytes.BytesReference;
1718
import org.elasticsearch.common.io.stream.BytesStreamOutput;
1819
import org.elasticsearch.common.io.stream.StreamInput;
1920
import org.elasticsearch.common.io.stream.StreamOutput;
21+
import org.elasticsearch.common.logging.DeprecationCategory;
22+
import org.elasticsearch.common.logging.DeprecationLogger;
2023
import org.elasticsearch.common.metrics.CounterMetric;
24+
import org.elasticsearch.common.util.concurrent.ThreadContext;
2125
import org.elasticsearch.core.Strings;
2226
import org.elasticsearch.core.TimeValue;
2327
import org.elasticsearch.logging.LogManager;
@@ -160,6 +164,7 @@ final class TransportHandshaker {
160164
*/
161165

162166
private static final Logger logger = LogManager.getLogger(TransportHandshaker.class);
167+
private static final DeprecationLogger deprecationLogger = DeprecationLogger.getLogger(logger.getName());
163168

164169
static final TransportVersion V7_HANDSHAKE_VERSION = TransportVersion.fromId(6_08_00_99);
165170
static final TransportVersion V8_HANDSHAKE_VERSION = TransportVersion.fromId(7_17_00_99);
@@ -171,6 +176,7 @@ final class TransportHandshaker {
171176
);
172177

173178
static final String HANDSHAKE_ACTION_NAME = "internal:tcp/handshake";
179+
static final TransportVersion V8_18_FIRST_VERSION = TransportVersions.INDEXING_PRESSURE_THROTTLING_STATS;
174180
private final ConcurrentMap<Long, HandshakeResponseHandler> pendingHandshakes = new ConcurrentHashMap<>();
175181
private final CounterMetric numHandshakes = new CounterMetric();
176182

@@ -246,17 +252,34 @@ void handleHandshake(TransportChannel channel, long requestId, StreamInput strea
246252
assert ignoreDeserializationErrors : exception;
247253
throw exception;
248254
}
249-
ensureCompatibleVersion(version, handshakeRequest.transportVersion, handshakeRequest.releaseVersion, channel);
255+
ensureCompatibleVersion(
256+
version,
257+
handshakeRequest.transportVersion,
258+
handshakeRequest.releaseVersion,
259+
channel,
260+
threadPool.getThreadContext()
261+
);
250262
channel.sendResponse(new HandshakeResponse(this.version, Build.current().version()));
251263
}
252264

253265
static void ensureCompatibleVersion(
254266
TransportVersion localTransportVersion,
255267
TransportVersion remoteTransportVersion,
256-
String releaseVersion,
257-
Object channel
268+
String remoteReleaseVersion,
269+
Object channel,
270+
ThreadContext threadContext
258271
) {
259272
if (TransportVersion.isCompatible(remoteTransportVersion)) {
273+
// Prevent log message headers from being added to the handshake response.
274+
try (var ignored = threadContext.stashContext()) {
275+
if (remoteTransportVersion.before(V8_18_FIRST_VERSION)) {
276+
deprecationLogger.warn(
277+
DeprecationCategory.OTHER,
278+
"handshake_version",
279+
getDeprecationMessage(localTransportVersion, remoteTransportVersion, remoteReleaseVersion, channel)
280+
);
281+
}
282+
}
260283
if (remoteTransportVersion.onOrAfter(localTransportVersion)) {
261284
// Remote is newer than us, so we will be using our transport protocol and it's up to the other end to decide whether it
262285
// knows how to do that.
@@ -273,7 +296,7 @@ static void ensureCompatibleVersion(
273296
"""
274297
Rejecting unreadable transport handshake from remote node with version [%s/%s] received on [%s] since this node has \
275298
version [%s/%s] which has an incompatible wire format.""",
276-
releaseVersion,
299+
remoteReleaseVersion,
277300
remoteTransportVersion,
278301
channel,
279302
Build.current().version(),
@@ -284,6 +307,24 @@ static void ensureCompatibleVersion(
284307

285308
}
286309

310+
// Non-private for testing
311+
static String getDeprecationMessage(
312+
TransportVersion localTransportVersion,
313+
TransportVersion remoteTransportVersion,
314+
String remoteReleaseVersion,
315+
Object channel
316+
) {
317+
return Strings.format(
318+
"Performed a handshake with a remote node with version [%s/%s] received on [%s] which "
319+
+ "will be incompatible after this node on version [%s/%s] is upgraded to 9.x.",
320+
remoteReleaseVersion,
321+
remoteTransportVersion,
322+
channel,
323+
Build.current().version(),
324+
localTransportVersion
325+
);
326+
}
327+
287328
TransportResponseHandler<HandshakeResponse> removeHandlerForHandshake(long requestId) {
288329
return pendingHandshakes.remove(requestId);
289330
}
@@ -323,7 +364,13 @@ public Executor executor() {
323364
public void handleResponse(HandshakeResponse response) {
324365
if (isDone.compareAndSet(false, true)) {
325366
ActionListener.completeWith(listener, () -> {
326-
ensureCompatibleVersion(version, response.getTransportVersion(), response.getReleaseVersion(), channel);
367+
ensureCompatibleVersion(
368+
version,
369+
response.getTransportVersion(),
370+
response.getReleaseVersion(),
371+
channel,
372+
threadPool.getThreadContext()
373+
);
327374
final var resultVersion = TransportVersion.min(TransportHandshaker.this.version, response.getTransportVersion());
328375
assert TransportVersion.current().before(version) // simulating a newer-version transport service for test purposes
329376
|| resultVersion.isKnown() : "negotiated unknown version " + resultVersion;

server/src/test/java/org/elasticsearch/transport/TransportHandshakerTests.java

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import java.util.concurrent.ExecutionException;
3232
import java.util.concurrent.TimeUnit;
3333

34+
import static org.elasticsearch.transport.TransportHandshaker.V8_18_FIRST_VERSION;
35+
import static org.elasticsearch.transport.TransportHandshaker.getDeprecationMessage;
3436
import static org.hamcrest.Matchers.allOf;
3537
import static org.hamcrest.Matchers.containsString;
3638
import static org.mockito.Mockito.doThrow;
@@ -100,10 +102,8 @@ public void testHandshakeRequestAndResponse() throws IOException {
100102

101103
@TestLogging(reason = "testing WARN logging", value = "org.elasticsearch.transport.TransportHandshaker:WARN")
102104
public void testIncompatibleHandshakeRequest() throws IOException {
103-
TransportHandshaker.HandshakeRequest handshakeRequest = new TransportHandshaker.HandshakeRequest(
104-
getRandomIncompatibleTransportVersion(),
105-
randomIdentifier()
106-
);
105+
var remoteVersion = getRandomIncompatibleTransportVersion();
106+
TransportHandshaker.HandshakeRequest handshakeRequest = new TransportHandshaker.HandshakeRequest(remoteVersion, randomIdentifier());
107107
BytesStreamOutput bytesStreamOutput = new BytesStreamOutput();
108108
bytesStreamOutput.setTransportVersion(HANDSHAKE_REQUEST_VERSION);
109109
handshakeRequest.writeTo(bytesStreamOutput);
@@ -132,6 +132,7 @@ public void testIncompatibleHandshakeRequest() throws IOException {
132132
"Rejecting unreadable transport handshake * incompatible wire format."
133133
)
134134
);
135+
assertDeprecationMessageIsLogged(remoteVersion, remoteVersion.toReleaseVersion(), channel);
135136
}
136137

137138
public void testHandshakeResponseFromOlderNode() throws Exception {
@@ -143,10 +144,13 @@ public void testHandshakeResponseFromOlderNode() throws Exception {
143144
assertFalse(versionFuture.isDone());
144145

145146
final var remoteVersion = TransportVersionUtils.randomCompatibleVersion(random());
146-
handler.handleResponse(new TransportHandshaker.HandshakeResponse(remoteVersion, randomIdentifier()));
147+
var releaseVersion = randomIdentifier();
148+
handler.handleResponse(new TransportHandshaker.HandshakeResponse(remoteVersion, releaseVersion));
147149

148150
assertTrue(versionFuture.isDone());
149151
assertEquals(remoteVersion, versionFuture.result());
152+
153+
assertDeprecationMessageIsLogged(remoteVersion, releaseVersion, channel);
150154
}
151155

152156
@TestLogging(reason = "testing WARN logging", value = "org.elasticsearch.transport.TransportHandshaker:WARN")
@@ -158,10 +162,9 @@ public void testHandshakeResponseFromOlderNodeWithPatchedProtocol() {
158162

159163
assertFalse(versionFuture.isDone());
160164

161-
final var handshakeResponse = new TransportHandshaker.HandshakeResponse(
162-
getRandomIncompatibleTransportVersion(),
163-
randomIdentifier()
164-
);
165+
var remoteVersion = getRandomIncompatibleTransportVersion();
166+
var releaseVersion = randomIdentifier();
167+
final var handshakeResponse = new TransportHandshaker.HandshakeResponse(remoteVersion, releaseVersion);
165168

166169
MockLog.assertThatLogger(
167170
() -> handler.handleResponse(handshakeResponse),
@@ -184,6 +187,13 @@ public void testHandshakeResponseFromOlderNodeWithPatchedProtocol() {
184187
containsString("which has an incompatible wire format")
185188
)
186189
);
190+
assertDeprecationMessageIsLogged(remoteVersion, releaseVersion, channel);
191+
}
192+
193+
private void assertDeprecationMessageIsLogged(TransportVersion remoteVersion, String remoteReleaseVersion, Object channel) {
194+
if (remoteVersion.onOrAfter(TransportVersions.MINIMUM_COMPATIBLE) && remoteVersion.before(V8_18_FIRST_VERSION)) {
195+
assertWarnings(getDeprecationMessage(TransportVersion.current(), remoteVersion, remoteReleaseVersion, channel));
196+
}
187197
}
188198

189199
private static TransportVersion getRandomIncompatibleTransportVersion() {

0 commit comments

Comments
 (0)