Skip to content

Commit

Permalink
Snapshot/Restore: add validation of restored persistent settings
Browse files Browse the repository at this point in the history
  • Loading branch information
imotov committed Jan 18, 2015
1 parent e69b5c3 commit a4c92eb
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 15 deletions.
Expand Up @@ -186,7 +186,7 @@ public ClusterState execute(final ClusterState currentState) {
ImmutableSettings.Builder transientSettings = ImmutableSettings.settingsBuilder();
transientSettings.put(currentState.metaData().transientSettings());
for (Map.Entry<String, String> entry : request.transientSettings().getAsMap().entrySet()) {
if (dynamicSettings.hasDynamicSetting(entry.getKey()) || entry.getKey().startsWith("logger.")) {
if (dynamicSettings.isDynamicOrLoggingSetting(entry.getKey())) {
String error = dynamicSettings.validateDynamicSetting(entry.getKey(), entry.getValue());
if (error == null) {
transientSettings.put(entry.getKey(), entry.getValue());
Expand All @@ -203,7 +203,7 @@ public ClusterState execute(final ClusterState currentState) {
ImmutableSettings.Builder persistentSettings = ImmutableSettings.settingsBuilder();
persistentSettings.put(currentState.metaData().persistentSettings());
for (Map.Entry<String, String> entry : request.persistentSettings().getAsMap().entrySet()) {
if (dynamicSettings.hasDynamicSetting(entry.getKey()) || entry.getKey().startsWith("logger.")) {
if (dynamicSettings.isDynamicOrLoggingSetting(entry.getKey())) {
String error = dynamicSettings.validateDynamicSetting(entry.getKey(), entry.getValue());
if (error == null) {
persistentSettings.put(entry.getKey(), entry.getValue());
Expand Down
Expand Up @@ -31,6 +31,11 @@ public class DynamicSettings {

private ImmutableMap<String, Validator> dynamicSettings = ImmutableMap.of();


public boolean isDynamicOrLoggingSetting(String key) {
return hasDynamicSetting(key) || key.startsWith("logger.");
}

public boolean hasDynamicSetting(String key) {
for (String dynamicSetting : dynamicSettings.keySet()) {
if (Regex.simpleMatch(dynamicSetting, key)) {
Expand Down
28 changes: 26 additions & 2 deletions src/main/java/org/elasticsearch/snapshots/RestoreService.java
Expand Up @@ -34,11 +34,14 @@
import org.elasticsearch.cluster.routing.*;
import org.elasticsearch.cluster.routing.allocation.AllocationService;
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
import org.elasticsearch.cluster.settings.ClusterDynamicSettings;
import org.elasticsearch.cluster.settings.DynamicSettings;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.shard.ShardId;
Expand Down Expand Up @@ -92,16 +95,20 @@ public class RestoreService extends AbstractComponent implements ClusterStateLis

private final MetaDataCreateIndexService createIndexService;

private final DynamicSettings dynamicSettings;

private final CopyOnWriteArrayList<ActionListener<RestoreCompletionResponse>> listeners = new CopyOnWriteArrayList<>();

@Inject
public RestoreService(Settings settings, ClusterService clusterService, RepositoriesService repositoriesService, TransportService transportService, AllocationService allocationService, MetaDataCreateIndexService createIndexService) {
public RestoreService(Settings settings, ClusterService clusterService, RepositoriesService repositoriesService, TransportService transportService,
AllocationService allocationService, MetaDataCreateIndexService createIndexService, @ClusterDynamicSettings DynamicSettings dynamicSettings) {
super(settings);
this.clusterService = clusterService;
this.repositoriesService = repositoriesService;
this.transportService = transportService;
this.allocationService = allocationService;
this.createIndexService = createIndexService;
this.dynamicSettings = dynamicSettings;
transportService.registerHandler(UPDATE_RESTORE_ACTION_NAME, new UpdateRestoreStateRequestHandler());
clusterService.add(this);
}
Expand Down Expand Up @@ -283,7 +290,24 @@ private void validateExistingIndex(IndexMetaData currentIndexMetaData, IndexMeta
private void restoreGlobalStateIfRequested(MetaData.Builder mdBuilder) {
if (request.includeGlobalState()) {
if (metaData.persistentSettings() != null) {
mdBuilder.persistentSettings(metaData.persistentSettings());
boolean changed = false;
ImmutableSettings.Builder persistentSettings = ImmutableSettings.settingsBuilder().put();
for (Map.Entry<String, String> entry : metaData.persistentSettings().getAsMap().entrySet()) {
if (dynamicSettings.isDynamicOrLoggingSetting(entry.getKey())) {
String error = dynamicSettings.validateDynamicSetting(entry.getKey(), entry.getValue());
if (error == null) {
persistentSettings.put(entry.getKey(), entry.getValue());
changed = true;
} else {
logger.warn("ignoring persistent setting [{}], [{}]", entry.getKey(), error);
}
} else {
logger.warn("ignoring persistent setting [{}], not dynamically updateable", entry.getKey());
}
}
if (changed) {
mdBuilder.persistentSettings(persistentSettings.build());
}
}
if (metaData.templates() != null) {
// TODO: Should all existing templates be deleted first?
Expand Down
Expand Up @@ -51,11 +51,12 @@
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.discovery.zen.elect.ElectMasterService;
import org.elasticsearch.index.store.support.AbstractIndexStore;
import org.elasticsearch.indices.ttl.IndicesTTLService;
import org.elasticsearch.repositories.RepositoryMissingException;
import org.elasticsearch.snapshots.mockstore.MockRepositoryModule;
import org.elasticsearch.test.InternalTestCluster;
import org.elasticsearch.threadpool.ThreadPool;
import org.junit.Ignore;
import org.junit.Test;

Expand All @@ -66,6 +67,7 @@
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static com.google.common.collect.Lists.newArrayList;
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
Expand All @@ -82,16 +84,29 @@ public class DedicatedClusterSnapshotRestoreTests extends AbstractSnapshotTests

@Test
public void restorePersistentSettingsTest() throws Exception {
logger.info("--> start node");
internalCluster().startNode(settingsBuilder().put("gateway.type", "local"));
logger.info("--> start 2 nodes");
Settings nodeSettings = settingsBuilder()
.put("discovery.type", "zen")
.put("discovery.zen.ping_timeout", "200ms")
.put("discovery.initial_state_timeout", "500ms")
.build();
internalCluster().startNode(nodeSettings);
Client client = client();
String secondNode = internalCluster().startNode(nodeSettings);

int random = randomIntBetween(10, 42);

// Add dummy persistent setting
logger.info("--> set test persistent setting");
String settingValue = "test-" + randomInt();
client.admin().cluster().prepareUpdateSettings().setPersistentSettings(ImmutableSettings.settingsBuilder().put(ThreadPool.THREADPOOL_GROUP + "dummy.value", settingValue)).execute().actionGet();
client.admin().cluster().prepareUpdateSettings().setPersistentSettings(
ImmutableSettings.settingsBuilder()
.put(ElectMasterService.DISCOVERY_ZEN_MINIMUM_MASTER_NODES, 2)
.put(IndicesTTLService.INDICES_TTL_INTERVAL, random, TimeUnit.MINUTES))
.execute().actionGet();

assertThat(client.admin().cluster().prepareState().setRoutingTable(false).setNodes(false).execute().actionGet().getState()
.getMetaData().persistentSettings().get(ThreadPool.THREADPOOL_GROUP + "dummy.value"), equalTo(settingValue));
.getMetaData().persistentSettings().getAsTime(IndicesTTLService.INDICES_TTL_INTERVAL, TimeValue.timeValueMinutes(1)).millis(), equalTo(TimeValue.timeValueMinutes(random).millis()));
assertThat(client.admin().cluster().prepareState().setRoutingTable(false).setNodes(false).execute().actionGet().getState()
.getMetaData().persistentSettings().getAsInt(ElectMasterService.DISCOVERY_ZEN_MINIMUM_MASTER_NODES, -1), equalTo(2));

logger.info("--> create repository");
PutRepositoryResponse putRepositoryResponse = client.admin().cluster().preparePutRepository("test-repo")
Expand All @@ -105,14 +120,25 @@ public void restorePersistentSettingsTest() throws Exception {
assertThat(client.admin().cluster().prepareGetSnapshots("test-repo").setSnapshots("test-snap").execute().actionGet().getSnapshots().get(0).state(), equalTo(SnapshotState.SUCCESS));

logger.info("--> clean the test persistent setting");
client.admin().cluster().prepareUpdateSettings().setPersistentSettings(ImmutableSettings.settingsBuilder().put(ThreadPool.THREADPOOL_GROUP + "dummy.value", "")).execute().actionGet();
client.admin().cluster().prepareUpdateSettings().setPersistentSettings(
ImmutableSettings.settingsBuilder()
.put(ElectMasterService.DISCOVERY_ZEN_MINIMUM_MASTER_NODES, 1)
.put(IndicesTTLService.INDICES_TTL_INTERVAL, TimeValue.timeValueMinutes(1)))
.execute().actionGet();
assertThat(client.admin().cluster().prepareState().setRoutingTable(false).setNodes(false).execute().actionGet().getState()
.getMetaData().persistentSettings().get(ThreadPool.THREADPOOL_GROUP + "dummy.value"), equalTo(""));
.getMetaData().persistentSettings().getAsTime(IndicesTTLService.INDICES_TTL_INTERVAL, TimeValue.timeValueMinutes(1)).millis(), equalTo(TimeValue.timeValueMinutes(1).millis()));

stopNode(secondNode);
assertThat(client.admin().cluster().prepareHealth().setWaitForNodes("1").get().isTimedOut(), equalTo(false));

logger.info("--> restore snapshot");
client.admin().cluster().prepareRestoreSnapshot("test-repo", "test-snap").setRestoreGlobalState(true).setWaitForCompletion(true).execute().actionGet();
assertThat(client.admin().cluster().prepareState().setRoutingTable(false).setNodes(false).execute().actionGet().getState()
.getMetaData().persistentSettings().get(ThreadPool.THREADPOOL_GROUP + "dummy.value"), equalTo(settingValue));
.getMetaData().persistentSettings().getAsTime(IndicesTTLService.INDICES_TTL_INTERVAL, TimeValue.timeValueMinutes(1)).millis(), equalTo(TimeValue.timeValueMinutes(random).millis()));

logger.info("--> ensure that zen discovery minimum master nodes wasn't restored");
assertThat(client.admin().cluster().prepareState().setRoutingTable(false).setNodes(false).execute().actionGet().getState()
.getMetaData().persistentSettings().getAsInt(ElectMasterService.DISCOVERY_ZEN_MINIMUM_MASTER_NODES, -1), not(equalTo(2)));
}

@Test
Expand Down Expand Up @@ -545,7 +571,7 @@ public boolean clearData(String nodeName) {
}
}
logger.info("--> check that at least half of the shards had some reuse: [{}]", reusedShards);
assertThat(reusedShards.size(), greaterThanOrEqualTo(numberOfShards/2));
assertThat(reusedShards.size(), greaterThanOrEqualTo(numberOfShards / 2));
}

@Test
Expand Down

0 comments on commit a4c92eb

Please sign in to comment.