use of org.opensearch.action.admin.cluster.reroute.ClusterRerouteRequestBuilder in project OpenSearch by opensearch-project.
the class PrimaryAllocationIT method testForceStaleReplicaToBePromotedToPrimary.
public void testForceStaleReplicaToBePromotedToPrimary() throws Exception {
logger.info("--> starting 3 nodes, 1 cluster-manager, 2 data");
String clusterManager = internalCluster().startClusterManagerOnlyNode(Settings.EMPTY);
internalCluster().startDataOnlyNodes(2);
assertAcked(client().admin().indices().prepareCreate("test").setSettings(Settings.builder().put("index.number_of_shards", 1).put("index.number_of_replicas", 1)).get());
ensureGreen();
Set<String> historyUUIDs = Arrays.stream(client().admin().indices().prepareStats("test").clear().get().getShards()).map(shard -> shard.getCommitStats().getUserData().get(Engine.HISTORY_UUID_KEY)).collect(Collectors.toSet());
createStaleReplicaScenario(clusterManager);
if (randomBoolean()) {
assertAcked(client().admin().indices().prepareClose("test").setWaitForActiveShards(0));
}
// if true, use stale replica, otherwise a completely empty copy
boolean useStaleReplica = randomBoolean();
logger.info("--> explicitly promote old primary shard");
final String idxName = "test";
ImmutableOpenIntMap<List<IndicesShardStoresResponse.StoreStatus>> storeStatuses = client().admin().indices().prepareShardStores(idxName).get().getStoreStatuses().get(idxName);
ClusterRerouteRequestBuilder rerouteBuilder = client().admin().cluster().prepareReroute();
for (IntObjectCursor<List<IndicesShardStoresResponse.StoreStatus>> shardStoreStatuses : storeStatuses) {
int shardId = shardStoreStatuses.key;
IndicesShardStoresResponse.StoreStatus storeStatus = randomFrom(shardStoreStatuses.value);
logger.info("--> adding allocation command for shard {}", shardId);
// force allocation based on node id
if (useStaleReplica) {
rerouteBuilder.add(new AllocateStalePrimaryAllocationCommand(idxName, shardId, storeStatus.getNode().getId(), true));
} else {
rerouteBuilder.add(new AllocateEmptyPrimaryAllocationCommand(idxName, shardId, storeStatus.getNode().getId(), true));
}
}
final Set<String> expectedAllocationIds = useStaleReplica ? Collections.singleton(RecoverySource.ExistingStoreRecoverySource.FORCED_ALLOCATION_ID) : Collections.emptySet();
final CountDownLatch clusterStateChangeLatch = new CountDownLatch(1);
final ClusterStateListener clusterStateListener = event -> {
final Set<String> allocationIds = event.state().metadata().index(idxName).inSyncAllocationIds(0);
if (expectedAllocationIds.equals(allocationIds)) {
clusterStateChangeLatch.countDown();
}
logger.info("expected allocation ids: {} actual allocation ids: {}", expectedAllocationIds, allocationIds);
};
final ClusterService clusterService = internalCluster().getInstance(ClusterService.class, clusterManager);
clusterService.addListener(clusterStateListener);
rerouteBuilder.get();
assertTrue(clusterStateChangeLatch.await(30, TimeUnit.SECONDS));
clusterService.removeListener(clusterStateListener);
logger.info("--> check that the stale primary shard gets allocated and that documents are available");
ensureYellow(idxName);
if (useStaleReplica == false) {
// When invoking AllocateEmptyPrimaryAllocationCommand, due to the UnassignedInfo.Reason being changed to INDEX_CREATION,
// its possible that the shard has not completed initialization, even though the cluster health is yellow, so the
// search can throw an "all shards failed" exception. We will wait until the shard initialization has completed before
// verifying the search hit count.
assertBusy(() -> assertTrue(client().admin().cluster().prepareState().get().getState().routingTable().index(idxName).allPrimaryShardsActive()));
}
ShardStats[] shardStats = client().admin().indices().prepareStats("test").setIndicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN_CLOSED).get().getShards();
for (ShardStats shardStat : shardStats) {
assertThat(shardStat.getCommitStats().getNumDocs(), equalTo(useStaleReplica ? 1 : 0));
}
// allocation id of old primary was cleaned from the in-sync set
final ClusterState state = client().admin().cluster().prepareState().get().getState();
assertEquals(Collections.singleton(state.routingTable().index(idxName).shard(0).primary.allocationId().getId()), state.metadata().index(idxName).inSyncAllocationIds(0));
Set<String> newHistoryUUIds = Stream.of(shardStats).map(shard -> shard.getCommitStats().getUserData().get(Engine.HISTORY_UUID_KEY)).collect(Collectors.toSet());
assertThat(newHistoryUUIds, everyItem(is(not(in(historyUUIDs)))));
assertThat(newHistoryUUIds, hasSize(1));
}
Aggregations