diff --git a/build.gradle b/build.gradle index 46f113f010658..b53069d650709 100644 --- a/build.gradle +++ b/build.gradle @@ -189,8 +189,9 @@ tasks.register("verifyVersions") { * after the backport of the backcompat code is complete. */ -boolean bwc_tests_enabled = true -String bwc_tests_disabled_issue = "" /* place a PR link here when committing bwc changes */ +boolean bwc_tests_enabled = false +// place a PR link here when committing bwc changes: +String bwc_tests_disabled_issue = "https://github.com/elastic/elasticsearch/pull/70141" /* * FIPS 140-2 behavior was fixed in 7.11.0. Before that there is no way to run elasticsearch in a * JVM that is properly configured to be in fips mode with BCFIPS. For now we need to disable diff --git a/x-pack/plugin/core/src/internalClusterTest/java/org/elasticsearch/xpack/cluster/routing/allocation/DataTierIT.java b/x-pack/plugin/core/src/internalClusterTest/java/org/elasticsearch/xpack/cluster/routing/allocation/DataTierIT.java index cde70ec83143a..5d2cd38b5b2ac 100644 --- a/x-pack/plugin/core/src/internalClusterTest/java/org/elasticsearch/xpack/cluster/routing/allocation/DataTierIT.java +++ b/x-pack/plugin/core/src/internalClusterTest/java/org/elasticsearch/xpack/cluster/routing/allocation/DataTierIT.java @@ -7,6 +7,7 @@ package org.elasticsearch.xpack.cluster.routing.allocation; +import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest; import org.elasticsearch.action.admin.indices.shrink.ResizeType; import org.elasticsearch.action.admin.indices.template.put.PutComposableIndexTemplateAction; import org.elasticsearch.cluster.health.ClusterHealthStatus; @@ -271,6 +272,35 @@ public void testTierFilteringIgnoredByFilterAllocationDecider() { .get(); } + public void testIllegalOnFrozen() { + startDataNode(); + + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, + () -> createIndex(index, Settings.builder() + .put("index.number_of_shards", 1) + .put("index.number_of_replicas", 0) + .put(DataTierAllocationDecider.INDEX_ROUTING_PREFER, DataTier.DATA_FROZEN) + .build())); + assertThat(e.getMessage(), equalTo("[data_frozen] tier can only be used for partial searchable snapshots")); + + String initialTier = randomFrom(DataTier.DATA_HOT, DataTier.DATA_WARM, DataTier.DATA_COLD); + createIndex(index, Settings.builder() + .put("index.number_of_shards", 1) + .put("index.number_of_replicas", 0) + .put(DataTierAllocationDecider.INDEX_ROUTING_PREFER, initialTier) + .build()); + + IllegalArgumentException e2 = expectThrows(IllegalArgumentException.class, () -> updatePreference(DataTier.DATA_FROZEN)); + assertThat(e2.getMessage(), equalTo("[data_frozen] tier can only be used for partial searchable snapshots")); + + updatePreference(randomValueOtherThan(initialTier, () -> randomFrom(DataTier.DATA_HOT, DataTier.DATA_WARM, DataTier.DATA_COLD))); + } + + private void updatePreference(String tier) { + client().admin().indices().updateSettings(new UpdateSettingsRequest(index) + .settings(org.elasticsearch.common.collect.Map.of(DataTierAllocationDecider.INDEX_ROUTING_PREFER, tier))).actionGet(); + } + private DataTiersFeatureSetUsage getUsage() { XPackUsageResponse usages = new XPackUsageRequestBuilder(client()).execute().actionGet(); XPackFeatureSet.Usage dtUsage = usages.getUsages().stream() diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/cluster/routing/allocation/DataTierAllocationDecider.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/cluster/routing/allocation/DataTierAllocationDecider.java index 845b17851725f..7c29cb348dc46 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/cluster/routing/allocation/DataTierAllocationDecider.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/cluster/routing/allocation/DataTierAllocationDecider.java @@ -21,13 +21,20 @@ import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.index.IndexModule; import org.elasticsearch.xpack.core.DataTier; +import org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshotsConstants; import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import static org.elasticsearch.xpack.core.DataTier.DATA_FROZEN; + /** * The {@code DataTierAllocationDecider} is a custom allocation decider that behaves similar to the * {@link org.elasticsearch.cluster.routing.allocation.decider.FilterAllocationDecider}, however it @@ -45,6 +52,7 @@ public class DataTierAllocationDecider extends AllocationDecider { public static final String INDEX_ROUTING_PREFER = "index.routing.allocation.include._tier_preference"; public static final String INDEX_ROUTING_EXCLUDE = "index.routing.allocation.exclude._tier"; + private static final DataTierValidator VALIDATOR = new DataTierValidator(); public static final Setting CLUSTER_ROUTING_REQUIRE_SETTING = Setting.simpleString(CLUSTER_ROUTING_REQUIRE, DataTierAllocationDecider::validateTierSetting, Setting.Property.Dynamic, Setting.Property.NodeScope); public static final Setting CLUSTER_ROUTING_INCLUDE_SETTING = Setting.simpleString(CLUSTER_ROUTING_INCLUDE, @@ -52,13 +60,13 @@ public class DataTierAllocationDecider extends AllocationDecider { public static final Setting CLUSTER_ROUTING_EXCLUDE_SETTING = Setting.simpleString(CLUSTER_ROUTING_EXCLUDE, DataTierAllocationDecider::validateTierSetting, Setting.Property.Dynamic, Setting.Property.NodeScope); public static final Setting INDEX_ROUTING_REQUIRE_SETTING = Setting.simpleString(INDEX_ROUTING_REQUIRE, - DataTierAllocationDecider::validateTierSetting, Setting.Property.Dynamic, Setting.Property.IndexScope); + VALIDATOR, Setting.Property.Dynamic, Setting.Property.IndexScope); public static final Setting INDEX_ROUTING_INCLUDE_SETTING = Setting.simpleString(INDEX_ROUTING_INCLUDE, - DataTierAllocationDecider::validateTierSetting, Setting.Property.Dynamic, Setting.Property.IndexScope); + VALIDATOR, Setting.Property.Dynamic, Setting.Property.IndexScope); public static final Setting INDEX_ROUTING_EXCLUDE_SETTING = Setting.simpleString(INDEX_ROUTING_EXCLUDE, - DataTierAllocationDecider::validateTierSetting, Setting.Property.Dynamic, Setting.Property.IndexScope); + VALIDATOR, Setting.Property.Dynamic, Setting.Property.IndexScope); public static final Setting INDEX_ROUTING_PREFER_SETTING = Setting.simpleString(INDEX_ROUTING_PREFER, - DataTierAllocationDecider::validateTierSetting, Setting.Property.Dynamic, Setting.Property.IndexScope); + VALIDATOR, Setting.Property.Dynamic, Setting.Property.IndexScope); private static void validateTierSetting(String setting) { if (Strings.hasText(setting)) { @@ -71,6 +79,32 @@ private static void validateTierSetting(String setting) { } } + private static class DataTierValidator implements Setting.Validator { + private static final Collection> dependencies = + org.elasticsearch.common.collect.List.of(IndexModule.INDEX_STORE_TYPE_SETTING, + SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING); + + @Override + public void validate(String value) { + validateTierSetting(value); + } + + @Override + public void validate(String value, Map, Object> settings) { + if (Strings.hasText(value) && SearchableSnapshotsConstants.isPartialSearchableSnapshotIndex(settings) == false) { + String[] split = value.split(","); + if (Arrays.stream(split).anyMatch(DATA_FROZEN::equals)) { + throw new IllegalArgumentException("[" + DATA_FROZEN + "] tier can only be used for partial searchable snapshots"); + } + } + } + + @Override + public Iterator> settings() { + return dependencies.iterator(); + } + } + private volatile String clusterRequire; private volatile String clusterInclude; private volatile String clusterExclude; diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotsConstants.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotsConstants.java index c1b8d0e9b90af..5ad93d8955360 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotsConstants.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotsConstants.java @@ -7,19 +7,41 @@ package org.elasticsearch.xpack.searchablesnapshots; import org.elasticsearch.Version; +import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; +import java.util.Map; + import static org.elasticsearch.index.IndexModule.INDEX_STORE_TYPE_SETTING; public class SearchableSnapshotsConstants { public static final String SNAPSHOT_DIRECTORY_FACTORY_KEY = "snapshot"; public static final String SNAPSHOT_RECOVERY_STATE_FACTORY_KEY = "snapshot_prewarm"; + public static final Setting SNAPSHOT_PARTIAL_SETTING = Setting.boolSetting( + "index.store.snapshot.partial", + false, + Setting.Property.IndexScope, + Setting.Property.PrivateIndex, + Setting.Property.NotCopyableOnResize + ); public static boolean isSearchableSnapshotStore(Settings indexSettings) { return SNAPSHOT_DIRECTORY_FACTORY_KEY.equals(INDEX_STORE_TYPE_SETTING.get(indexSettings)); } + /** + * Based on a map from setting to value, do the settings represent a partial searchable snapshot index? + * + * Both index.store.type and index.store.snapshot.partial must be supplied. + */ + public static boolean isPartialSearchableSnapshotIndex(Map, Object> indexSettings) { + assert indexSettings.containsKey(INDEX_STORE_TYPE_SETTING) : "must include store type in map"; + assert indexSettings.get(SNAPSHOT_PARTIAL_SETTING) != null : "partial setting must be non-null in map (has default value)"; + return SNAPSHOT_DIRECTORY_FACTORY_KEY.equals(indexSettings.get(INDEX_STORE_TYPE_SETTING)) + && (boolean) indexSettings.get(SNAPSHOT_PARTIAL_SETTING); + } + public static final String CACHE_FETCH_ASYNC_THREAD_POOL_NAME = "searchable_snapshots_cache_fetch_async"; public static final String CACHE_FETCH_ASYNC_THREAD_POOL_SETTING = "xpack.searchable_snapshots.cache_fetch_async_thread_pool"; diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/cluster/routing/allocation/DataTierAllocationDeciderTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/cluster/routing/allocation/DataTierAllocationDeciderTests.java index 4a15cc59baeff..bc357ca4ef00d 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/cluster/routing/allocation/DataTierAllocationDeciderTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/cluster/routing/allocation/DataTierAllocationDeciderTests.java @@ -7,6 +7,7 @@ package org.elasticsearch.xpack.cluster.routing.allocation; +import joptsimple.internal.Strings; import org.elasticsearch.Version; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ESAllocationTestCase; @@ -27,20 +28,26 @@ import org.elasticsearch.cluster.routing.allocation.decider.Decision; import org.elasticsearch.cluster.routing.allocation.decider.ReplicaAfterPrimaryActiveAllocationDecider; import org.elasticsearch.cluster.routing.allocation.decider.SameShardAllocationDecider; +import org.elasticsearch.common.Randomness; import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.index.IndexModule; import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.snapshots.EmptySnapshotsInfoService; import org.elasticsearch.test.gateway.TestGatewayAllocator; import org.elasticsearch.xpack.core.DataTier; +import org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshotsConstants; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Optional; import java.util.Set; +import static org.elasticsearch.xpack.core.DataTier.DATA_FROZEN; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -702,6 +709,53 @@ public void testExistedClusterFilters() { "tier filters [data_hot,data_warm]")); } + public void testFrozenIllegalForRegularIndices() { + List tierList = new ArrayList<>(randomSubsetOf(DataTier.ALL_DATA_TIERS)); + if (tierList.contains(DATA_FROZEN) == false) { + tierList.add(DATA_FROZEN); + } + Randomness.shuffle(tierList); + + String value = Strings.join(tierList, ","); + Setting setting = randomTierSetting(); + Settings.Builder builder = Settings.builder().put(setting.getKey(), value); + if (randomBoolean()) { + builder.put(IndexModule.INDEX_STORE_TYPE_SETTING.getKey(), SearchableSnapshotsConstants.SNAPSHOT_DIRECTORY_FACTORY_KEY); + } + + Settings settings = builder.build(); + IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> setting.get(settings)); + assertThat(exception.getMessage(), equalTo("[data_frozen] tier can only be used for partial searchable snapshots")); + } + + public void testFrozenLegalForPartialSnapshot() { + List tierList = new ArrayList<>(randomSubsetOf(DataTier.ALL_DATA_TIERS)); + if (tierList.contains(DATA_FROZEN) == false) { + tierList.add(DATA_FROZEN); + } + Randomness.shuffle(tierList); + + String value = Strings.join(tierList, ","); + Setting setting = randomTierSetting(); + Settings.Builder builder = Settings.builder().put(setting.getKey(), value); + builder.put(IndexModule.INDEX_STORE_TYPE_SETTING.getKey(), SearchableSnapshotsConstants.SNAPSHOT_DIRECTORY_FACTORY_KEY); + builder.put(SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING.getKey(), true); + + Settings settings = builder.build(); + + // validate do not throw + assertThat(setting.get(settings), equalTo(value)); + } + + public Setting randomTierSetting() { + //noinspection unchecked + return randomFrom( + DataTierAllocationDecider.INDEX_ROUTING_EXCLUDE_SETTING, + DataTierAllocationDecider.INDEX_ROUTING_INCLUDE_SETTING, + DataTierAllocationDecider.INDEX_ROUTING_REQUIRE_SETTING, + DataTierAllocationDecider.INDEX_ROUTING_PREFER_SETTING); + } + private ClusterState prepareState(ClusterState initialState) { return prepareState(initialState, Settings.EMPTY); } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotsConstantsTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotsConstantsTests.java new file mode 100644 index 0000000000000..56fc2a4f5a04b --- /dev/null +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotsConstantsTests.java @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.searchablesnapshots; + +import org.elasticsearch.index.IndexModule; +import org.elasticsearch.test.ESTestCase; + +import org.elasticsearch.common.collect.Map; + +import static org.hamcrest.Matchers.is; + +public class SearchableSnapshotsConstantsTests extends ESTestCase { + + public void testIsPartialSearchableSnapshotIndex() { + assertThat(SearchableSnapshotsConstants.isPartialSearchableSnapshotIndex( + Map.of(IndexModule.INDEX_STORE_TYPE_SETTING, SearchableSnapshotsConstants.SNAPSHOT_DIRECTORY_FACTORY_KEY, + SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING, false)), + is(false)); + + assertThat(SearchableSnapshotsConstants.isPartialSearchableSnapshotIndex( + Map.of(IndexModule.INDEX_STORE_TYPE_SETTING, "abc", + SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING, randomBoolean())), + is(false)); + + assertThat(SearchableSnapshotsConstants.isPartialSearchableSnapshotIndex( + Map.of(IndexModule.INDEX_STORE_TYPE_SETTING, SearchableSnapshotsConstants.SNAPSHOT_DIRECTORY_FACTORY_KEY, + SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING, true)), + is(true)); + } +} diff --git a/x-pack/plugin/searchable-snapshots/src/internalClusterTest/java/org/elasticsearch/xpack/searchablesnapshots/BaseSearchableSnapshotsIntegTestCase.java b/x-pack/plugin/searchable-snapshots/src/internalClusterTest/java/org/elasticsearch/xpack/searchablesnapshots/BaseSearchableSnapshotsIntegTestCase.java index 3c9dcdddc85b3..93675b2de2f63 100644 --- a/x-pack/plugin/searchable-snapshots/src/internalClusterTest/java/org/elasticsearch/xpack/searchablesnapshots/BaseSearchableSnapshotsIntegTestCase.java +++ b/x-pack/plugin/searchable-snapshots/src/internalClusterTest/java/org/elasticsearch/xpack/searchablesnapshots/BaseSearchableSnapshotsIntegTestCase.java @@ -157,7 +157,7 @@ protected void mountSnapshot( storage ); - final RestoreSnapshotResponse restoreResponse = client().execute(MountSearchableSnapshotAction.INSTANCE, mountRequest).get(); + final RestoreSnapshotResponse restoreResponse = client().execute(MountSearchableSnapshotAction.INSTANCE, mountRequest).actionGet(); assertThat(restoreResponse.getRestoreInfo().successfulShards(), equalTo(getNumShards(restoredIndexName).numPrimaries)); assertThat(restoreResponse.getRestoreInfo().failedShards(), equalTo(0)); } diff --git a/x-pack/plugin/searchable-snapshots/src/internalClusterTest/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotDataTierIntegTests.java b/x-pack/plugin/searchable-snapshots/src/internalClusterTest/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotDataTierIntegTests.java new file mode 100644 index 0000000000000..4566968268906 --- /dev/null +++ b/x-pack/plugin/searchable-snapshots/src/internalClusterTest/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotDataTierIntegTests.java @@ -0,0 +1,84 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.searchablesnapshots; + +import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.test.ESIntegTestCase; +import org.elasticsearch.xpack.cluster.routing.allocation.DataTierAllocationDecider; +import org.elasticsearch.xpack.core.DataTier; +import org.elasticsearch.xpack.core.searchablesnapshots.MountSearchableSnapshotRequest; + +@ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.TEST) +public class SearchableSnapshotDataTierIntegTests extends BaseSearchableSnapshotsIntegTestCase { + + private static final String repoName = "test-repo"; + private static final String indexName = "test-index"; + private static final String snapshotName = "test-snapshot"; + private static final String mountedIndexName = "test-index-mounted"; + private static final Settings frozenSettings = Settings.builder() + .put(DataTierAllocationDecider.INDEX_ROUTING_PREFER, DataTier.DATA_FROZEN) + .build(); + + public void testPartialLegalOnFrozen() throws Exception { + createRepository(repoName, "fs"); + createIndex(indexName); + createFullSnapshot(repoName, snapshotName); + Settings mountSettings = randomFrom(Settings.EMPTY, frozenSettings); + mountSnapshot( + repoName, + snapshotName, + indexName, + mountedIndexName, + mountSettings, + MountSearchableSnapshotRequest.Storage.SHARED_CACHE + ); + + updatePreference(DataTier.DATA_FROZEN); + } + + public void testFullIllegalOnFrozen() throws Exception { + createRepository(repoName, "fs"); + createIndex(indexName); + createFullSnapshot(repoName, snapshotName); + expectThrows( + IllegalArgumentException.class, + () -> mountSnapshot( + repoName, + snapshotName, + indexName, + mountedIndexName, + frozenSettings, + MountSearchableSnapshotRequest.Storage.FULL_COPY + ) + ); + Settings mountSettings = randomFrom( + Settings.EMPTY, + Settings.builder() + .put( + DataTierAllocationDecider.INDEX_ROUTING_PREFER, + randomValueOtherThan(DataTier.DATA_FROZEN, () -> randomFrom(DataTier.ALL_DATA_TIERS)) + ) + .build() + ); + mountSnapshot(repoName, snapshotName, indexName, mountedIndexName, mountSettings, MountSearchableSnapshotRequest.Storage.FULL_COPY); + + expectThrows(IllegalArgumentException.class, () -> updatePreference(DataTier.DATA_FROZEN)); + } + + private void updatePreference(String tier) { + client().admin() + .indices() + .updateSettings( + new UpdateSettingsRequest(mountedIndexName).settings( + org.elasticsearch.common.collect.Map.of(DataTierAllocationDecider.INDEX_ROUTING_PREFER, tier) + ) + ) + .actionGet(); + } +} diff --git a/x-pack/plugin/searchable-snapshots/src/internalClusterTest/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotsIntegTests.java b/x-pack/plugin/searchable-snapshots/src/internalClusterTest/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotsIntegTests.java index 78f0c90fd8cd0..056f7aefffaac 100644 --- a/x-pack/plugin/searchable-snapshots/src/internalClusterTest/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotsIntegTests.java +++ b/x-pack/plugin/searchable-snapshots/src/internalClusterTest/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotsIntegTests.java @@ -223,7 +223,12 @@ public void testCreateAndRestoreSearchableSnapshot() throws Exception { } final String expectedDataTiersPreference; if (randomBoolean()) { - expectedDataTiersPreference = String.join(",", randomSubsetOf(DataTier.ALL_DATA_TIERS)); + expectedDataTiersPreference = String.join( + ",", + randomSubsetOf( + DataTier.ALL_DATA_TIERS.stream().filter(tier -> tier.equals(DataTier.DATA_FROZEN) == false).collect(Collectors.toSet()) + ) + ); indexSettingsBuilder.put(DataTierAllocationDecider.INDEX_ROUTING_PREFER, expectedDataTiersPreference); } else { expectedDataTiersPreference = getDataTiersPreference(MountSearchableSnapshotRequest.Storage.FULL_COPY); @@ -557,7 +562,7 @@ public void testCreateAndRestorePartialSearchableSnapshot() throws Exception { assertThat(IndexMetadata.INDEX_AUTO_EXPAND_REPLICAS_SETTING.get(settings).toString(), equalTo("false")); assertThat(IndexMetadata.INDEX_NUMBER_OF_REPLICAS_SETTING.get(settings), equalTo(expectedReplicas)); assertThat(DataTierAllocationDecider.INDEX_ROUTING_PREFER_SETTING.get(settings), equalTo(expectedDataTiersPreference)); - assertTrue(SearchableSnapshots.SNAPSHOT_PARTIAL_SETTING.get(settings)); + assertTrue(SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING.get(settings)); assertTrue(DiskThresholdDecider.SETTING_IGNORE_DISK_WATERMARKS.get(settings)); checkSoftDeletesNotEagerlyLoaded(restoredIndexName); @@ -691,6 +696,7 @@ public void testCreateAndRestorePartialSearchableSnapshot() throws Exception { Settings.builder() .putNull(IndexModule.INDEX_STORE_TYPE_SETTING.getKey()) .putNull(IndexModule.INDEX_RECOVERY_TYPE_SETTING.getKey()) + .put(DataTierAllocationDecider.INDEX_ROUTING_PREFER, DataTier.DATA_HOT) .build() ) ); diff --git a/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/index/store/SearchableSnapshotDirectory.java b/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/index/store/SearchableSnapshotDirectory.java index 2661e3c91da66..7d559e24073f9 100644 --- a/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/index/store/SearchableSnapshotDirectory.java +++ b/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/index/store/SearchableSnapshotDirectory.java @@ -94,7 +94,7 @@ import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_CACHE_PREWARM_ENABLED_SETTING; import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_INDEX_ID_SETTING; import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_INDEX_NAME_SETTING; -import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_PARTIAL_SETTING; +import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING; import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_REPOSITORY_NAME_SETTING; import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_REPOSITORY_UUID_SETTING; import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_SNAPSHOT_ID_SETTING; diff --git a/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/HasFrozenCacheAllocationDecider.java b/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/HasFrozenCacheAllocationDecider.java index 2a4d4df06b676..fbdf446eabe6c 100644 --- a/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/HasFrozenCacheAllocationDecider.java +++ b/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/HasFrozenCacheAllocationDecider.java @@ -18,7 +18,7 @@ import org.elasticsearch.xpack.searchablesnapshots.cache.FrozenCacheInfoService; import static org.elasticsearch.snapshots.SnapshotsService.SNAPSHOT_CACHE_SIZE_SETTING; -import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_PARTIAL_SETTING; +import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING; public class HasFrozenCacheAllocationDecider extends AllocationDecider { diff --git a/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotAllocator.java b/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotAllocator.java index 1b10c29c95ff2..133d13f9f6df9 100644 --- a/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotAllocator.java +++ b/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotAllocator.java @@ -60,7 +60,7 @@ import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_INDEX_ID_SETTING; import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_INDEX_NAME_SETTING; -import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_PARTIAL_SETTING; +import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING; import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_REPOSITORY_NAME_SETTING; import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_SNAPSHOT_ID_SETTING; import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_SNAPSHOT_NAME_SETTING; diff --git a/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshots.java b/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshots.java index fcb12c8ef8b4c..8fbf149b8491a 100644 --- a/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshots.java +++ b/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshots.java @@ -188,13 +188,6 @@ public class SearchableSnapshots extends Plugin implements IndexStorePlugin, Eng Setting.Property.NodeScope, Setting.Property.NotCopyableOnResize ); - public static final Setting SNAPSHOT_PARTIAL_SETTING = Setting.boolSetting( - "index.store.snapshot.partial", - false, - Setting.Property.IndexScope, - Setting.Property.PrivateIndex, - Setting.Property.NotCopyableOnResize - ); public static final String SNAPSHOT_BLOB_CACHE_METADATA_FILES_MAX_LENGTH = "index.store.snapshot.blob_cache.metadata_files.max_length"; public static final Setting SNAPSHOT_BLOB_CACHE_METADATA_FILES_MAX_LENGTH_SETTING = new Setting<>( new Setting.SimpleKey(SNAPSHOT_BLOB_CACHE_METADATA_FILES_MAX_LENGTH), @@ -222,13 +215,12 @@ public class SearchableSnapshots extends Plugin implements IndexStorePlugin, Eng ); /** - * Prefer to allocate to the cold tier, then the frozen tier, then the warm tier, then the hot tier + * Prefer to allocate to the cold tier, then the warm tier, then the hot tier * This affects the system searchable snapshot cache index (not the searchable snapshot index itself) */ public static final String DATA_TIERS_CACHE_INDEX_PREFERENCE = String.join( ",", DataTier.DATA_COLD, - DataTier.DATA_FROZEN, DataTier.DATA_WARM, DataTier.DATA_HOT ); @@ -300,7 +292,7 @@ public List> getSettings() { SNAPSHOT_CACHE_PREWARM_ENABLED_SETTING, SNAPSHOT_CACHE_EXCLUDED_FILE_TYPES_SETTING, SNAPSHOT_UNCACHED_CHUNK_SIZE_SETTING, - SNAPSHOT_PARTIAL_SETTING, + SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING, SNAPSHOT_BLOB_CACHE_METADATA_FILES_MAX_LENGTH_SETTING, CacheService.SNAPSHOT_CACHE_SIZE_SETTING, CacheService.SNAPSHOT_CACHE_RANGE_SIZE_SETTING, @@ -445,7 +437,7 @@ public Map getDirectoryFactories() { public Optional getEngineFactory(IndexSettings indexSettings) { if (SearchableSnapshotsConstants.isSearchableSnapshotStore(indexSettings.getSettings())) { final Boolean frozen = indexSettings.getSettings().getAsBoolean("index.frozen", null); - final boolean useFrozenEngine = SearchableSnapshots.SNAPSHOT_PARTIAL_SETTING.get(indexSettings.getSettings()) + final boolean useFrozenEngine = SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING.get(indexSettings.getSettings()) && (frozen == null || frozen.equals(Boolean.TRUE)); if (useFrozenEngine) { diff --git a/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/action/TransportMountSearchableSnapshotAction.java b/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/action/TransportMountSearchableSnapshotAction.java index 353076aa3950b..368a93afcc65c 100644 --- a/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/action/TransportMountSearchableSnapshotAction.java +++ b/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/action/TransportMountSearchableSnapshotAction.java @@ -23,6 +23,7 @@ import org.elasticsearch.cluster.routing.allocation.decider.DiskThresholdDecider; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.indices.SystemIndices; @@ -42,6 +43,7 @@ import org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshotsConstants; import java.util.Arrays; +import java.util.Collection; import java.util.LinkedHashSet; import java.util.Locale; import java.util.Map; @@ -64,6 +66,13 @@ public class TransportMountSearchableSnapshotAction extends TransportMasterNodeA MountSearchableSnapshotRequest, RestoreSnapshotResponse> { + private static final Collection> DATA_TIER_ALLOCATION_SETTINGS = org.elasticsearch.common.collect.List.of( + DataTierAllocationDecider.INDEX_ROUTING_EXCLUDE_SETTING, + DataTierAllocationDecider.INDEX_ROUTING_INCLUDE_SETTING, + DataTierAllocationDecider.INDEX_ROUTING_REQUIRE_SETTING, + DataTierAllocationDecider.INDEX_ROUTING_PREFER_SETTING + ); + private final Client client; private final RepositoriesService repositoriesService; private final XPackLicenseState licenseState; @@ -133,7 +142,7 @@ private static Settings buildIndexSettings( .put(INDEX_RECOVERY_TYPE_SETTING.getKey(), SearchableSnapshotsConstants.SNAPSHOT_RECOVERY_STATE_FACTORY_KEY); if (storage == MountSearchableSnapshotRequest.Storage.SHARED_CACHE) { - settings.put(SearchableSnapshots.SNAPSHOT_PARTIAL_SETTING.getKey(), true) + settings.put(SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING.getKey(), true) .put(DiskThresholdDecider.SETTING_IGNORE_DISK_WATERMARKS.getKey(), true); } @@ -209,6 +218,20 @@ protected void masterOperation( } } + Settings indexSettings = Settings.builder() + .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) // can be overridden + .put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, false) // can be overridden + .put(DataTierAllocationDecider.INDEX_ROUTING_PREFER, getDataTiersPreference(request.storage())) + .put(request.indexSettings()) + .put(buildIndexSettings(repoData.getUuid(), request.repositoryName(), snapshotId, indexId, request.storage())) + .build(); + + // todo: restore archives bad settings, for now we verify just the data tiers, since we know their dependencies are available + // in settings + for (Setting dataTierAllocationSetting : DATA_TIER_ALLOCATION_SETTINGS) { + dataTierAllocationSetting.get(indexSettings); + } + client.admin() .cluster() .restoreSnapshot( @@ -219,17 +242,7 @@ protected void masterOperation( .renamePattern(".+") .renameReplacement(mountedIndexName) // Pass through index settings, adding the index-level settings required to use searchable snapshots - .indexSettings( - Settings.builder() - .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) // can be overridden - .put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, false) // can be overridden - .put(DataTierAllocationDecider.INDEX_ROUTING_PREFER, getDataTiersPreference(request.storage())) - .put(request.indexSettings()) - .put( - buildIndexSettings(repoData.getUuid(), request.repositoryName(), snapshotId, indexId, request.storage()) - ) - .build() - ) + .indexSettings(indexSettings) // Pass through ignored index settings .ignoreIndexSettings(ignoreIndexSettings.toArray(new String[0])) // Don't include global state diff --git a/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/action/cache/TransportSearchableSnapshotCacheStoresAction.java b/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/action/cache/TransportSearchableSnapshotCacheStoresAction.java index 09035aa0b2738..0a9ecd1e9f5a9 100644 --- a/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/action/cache/TransportSearchableSnapshotCacheStoresAction.java +++ b/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/action/cache/TransportSearchableSnapshotCacheStoresAction.java @@ -31,7 +31,7 @@ import java.util.List; import java.util.Optional; -import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_PARTIAL_SETTING; +import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING; public class TransportSearchableSnapshotCacheStoresAction extends TransportNodesAction< TransportSearchableSnapshotCacheStoresAction.Request, diff --git a/x-pack/plugin/searchable-snapshots/src/test/java/org/elasticsearch/index/store/SearchableSnapshotDirectoryStatsTests.java b/x-pack/plugin/searchable-snapshots/src/test/java/org/elasticsearch/index/store/SearchableSnapshotDirectoryStatsTests.java index fbed51040bba5..fb757ecbc38a3 100644 --- a/x-pack/plugin/searchable-snapshots/src/test/java/org/elasticsearch/index/store/SearchableSnapshotDirectoryStatsTests.java +++ b/x-pack/plugin/searchable-snapshots/src/test/java/org/elasticsearch/index/store/SearchableSnapshotDirectoryStatsTests.java @@ -36,7 +36,7 @@ import org.elasticsearch.snapshots.Snapshot; import org.elasticsearch.snapshots.SnapshotId; import org.elasticsearch.xpack.searchablesnapshots.AbstractSearchableSnapshotsTestCase; -import org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots; +import org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshotsConstants; import org.elasticsearch.xpack.searchablesnapshots.cache.CacheService; import org.elasticsearch.xpack.searchablesnapshots.cache.FrozenCacheService; @@ -544,7 +544,7 @@ private void executeTestCase(final TriConsumer