Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to data tiers should always ensure a TIER_PREFERENCE is set #79100

Merged
merged 13 commits into from
Oct 15, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,21 @@
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xcontent.NamedObjectNotFoundException;
import org.elasticsearch.xcontent.NamedXContentRegistry;
import org.elasticsearch.xcontent.ToXContent;
import org.elasticsearch.xcontent.ToXContentFragment;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentParserUtils;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.gateway.MetadataStateFormat;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.plugins.MapperPlugin;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.xcontent.NamedObjectNotFoundException;
import org.elasticsearch.xcontent.NamedXContentRegistry;
import org.elasticsearch.xcontent.ToXContent;
import org.elasticsearch.xcontent.ToXContentFragment;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentFactory;
import org.elasticsearch.xcontent.XContentParser;

import java.io.IOException;
import java.util.ArrayList;
Expand Down Expand Up @@ -427,7 +427,7 @@ public ImmutableOpenMap<String, MappingMetadata> findMappings(String[] concreteI
/**
* Finds the parent data streams, if any, for the specified concrete indices.
*/
public ImmutableOpenMap<String, IndexAbstraction.DataStream> findDataStreams(String[] concreteIndices) {
public ImmutableOpenMap<String, IndexAbstraction.DataStream> findDataStreams(String... concreteIndices) {
assert concreteIndices != null;
final ImmutableOpenMap.Builder<String, IndexAbstraction.DataStream> builder = ImmutableOpenMap.builder();
final SortedMap<String, IndexAbstraction> lookup = getIndicesLookup();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

package org.elasticsearch.xpack;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
Expand Down Expand Up @@ -36,8 +39,8 @@
import org.junit.Before;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;
Expand All @@ -49,6 +52,7 @@
import static org.elasticsearch.xpack.TimeSeriesRestDriver.getOnlyIndexSettings;
import static org.elasticsearch.xpack.TimeSeriesRestDriver.getStepKeyForIndex;
import static org.hamcrest.Matchers.anEmptyMap;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
Expand Down Expand Up @@ -134,9 +138,9 @@ public void testMigrateToDataTiersAction() throws Exception {
createNewSingletonPolicy(client(), rolloverOnlyPolicyName, "hot", new RolloverAction(null, null, null, 1L));

String rolloverIndexPrefix = "rolloverpolicytest_index";
for (int i = 1; i < randomIntBetween(2, 5); i++) {
// assign the rollover-only policy to a few other indices - these indices and the rollover-only policy should not be migrated
// in any way
for (int i = 1; i <= 2; i++) {
// assign the rollover-only policy to a few other indices - these indices will end up getting caught by the catch-all
// tier preference migration
createIndexWithSettings(client(), rolloverIndexPrefix + "-00000" + i, alias + i, Settings.builder()
.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1)
.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0)
Expand Down Expand Up @@ -167,10 +171,10 @@ public void testMigrateToDataTiersAction() throws Exception {
assertOK(migrateDeploymentResponse);

Map<String, Object> migrateResponseAsMap = responseAsMap(migrateDeploymentResponse);
assertThat((ArrayList<String>) migrateResponseAsMap.get(MigrateToDataTiersResponse.MIGRATED_ILM_POLICIES.getPreferredName()),
containsInAnyOrder(policy));
assertThat((ArrayList<String>) migrateResponseAsMap.get(MigrateToDataTiersResponse.MIGRATED_INDICES.getPreferredName()),
containsInAnyOrder(index, indexWithDataWarmRouting));
assertThat((List<String>) migrateResponseAsMap.get(MigrateToDataTiersResponse.MIGRATED_ILM_POLICIES.getPreferredName()),
contains(policy));
assertThat((List<String>) migrateResponseAsMap.get(MigrateToDataTiersResponse.MIGRATED_INDICES.getPreferredName()),
containsInAnyOrder(index, indexWithDataWarmRouting, rolloverIndexPrefix + "-000001", rolloverIndexPrefix + "-000002"));
assertThat(migrateResponseAsMap.get(MigrateToDataTiersResponse.REMOVED_LEGACY_TEMPLATE.getPreferredName()),
is(templateName));

Expand Down Expand Up @@ -209,6 +213,13 @@ public void testMigrateToDataTiersAction() throws Exception {
assertThat(cachedPhaseDefinition, containsString(ShrinkAction.NAME));
assertThat(cachedPhaseDefinition, containsString(SetPriorityAction.NAME));
assertThat(cachedPhaseDefinition, containsString(ForceMergeAction.NAME));

// ENFORCE_DEFAULT_TIER_PREFERENCE has been set to true
Request getSettingsRequest = new Request("GET", "_cluster/settings");
Response getSettingsResponse = client().performRequest(getSettingsRequest);
ObjectMapper mapper = new ObjectMapper();
JsonNode json = mapper.readTree(getSettingsResponse.getEntity().getContent());
assertTrue(json.at("/persistent/cluster/routing/allocation/enforce_default_tier_preference").asBoolean());
}

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -274,9 +285,9 @@ public void testMigrationDryRun() throws Exception {

// response should contain the correct "to migrate" entities
Map<String, Object> migrateResponseAsMap = responseAsMap(migrateDeploymentResponse);
assertThat((ArrayList<String>) migrateResponseAsMap.get(MigrateToDataTiersResponse.MIGRATED_ILM_POLICIES.getPreferredName()),
assertThat((List<String>) migrateResponseAsMap.get(MigrateToDataTiersResponse.MIGRATED_ILM_POLICIES.getPreferredName()),
containsInAnyOrder(policy));
assertThat((ArrayList<String>) migrateResponseAsMap.get(MigrateToDataTiersResponse.MIGRATED_INDICES.getPreferredName()),
assertThat((List<String>) migrateResponseAsMap.get(MigrateToDataTiersResponse.MIGRATED_INDICES.getPreferredName()),
containsInAnyOrder(index, indexWithDataWarmRouting));
assertThat(migrateResponseAsMap.get(MigrateToDataTiersResponse.REMOVED_LEGACY_TEMPLATE.getPreferredName()),
is(templateName));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.IndexMetadata;
import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.routing.allocation.DataTier;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xcontent.NamedXContentRegistry;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.core.Tuple;
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.cluster.routing.allocation.DataTier;
import org.elasticsearch.xcontent.NamedXContentRegistry;
import org.elasticsearch.xpack.core.ilm.AllocateAction;
import org.elasticsearch.xpack.core.ilm.IndexLifecycleMetadata;
import org.elasticsearch.xpack.core.ilm.LifecycleAction;
Expand All @@ -48,6 +48,7 @@
import static org.elasticsearch.cluster.metadata.IndexMetadata.INDEX_ROUTING_EXCLUDE_GROUP_SETTING;
import static org.elasticsearch.cluster.metadata.IndexMetadata.INDEX_ROUTING_INCLUDE_GROUP_SETTING;
import static org.elasticsearch.cluster.metadata.IndexMetadata.INDEX_ROUTING_REQUIRE_GROUP_SETTING;
import static org.elasticsearch.cluster.routing.allocation.DataTier.ENFORCE_DEFAULT_TIER_PREFERENCE;
import static org.elasticsearch.cluster.routing.allocation.DataTier.TIER_PREFERENCE;
import static org.elasticsearch.xpack.core.ilm.LifecycleExecutionState.ILM_CUSTOM_METADATA_KEY;
import static org.elasticsearch.xpack.core.ilm.OperationMode.STOPPED;
Expand Down Expand Up @@ -127,6 +128,18 @@ public static Tuple<ClusterState, MigratedEntities> migrateToDataTiersRouting(Cl
}

Metadata.Builder mb = Metadata.builder(currentState.metadata());

// set ENFORCE_DEFAULT_TIER_PREFERENCE to true (in the persistent settings)
mb.persistentSettings(Settings.builder()
.put(mb.persistentSettings())
.put(ENFORCE_DEFAULT_TIER_PREFERENCE, true)
.build());

// and remove it from the transient settings, just in case it was there
Settings.Builder transientSettingsBuilder = Settings.builder().put(mb.transientSettings());
transientSettingsBuilder.remove(ENFORCE_DEFAULT_TIER_PREFERENCE);
mb.transientSettings(transientSettingsBuilder.build());

String removedIndexTemplateName = null;
if (Strings.hasText(indexTemplateToDelete)) {
if (currentState.metadata().getTemplates().containsKey(indexTemplateToDelete)) {
Expand Down Expand Up @@ -376,20 +389,34 @@ static List<String> migrateIndices(Metadata.Builder mb, ClusterState currentStat
for (ObjectObjectCursor<String, IndexMetadata> index : currentState.metadata().indices()) {
IndexMetadata indexMetadata = index.value;
Settings currentSettings = indexMetadata.getSettings();

boolean removeNodeAttrIndexRoutingSettings = true;

// migrate using the `require` setting
Settings newSettings = maybeMigrateRoutingSettingToTierPreference(nodeAttrIndexRequireRoutingSetting, indexMetadata);

if (newSettings.equals(currentSettings)) {
// migrating based on the `require` setting was not successful so let's check if the index used the `include` routing
// migrating based on the `require` setting was not successful, so let's check if the index used the `include` routing
// setting to configure the allocations and try to migrate it
newSettings = maybeMigrateRoutingSettingToTierPreference(nodeAttrIndexIncludeRoutingSetting, indexMetadata);
}
if (newSettings.equals(currentSettings)) {
removeNodeAttrIndexRoutingSettings = false;
// migrating based on the `include` setting was not successful,
// so, last stop, we just inject a tier preference regardless of anything else
newSettings = migrateToDefaultTierPreference(currentState, indexMetadata);
}

if (newSettings.equals(currentSettings) == false) {
// we converted either the require or the include routing setting to tier preference
// so let's clear all the routing settings for the given attribute
Settings.Builder finalSettings = Settings.builder().put(newSettings);
finalSettings.remove(nodeAttrIndexExcludeRoutingSetting);
finalSettings.remove(nodeAttrIndexRequireRoutingSetting);
finalSettings.remove(nodeAttrIndexIncludeRoutingSetting);

if (removeNodeAttrIndexRoutingSettings) {
// we converted either the `require` or the `include` routing setting to tier preference
// so let's clear all the routing settings for the given attribute
finalSettings.remove(nodeAttrIndexExcludeRoutingSetting);
finalSettings.remove(nodeAttrIndexRequireRoutingSetting);
finalSettings.remove(nodeAttrIndexIncludeRoutingSetting);
}

mb.put(IndexMetadata.builder(indexMetadata)
.settings(finalSettings)
Expand All @@ -413,9 +440,11 @@ private static Settings maybeMigrateRoutingSettingToTierPreference(String attrib
if (currentIndexSettings.keySet().contains(attributeBasedRoutingSettingName) == false) {
return currentIndexSettings;
}
// look at the value, get the correct tiers config and update the settings and index metadata

Settings.Builder newSettingsBuilder = Settings.builder().put(currentIndexSettings);
String indexName = indexMetadata.getIndex().getName();

// look at the value, get the correct tiers config and update the settings
if (currentIndexSettings.keySet().contains(TIER_PREFERENCE)) {
newSettingsBuilder.remove(attributeBasedRoutingSettingName);
logger.debug("index [{}]: removed setting [{}]", indexName, attributeBasedRoutingSettingName);
Expand All @@ -428,7 +457,7 @@ private static Settings maybeMigrateRoutingSettingToTierPreference(String attrib
newSettingsBuilder.remove(attributeBasedRoutingSettingName);
logger.debug("index [{}]: removed setting [{}]", indexName, attributeBasedRoutingSettingName);
logger.debug("index [{}]: configured setting [{}] to [{}]", indexName,
TIER_PREFERENCE, convertedTierPreference);
TIER_PREFERENCE, convertedTierPreference);
} else {
// log warning and do *not* remove setting, return the settings unchanged
logger.warn("index [{}]: could not convert attribute based setting [{}] value of [{}] to a tier preference " +
Expand All @@ -440,6 +469,23 @@ private static Settings maybeMigrateRoutingSettingToTierPreference(String attrib
return newSettingsBuilder.build();
}

private static Settings migrateToDefaultTierPreference(ClusterState currentState, IndexMetadata indexMetadata) {
Settings currentIndexSettings = indexMetadata.getSettings();
List<String> tierPreference = DataTier.parseTierList(currentIndexSettings.get(DataTier.TIER_PREFERENCE));
if (tierPreference.isEmpty() == false) {
return currentIndexSettings;
}

Settings.Builder newSettingsBuilder = Settings.builder().put(currentIndexSettings);
String indexName = indexMetadata.getIndex().getName();

boolean isDataStream = currentState.metadata().findDataStreams(indexName).isEmpty() == false;
String convertedTierPreference = isDataStream ? DataTier.DATA_HOT : DataTier.DATA_CONTENT;
newSettingsBuilder.put(TIER_PREFERENCE, convertedTierPreference);
logger.debug("index [{}]: configured setting [{}] to [{}]", indexName, TIER_PREFERENCE, convertedTierPreference);
return newSettingsBuilder.build();
}

/**
* Converts the provided node attribute value to the corresponding `_tier_preference` configuration.
* Known (and convertible) attribute values are:
Expand Down
Loading