From e6f83248a2d0608b67baa6afa93ab4fd204eb101 Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Mon, 6 Jan 2014 13:24:31 +0100 Subject: [PATCH] Deprecated disable allocation decider which has the following options: `allocation.disable_new_allocation`, `allocation.disable_allocation`, `allocation.disable_replica_allocation`, in favour for the enable allocation decider which has a single option `allocation.enable` wich can be set to the following values: `none`, `new_primaries`, `primaries` and `all` (default). Closes #4488 --- .../cluster/update-settings.asciidoc | 11 ++ .../indices/update-settings.asciidoc | 15 +- docs/reference/modules/cluster.asciidoc | 16 +- .../decider/AllocationDecidersModule.java | 1 + .../decider/DisableAllocationDecider.java | 3 + .../decider/EnableAllocationDecider.java | 122 +++++++++++++++ .../ClusterDynamicSettingsModule.java | 1 + .../settings/IndexDynamicSettingsModule.java | 2 + .../allocation/ClusterRerouteTests.java | 30 +++- .../decider/EnableAllocationTests.java | 148 ++++++++++++++++++ 10 files changed, 341 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/elasticsearch/cluster/routing/allocation/decider/EnableAllocationDecider.java create mode 100644 src/test/java/org/elasticsearch/cluster/routing/allocation/decider/EnableAllocationTests.java diff --git a/docs/reference/cluster/update-settings.asciidoc b/docs/reference/cluster/update-settings.asciidoc index c8d763d952d..4e608683b3a 100644 --- a/docs/reference/cluster/update-settings.asciidoc +++ b/docs/reference/cluster/update-settings.asciidoc @@ -93,6 +93,11 @@ There is a specific list of settings that can be updated, those include: [float] ===== Disable allocation +added[1.0.0.RC1] + +All the disable allocation settings have been deprecated in favour for +`cluster.routing.allocation.enable` setting. + `cluster.routing.allocation.disable_allocation`:: See <>. @@ -102,6 +107,12 @@ There is a specific list of settings that can be updated, those include: `cluster.routing.allocation.disable_new_allocation`:: See <>. +[float] +===== Enable allocation + +`cluster.routing.allocation.enable`:: + See <>. + [float] ===== Throttling allocation diff --git a/docs/reference/indices/update-settings.asciidoc b/docs/reference/indices/update-settings.asciidoc index ae0316f7e0e..19af576d75d 100644 --- a/docs/reference/indices/update-settings.asciidoc +++ b/docs/reference/indices/update-settings.asciidoc @@ -105,13 +105,22 @@ settings API: Only nodes matching all rules will be allowed to host shards from the index. `index.routing.allocation.disable_allocation`:: - Disable allocation. Defaults to `false`. + Disable allocation. Defaults to `false`. Deprecated in favour for `index.routing.allocation.enable`. `index.routing.allocation.disable_new_allocation`:: - Disable new allocation. Defaults to `false`. + Disable new allocation. Defaults to `false`. Deprecated in favour for `index.routing.allocation.enable`. `index.routing.allocation.disable_replica_allocation`:: - Disable replica allocation. Defaults to `false`. + Disable replica allocation. Defaults to `false`. Deprecated in favour for `index.routing.allocation.enable`. + +added[1.0.0.RC1] + +`index.routing.allocation.enable`:: + Enables shard allocation for a specific index. It can be set to: + * `all` (default) - Allows shard allocation for all shards. + * `primaries` - Allows shard allocation only for primary shards. + * `new_primaries` - Allows shard allocation only for primary shards for new indices. + * `none` - No shard allocation is allowed. `index.routing.allocation.total_shards_per_node`:: Controls the total number of shards allowed to be allocated on a single node. Defaults to unbounded (`-1`). diff --git a/docs/reference/modules/cluster.asciidoc b/docs/reference/modules/cluster.asciidoc index dd03ce7a1cb..f39ec8ed672 100644 --- a/docs/reference/modules/cluster.asciidoc +++ b/docs/reference/modules/cluster.asciidoc @@ -35,12 +35,22 @@ The following settings may be used: How many concurrent recoveries are allowed to happen on a node. Defaults to `2`. +added[1.0.0.RC1] + +`cluster.routing.allocation.enable`:: + Controls shard allocation for all indices, by allowing specific + kinds of shard to be allocated. Can be set to: + * `all` (default) - Allows shard allocation for all kinds of shards. + * `primaries` - Allows shard allocation only for primary shards. + * `new_primaries` - Allows shard allocation only for primary shards for new indices. + * `none` - No shard allocations of any kind are allowed for all indices. `cluster.routing.allocation.disable_new_allocation`:: Allows to disable new primary allocations. Note, this will prevent allocations for newly created indices. This setting really make sense when dynamically updating it using the cluster update - settings API. + settings API. This setting has been deprecated in favour + for `cluster.routing.allocation.enable`. `cluster.routing.allocation.disable_allocation`:: @@ -49,12 +59,14 @@ The following settings may be used: above). Note, a replica will still be promoted to primary if one does not exist. This setting really make sense when dynamically updating it using the cluster update settings API. + This setting has been deprecated in favour for `cluster.routing.allocation.enable`. `cluster.routing.allocation.disable_replica_allocation`:: Allows to disable only replica allocation. Similar to the previous setting, mainly make sense when using it dynamically using the - cluster update settings API. + cluster update settings API. This setting has been deprecated in + favour for `cluster.routing.allocation.enable`. `indices.recovery.concurrent_streams`:: diff --git a/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/AllocationDecidersModule.java b/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/AllocationDecidersModule.java index 29acc3cbba7..6f19e9557d7 100644 --- a/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/AllocationDecidersModule.java +++ b/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/AllocationDecidersModule.java @@ -70,6 +70,7 @@ public class AllocationDecidersModule extends AbstractModule { add(RebalanceOnlyWhenActiveAllocationDecider.class). add(ClusterRebalanceAllocationDecider.class). add(ConcurrentRebalanceAllocationDecider.class). + add(EnableAllocationDecider.class). // new enable allocation logic should proceed old disable allocation logic add(DisableAllocationDecider.class). add(AwarenessAllocationDecider.class). add(ShardsLimitAllocationDecider.class). diff --git a/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/DisableAllocationDecider.java b/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/DisableAllocationDecider.java index fa0f1190f21..0ba206c77e1 100644 --- a/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/DisableAllocationDecider.java +++ b/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/DisableAllocationDecider.java @@ -50,7 +50,10 @@ import org.elasticsearch.node.settings.NodeSettingsService; * {@link RoutingAllocation#ignoreDisable()}. Which is set if allocation are * explicit. *

