Skip to content

Commit 2482387

Browse files
committed
ILM migrate data between tiers (elastic#61377)
This adds ILM support for automatically migrating the managed indices between data tiers. This proposal makes use of a MigrateAction that is injected (similar to how the Unfollow action is injected) in phases that don't define index allocation rules using the AllocateAction or don't explicitly define the MigrateAction itself (regardless if it's enabled or disabled). (cherry picked from commit c1746af) Signed-off-by: Andrei Dan <[email protected]>
1 parent abce048 commit 2482387

File tree

28 files changed

+1134
-154
lines changed

28 files changed

+1134
-154
lines changed

client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/IndexLifecycleNamedXContentProvider.java

+3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ public List<NamedXContentRegistry.Entry> getNamedXContentParsers() {
5757
new NamedXContentRegistry.Entry(LifecycleAction.class,
5858
new ParseField(SetPriorityAction.NAME),
5959
SetPriorityAction::parse),
60+
new NamedXContentRegistry.Entry(LifecycleAction.class,
61+
new ParseField(MigrateAction.NAME),
62+
MigrateAction::parse),
6063
new NamedXContentRegistry.Entry(LifecycleAction.class,
6164
new ParseField(UnfollowAction.NAME),
6265
UnfollowAction::parse)

client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/LifecyclePolicy.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,10 @@ public class LifecyclePolicy implements ToXContentObject {
5858
}, PHASES_FIELD);
5959

6060
ALLOWED_ACTIONS.put("hot", Sets.newHashSet(UnfollowAction.NAME, SetPriorityAction.NAME, RolloverAction.NAME));
61-
ALLOWED_ACTIONS.put("warm", Sets.newHashSet(UnfollowAction.NAME, SetPriorityAction.NAME, AllocateAction.NAME, ForceMergeAction.NAME,
62-
ReadOnlyAction.NAME, ShrinkAction.NAME));
63-
ALLOWED_ACTIONS.put("cold", Sets.newHashSet(UnfollowAction.NAME, SetPriorityAction.NAME, AllocateAction.NAME, FreezeAction.NAME));
61+
ALLOWED_ACTIONS.put("warm", Sets.newHashSet(UnfollowAction.NAME, SetPriorityAction.NAME, MigrateAction.NAME, AllocateAction.NAME,
62+
ForceMergeAction.NAME, ReadOnlyAction.NAME, ShrinkAction.NAME));
63+
ALLOWED_ACTIONS.put("cold", Sets.newHashSet(UnfollowAction.NAME, SetPriorityAction.NAME, MigrateAction.NAME, AllocateAction.NAME,
64+
FreezeAction.NAME));
6465
ALLOWED_ACTIONS.put("delete", Sets.newHashSet(DeleteAction.NAME));
6566
}
6667

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.elasticsearch.client.ilm;
20+
21+
import org.elasticsearch.common.ParseField;
22+
import org.elasticsearch.common.Strings;
23+
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
24+
import org.elasticsearch.common.xcontent.ToXContentObject;
25+
import org.elasticsearch.common.xcontent.XContentBuilder;
26+
import org.elasticsearch.common.xcontent.XContentParser;
27+
28+
import java.io.IOException;
29+
import java.util.Objects;
30+
31+
public class MigrateAction implements LifecycleAction, ToXContentObject {
32+
public static final String NAME = "migrate";
33+
34+
public static final ParseField ENABLED_FIELD = new ParseField("enabled");
35+
36+
private static final ConstructingObjectParser<MigrateAction, Void> PARSER = new ConstructingObjectParser<>(NAME,
37+
a -> new MigrateAction(a[0] == null ? true : (boolean) a[0]));
38+
39+
static {
40+
PARSER.declareBoolean(ConstructingObjectParser.optionalConstructorArg(), ENABLED_FIELD);
41+
}
42+
43+
public static MigrateAction parse(XContentParser parser) {
44+
return PARSER.apply(parser, null);
45+
}
46+
47+
private final boolean enabled;
48+
49+
public MigrateAction() {
50+
this(true);
51+
}
52+
53+
public MigrateAction(boolean enabled) {
54+
this.enabled = enabled;
55+
}
56+
57+
@Override
58+
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
59+
builder.startObject();
60+
builder.field(ENABLED_FIELD.getPreferredName(), enabled);
61+
builder.endObject();
62+
return builder;
63+
}
64+
65+
@Override
66+
public String getName() {
67+
return NAME;
68+
}
69+
70+
@Override
71+
public int hashCode() {
72+
return Objects.hashCode(enabled);
73+
}
74+
75+
@Override
76+
public boolean equals(Object obj) {
77+
if (obj == null) {
78+
return false;
79+
}
80+
if (obj.getClass() != getClass()) {
81+
return false;
82+
}
83+
return true;
84+
}
85+
86+
@Override
87+
public String toString() {
88+
return Strings.toString(this);
89+
}
90+
}

