Skip to content

Commit

Permalink
ILM actions check the managed index is not a DS write index (#58239) (#…
Browse files Browse the repository at this point in the history
…58295)

This changes the actions that would attempt to make the managed index read only to
check if the managed index is the write index of a data stream before proceeding.
The updated actions are shrink, readonly, freeze and forcemerge.

(cherry picked from commit c906f63)
Signed-off-by: Andrei Dan <[email protected]>
  • Loading branch information
andreidan authored Jun 18, 2020
1 parent abc72c1 commit caa5d3a
Show file tree
Hide file tree
Showing 12 changed files with 259 additions and 247 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ public List<Step> toSteps(Client client, String phase, Step.StepKey nextStepKey)

final boolean codecChange = codec != null && codec.equals(CodecService.BEST_COMPRESSION_CODEC);

StepKey checkNotWriteIndex = new StepKey(phase, NAME, CheckNotDataStreamWriteIndexStep.NAME);
StepKey readOnlyKey = new StepKey(phase, NAME, ReadOnlyAction.NAME);

StepKey closeKey = new StepKey(phase, NAME, CloseIndexStep.NAME);
Expand All @@ -130,6 +131,8 @@ public List<Step> toSteps(Client client, String phase, Step.StepKey nextStepKey)
StepKey forceMergeKey = new StepKey(phase, NAME, ForceMergeStep.NAME);
StepKey countKey = new StepKey(phase, NAME, SegmentCountStep.NAME);

CheckNotDataStreamWriteIndexStep checkNotWriteIndexStep = new CheckNotDataStreamWriteIndexStep(checkNotWriteIndex,
readOnlyKey);
UpdateSettingsStep readOnlyStep =
new UpdateSettingsStep(readOnlyKey, codecChange ? closeKey : forceMergeKey, client, readOnlySettings);

Expand All @@ -144,6 +147,7 @@ public List<Step> toSteps(Client client, String phase, Step.StepKey nextStepKey)
SegmentCountStep segmentCountStep = new SegmentCountStep(countKey, nextStepKey, client, maxNumSegments);

List<Step> mergeSteps = new ArrayList<>();
mergeSteps.add(checkNotWriteIndexStep);
mergeSteps.add(readOnlyStep);

