You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by pr...@apache.org on 2018/04/02 17:02:57 UTC
[geode] branch develop updated: GEODE-4893: Improve reloading the
cluster configuration on existing vanilla servers
This is an automated email from the ASF dual-hosted git repository.
prhomberg pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push:
new 8b8cef1 GEODE-4893: Improve reloading the cluster configuration on existing vanilla servers
8b8cef1 is described below
commit 8b8cef12fa423cbd0e18dd9ddcf7793e8f0090c5
Author: jinmeiliao <ji...@pivotal.io>
AuthorDate: Mon Apr 2 10:02:53 2018 -0700
GEODE-4893: Improve reloading the cluster configuration on existing vanilla servers
---
.../cli/commands/ImportClusterConfigTest.java | 60 ++++++++++++++++++
.../geode/internal/cache/GemFireCacheImpl.java | 13 ++++
.../apache/geode/internal/cache/InternalCache.java | 2 +
.../internal/cache/xmlcache/CacheCreation.java | 5 ++
.../ExportImportClusterConfigurationCommands.java | 72 +++++++++++++---------
.../functions/RecreateCacheFunction.java | 20 +++---
.../ClusterConfigDeployJarDUnitTest.java | 4 ++
.../ClusterConfigImportDUnitTest.java | 34 +++++++++-
.../ClusterConfigStartMemberDUnitTest.java | 5 ++
.../configuration/ClusterConfigTestBase.java | 4 --
10 files changed, 173 insertions(+), 46 deletions(-)
diff --git a/geode-assembly/src/test/java/org/apache/geode/management/internal/cli/commands/ImportClusterConfigTest.java b/geode-assembly/src/test/java/org/apache/geode/management/internal/cli/commands/ImportClusterConfigTest.java
new file mode 100644
index 0000000..2b6a38b
--- /dev/null
+++ b/geode-assembly/src/test/java/org/apache/geode/management/internal/cli/commands/ImportClusterConfigTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.geode.management.internal.cli.commands;
+
+import static org.assertj.core.api.Java6Assertions.assertThat;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.management.internal.configuration.ClusterConfigTestBase;
+import org.apache.geode.test.junit.categories.AcceptanceTest;
+import org.apache.geode.test.junit.rules.gfsh.GfshExecution;
+import org.apache.geode.test.junit.rules.gfsh.GfshRule;
+import org.apache.geode.test.junit.rules.gfsh.GfshScript;
+
+@Category(AcceptanceTest.class)
+public class ImportClusterConfigTest extends ClusterConfigTestBase {
+ private static final String locatorName = "locator";
+ private static final String serverNotShutDownName = "serverNotShutDown";
+
+ @Rule
+ public GfshRule gfsh = new GfshRule();
+
+ @Test
+ public void importWouldNotShutDownServer() {
+ GfshExecution startCluster = GfshScript
+ .of("start locator --name=" + locatorName, "start server --name=" + serverNotShutDownName)
+ .withName("startCluster").execute(gfsh);
+ assertThat(startCluster.getOutputText()).contains(locatorName + " is currently online")
+ .contains(serverNotShutDownName + " is currently online");
+
+ GfshExecution importConfiguration = GfshScript
+ .of("connect", "import cluster-configuration --zip-file-name=" + clusterConfigZipPath)
+ .withName("importConfiguration").execute(gfsh);
+ assertThat(importConfiguration.getOutputText())
+ .contains("Cluster configuration successfully imported").contains(
+ "Successfully applied the imported cluster configuration on " + serverNotShutDownName);
+
+ GfshExecution listMembers =
+ GfshScript.of("connect", "list members").withName("listMembers").execute(gfsh);
+ assertThat(listMembers.getOutputText()).contains("serverNotShutDown");
+ }
+
+}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/GemFireCacheImpl.java b/geode-core/src/main/java/org/apache/geode/internal/cache/GemFireCacheImpl.java
index f6b35c1..3b69fa2 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/GemFireCacheImpl.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/GemFireCacheImpl.java
@@ -978,6 +978,19 @@ public class GemFireCacheImpl implements InternalCache, InternalClientCache, Has
} // synchronized
}
+ @Override
+ public void reLoadClusterConfiguration() throws IOException, ClassNotFoundException {
+ this.configurationResponse = requestSharedConfiguration();
+ if (this.configurationResponse != null) {
+ ccLoader.deployJarsReceivedFromClusterConfiguration(this.configurationResponse);
+ ccLoader.applyClusterPropertiesConfiguration(this.configurationResponse,
+ this.system.getConfig());
+ ccLoader.applyClusterXmlConfiguration(this, this.configurationResponse,
+ this.system.getConfig().getGroups());
+ initializeDeclarativeCache();
+ }
+ }
+
/**
* Initialize the EventTracker's timer task. This is stored for tracking and shutdown purposes
*/
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/InternalCache.java b/geode-core/src/main/java/org/apache/geode/internal/cache/InternalCache.java
index d9f989f..dc05a3a 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/InternalCache.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/InternalCache.java
@@ -331,6 +331,8 @@ public interface InternalCache extends Cache, Extensible<Cache>, CacheTime {
void waitForRegisterInterestsInProgress();
+ void reLoadClusterConfiguration() throws IOException, ClassNotFoundException;
+
SecurityService getSecurityService();
boolean hasPersistentRegion();
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/xmlcache/CacheCreation.java b/geode-core/src/main/java/org/apache/geode/internal/cache/xmlcache/CacheCreation.java
index ffc452e..3898a55 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/xmlcache/CacheCreation.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/xmlcache/CacheCreation.java
@@ -1129,6 +1129,11 @@ public class CacheCreation implements InternalCache {
}
@Override
+ public void reLoadClusterConfiguration() throws IOException, ClassNotFoundException {
+ throw new UnsupportedOperationException(LocalizedStrings.SHOULDNT_INVOKE.toLocalizedString());
+ }
+
+ @Override
public SecurityService getSecurityService() {
return SecurityServiceFactory.create();
}
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportClusterConfigurationCommands.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportClusterConfigurationCommands.java
index 61118ba..c3a8eb5 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportClusterConfigurationCommands.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportClusterConfigurationCommands.java
@@ -35,7 +35,9 @@ import org.springframework.shell.core.annotation.CliCommand;
import org.springframework.shell.core.annotation.CliOption;
import org.xml.sax.SAXException;
+import org.apache.geode.cache.configuration.CacheConfig;
import org.apache.geode.cache.execute.ResultCollector;
+import org.apache.geode.distributed.ClusterConfigurationService;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.internal.InternalClusterConfigurationService;
import org.apache.geode.distributed.internal.InternalLocator;
@@ -133,23 +135,40 @@ public class ExportImportClusterConfigurationCommands extends InternalGfshComman
help = CliStrings.IMPORT_SHARED_CONFIG__ZIP__HELP) String zip)
throws IOException, TransformerException, SAXException, ParserConfigurationException {
- InternalLocator locator = InternalLocator.getLocator();
+ InternalClusterConfigurationService sc =
+ (InternalClusterConfigurationService) getConfigurationService();
- if (!locator.isSharedConfigurationRunning()) {
- ErrorResultData errorData = ResultBuilder.createErrorResultData();
- errorData.addLine(CliStrings.SHARED_CONFIGURATION_NOT_STARTED);
- return ResultBuilder.buildResult(errorData);
+ if (sc == null) {
+ return ResultBuilder.createGemFireErrorResult(CliStrings.SHARED_CONFIGURATION_NOT_STARTED);
}
Set<DistributedMember> servers = getAllNormalMembers();
- Set<String> regionsWithData = servers.stream().map(this::getRegionNamesOnServer)
- .flatMap(Collection::stream).collect(toSet());
+ // check if running servers are vanilla servers
+ if (servers.size() > 0) {
+ Set<String> groupNames = sc.getConfigurationRegion().keySet();
+ for (String groupName : groupNames) {
+ CacheConfig cacheConfig = sc.getCacheConfig(groupName);
+ if (cacheConfig.getRegion().size() > 0 || cacheConfig.getAsyncEventQueue().size() > 0
+ || cacheConfig.getDiskStore().size() > 0
+ || cacheConfig.getCustomCacheElements().size() > 0
+ || cacheConfig.getJndiBindings().size() > 0 || cacheConfig.getGatewayReceiver() != null
+ || cacheConfig.getGatewaySender().size() > 0) {
+ return ResultBuilder.createGemFireErrorResult(
+ "Running servers have existing cluster configuration applied already.");
+ }
+ }
- if (!regionsWithData.isEmpty()) {
- return ResultBuilder
- .createGemFireErrorResult("Cannot import cluster configuration with existing regions: "
- + regionsWithData.stream().collect(joining(",")));
+ // further checks in case any servers has regions not defined by the cluster configuration to
+ // avoid data loss.
+ Set<String> serverRegionNames = servers.stream().map(this::getRegionNamesOnServer)
+ .flatMap(Collection::stream).collect(toSet());
+
+ if (!serverRegionNames.isEmpty()) {
+ return ResultBuilder
+ .createGemFireErrorResult("Cannot import cluster configuration with existing regions: "
+ + serverRegionNames.stream().collect(joining(",")));
+ }
}
List<String> filePathFromShell = CommandExecutionContext.getFilePathFromShell();
@@ -158,8 +177,6 @@ public class ExportImportClusterConfigurationCommands extends InternalGfshComman
InfoResultData infoData = ResultBuilder.createInfoResultData();
String zipFilePath = filePathFromShell.get(0);
- InternalClusterConfigurationService sc = locator.getSharedConfiguration();
-
// backup the old config
for (Configuration config : sc.getConfigurationRegion().values()) {
sc.writeConfigToFile(config);
@@ -173,16 +190,18 @@ public class ExportImportClusterConfigurationCommands extends InternalGfshComman
infoData.addLine(CliStrings.IMPORT_SHARED_CONFIG__SUCCESS__MSG);
// Bounce the cache of each member
- Set<CliFunctionResult> functionResults =
- servers.stream().map(this::reCreateCache).collect(toSet());
-
- for (CliFunctionResult functionResult : functionResults) {
- if (functionResult.isSuccessful()) {
- infoData.addLine("Successfully applied the imported cluster configuration on "
- + functionResult.getMemberIdOrName());
- } else {
- infoData.addLine("Failed to apply the imported cluster configuration on "
- + functionResult.getMemberIdOrName() + " due to " + functionResult.getMessage());
+ if (servers.size() > 0) {
+ List<CliFunctionResult> functionResults =
+ executeAndGetFunctionResult(new RecreateCacheFunction(), null, servers);
+
+ for (CliFunctionResult functionResult : functionResults) {
+ if (functionResult.isSuccessful()) {
+ infoData.addLine("Successfully applied the imported cluster configuration on "
+ + functionResult.getMemberIdOrName());
+ } else {
+ infoData.addLine("Failed to apply the imported cluster configuration on "
+ + functionResult.getMemberIdOrName() + " due to " + functionResult.getMessage());
+ }
}
}
@@ -197,13 +216,6 @@ public class ExportImportClusterConfigurationCommands extends InternalGfshComman
return results.get(0);
}
- private CliFunctionResult reCreateCache(DistributedMember server) {
- ResultCollector rc = executeFunction(new RecreateCacheFunction(), null, server);
- List<CliFunctionResult> results = (List<CliFunctionResult>) rc.getResult();
-
- return results.get(0);
- }
-
/**
* Interceptor used by gfsh to intercept execution of export shared config command at "shell".
*/
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/functions/RecreateCacheFunction.java b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/functions/RecreateCacheFunction.java
index 1c0b40b..0b7892a 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/functions/RecreateCacheFunction.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/functions/RecreateCacheFunction.java
@@ -14,30 +14,30 @@
*/
package org.apache.geode.management.internal.configuration.functions;
+import org.apache.logging.log4j.Logger;
+
import org.apache.geode.cache.execute.FunctionContext;
-import org.apache.geode.distributed.internal.InternalDistributedSystem;
-import org.apache.geode.internal.cache.CacheConfig;
-import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.cache.execute.InternalFunction;
+import org.apache.geode.internal.logging.LogService;
import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
public class RecreateCacheFunction implements InternalFunction {
+ private static Logger logger = LogService.getLogger();
+
@Override
public void execute(FunctionContext context) {
CliFunctionResult result = null;
InternalCache cache = (InternalCache) context.getCache();
- InternalDistributedSystem ds = cache.getInternalDistributedSystem();
- CacheConfig cacheConfig = cache.getCacheConfig();
try {
- cache.close("Re-create Cache", true, true);
- GemFireCacheImpl.create(ds, cacheConfig);
- } catch (RuntimeException e) {
- result = new CliFunctionResult(ds.getName(), e, e.getMessage());
+ cache.reLoadClusterConfiguration();
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ result = new CliFunctionResult(context.getMemberName(), false, e.getMessage());
context.getResultSender().lastResult(result);
return;
}
- result = new CliFunctionResult(ds.getName(), true, "Cache successfully re-created.");
+ result = new CliFunctionResult(context.getMemberName(), true, "Cache successfully reloaded.");
context.getResultSender().lastResult(result);
}
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigDeployJarDUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigDeployJarDUnitTest.java
index 5a1058f..8da9410 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigDeployJarDUnitTest.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigDeployJarDUnitTest.java
@@ -23,6 +23,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
import org.apache.geode.test.dunit.rules.MemberVM;
import org.apache.geode.test.junit.categories.DistributedTest;
import org.apache.geode.test.junit.rules.GfshCommandRule;
@@ -35,6 +36,9 @@ public class ClusterConfigDeployJarDUnitTest extends ClusterConfigTestBase {
private String group2Jar;
@Rule
+ public ClusterStartupRule lsRule = new ClusterStartupRule();
+
+ @Rule
public GfshCommandRule gfshConnector = new GfshCommandRule();
@Before
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigImportDUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigImportDUnitTest.java
index 31fcdf4..5487e49 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigImportDUnitTest.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigImportDUnitTest.java
@@ -50,6 +50,9 @@ public class ClusterConfigImportDUnitTest extends ClusterConfigTestBase {
private MemberVM locatorVM;
@Rule
+ public ClusterStartupRule lsRule = new ClusterStartupRule();
+
+ @Rule
public GfshCommandRule gfshConnector = new GfshCommandRule();
@Before
@@ -87,8 +90,6 @@ public class ClusterConfigImportDUnitTest extends ClusterConfigTestBase {
serverProps.setProperty("groups", "group2");
MemberVM server2 = lsRule.startServerVM(2, serverProps, locatorVM.getPort());
- // even though we have a region recreated, we can still import since there is no data
- // in the region
CommandResult result = gfshConnector
.executeCommand("import cluster-configuration --zip-file-name=" + clusterConfigZipPath);
assertThat(result.getContent().toString())
@@ -97,6 +98,35 @@ public class ClusterConfigImportDUnitTest extends ClusterConfigTestBase {
.contains("Successfully applied the imported cluster configuration on server-2");
new ClusterConfig(CLUSTER).verify(server1);
new ClusterConfig(CLUSTER, GROUP2).verify(server2);
+
+ gfshConnector.executeAndAssertThat("list members").statusIsSuccess()
+ .tableHasColumnWithExactValuesInAnyOrder("Name", "locator-0", "server-1", "server-2");
+ }
+
+ @Test
+ public void importFailWithExistingDiskStore() {
+ lsRule.startServerVM(1, locatorVM.getPort());
+ gfshConnector.executeAndAssertThat("create disk-store --name=diskStore1 --dir=testStore")
+ .statusIsSuccess();
+ locatorVM.waitTillDiskstoreIsReady("diskStore1", 1);
+ gfshConnector
+ .executeAndAssertThat(
+ "import cluster-configuration --zip-file-name=" + clusterConfigZipPath)
+ .statusIsError()
+ .containsOutput("Running servers have existing cluster configuration applied already.");
+ }
+
+ @Test
+ public void importFailWithExistingRegion() {
+ lsRule.startServerVM(1, "group1", locatorVM.getPort());
+ gfshConnector
+ .executeAndAssertThat("create region --name=regionA --type=REPLICATE --group=group1")
+ .statusIsSuccess();
+ gfshConnector
+ .executeAndAssertThat(
+ "import cluster-configuration --zip-file-name=" + clusterConfigZipPath)
+ .statusIsError()
+ .containsOutput("Running servers have existing cluster configuration applied already.");
}
@Test
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigStartMemberDUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigStartMemberDUnitTest.java
index bd8ba50..1fcafc6 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigStartMemberDUnitTest.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigStartMemberDUnitTest.java
@@ -24,10 +24,12 @@ import java.io.File;
import java.util.Properties;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.apache.geode.management.internal.configuration.utils.ZipUtils;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
import org.apache.geode.test.dunit.rules.MemberVM;
import org.apache.geode.test.junit.categories.DistributedTest;
@@ -36,6 +38,9 @@ public class ClusterConfigStartMemberDUnitTest extends ClusterConfigTestBase {
private MemberVM locator;
+ @Rule
+ public ClusterStartupRule lsRule = new ClusterStartupRule();
+
@Before
public void before() throws Exception {
locator = startLocatorWithLoadCCFromDir();
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigTestBase.java b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigTestBase.java
index ecc4d63..5831977 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigTestBase.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfigTestBase.java
@@ -29,7 +29,6 @@ import org.junit.Rule;
import org.apache.geode.management.internal.configuration.utils.ZipUtils;
import org.apache.geode.test.compiler.ClassBuilder;
-import org.apache.geode.test.dunit.rules.ClusterStartupRule;
import org.apache.geode.test.junit.rules.serializable.SerializableTemporaryFolder;
public abstract class ClusterConfigTestBase {
@@ -55,9 +54,6 @@ public abstract class ClusterConfigTestBase {
@Rule
public SerializableTemporaryFolder temporaryFolder = new SerializableTemporaryFolder();
- @Rule
- public ClusterStartupRule lsRule = new ClusterStartupRule();
-
protected Properties locatorProps;
protected Properties serverProps;
--
To stop receiving notification emails like this one, please contact
prhomberg@apache.org.