+ * + * @deprecated In favour for {@link EnableAllocationDecider}. */ +@Deprecated public class DisableAllocationDecider extends AllocationDecider { public static final String CLUSTER_ROUTING_ALLOCATION_DISABLE_NEW_ALLOCATION = "cluster.routing.allocation.disable_new_allocation"; diff --git a/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/EnableAllocationDecider.java b/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/EnableAllocationDecider.java new file mode 100644 index 00000000000..13aafe41259 --- /dev/null +++ b/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/EnableAllocationDecider.java @@ -0,0 +1,122 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.cluster.routing.allocation.decider; + +import org.elasticsearch.ElasticsearchIllegalArgumentException; +import org.elasticsearch.ElasticsearchIllegalStateException; +import org.elasticsearch.cluster.routing.RoutingNode; +import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.node.settings.NodeSettingsService; + +import java.util.Locale; + +/** + * This allocation decider allows shard allocations via the cluster wide settings {@link #CLUSTER_ROUTING_ALLOCATION_ENABLE} + * and the per index setting {@link #INDEX_ROUTING_ALLOCATION_ENABLE}. The per index settings overrides the cluster wide + * setting. Depending on the + * + * Both settings can have the following values: + *
    + *
  • NONE, no shard allocation is allowed. + *
  • NEW_PRIMARIES only primary shards of new indices are allowed to be allocated + *
  • PRIMARIES only primary shards (of any index) are allowed to be allocated + *
  • ALL all shards are allowed to be allocated + *
+ */ +public class EnableAllocationDecider extends AllocationDecider implements NodeSettingsService.Listener { + + public static final String CLUSTER_ROUTING_ALLOCATION_ENABLE = "cluster.routing.allocation.enable"; + public static final String INDEX_ROUTING_ALLOCATION_ENABLE = "index.routing.allocation.enable"; + + private volatile Allocation enable; + + @Inject + public EnableAllocationDecider(Settings settings, NodeSettingsService nodeSettingsService) { + super(settings); + this.enable = Allocation.parse(settings.get(CLUSTER_ROUTING_ALLOCATION_ENABLE, Allocation.ALL.name())); + nodeSettingsService.addListener(this); + } + + @Override + public Decision canAllocate(ShardRouting shardRouting, RoutingNode node, RoutingAllocation allocation) { + if (allocation.ignoreDisable()) { + return Decision.YES; + } + + Settings indexSettings = allocation.routingNodes().metaData().index(shardRouting.index()).settings(); + String enableIndexValue = indexSettings.get(INDEX_ROUTING_ALLOCATION_ENABLE); + final Allocation enable; + if (enableIndexValue != null) { + enable = Allocation.parse(enableIndexValue); + } else { + enable = this.enable; + } + switch (enable) { + case ALL: + return Decision.YES; + case NONE: + return Decision.NO; + case NEW_PRIMARIES: + if (shardRouting.primary() && !allocation.routingNodes().routingTable().index(shardRouting.index()).shard(shardRouting.id()).primaryAllocatedPostApi()) { + return Decision.YES; + } else { + return Decision.NO; + } + case PRIMARIES: + return shardRouting.primary() ? Decision.YES : Decision.NO; + default: + throw new ElasticsearchIllegalStateException("Unknown allocation option"); + } + } + + @Override + public void onRefreshSettings(Settings settings) { + Allocation enable = Allocation.parse(settings.get(CLUSTER_ROUTING_ALLOCATION_ENABLE, this.enable.name())); + if (enable != this.enable) { + logger.info("updating [cluster.routing.allocation.enable] from [{}] to [{}]", this.enable, enable); + EnableAllocationDecider.this.enable = enable; + } + } + + public enum Allocation { + + NONE, + NEW_PRIMARIES, + PRIMARIES, + ALL; + + public static Allocation parse(String strValue) { + if (strValue == null) { + return null; + } else { + strValue = strValue.toUpperCase(Locale.ROOT); + try { + return Allocation.valueOf(strValue); + } catch (IllegalArgumentException e) { + throw new ElasticsearchIllegalArgumentException("Illegal allocation.enable value [" + strValue + "]"); + } + } + } + } + +} diff --git a/src/main/java/org/elasticsearch/cluster/settings/ClusterDynamicSettingsModule.java b/src/main/java/org/elasticsearch/cluster/settings/ClusterDynamicSettingsModule.java index 3c7cc8b0388..d4a8881e711 100644 --- a/src/main/java/org/elasticsearch/cluster/settings/ClusterDynamicSettingsModule.java +++ b/src/main/java/org/elasticsearch/cluster/settings/ClusterDynamicSettingsModule.java @@ -47,6 +47,7 @@ public class ClusterDynamicSettingsModule extends AbstractModule { clusterDynamicSettings.addDynamicSetting(BalancedShardsAllocator.SETTING_SHARD_BALANCE_FACTOR, Validator.FLOAT); clusterDynamicSettings.addDynamicSetting(BalancedShardsAllocator.SETTING_THRESHOLD, Validator.NON_NEGATIVE_FLOAT); clusterDynamicSettings.addDynamicSetting(ConcurrentRebalanceAllocationDecider.CLUSTER_ROUTING_ALLOCATION_CLUSTER_CONCURRENT_REBALANCE, Validator.INTEGER); + clusterDynamicSettings.addDynamicSetting(EnableAllocationDecider.CLUSTER_ROUTING_ALLOCATION_ENABLE); clusterDynamicSettings.addDynamicSetting(DisableAllocationDecider.CLUSTER_ROUTING_ALLOCATION_DISABLE_NEW_ALLOCATION); clusterDynamicSettings.addDynamicSetting(DisableAllocationDecider.CLUSTER_ROUTING_ALLOCATION_DISABLE_ALLOCATION); clusterDynamicSettings.addDynamicSetting(DisableAllocationDecider.CLUSTER_ROUTING_ALLOCATION_DISABLE_REPLICA_ALLOCATION); diff --git a/src/main/java/org/elasticsearch/index/settings/IndexDynamicSettingsModule.java b/src/main/java/org/elasticsearch/index/settings/IndexDynamicSettingsModule.java index 40d62168984..340ecf92c74 100644 --- a/src/main/java/org/elasticsearch/index/settings/IndexDynamicSettingsModule.java +++ b/src/main/java/org/elasticsearch/index/settings/IndexDynamicSettingsModule.java @@ -21,6 +21,7 @@ package org.elasticsearch.index.settings; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.routing.allocation.decider.DisableAllocationDecider; +import org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider; import org.elasticsearch.cluster.routing.allocation.decider.FilterAllocationDecider; import org.elasticsearch.cluster.routing.allocation.decider.ShardsLimitAllocationDecider; import org.elasticsearch.cluster.settings.DynamicSettings; @@ -55,6 +56,7 @@ public class IndexDynamicSettingsModule extends AbstractModule { indexDynamicSettings.addDynamicSetting(FilterAllocationDecider.INDEX_ROUTING_REQUIRE_GROUP + "*"); indexDynamicSettings.addDynamicSetting(FilterAllocationDecider.INDEX_ROUTING_INCLUDE_GROUP + "*"); indexDynamicSettings.addDynamicSetting(FilterAllocationDecider.INDEX_ROUTING_EXCLUDE_GROUP + "*"); + indexDynamicSettings.addDynamicSetting(EnableAllocationDecider.INDEX_ROUTING_ALLOCATION_ENABLE); indexDynamicSettings.addDynamicSetting(DisableAllocationDecider.INDEX_ROUTING_ALLOCATION_DISABLE_ALLOCATION); indexDynamicSettings.addDynamicSetting(DisableAllocationDecider.INDEX_ROUTING_ALLOCATION_DISABLE_NEW_ALLOCATION); indexDynamicSettings.addDynamicSetting(DisableAllocationDecider.INDEX_ROUTING_ALLOCATION_DISABLE_REPLICA_ALLOCATION); diff --git a/src/test/java/org/elasticsearch/cluster/allocation/ClusterRerouteTests.java b/src/test/java/org/elasticsearch/cluster/allocation/ClusterRerouteTests.java index bfa2b534ffb..3b969653477 100644 --- a/src/test/java/org/elasticsearch/cluster/allocation/ClusterRerouteTests.java +++ b/src/test/java/org/elasticsearch/cluster/allocation/ClusterRerouteTests.java @@ -26,6 +26,7 @@ import org.elasticsearch.cluster.routing.ShardRoutingState; import org.elasticsearch.cluster.routing.allocation.command.AllocateAllocationCommand; import org.elasticsearch.cluster.routing.allocation.command.MoveAllocationCommand; import org.elasticsearch.cluster.routing.allocation.decider.DisableAllocationDecider; +import org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider; import org.elasticsearch.common.Priority; import org.elasticsearch.common.io.FileSystemUtils; import org.elasticsearch.common.logging.ESLogger; @@ -51,14 +52,25 @@ public class ClusterRerouteTests extends ElasticsearchIntegrationTest { private final ESLogger logger = Loggers.getLogger(ClusterRerouteTests.class); - @Test - public void rerouteWithCommands() throws Exception { + public void rerouteWithCommands_disableAllocationSettings() throws Exception { Settings commonSettings = settingsBuilder() .put(DisableAllocationDecider.CLUSTER_ROUTING_ALLOCATION_DISABLE_NEW_ALLOCATION, true) .put(DisableAllocationDecider.CLUSTER_ROUTING_ALLOCATION_DISABLE_ALLOCATION, true) .build(); + rerouteWithCommands(commonSettings); + } + @Test + public void rerouteWithCommands_enableAllocationSettings() throws Exception { + Settings commonSettings = settingsBuilder() + .put(EnableAllocationDecider.CLUSTER_ROUTING_ALLOCATION_ENABLE, EnableAllocationDecider.Allocation.NONE.name()) + .put("gateway.type", "local") + .build(); + rerouteWithCommands(commonSettings); + } + + private void rerouteWithCommands(Settings commonSettings) throws Exception { String node_1 = cluster().startNode(commonSettings); String node_2 = cluster().startNode(commonSettings); @@ -116,13 +128,25 @@ public class ClusterRerouteTests extends ElasticsearchIntegrationTest { } @Test - public void rerouteWithAllocateLocalGateway() throws Exception { + public void rerouteWithAllocateLocalGateway_disableAllocationSettings() throws Exception { Settings commonSettings = settingsBuilder() .put(DisableAllocationDecider.CLUSTER_ROUTING_ALLOCATION_DISABLE_NEW_ALLOCATION, true) .put(DisableAllocationDecider.CLUSTER_ROUTING_ALLOCATION_DISABLE_ALLOCATION, true) .put("gateway.type", "local") .build(); + rerouteWithAllocateLocalGateway(commonSettings); + } + @Test + public void rerouteWithAllocateLocalGateway_enableAllocationSettings() throws Exception { + Settings commonSettings = settingsBuilder() + .put(EnableAllocationDecider.CLUSTER_ROUTING_ALLOCATION_ENABLE, EnableAllocationDecider.Allocation.NONE.name()) + .put("gateway.type", "local") + .build(); + rerouteWithAllocateLocalGateway(commonSettings); + } + + private void rerouteWithAllocateLocalGateway(Settings commonSettings) throws Exception { logger.info("--> starting 2 nodes"); String node_1 = cluster().startNode(commonSettings); cluster().startNode(commonSettings); diff --git a/src/test/java/org/elasticsearch/cluster/routing/allocation/decider/EnableAllocationTests.java b/src/test/java/org/elasticsearch/cluster/routing/allocation/decider/EnableAllocationTests.java new file mode 100644 index 00000000000..595b25891c8 --- /dev/null +++ b/src/test/java/org/elasticsearch/cluster/routing/allocation/decider/EnableAllocationTests.java @@ -0,0 +1,148 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.cluster.routing.allocation.decider; + +import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.cluster.node.DiscoveryNodes; +import org.elasticsearch.cluster.routing.RoutingTable; +import org.elasticsearch.cluster.routing.allocation.AllocationService; +import org.elasticsearch.common.logging.ESLogger; +import org.elasticsearch.common.logging.Loggers; +import org.elasticsearch.common.settings.ImmutableSettings; +import org.elasticsearch.test.ElasticsearchAllocationTestCase; +import org.junit.Test; + +import static org.elasticsearch.cluster.routing.ShardRoutingState.INITIALIZING; +import static org.elasticsearch.cluster.routing.ShardRoutingState.STARTED; +import static org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider.*; +import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder; +import static org.hamcrest.Matchers.equalTo; + +/** + */ +public class EnableAllocationTests extends ElasticsearchAllocationTestCase { + + private final ESLogger logger = Loggers.getLogger(EnableAllocationTests.class); + + @Test + public void testClusterEnableNone() { + AllocationService strategy = createAllocationService(settingsBuilder() + .put(CLUSTER_ROUTING_ALLOCATION_ENABLE, Allocation.NONE.name()) + .build()); + + logger.info("Building initial routing table"); + + MetaData metaData = MetaData.builder() + .put(IndexMetaData.builder("test").numberOfShards(1).numberOfReplicas(1)) + .build(); + + RoutingTable routingTable = RoutingTable.builder() + .addAsNew(metaData.index("test")) + .build(); + + ClusterState clusterState = ClusterState.builder().metaData(metaData).routingTable(routingTable).build(); + + logger.info("--> adding two nodes and do rerouting"); + clusterState = ClusterState.builder(clusterState).nodes(DiscoveryNodes.builder() + .put(newNode("node1")) + .put(newNode("node2")) + ).build(); + routingTable = strategy.reroute(clusterState).routingTable(); + clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build(); + assertThat(clusterState.routingNodes().shardsWithState(INITIALIZING).size(), equalTo(0)); + + } + + @Test + public void testClusterEnableOnlyPrimaries() { + AllocationService strategy = createAllocationService(settingsBuilder() + .put(CLUSTER_ROUTING_ALLOCATION_ENABLE, Allocation.PRIMARIES.name()) + .build()); + + logger.info("Building initial routing table"); + + MetaData metaData = MetaData.builder() + .put(IndexMetaData.builder("test").numberOfShards(1).numberOfReplicas(1)) + .build(); + + RoutingTable routingTable = RoutingTable.builder() + .addAsNew(metaData.index("test")) + .build(); + + ClusterState clusterState = ClusterState.builder().metaData(metaData).routingTable(routingTable).build(); + + logger.info("--> adding two nodes do rerouting"); + clusterState = ClusterState.builder(clusterState).nodes(DiscoveryNodes.builder() + .put(newNode("node1")) + .put(newNode("node2")) + ).build(); + routingTable = strategy.reroute(clusterState).routingTable(); + clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build(); + assertThat(clusterState.routingNodes().shardsWithState(INITIALIZING).size(), equalTo(1)); + + logger.info("--> start the shards (primaries)"); + routingTable = strategy.applyStartedShards(clusterState, clusterState.routingNodes().shardsWithState(INITIALIZING)).routingTable(); + clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build(); + + assertThat(clusterState.routingNodes().shardsWithState(INITIALIZING).size(), equalTo(0)); + } + + @Test + public void testIndexEnableNone() { + AllocationService strategy = createAllocationService(settingsBuilder() + .build()); + + MetaData metaData = MetaData.builder() + .put(IndexMetaData.builder("disabled").settings(ImmutableSettings.builder() + .put(INDEX_ROUTING_ALLOCATION_ENABLE, Allocation.NONE.name())) + .numberOfShards(1).numberOfReplicas(1)) + .put(IndexMetaData.builder("enabled").numberOfShards(1).numberOfReplicas(1)) + .build(); + + RoutingTable routingTable = RoutingTable.builder() + .addAsNew(metaData.index("disabled")) + .addAsNew(metaData.index("enabled")) + .build(); + + ClusterState clusterState = ClusterState.builder().metaData(metaData).routingTable(routingTable).build(); + + logger.info("--> adding two nodes and do rerouting"); + clusterState = ClusterState.builder(clusterState).nodes(DiscoveryNodes.builder() + .put(newNode("node1")) + .put(newNode("node2")) + ).build(); + routingTable = strategy.reroute(clusterState).routingTable(); + clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build(); + assertThat(clusterState.routingNodes().shardsWithState(INITIALIZING).size(), equalTo(1)); + logger.info("--> start the shards (primaries)"); + routingTable = strategy.applyStartedShards(clusterState, clusterState.routingNodes().shardsWithState(INITIALIZING)).routingTable(); + clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build(); + logger.info("--> start the shards (replicas)"); + routingTable = strategy.applyStartedShards(clusterState, clusterState.routingNodes().shardsWithState(INITIALIZING)).routingTable(); + clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build(); + + logger.info("--> verify only enabled index has been routed"); + assertThat(clusterState.readOnlyRoutingNodes().shardsWithState("enabled", STARTED).size(), equalTo(2)); + assertThat(clusterState.readOnlyRoutingNodes().shardsWithState("disabled", STARTED).size(), equalTo(0)); + } + +}