GEODE-5194: allow gfsh to connect if serialization version matches (#4202)
* GEODE-5194: allow gfsh to connect if serialization version matches
This builds on the previous work that relaxed the version check to
ignore patch version changes. Now even differing minor versions may be
compatible (i.e. no changes to gfsh commands or options). Serialization
version is not a perfect proxy for when gfsh commands have changed, but
this is at least an improvement over the previous check...
Co-authored-by: Jinmei Liao <jiliao@pivotal.io>
* empty
* rename geodeVersion to geodeSerializationVersion to more accurately reflect what it represents
diff --git a/geode-core/src/main/java/org/apache/geode/management/MemberMXBean.java b/geode-core/src/main/java/org/apache/geode/management/MemberMXBean.java
index a240106..f81a272 100644
--- a/geode-core/src/main/java/org/apache/geode/management/MemberMXBean.java
+++ b/geode-core/src/main/java/org/apache/geode/management/MemberMXBean.java
@@ -299,6 +299,12 @@
String getReleaseVersion();
/**
+ * returns only the Geode version string
+ */
+ @ResourceOperation()
+ String getGeodeReleaseVersion();
+
+ /**
* Returns whether this member is attached to at least one Locator.
*
* @return True if this member is attached to a Locator, false otherwise.
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/beans/MemberMBean.java b/geode-core/src/main/java/org/apache/geode/management/internal/beans/MemberMBean.java
index fd6a222..9cf7a8a 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/beans/MemberMBean.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/beans/MemberMBean.java
@@ -363,6 +363,11 @@
}
@Override
+ public String getGeodeReleaseVersion() {
+ return bridge.getGeodeReleaseVersion();
+ }
+
+ @Override
public boolean hasGatewayReceiver() {
return bridge.hasGatewayReceiver();
}
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/beans/MemberMBeanBridge.java b/geode-core/src/main/java/org/apache/geode/management/internal/beans/MemberMBeanBridge.java
index a06dfd4..3108425 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/beans/MemberMBeanBridge.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/beans/MemberMBeanBridge.java
@@ -75,6 +75,7 @@
import org.apache.geode.internal.offheap.OffHeapMemoryStats;
import org.apache.geode.internal.process.PidUnavailableException;
import org.apache.geode.internal.process.ProcessUtils;
+import org.apache.geode.internal.serialization.Version;
import org.apache.geode.internal.statistics.OsStatisticsProvider;
import org.apache.geode.internal.statistics.StatSamplerStats;
import org.apache.geode.internal.statistics.StatisticsManager;
@@ -1441,4 +1442,8 @@
String getReleaseVersion() {
return GemFireVersion.getGemFireVersion();
}
+
+ String getGeodeReleaseVersion() {
+ return Version.CURRENT.getName();
+ }
}
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConnectCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConnectCommand.java
index c84e0fb..82c9e70 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConnectCommand.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConnectCommand.java
@@ -163,15 +163,19 @@
String gfshVersion = gfsh.getVersion();
String remoteVersion = null;
try {
- remoteVersion = invoker.getRemoteVersion();
- if (versionComponent(remoteVersion, VERSION_MAJOR)
- .equalsIgnoreCase(versionComponent(gfshVersion, VERSION_MAJOR))
- && versionComponent(remoteVersion, VERSION_MINOR)
- .equalsIgnoreCase(versionComponent(gfshVersion, VERSION_MINOR))) {
+ String gfshGeodeSerializationVersion = gfsh.getGeodeSerializationVersion();
+ String remoteGeodeSerializationVersion = invoker.getRemoteGeodeSerializationVersion();
+ if (hasSameMajorMinor(gfshGeodeSerializationVersion, remoteGeodeSerializationVersion)) {
return result;
}
} catch (Exception e) {
- gfsh.logInfo("failed to get the the remote version.", e);
+ // we failed to get the remote geode serialization version; get remote product version for
+ // error message
+ try {
+ remoteVersion = invoker.getRemoteVersion();
+ } catch (Exception ex) {
+ gfsh.logInfo("failed to get the the remote version.", ex);
+ }
}
// will reach here only when remoteVersion is not available or does not match
@@ -185,7 +189,14 @@
}
}
- private String versionComponent(String version, int component) {
+ private static boolean hasSameMajorMinor(String gfshVersion, String remoteVersion) {
+ return versionComponent(remoteVersion, VERSION_MAJOR)
+ .equalsIgnoreCase(versionComponent(gfshVersion, VERSION_MAJOR))
+ && versionComponent(remoteVersion, VERSION_MINOR)
+ .equalsIgnoreCase(versionComponent(gfshVersion, VERSION_MINOR));
+ }
+
+ private static String versionComponent(String version, int component) {
String[] versionComponents = StringUtils.split(version, '.');
return versionComponents.length >= component + 1 ? versionComponents[component] : "";
}
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/Gfsh.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/Gfsh.java
index fa3c7e4..4dcabed 100755
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/Gfsh.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/Gfsh.java
@@ -50,6 +50,7 @@
import org.apache.geode.internal.logging.Banner;
import org.apache.geode.internal.logging.LoggingThread;
import org.apache.geode.internal.process.signal.AbstractSignalNotificationHandler;
+import org.apache.geode.internal.serialization.Version;
import org.apache.geode.internal.util.ArgumentRedactor;
import org.apache.geode.internal.util.HostName;
import org.apache.geode.internal.util.SunAPINotFoundException;
@@ -672,10 +673,15 @@
if (full) {
return GemFireVersion.asString();
} else {
+
return GemFireVersion.getGemFireVersion();
}
}
+ public String getGeodeSerializationVersion() {
+ return Version.CURRENT.getName();
+ }
+
public String getWelcomeMessage() {
return ansiHandler.decorateString("Monitor and Manage " + GemFireVersion.getProductName(),
ANSIStyle.CYAN);
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/JmxOperationInvoker.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/JmxOperationInvoker.java
index 7f5467a..05b706a 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/JmxOperationInvoker.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/JmxOperationInvoker.java
@@ -186,6 +186,11 @@
}
@Override
+ public String getRemoteGeodeSerializationVersion() {
+ return memberMXBeanProxy.getGeodeReleaseVersion();
+ }
+
+ @Override
public Object invoke(String resourceName, String operationName, Object[] params,
String[] signature) throws JMXInvocationException {
try {
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/OperationInvoker.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/OperationInvoker.java
index f1819ed..45d4c71 100755
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/OperationInvoker.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/shell/OperationInvoker.java
@@ -130,6 +130,8 @@
String getRemoteVersion();
+ String getRemoteGeodeSerializationVersion();
+
/**
* Processes the requested command. Sends the command to the GemFire Manager for remote processing
* (execution). NOTE refactoring return type in favor of covariant return types.
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/HttpOperationInvoker.java b/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/HttpOperationInvoker.java
index d1f508f..45b4855 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/HttpOperationInvoker.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/web/shell/HttpOperationInvoker.java
@@ -411,6 +411,11 @@
return httpRequester.get(link, String.class);
}
+ @Override
+ public String getRemoteGeodeSerializationVersion() {
+ final URI link = HttpRequester.createURI(baseUrl, "/version/geodeSerializationVersion");
+ return httpRequester.get(link, String.class);
+ }
/**
* Processes the requested command. Sends the command to the GemFire Manager for remote processing
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ConnectCommandTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ConnectCommandTest.java
index c4f9017..4f9adf3 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ConnectCommandTest.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ConnectCommandTest.java
@@ -323,8 +323,8 @@
@Test
public void connectToManagerWithGreaterPatchVersion() {
- when(gfsh.getVersion()).thenReturn("1.5.1");
- when(operationInvoker.getRemoteVersion()).thenReturn("1.5.2");
+ when(gfsh.getGeodeSerializationVersion()).thenReturn("1.5.1");
+ when(operationInvoker.getRemoteGeodeSerializationVersion()).thenReturn("1.5.2");
when(operationInvoker.isConnected()).thenReturn(true);
when(resultModel.getStatus()).thenReturn(Result.Status.OK);
@@ -334,8 +334,8 @@
@Test
public void connectToManagerWithNoPatchVersion() {
- when(gfsh.getVersion()).thenReturn("1.5.1");
- when(operationInvoker.getRemoteVersion()).thenReturn("1.5");
+ when(gfsh.getGeodeSerializationVersion()).thenReturn("1.5.1");
+ when(operationInvoker.getRemoteGeodeSerializationVersion()).thenReturn("1.5");
when(operationInvoker.isConnected()).thenReturn(true);
when(resultModel.getStatus()).thenReturn(Result.Status.OK);
@@ -345,8 +345,8 @@
@Test
public void connectToManagerWithLessorPatchVersion() {
- when(gfsh.getVersion()).thenReturn("1.5.1");
- when(operationInvoker.getRemoteVersion()).thenReturn("1.5.0");
+ when(gfsh.getGeodeSerializationVersion()).thenReturn("1.5.1");
+ when(operationInvoker.getRemoteGeodeSerializationVersion()).thenReturn("1.5.0");
when(operationInvoker.isConnected()).thenReturn(true);
when(resultModel.getStatus()).thenReturn(Result.Status.OK);
@@ -367,8 +367,8 @@
@Test
public void connectToAValidManager() {
- when(gfsh.getVersion()).thenReturn("1.5");
- when(operationInvoker.getRemoteVersion()).thenReturn("1.5");
+ when(gfsh.getGeodeSerializationVersion()).thenReturn("1.5");
+ when(operationInvoker.getRemoteGeodeSerializationVersion()).thenReturn("1.5");
when(operationInvoker.isConnected()).thenReturn(true);
when(resultModel.getStatus()).thenReturn(Result.Status.OK);
diff --git a/geode-web/build.gradle b/geode-web/build.gradle
index a02d491..b2dcd55 100644
--- a/geode-web/build.gradle
+++ b/geode-web/build.gradle
@@ -31,6 +31,7 @@
//a container that has geode-core on the classpath, is prevents duplicating jars. geode-core
//in particular should not be duplicated in the war.
providedCompile(project(':geode-logging'))
+ providedCompile(project(':geode-serialization'))
providedCompile(project(path: ':geode-core')) {
//spring-web is excluded from the providedCompile configuration to ensure
//that it is included as part of the war. spring-web must be loaded with the war's
diff --git a/geode-web/src/main/java/org/apache/geode/management/internal/web/controllers/ShellCommandsController.java b/geode-web/src/main/java/org/apache/geode/management/internal/web/controllers/ShellCommandsController.java
index 9d8f3e4..51ea876 100644
--- a/geode-web/src/main/java/org/apache/geode/management/internal/web/controllers/ShellCommandsController.java
+++ b/geode-web/src/main/java/org/apache/geode/management/internal/web/controllers/ShellCommandsController.java
@@ -49,6 +49,7 @@
import org.apache.geode.annotations.Immutable;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.internal.GemFireVersion;
+import org.apache.geode.internal.serialization.Version;
import org.apache.geode.internal.util.IOUtils;
import org.apache.geode.management.cli.Result;
import org.apache.geode.management.internal.cli.i18n.CliStrings;
@@ -192,6 +193,11 @@
return GemFireVersion.getGemFireVersion();
}
+ @RequestMapping(method = RequestMethod.GET, value = "/version/geodeSerializationVersion")
+ @ResponseBody
+ public String geodeSerializationVersion() {
+ return Version.CURRENT.getName();
+ }
private ResponseEntity<InputStreamResource> getResponse(String result) {
ResultModel commandResult = ResultModel.fromJson(result);