if (codecChange) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,13 @@ public boolean isSafeAction() {

@Override
public List<Step> toSteps(Client client, String phase, StepKey nextStepKey) {
StepKey checkNotWriteIndex = new StepKey(phase, NAME, CheckNotDataStreamWriteIndexStep.NAME);
StepKey freezeStepKey = new StepKey(phase, NAME, FreezeStep.NAME);

CheckNotDataStreamWriteIndexStep checkNoWriteIndexStep = new CheckNotDataStreamWriteIndexStep(checkNotWriteIndex,
freezeStepKey);
FreezeStep freezeStep = new FreezeStep(freezeStepKey, nextStepKey, client);
return Arrays.asList(freezeStep);
return Arrays.asList(checkNoWriteIndexStep, freezeStep);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.xpack.core.ilm.Step.StepKey;

import java.io.IOException;
import java.util.Collections;
import java.util.Arrays;
import java.util.List;

/**
Expand Down Expand Up @@ -59,10 +60,14 @@ public boolean isSafeAction() {
}

@Override
public List<Step> toSteps(Client client, String phase, Step.StepKey nextStepKey) {
Step.StepKey key = new Step.StepKey(phase, NAME, NAME);
public List<Step> toSteps(Client client, String phase, StepKey nextStepKey) {
StepKey checkNotWriteIndex = new StepKey(phase, NAME, CheckNotDataStreamWriteIndexStep.NAME);
StepKey readOnlyKey = new StepKey(phase, NAME, NAME);
CheckNotDataStreamWriteIndexStep checkNotWriteIndexStep = new CheckNotDataStreamWriteIndexStep(checkNotWriteIndex,
readOnlyKey);
Settings readOnlySettings = Settings.builder().put(IndexMetadata.SETTING_BLOCKS_WRITE, true).build();
return Collections.singletonList(new UpdateSettingsStep(key, nextStepKey, client, readOnlySettings));
UpdateSettingsStep readOnlyStep = new UpdateSettingsStep(readOnlyKey, nextStepKey, client, readOnlySettings);
return Arrays.asList(checkNotWriteIndexStep, readOnlyStep);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.IndexAbstraction;
import org.elasticsearch.cluster.metadata.IndexMetadata;
import org.elasticsearch.common.ParseField;
Expand All @@ -19,15 +18,12 @@
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.Index;
import org.elasticsearch.xpack.core.ilm.Step.StepKey;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.function.BiPredicate;

/**
* A {@link LifecycleAction} which shrinks the index.
Expand Down Expand Up @@ -97,6 +93,7 @@ public List<Step> toSteps(Client client, String phase, Step.StepKey nextStepKey)
Settings readOnlySettings = Settings.builder().put(IndexMetadata.SETTING_BLOCKS_WRITE, true).build();

StepKey preShrinkBranchingKey = new StepKey(phase, NAME, CONDITIONAL_SKIP_SHRINK_STEP);
StepKey checkNotWriteIndex = new StepKey(phase, NAME, CheckNotDataStreamWriteIndexStep.NAME);
StepKey waitForNoFollowerStepKey = new StepKey(phase, NAME, WaitForNoFollowersStep.NAME);
StepKey readOnlyKey = new StepKey(phase, NAME, ReadOnlyAction.NAME);
StepKey setSingleNodeKey = new StepKey(phase, NAME, SetSingleNodeAllocateStep.NAME);
Expand All @@ -110,8 +107,10 @@ public List<Step> toSteps(Client client, String phase, Step.StepKey nextStepKey)
StepKey replaceDataStreamIndexKey = new StepKey(phase, NAME, ReplaceDataStreamBackingIndexStep.NAME);
StepKey deleteIndexKey = new StepKey(phase, NAME, DeleteStep.NAME);

BranchingStep conditionalSkipShrinkStep = new BranchingStep(preShrinkBranchingKey, waitForNoFollowerStepKey, nextStepKey,
getSkipShrinkStepPredicate(numberOfShards));
BranchingStep conditionalSkipShrinkStep = new BranchingStep(preShrinkBranchingKey, checkNotWriteIndex, nextStepKey,
(index, clusterState) -> clusterState.getMetadata().index(index).getNumberOfShards() == numberOfShards);
CheckNotDataStreamWriteIndexStep checkNotWriteIndexStep = new CheckNotDataStreamWriteIndexStep(checkNotWriteIndex,
waitForNoFollowerStepKey);
WaitForNoFollowersStep waitForNoFollowersStep = new WaitForNoFollowersStep(waitForNoFollowerStepKey, readOnlyKey, client);
UpdateSettingsStep readOnlyStep = new UpdateSettingsStep(readOnlyKey, setSingleNodeKey, client, readOnlySettings);
SetSingleNodeAllocateStep setSingleNodeStep = new SetSingleNodeAllocateStep(setSingleNodeKey, allocationRoutedKey, client);
Expand All @@ -136,45 +135,11 @@ public List<Step> toSteps(Client client, String phase, Step.StepKey nextStepKey)
deleteIndexKey, SHRUNKEN_INDEX_PREFIX);
DeleteStep deleteSourceIndexStep = new DeleteStep(deleteIndexKey, isShrunkIndexKey, client);
ShrunkenIndexCheckStep waitOnShrinkTakeover = new ShrunkenIndexCheckStep(isShrunkIndexKey, nextStepKey, SHRUNKEN_INDEX_PREFIX);
return Arrays.asList(conditionalSkipShrinkStep, waitForNoFollowersStep, readOnlyStep, setSingleNodeStep, checkShrinkReadyStep,
shrink, allocated, copyMetadata, isDataStreamBranchingStep, aliasSwapAndDelete, waitOnShrinkTakeover,
return Arrays.asList(conditionalSkipShrinkStep, checkNotWriteIndexStep, waitForNoFollowersStep, readOnlyStep, setSingleNodeStep,
checkShrinkReadyStep, shrink, allocated, copyMetadata, isDataStreamBranchingStep, aliasSwapAndDelete, waitOnShrinkTakeover,
replaceDataStreamBackingIndex, deleteSourceIndexStep);
}

static BiPredicate<Index, ClusterState> getSkipShrinkStepPredicate(int targetNumberOfShards) {
return (index, clusterState) -> {
IndexMetadata indexMetadata = clusterState.getMetadata().index(index);
if (indexMetadata == null) {
// Index must have been since deleted, skip the shrink action
logger.debug("[{}] lifecycle action for index [{}] executed but index no longer exists", NAME, index.getName());
return true;
}

if (indexMetadata.getNumberOfShards() == targetNumberOfShards) {
logger.debug("skipping [{}] lifecycle action for index [{}] because the index already has the target number of shards",
NAME, index.getName());
return true;
}

IndexAbstraction indexAbstraction = clusterState.metadata().getIndicesLookup().get(index.getName());
assert indexAbstraction != null : "invalid cluster metadata. index [" + index.getName() + "] was not found";

if (indexAbstraction.getParentDataStream() != null) {
IndexAbstraction.DataStream dataStream = indexAbstraction.getParentDataStream();
assert dataStream.getWriteIndex() != null : dataStream.getName() + " has no write index";
if (dataStream.getWriteIndex().getIndex().equals(index)) {
String policyName = indexMetadata.getSettings().get(LifecycleSettings.LIFECYCLE_NAME);
String errorMessage = String.format(Locale.ROOT, "index [%s] is the write index for data stream [%s], pausing " +
"ILM execution of lifecycle [%s] until this index is no longer the write index for the data stream via manual or " +
"automated rollover", index.getName(), dataStream.getName(), policyName);
logger.debug(errorMessage);
throw new IllegalStateException(errorMessage);
}
}
return false;
};
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,28 +65,33 @@ private void assertNonBestCompression(ForceMergeAction instance) {
StepKey nextStepKey = new StepKey(randomAlphaOfLength(10), randomAlphaOfLength(10), randomAlphaOfLength(10));
List<Step> steps = instance.toSteps(null, phase, nextStepKey);
assertNotNull(steps);
assertEquals(3, steps.size());
UpdateSettingsStep firstStep = (UpdateSettingsStep) steps.get(0);
ForceMergeStep secondStep = (ForceMergeStep) steps.get(1);
SegmentCountStep thirdStep = (SegmentCountStep) steps.get(2);
assertThat(firstStep.getKey(), equalTo(new StepKey(phase, ForceMergeAction.NAME, ReadOnlyAction.NAME)));
assertThat(firstStep.getNextStepKey(), equalTo(new StepKey(phase, ForceMergeAction.NAME, ForceMergeStep.NAME)));
assertTrue(IndexMetadata.INDEX_BLOCKS_WRITE_SETTING.get(firstStep.getSettings()));
assertThat(secondStep.getKey(), equalTo(new StepKey(phase, ForceMergeAction.NAME, ForceMergeStep.NAME)));
assertThat(secondStep.getNextStepKey(), equalTo(thirdStep.getKey()));
assertThat(thirdStep.getKey(), equalTo(new StepKey(phase, ForceMergeAction.NAME, SegmentCountStep.NAME)));
assertThat(thirdStep.getNextStepKey(), equalTo(nextStepKey));
assertEquals(4, steps.size());
CheckNotDataStreamWriteIndexStep firstStep = (CheckNotDataStreamWriteIndexStep) steps.get(0);
UpdateSettingsStep secondStep = (UpdateSettingsStep) steps.get(1);
ForceMergeStep thirdStep = (ForceMergeStep) steps.get(2);
SegmentCountStep fourthStep = (SegmentCountStep) steps.get(3);

assertThat(firstStep.getKey(), equalTo(new StepKey(phase, ForceMergeAction.NAME, CheckNotDataStreamWriteIndexStep.NAME)));
assertThat(firstStep.getNextStepKey(), equalTo(new StepKey(phase, ForceMergeAction.NAME, ReadOnlyAction.NAME)));
assertThat(secondStep.getKey(), equalTo(new StepKey(phase, ForceMergeAction.NAME, ReadOnlyAction.NAME)));
assertThat(secondStep.getNextStepKey(), equalTo(new StepKey(phase, ForceMergeAction.NAME, ForceMergeStep.NAME)));
assertTrue(IndexMetadata.INDEX_BLOCKS_WRITE_SETTING.get(secondStep.getSettings()));
assertThat(thirdStep.getKey(), equalTo(new StepKey(phase, ForceMergeAction.NAME, ForceMergeStep.NAME)));
assertThat(thirdStep.getNextStepKey(), equalTo(fourthStep.getKey()));
assertThat(fourthStep.getKey(), equalTo(new StepKey(phase, ForceMergeAction.NAME, SegmentCountStep.NAME)));
assertThat(fourthStep.getNextStepKey(), equalTo(nextStepKey));
}

private void assertBestCompression(ForceMergeAction instance) {
String phase = randomAlphaOfLength(5);
StepKey nextStepKey = new StepKey(randomAlphaOfLength(10), randomAlphaOfLength(10), randomAlphaOfLength(10));
List<Step> steps = instance.toSteps(null, phase, nextStepKey);
assertNotNull(steps);
assertEquals(7, steps.size());
assertEquals(8, steps.size());
List<Tuple<StepKey, StepKey>> stepKeys = steps.stream()
.map(s -> new Tuple<>(s.getKey(), s.getNextStepKey()))
.collect(Collectors.toList());
StepKey checkNotWriteIndex = new StepKey(phase, ForceMergeAction.NAME, CheckNotDataStreamWriteIndexStep.NAME);
StepKey readOnly = new StepKey(phase, ForceMergeAction.NAME, ReadOnlyAction.NAME);
StepKey closeIndex = new StepKey(phase, ForceMergeAction.NAME, CloseIndexStep.NAME);
StepKey updateCodec = new StepKey(phase, ForceMergeAction.NAME, UpdateSettingsStep.NAME);
Expand All @@ -95,6 +100,7 @@ private void assertBestCompression(ForceMergeAction instance) {
StepKey forceMerge = new StepKey(phase, ForceMergeAction.NAME, ForceMergeStep.NAME);
StepKey segmentCount = new StepKey(phase, ForceMergeAction.NAME, SegmentCountStep.NAME);
assertThat(stepKeys, contains(
new Tuple<>(checkNotWriteIndex, readOnly),
new Tuple<>(readOnly, closeIndex),
new Tuple<>(closeIndex, updateCodec),
new Tuple<>(updateCodec, openIndex),
Expand All @@ -103,11 +109,11 @@ private void assertBestCompression(ForceMergeAction instance) {
new Tuple<>(forceMerge, segmentCount),
new Tuple<>(segmentCount, nextStepKey)));

UpdateSettingsStep firstStep = (UpdateSettingsStep) steps.get(0);
UpdateSettingsStep thirdStep = (UpdateSettingsStep) steps.get(2);
UpdateSettingsStep secondStep = (UpdateSettingsStep) steps.get(1);
UpdateSettingsStep fourthStep = (UpdateSettingsStep) steps.get(3);

assertTrue(IndexMetadata.INDEX_BLOCKS_WRITE_SETTING.get(firstStep.getSettings()));
assertThat(thirdStep.getSettings().get(EngineConfig.INDEX_CODEC_SETTING.getKey()), equalTo(CodecService.BEST_COMPRESSION_CODEC));
assertTrue(IndexMetadata.INDEX_BLOCKS_WRITE_SETTING.get(secondStep.getSettings()));
assertThat(fourthStep.getSettings().get(EngineConfig.INDEX_CODEC_SETTING.getKey()), equalTo(CodecService.BEST_COMPRESSION_CODEC));
}

public void testMissingMaxNumSegments() throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import java.io.IOException;
import java.util.List;

import static org.hamcrest.Matchers.equalTo;

public class FreezeActionTests extends AbstractActionTestCase<FreezeAction> {

@Override
Expand All @@ -36,10 +38,17 @@ public void testToSteps() {
randomAlphaOfLengthBetween(1, 10));
List<Step> steps = action.toSteps(null, phase, nextStepKey);
assertNotNull(steps);
assertEquals(1, steps.size());
StepKey expectedFirstStepKey = new StepKey(phase, FreezeAction.NAME, FreezeStep.NAME);
FreezeStep firstStep = (FreezeStep) steps.get(0);
assertEquals(expectedFirstStepKey, firstStep.getKey());
assertEquals(nextStepKey, firstStep.getNextStepKey());
assertEquals(2, steps.size());
StepKey expectedFirstStepKey = new StepKey(phase, FreezeAction.NAME, CheckNotDataStreamWriteIndexStep.NAME);
StepKey expectedSecondStepKey = new StepKey(phase, FreezeAction.NAME, FreezeStep.NAME);

CheckNotDataStreamWriteIndexStep firstStep = (CheckNotDataStreamWriteIndexStep) steps.get(0);
FreezeStep secondStep = (FreezeStep) steps.get(1);

assertThat(firstStep.getKey(), equalTo(expectedFirstStepKey));
assertThat(firstStep.getNextStepKey(), equalTo(expectedSecondStepKey));

assertEquals(expectedSecondStepKey, secondStep.getKey());
assertEquals(nextStepKey, secondStep.getNextStepKey());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,19 @@ public void testToSteps() {
randomAlphaOfLengthBetween(1, 10));
List<Step> steps = action.toSteps(null, phase, nextStepKey);
assertNotNull(steps);
assertEquals(1, steps.size());
StepKey expectedFirstStepKey = new StepKey(phase, ReadOnlyAction.NAME, ReadOnlyAction.NAME);
UpdateSettingsStep firstStep = (UpdateSettingsStep) steps.get(0);
assertEquals(2, steps.size());
StepKey expectedFirstStepKey = new StepKey(phase, ReadOnlyAction.NAME, CheckNotDataStreamWriteIndexStep.NAME);
StepKey expectedSecondStepKey = new StepKey(phase, ReadOnlyAction.NAME, ReadOnlyAction.NAME);
CheckNotDataStreamWriteIndexStep firstStep = (CheckNotDataStreamWriteIndexStep) steps.get(0);
UpdateSettingsStep secondStep = (UpdateSettingsStep) steps.get(1);

assertThat(firstStep.getKey(), equalTo(expectedFirstStepKey));
assertThat(firstStep.getNextStepKey(), equalTo(nextStepKey));
assertThat(firstStep.getSettings().size(), equalTo(1));
assertTrue(IndexMetadata.INDEX_BLOCKS_WRITE_SETTING.get(firstStep.getSettings()));
assertThat(firstStep.getNextStepKey(), equalTo(expectedSecondStepKey));

assertThat(secondStep.getKey(), equalTo(expectedSecondStepKey));
assertThat(secondStep.getNextStepKey(), equalTo(nextStepKey));
assertThat(secondStep.getSettings().size(), equalTo(1));
assertTrue(IndexMetadata.INDEX_BLOCKS_WRITE_SETTING.get(secondStep.getSettings()));
}

}
Loading

0 comments on commit caa5d3a

Please sign in to comment.