/* * 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.routing.ShardRoutingState; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.test.ESIntegTestCase; import java.util.Set; import static org.elasticsearch.cluster.routing.allocation.decider.SameShardAllocationDecider.CLUSTER_ROUTING_ALLOCATION_SAME_HOST_SETTING; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.hamcrest.Matchers.equalTo; /** * An integration test for testing updating shard allocation/routing settings and * ensuring the updated settings take effect as expected. */ @ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.TEST, numDataNodes = 0) public class UpdateShardAllocationSettingsIT extends ESIntegTestCase { /** * Tests that updating the {@link EnableAllocationDecider} related settings works as expected. */ public void testEnableRebalance() throws InterruptedException { final String firstNode = internalCluster().startNode(); client().admin().cluster().prepareUpdateSettings().setTransientSettings(Settings.builder() .put(EnableAllocationDecider.CLUSTER_ROUTING_REBALANCE_ENABLE_SETTING.getKey(), EnableAllocationDecider.Rebalance.NONE)) .get(); // we test with 2 shards since otherwise it's pretty fragile if there are difference in the num or shards such that // all shards are relocated to the second node which is not what we want here. It's solely a test for the settings to take effect final int numShards = 2; assertAcked(prepareCreate("test").setSettings(Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0) .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, numShards))); assertAcked(prepareCreate("test_1").setSettings(Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0) .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, numShards))); ensureGreen(); assertAllShardsOnNodes("test", firstNode); assertAllShardsOnNodes("test_1", firstNode); final String secondNode = internalCluster().startNode(); // prevent via index setting but only on index test client().admin().indices().prepareUpdateSettings("test").setSettings(Settings.builder() .put(EnableAllocationDecider.INDEX_ROUTING_REBALANCE_ENABLE_SETTING.getKey(), EnableAllocationDecider.Rebalance.NONE)) .get(); client().admin().cluster().prepareReroute().get(); ensureGreen(); assertAllShardsOnNodes("test", firstNode); assertAllShardsOnNodes("test_1", firstNode); // now enable the index test to relocate since index settings override cluster settings client().admin().indices().prepareUpdateSettings("test") .setSettings(Settings.builder().put(EnableAllocationDecider.INDEX_ROUTING_REBALANCE_ENABLE_SETTING.getKey(), randomBoolean() ? EnableAllocationDecider.Rebalance.PRIMARIES : EnableAllocationDecider.Rebalance.ALL)) .get(); logger.info("--> balance index [test]"); client().admin().cluster().prepareReroute().get(); ensureGreen("test"); Set<String> test = assertAllShardsOnNodes("test", firstNode, secondNode); assertThat("index: [test] expected to be rebalanced on both nodes", test.size(), equalTo(2)); // flip the cluster wide setting such that we can also balance for index // test_1 eventually we should have one shard of each index on each node client().admin().cluster().prepareUpdateSettings() .setTransientSettings(Settings.builder().put(EnableAllocationDecider.CLUSTER_ROUTING_REBALANCE_ENABLE_SETTING.getKey(), randomBoolean() ? EnableAllocationDecider.Rebalance.PRIMARIES : EnableAllocationDecider.Rebalance.ALL)) .get(); logger.info("--> balance index [test_1]"); client().admin().cluster().prepareReroute().get(); ensureGreen("test_1"); Set<String> test_1 = assertAllShardsOnNodes("test_1", firstNode, secondNode); assertThat("index: [test_1] expected to be rebalanced on both nodes", test_1.size(), equalTo(2)); test = assertAllShardsOnNodes("test", firstNode, secondNode); assertThat("index: [test] expected to be rebalanced on both nodes", test.size(), equalTo(2)); } /** * Tests that updating the {@link SameShardAllocationDecider#CLUSTER_ROUTING_ALLOCATION_SAME_HOST_SETTING} setting works as expected. */ public void testUpdateSameHostSetting() { internalCluster().startNodes(2); // same same_host to true, since 2 nodes are started on the same host, // only primaries should be assigned client().admin().cluster().prepareUpdateSettings().setTransientSettings( Settings.builder().put(CLUSTER_ROUTING_ALLOCATION_SAME_HOST_SETTING.getKey(), true) ).get(); final String indexName = "idx"; client().admin().indices().prepareCreate(indexName).setSettings( Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1) .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 1) ).get(); ClusterState clusterState = client().admin().cluster().prepareState().get().getState(); assertFalse("replica should be unassigned", clusterState.getRoutingTable().index(indexName).shardsWithState(ShardRoutingState.UNASSIGNED).isEmpty()); // now, update the same_host setting to allow shards to be allocated to multiple nodes on // the same host - the replica should get assigned client().admin().cluster().prepareUpdateSettings().setTransientSettings( Settings.builder().put(CLUSTER_ROUTING_ALLOCATION_SAME_HOST_SETTING.getKey(), false) ).get(); clusterState = client().admin().cluster().prepareState().get().getState(); assertTrue("all shards should be assigned", clusterState.getRoutingTable().index(indexName).shardsWithState(ShardRoutingState.UNASSIGNED).isEmpty()); } }