Search in sources :

Example 1 with ClusterRerouteRequestBuilder

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));
}
Also used : Arrays(java.util.Arrays) IndexResponse(org.opensearch.action.index.IndexResponse) Matchers.not(org.hamcrest.Matchers.not) AllocateStalePrimaryAllocationCommand(org.opensearch.cluster.routing.allocation.command.AllocateStalePrimaryAllocationCommand) Strings(org.opensearch.common.Strings) IndexShardTestCase(org.opensearch.index.shard.IndexShardTestCase) OpenSearchAssertions.assertHitCount(org.opensearch.test.hamcrest.OpenSearchAssertions.assertHitCount) Matchers.everyItem(org.hamcrest.Matchers.everyItem) QueryBuilders.matchAllQuery(org.opensearch.index.query.QueryBuilders.matchAllQuery) ClusterRerouteRequestBuilder(org.opensearch.action.admin.cluster.reroute.ClusterRerouteRequestBuilder) SETTING_NUMBER_OF_REPLICAS(org.opensearch.cluster.metadata.IndexMetadata.SETTING_NUMBER_OF_REPLICAS) EngineTestCase(org.opensearch.index.engine.EngineTestCase) ImmutableOpenIntMap(org.opensearch.common.collect.ImmutableOpenIntMap) Collection(java.util.Collection) IndicesService(org.opensearch.indices.IndicesService) Set(java.util.Set) Settings(org.opensearch.common.settings.Settings) Collectors(java.util.stream.Collectors) Engine(org.opensearch.index.engine.Engine) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) Stream(java.util.stream.Stream) GatewayAllocator(org.opensearch.gateway.GatewayAllocator) Matchers.equalTo(org.hamcrest.Matchers.equalTo) DocWriteResponse(org.opensearch.action.DocWriteResponse) Matchers.is(org.hamcrest.Matchers.is) OpenSearchIntegTestCase(org.opensearch.test.OpenSearchIntegTestCase) Matchers.in(org.hamcrest.Matchers.in) AllocateEmptyPrimaryAllocationCommand(org.opensearch.cluster.routing.allocation.command.AllocateEmptyPrimaryAllocationCommand) IntObjectCursor(com.carrotsearch.hppc.cursors.IntObjectCursor) XContentFactory.jsonBuilder(org.opensearch.common.xcontent.XContentFactory.jsonBuilder) IndexMetadata(org.opensearch.cluster.metadata.IndexMetadata) IndicesOptions(org.opensearch.action.support.IndicesOptions) ClusterStateListener(org.opensearch.cluster.ClusterStateListener) MockTransportService(org.opensearch.test.transport.MockTransportService) InternalTestCluster(org.opensearch.test.InternalTestCluster) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) ClusterState(org.opensearch.cluster.ClusterState) IndexShard(org.opensearch.index.shard.IndexShard) InternalSettingsPlugin(org.opensearch.test.InternalSettingsPlugin) Matchers.hasSize(org.hamcrest.Matchers.hasSize) OpenSearchAssertions.assertAcked(org.opensearch.test.hamcrest.OpenSearchAssertions.assertAcked) IndicesShardStoresResponse(org.opensearch.action.admin.indices.shards.IndicesShardStoresResponse) Matchers.empty(org.hamcrest.Matchers.empty) IndexNotFoundException(org.opensearch.index.IndexNotFoundException) Plugin(org.opensearch.plugins.Plugin) ActiveShardCount(org.opensearch.action.support.ActiveShardCount) ShardId(org.opensearch.index.shard.ShardId) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) Sets(org.opensearch.common.util.set.Sets) TwoPartitions(org.opensearch.test.disruption.NetworkDisruption.TwoPartitions) BulkResponse(org.opensearch.action.bulk.BulkResponse) ClusterService(org.opensearch.cluster.service.ClusterService) NetworkDisruption(org.opensearch.test.disruption.NetworkDisruption) SETTING_NUMBER_OF_SHARDS(org.opensearch.cluster.metadata.IndexMetadata.SETTING_NUMBER_OF_SHARDS) ShardStats(org.opensearch.action.admin.indices.stats.ShardStats) Collections(java.util.Collections) ShardStats(org.opensearch.action.admin.indices.stats.ShardStats) ClusterState(org.opensearch.cluster.ClusterState) IndicesShardStoresResponse(org.opensearch.action.admin.indices.shards.IndicesShardStoresResponse) Set(java.util.Set) HashSet(java.util.HashSet) ClusterRerouteRequestBuilder(org.opensearch.action.admin.cluster.reroute.ClusterRerouteRequestBuilder) AllocateStalePrimaryAllocationCommand(org.opensearch.cluster.routing.allocation.command.AllocateStalePrimaryAllocationCommand) AllocateEmptyPrimaryAllocationCommand(org.opensearch.cluster.routing.allocation.command.AllocateEmptyPrimaryAllocationCommand) CountDownLatch(java.util.concurrent.CountDownLatch) ClusterStateListener(org.opensearch.cluster.ClusterStateListener) ClusterService(org.opensearch.cluster.service.ClusterService) List(java.util.List) ArrayList(java.util.ArrayList)

Aggregations

IntObjectCursor (com.carrotsearch.hppc.cursors.IntObjectCursor)1 ArrayList (java.util.ArrayList)1 Arrays (java.util.Arrays)1 Collection (java.util.Collection)1 Collections (java.util.Collections)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Set (java.util.Set)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 ExecutionException (java.util.concurrent.ExecutionException)1 TimeUnit (java.util.concurrent.TimeUnit)1 Collectors (java.util.stream.Collectors)1 Stream (java.util.stream.Stream)1 Matchers.empty (org.hamcrest.Matchers.empty)1 Matchers.equalTo (org.hamcrest.Matchers.equalTo)1 Matchers.everyItem (org.hamcrest.Matchers.everyItem)1 Matchers.hasSize (org.hamcrest.Matchers.hasSize)1 Matchers.in (org.hamcrest.Matchers.in)1 Matchers.is (org.hamcrest.Matchers.is)1 Matchers.not (org.hamcrest.Matchers.not)1