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
This commit is contained in:
Martijn van Groningen 2014-01-06 13:24:31 +01:00
parent 7e341cefd0
commit e6f83248a2
10 changed files with 341 additions and 8 deletions

View File

@ -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 <<modules-cluster>>.
@ -102,6 +107,12 @@ There is a specific list of settings that can be updated, those include:
`cluster.routing.allocation.disable_new_allocation`::
See <<modules-cluster>>.
[float]
===== Enable allocation
`cluster.routing.allocation.enable`::
See <<modules-cluster>>.
[float]
===== Throttling allocation

View File

@ -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`).

View File

@ -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`::

View File

@ -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).

View File

@ -50,7 +50,10 @@ import org.elasticsearch.node.settings.NodeSettingsService;
* {@link RoutingAllocation#ignoreDisable()}. Which is set if allocation are
* explicit.
* </p>
*
* @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";

View File

@ -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:
* <ul>
* <li> <code>NONE</code>, no shard allocation is allowed.
* <li> <code>NEW_PRIMARIES</code> only primary shards of new indices are allowed to be allocated
* <li> <code>PRIMARIES</code> only primary shards (of any index) are allowed to be allocated
* <li> <code>ALL</code> all shards are allowed to be allocated
* </ul>
*/
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 + "]");
}
}
}
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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));
}
}