Skip to content

Commit

Permalink
Added IT for ResizeIndex During migration
Browse files Browse the repository at this point in the history
Signed-off-by: Shubh Sahu <shubhvs@amazon.com>
  • Loading branch information
Shubh Sahu committed Mar 19, 2024
1 parent 6672cbe commit ace7752
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

package org.opensearch.remotemigration;

import org.opensearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.opensearch.action.admin.indices.shrink.ResizeType;
import org.opensearch.action.support.ActiveShardCount;
import org.opensearch.client.Client;
import org.opensearch.common.settings.Settings;
import org.opensearch.indices.replication.common.ReplicationType;
import org.opensearch.test.OpenSearchIntegTestCase;

import java.util.List;

import static org.opensearch.cluster.metadata.IndexMetadata.SETTING_REPLICATION_TYPE;
import static org.opensearch.node.remotestore.RemoteStoreNodeService.MIGRATION_DIRECTION_SETTING;
import static org.opensearch.node.remotestore.RemoteStoreNodeService.REMOTE_STORE_COMPATIBILITY_MODE_SETTING;
import static org.opensearch.test.hamcrest.OpenSearchAssertions.assertAcked;

@OpenSearchIntegTestCase.ClusterScope(scope = OpenSearchIntegTestCase.Scope.TEST, numDataNodes = 0, autoManageMasterNodes = false)
public class ResizeIndexMigrationTestCase extends MigrationBaseTestCase {
private static final String TEST_INDEX = "test_index";
private final static String REMOTE_STORE_DIRECTION = "remote_store";
private final static String NONE_DIRECTION = "none";
private final static String STRICT_MODE = "strict";
private final static String MIXED_MODE = "mixed";

public void testFailResizeIndexWhileMigration() throws Exception {

internalCluster().setBootstrapClusterManagerNodeIndex(0);
List<String> cmNodes = internalCluster().startNodes(1);
Client client = internalCluster().client(cmNodes.get(0));
ClusterUpdateSettingsRequest updateSettingsRequest = new ClusterUpdateSettingsRequest();
updateSettingsRequest.persistentSettings(Settings.builder().put(REMOTE_STORE_COMPATIBILITY_MODE_SETTING.getKey(), MIXED_MODE));
assertAcked(client().admin().cluster().updateSettings(updateSettingsRequest).actionGet());

// Adding a non remote and a remote node
addRemote = false;
String nonRemoteNodeName = internalCluster().startNode();

addRemote = true;
String remoteNodeName = internalCluster().startNode();

logger.info("-->Create index on non-remote node and SETTING_REMOTE_STORE_ENABLED is false. Resize should not happen");
Settings.Builder builder = Settings.builder().put(SETTING_REPLICATION_TYPE, ReplicationType.SEGMENT);
client.admin()
.indices()
.prepareCreate(TEST_INDEX)
.setSettings(
builder.put("index.number_of_shards", 10)
.put("index.number_of_replicas", 0)
.put("index.routing.allocation.include._name", nonRemoteNodeName)
.put("index.routing.allocation.exclude._name", remoteNodeName)
)
.setWaitForActiveShards(ActiveShardCount.ALL)
.execute()
.actionGet();

updateSettingsRequest.persistentSettings(Settings.builder().put(MIGRATION_DIRECTION_SETTING.getKey(), REMOTE_STORE_DIRECTION));
assertAcked(client.admin().cluster().updateSettings(updateSettingsRequest).actionGet());

ResizeType resizeType;
int resizeShardsNum;
String cause;
switch (randomIntBetween(0, 2)) {
case 0:
resizeType = ResizeType.SHRINK;
resizeShardsNum = 5;
cause = "shrink_index";
break;
case 1:
resizeType = ResizeType.SPLIT;
resizeShardsNum = 20;
cause = "split_index";
break;
default:
resizeType = ResizeType.CLONE;
resizeShardsNum = 10;
cause = "clone_index";
}

client.admin()
.indices()
.prepareUpdateSettings(TEST_INDEX)
.setSettings(Settings.builder().put("index.blocks.write", true))
.execute()
.actionGet();

ensureGreen(TEST_INDEX);

Settings.Builder resizeSettingsBuilder = Settings.builder()
.put("index.number_of_replicas", 0)
.put("index.number_of_shards", resizeShardsNum)
.putNull("index.blocks.write");

IllegalStateException ex = expectThrows(
IllegalStateException.class,
() -> client().admin()
.indices()
.prepareResizeIndex(TEST_INDEX, "first_split")
.setResizeType(resizeType)
.setSettings(resizeSettingsBuilder.build())
.get()
);
assertEquals(
ex.getMessage(),
"index Resizing for type ["
+ resizeType
+ "] is not allowed as Cluster mode is [Mixed]"
+ " and migration direction is [Remote Store]"
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@
import org.opensearch.index.IndexSettings;
import org.opensearch.index.shard.DocsStats;
import org.opensearch.index.store.StoreStats;
import org.opensearch.node.remotestore.RemoteStoreNodeService;
import org.opensearch.threadpool.ThreadPool;
import org.opensearch.transport.TransportService;
import org.opensearch.node.remotestore.RemoteStoreNodeService;

import java.io.IOException;
import java.util.Locale;
Expand Down Expand Up @@ -164,7 +164,7 @@ protected void clusterManagerOperation(
CreateIndexClusterStateUpdateRequest updateRequest = prepareCreateIndexRequest(resizeRequest, state, i -> {
IndexShardStats shard = indicesStatsResponse.getIndex(sourceIndex).getIndexShards().get(i);
return shard == null ? null : shard.getPrimary().getDocs();
}, indicesStatsResponse.getPrimaries().store, clusterSettings,sourceIndex, targetIndex);
}, indicesStatsResponse.getPrimaries().store, clusterSettings, sourceIndex, targetIndex);

Check warning on line 167 in server/src/main/java/org/opensearch/action/admin/indices/shrink/TransportResizeAction.java

View check run for this annotation

Codecov / codecov/patch

server/src/main/java/org/opensearch/action/admin/indices/shrink/TransportResizeAction.java#L167

Added line #L167 was not covered by tests

if (indicesStatsResponse.getIndex(sourceIndex)
.getTotal()
Expand Down Expand Up @@ -235,7 +235,7 @@ static CreateIndexClusterStateUpdateRequest prepareCreateIndexRequest(
if (metadata == null) {
throw new IndexNotFoundException(sourceIndexName);
}
validateClusterModeSettings(resizeRequest.getResizeType(),metadata,clusterSettings);
validateClusterModeSettings(resizeRequest.getResizeType(), metadata, clusterSettings);
final Settings.Builder targetIndexSettingsBuilder = Settings.builder()
.put(targetIndex.settings())
.normalizePrefix(IndexMetadata.INDEX_SETTING_PREFIX);
Expand Down Expand Up @@ -374,15 +374,23 @@ protected String getClusterManagerActionName(DiscoveryNode node) {
return super.getClusterManagerActionName(node);
}

private static void validateClusterModeSettings(final ResizeType type,IndexMetadata sourceIndexMetadata,ClusterSettings clusterSettings) {
boolean isMixed = clusterSettings.get(RemoteStoreNodeService.REMOTE_STORE_COMPATIBILITY_MODE_SETTING)
private static void validateClusterModeSettings(
final ResizeType type,
IndexMetadata sourceIndexMetadata,
ClusterSettings clusterSettings
) {
boolean isMixed = clusterSettings.get(RemoteStoreNodeService.REMOTE_STORE_COMPATIBILITY_MODE_SETTING)
.equals(RemoteStoreNodeService.CompatibilityMode.MIXED);
boolean isRemoteStoreMigrationDirection = clusterSettings.get(RemoteStoreNodeService.MIGRATION_DIRECTION_SETTING)
.equals(RemoteStoreNodeService.Direction.REMOTE_STORE);
boolean isRemoteStoreEnabled = sourceIndexMetadata.getSettings().getAsBoolean(SETTING_REMOTE_STORE_ENABLED, false);
boolean isRemoteStoreEnabled = sourceIndexMetadata.getSettings().getAsBoolean(SETTING_REMOTE_STORE_ENABLED, false);
if (isMixed && isRemoteStoreMigrationDirection && !isRemoteStoreEnabled) {
throw new IllegalStateException("index Resizing for type [" + type + "] is not allowed as Cluster mode is [Mixed]"
+ " and migration direction is [Remote Store]");
throw new IllegalStateException(

Check warning on line 388 in server/src/main/java/org/opensearch/action/admin/indices/shrink/TransportResizeAction.java

View check run for this annotation

Codecov / codecov/patch

server/src/main/java/org/opensearch/action/admin/indices/shrink/TransportResizeAction.java#L388

Added line #L388 was not covered by tests
"index Resizing for type ["
+ type
+ "] is not allowed as Cluster mode is [Mixed]"
+ " and migration direction is [Remote Store]"
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,30 +55,25 @@
import org.opensearch.common.settings.Settings;
import org.opensearch.common.util.FeatureFlags;
import org.opensearch.core.common.unit.ByteSizeValue;
import org.opensearch.index.query.Rewriteable;
import org.opensearch.index.query.RewriteableTests;
import org.opensearch.index.shard.DocsStats;
import org.opensearch.index.store.StoreStats;
import org.opensearch.node.remotestore.RemoteStoreNodeService;
import org.opensearch.snapshots.EmptySnapshotsInfoService;
import org.opensearch.test.OpenSearchTestCase;
import org.opensearch.test.gateway.TestGatewayAllocator;

import static org.hamcrest.CoreMatchers.startsWith;
import static org.hamcrest.Matchers.*;
import static org.opensearch.cluster.metadata.IndexMetadata.SETTING_REMOTE_STORE_ENABLED;
import static org.opensearch.node.remotestore.RemoteStoreNodeService.CompatibilityMode;


import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import static java.util.Collections.emptyMap;
import static org.opensearch.cluster.metadata.IndexMetadata.SETTING_REMOTE_STORE_ENABLED;
import static org.opensearch.common.util.FeatureFlags.REMOTE_STORE_MIGRATION_EXPERIMENTAL;
import static org.opensearch.node.remotestore.RemoteStoreNodeService.CompatibilityMode;
import static org.opensearch.node.remotestore.RemoteStoreNodeService.MIGRATION_DIRECTION_SETTING;
import static org.opensearch.node.remotestore.RemoteStoreNodeService.REMOTE_STORE_COMPATIBILITY_MODE_SETTING;
import static org.opensearch.common.util.FeatureFlags.REMOTE_STORE_MIGRATION_EXPERIMENTAL;
import static org.hamcrest.CoreMatchers.equalTo;

public class TransportResizeActionTests extends OpenSearchTestCase {

Expand Down Expand Up @@ -108,10 +103,14 @@ private ClusterState createClusterState(String name, int numShards, int numRepli
return clusterState;
}

private ClusterSettings createClusterSettings(CompatibilityMode compatibilityMode, RemoteStoreNodeService.Direction migrationDirection) {
private ClusterSettings createClusterSettings(
CompatibilityMode compatibilityMode,
RemoteStoreNodeService.Direction migrationDirection
) {
ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
clusterSettings.applySettings(
(Settings.builder().put(REMOTE_STORE_COMPATIBILITY_MODE_SETTING.getKey(), compatibilityMode)
(Settings.builder()
.put(REMOTE_STORE_COMPATIBILITY_MODE_SETTING.getKey(), compatibilityMode)
.put(MIGRATION_DIRECTION_SETTING.getKey(), migrationDirection)).build()
);
return clusterSettings;
Expand All @@ -124,7 +123,7 @@ public void testErrorCondition() {
randomIntBetween(0, 10),
Settings.builder().put("index.blocks.write", true).build()
);
ClusterSettings clusterSettings = createClusterSettings(CompatibilityMode.STRICT,RemoteStoreNodeService.Direction.NONE);
ClusterSettings clusterSettings = createClusterSettings(CompatibilityMode.STRICT, RemoteStoreNodeService.Direction.NONE);
assertTrue(
expectThrows(
IllegalStateException.class,
Expand Down Expand Up @@ -216,7 +215,7 @@ public void testPassNumRoutingShards() {
EmptyClusterInfoService.INSTANCE,
EmptySnapshotsInfoService.INSTANCE
);
ClusterSettings clusterSettings = createClusterSettings(CompatibilityMode.STRICT,RemoteStoreNodeService.Direction.NONE);
ClusterSettings clusterSettings = createClusterSettings(CompatibilityMode.STRICT, RemoteStoreNodeService.Direction.NONE);
RoutingTable routingTable = service.reroute(clusterState, "reroute").routingTable();
clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build();
// now we start the shard
Expand Down Expand Up @@ -264,7 +263,7 @@ public void testPassNumRoutingShardsAndFail() {
EmptySnapshotsInfoService.INSTANCE
);

ClusterSettings clusterSettings = createClusterSettings(CompatibilityMode.STRICT,RemoteStoreNodeService.Direction.NONE);
ClusterSettings clusterSettings = createClusterSettings(CompatibilityMode.STRICT, RemoteStoreNodeService.Direction.NONE);
RoutingTable routingTable = service.reroute(clusterState, "reroute").routingTable();
clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build();
// now we start the shard
Expand Down Expand Up @@ -318,7 +317,7 @@ public void testShrinkIndexSettings() {
EmptySnapshotsInfoService.INSTANCE
);

ClusterSettings clusterSettings = createClusterSettings(CompatibilityMode.STRICT,RemoteStoreNodeService.Direction.NONE);
ClusterSettings clusterSettings = createClusterSettings(CompatibilityMode.STRICT, RemoteStoreNodeService.Direction.NONE);
RoutingTable routingTable = service.reroute(clusterState, "reroute").routingTable();
clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build();
// now we start the shard
Expand Down Expand Up @@ -360,7 +359,7 @@ public void testShrinkWithMaxShardSize() {
EmptySnapshotsInfoService.INSTANCE
);

ClusterSettings clusterSettings = createClusterSettings(CompatibilityMode.STRICT,RemoteStoreNodeService.Direction.NONE);
ClusterSettings clusterSettings = createClusterSettings(CompatibilityMode.STRICT, RemoteStoreNodeService.Direction.NONE);
RoutingTable routingTable = service.reroute(clusterState, "reroute").routingTable();
clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build();
// now we start the shard
Expand Down Expand Up @@ -516,7 +515,7 @@ public void testIndexBlocks() {
createClusterState(indexName, 10, 0, 40, Settings.builder().put("index.blocks.read_only", true).build())
).nodes(DiscoveryNodes.builder().add(newNode("node1"))).build();

ClusterSettings clusterSettings = createClusterSettings(CompatibilityMode.STRICT,RemoteStoreNodeService.Direction.NONE);
ClusterSettings clusterSettings = createClusterSettings(CompatibilityMode.STRICT, RemoteStoreNodeService.Direction.NONE);
// Target index will be blocked by [index.blocks.read_only=true] copied from the source index
ResizeRequest resizeRequest = new ResizeRequest("target", indexName);
ResizeType resizeType;
Expand Down Expand Up @@ -604,24 +603,27 @@ public void testIndexBlocks() {
}

public void testResizeFailuresDuringMigration() {
//We will keep all other settings correct for resize request,
//So we only need to test for the failures due to cluster setting validation while migration
// We will keep all other settings correct for resize request,
// So we only need to test for the failures due to cluster setting validation while migration
final Settings directionEnabledNodeSettings = Settings.builder().put(REMOTE_STORE_MIGRATION_EXPERIMENTAL, "true").build();
FeatureFlags.initializeFeatureFlags(directionEnabledNodeSettings);
boolean isRemoteStoreEnabled = randomBoolean();
CompatibilityMode compatibilityMode = randomFrom(CompatibilityMode.values());
RemoteStoreNodeService.Direction migrationDirection = randomFrom(RemoteStoreNodeService.Direction.values());
//If not mixed mode, then migration direction is NONE.
if(!compatibilityMode.equals(CompatibilityMode.MIXED)){
// If not mixed mode, then migration direction is NONE.
if (!compatibilityMode.equals(CompatibilityMode.MIXED)) {
migrationDirection = RemoteStoreNodeService.Direction.NONE;
}
ClusterSettings clusterSettings = createClusterSettings(compatibilityMode,migrationDirection);
ClusterSettings clusterSettings = createClusterSettings(compatibilityMode, migrationDirection);

ClusterState clusterState = ClusterState.builder(
createClusterState("source", 10, 0,40,
Settings.builder().put("index.blocks.write", true)
.put(SETTING_REMOTE_STORE_ENABLED, isRemoteStoreEnabled)
.build())
createClusterState(
"source",
10,
0,
40,
Settings.builder().put("index.blocks.write", true).put(SETTING_REMOTE_STORE_ENABLED, isRemoteStoreEnabled).build()
)
).nodes(DiscoveryNodes.builder().add(newNode("node1"))).build();
AllocationService service = new AllocationService(
new AllocationDeciders(Collections.singleton(new MaxRetryAllocationDecider())),
Expand Down Expand Up @@ -662,14 +664,14 @@ public void testResizeFailuresDuringMigration() {
.settings(Settings.builder().put("index.number_of_shards", expectedShardsNum).put("index.blocks.read_only", false).build());
final ActiveShardCount activeShardCount = randomBoolean() ? ActiveShardCount.ALL : ActiveShardCount.ONE;
resizeRequest.setWaitForActiveShards(activeShardCount);
//startsWith("index Resizing for type [")
// startsWith("index Resizing for type [")
if (compatibilityMode == CompatibilityMode.MIXED
&& migrationDirection == RemoteStoreNodeService.Direction.REMOTE_STORE
&& !isRemoteStoreEnabled) {
ClusterState finalState = clusterState;
IllegalStateException ise = expectThrows(
IllegalStateException.class,
() ->TransportResizeAction.prepareCreateIndexRequest(
() -> TransportResizeAction.prepareCreateIndexRequest(
new ResizeRequest("target", "source"),
finalState,
(i) -> stats,
Expand All @@ -679,12 +681,12 @@ public void testResizeFailuresDuringMigration() {
"target"
)
);
assertThat(
assertEquals(
ise.getMessage(),
allOf(
startsWith("index Resizing for type"),
endsWith("Cluster mode is [Mixed] and migration direction is [Remote Store]")
)
"index Resizing for type ["
+ resizeType
+ "] is not allowed as Cluster mode is [Mixed]"
+ " and migration direction is [Remote Store]"
);
} else {
CreateIndexClusterStateUpdateRequest request = TransportResizeAction.prepareCreateIndexRequest(
Expand Down

0 comments on commit ace7752

Please sign in to comment.