client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ public void testDefaultNamedXContents() {
705705

706706
public void testProvidedNamedXContents() {
707707
List<NamedXContentRegistry.Entry> namedXContents = RestHighLevelClient.getProvidedNamedXContents();
708-
assertEquals(70, namedXContents.size());
708+
assertEquals(71, namedXContents.size());
709709
Map<Class<?>, Integer> categories = new HashMap<>();
710710
List<String> names = new ArrayList<>();
711711
for (NamedXContentRegistry.Entry namedXContent : namedXContents) {
@@ -731,7 +731,7 @@ public void testProvidedNamedXContents() {
731731
assertTrue(names.contains(MeanReciprocalRank.NAME));
732732
assertTrue(names.contains(DiscountedCumulativeGain.NAME));
733733
assertTrue(names.contains(ExpectedReciprocalRank.NAME));
734-
assertEquals(Integer.valueOf(9), categories.get(LifecycleAction.class));
734+
assertEquals(Integer.valueOf(10), categories.get(LifecycleAction.class));
735735
assertTrue(names.contains(UnfollowAction.NAME));
736736
assertTrue(names.contains(AllocateAction.NAME));
737737
assertTrue(names.contains(DeleteAction.NAME));

client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ILMDocumentationIT.java

+4
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ public void testExplainLifecycle() throws Exception {
362362
CreateIndexRequest createIndexRequest = new CreateIndexRequest("my_index-1")
363363
.settings(Settings.builder()
364364
.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1)
365+
.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0)
365366
.put("index.lifecycle.name", "my_policy")
366367
.put("index.lifecycle.rollover_alias", "my_alias")
367368
.build());
@@ -370,6 +371,7 @@ public void testExplainLifecycle() throws Exception {
370371
CreateIndexRequest createOtherIndexRequest = new CreateIndexRequest("other_index")
371372
.settings(Settings.builder()
372373
.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1)
374+
.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0)
373375
.build());
374376
client.indices().create(createOtherIndexRequest, RequestOptions.DEFAULT);
375377

@@ -624,6 +626,7 @@ public void testRetryPolicy() throws Exception {
624626
CreateIndexRequest createIndexRequest = new CreateIndexRequest("my_index")
625627
.settings(Settings.builder()
626628
.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 2)
629+
.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0)
627630
.put("index.lifecycle.name", "my_policy")
628631
.build());
629632
client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
@@ -689,6 +692,7 @@ public void testRemovePolicyFromIndex() throws Exception {
689692
CreateIndexRequest createIndexRequest = new CreateIndexRequest("my_index")
690693
.settings(Settings.builder()
691694
.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1)
695+
.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0)
692696
.put("index.lifecycle.name", "my_policy")
693697
.build());
694698
client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.elasticsearch.client.ilm;
20+
21+
import org.elasticsearch.common.xcontent.XContentParser;
22+
import org.elasticsearch.test.AbstractXContentTestCase;
23+
24+
import java.io.IOException;
25+
26+
public class MigrateActionTests extends AbstractXContentTestCase<MigrateAction> {
27+
28+
@Override
29+
protected MigrateAction doParseInstance(XContentParser parser) throws IOException {
30+
return MigrateAction.parse(parser);
31+
}
32+
33+
@Override
34+
protected MigrateAction createTestInstance() {
35+
return randomInstance();
36+
}
37+
38+
static MigrateAction randomInstance() {
39+
return new MigrateAction(randomBoolean());
40+
}
41+
42+
@Override
43+
protected boolean supportsUnknownFields() {
44+
return false;
45+
}
46+
}

docs/reference/ilm/apis/explain.asciidoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ information for the step that's being performed on the index.
217217
"message": "Waiting for all shard copies to be active",
218218
"shards_left_to_allocate": -1,
219219
"all_shards_active": false,
220-
"actual_replicas": 2
220+
"number_of_replicas": 2
221221
},
222222
"phase_execution": {
223223
"policy": "my_lifecycle3",

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackClientPlugin.java

+2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
import org.elasticsearch.xpack.core.ilm.IndexLifecycleMetadata;
6767
import org.elasticsearch.xpack.core.ilm.LifecycleAction;
6868
import org.elasticsearch.xpack.core.ilm.LifecycleType;
69+
import org.elasticsearch.xpack.core.ilm.MigrateAction;
6970
import org.elasticsearch.xpack.core.ilm.ReadOnlyAction;
7071
import org.elasticsearch.xpack.core.ilm.RolloverAction;
7172
import org.elasticsearch.xpack.core.ilm.SearchableSnapshotAction;
@@ -623,6 +624,7 @@ public List<NamedWriteableRegistry.Entry> getNamedWriteables() {
623624
new NamedWriteableRegistry.Entry(LifecycleAction.class, UnfollowAction.NAME, UnfollowAction::new),
624625
new NamedWriteableRegistry.Entry(LifecycleAction.class, WaitForSnapshotAction.NAME, WaitForSnapshotAction::new),
625626
new NamedWriteableRegistry.Entry(LifecycleAction.class, SearchableSnapshotAction.NAME, SearchableSnapshotAction::new),
627+
new NamedWriteableRegistry.Entry(LifecycleAction.class, MigrateAction.NAME, MigrateAction::new),
626628
// Transforms
627629
new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, XPackField.TRANSFORM, TransformFeatureSetUsage::new),
628630
new NamedWriteableRegistry.Entry(PersistentTaskParams.class, TransformField.TASK_NAME, TransformTaskParams::new),

0 commit comments

Comments
 (0)