Skip to content

GET _ilm/status returns STOPPED before it's safe to run POST _ilm/migrate_to_data_tiers #140885

@DaveCTurner

Description

@DaveCTurner

GET _ilm/status returns its response according to the responding node's last-applied cluster state, but POST _ilm/migrate_to_data_tiers requires the ILM status to be STOPPED in the last-applied cluster state on the elected master node.

Prior to #129367 these would usually be the same node, but ever since then it is more likely that the node which responds to GET _ilm/status might have applied a cluster state newer than the one on the elected master, responding with STOPPED before the point at which POST _ilm/migrate_to_data_tiers can be called.

It should be enough to move the STOPPED check inside the cluster state update task, but this needs some testing to verify that it works and I don't currently have capacity to add that testing.

diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/action/TransportMigrateToDataTiersAction.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/action/TransportMigrateToDataTiersAction.java
index 2ef2260891f0..0b95ecc28961 100644
--- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/action/TransportMigrateToDataTiersAction.java
+++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/action/TransportMigrateToDataTiersAction.java
@@ -115,21 +115,18 @@ public class TransportMigrateToDataTiersAction extends TransportMasterNodeAction
             return;
         }

-        ProjectMetadata projectMetadata = projectResolver.getProjectMetadata(state);
-        IndexLifecycleMetadata currentMetadata = projectMetadata.custom(IndexLifecycleMetadata.TYPE);
-        if (currentMetadata != null && currentILMMode(projectMetadata) != STOPPED) {
-            listener.onFailure(
-                new IllegalStateException(
-                    "stop ILM before migrating to data tiers, current state is [" + currentILMMode(projectMetadata) + "]"
-                )
-            );
-            return;
-        }
-
         final SetOnce<MigratedEntities> migratedEntities = new SetOnce<>();
         submitUnbatchedTask("migrate-to-data-tiers []", new ClusterStateUpdateTask(Priority.HIGH) {
             @Override
             public ClusterState execute(ClusterState currentState) {
+                ProjectMetadata projectMetadata = projectResolver.getProjectMetadata(currentState);
+                IndexLifecycleMetadata currentMetadata = projectMetadata.custom(IndexLifecycleMetadata.TYPE);
+                if (currentMetadata != null && currentILMMode(projectMetadata) != STOPPED) {
+                    throw new IllegalStateException(
+                        "stop ILM before migrating to data tiers, current state is [" + currentILMMode(projectMetadata) + "]"
+                    );
+                }
+
                 Tuple<ClusterState, MigratedEntities> migratedEntitiesTuple = migrateToDataTiersRouting(
                     currentState.projectState(projectId),
                     request.getNodeAttributeName(),

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions