Search in sources :

Example 11 with NodeAllocationResult

use of org.elasticsearch.cluster.routing.allocation.NodeAllocationResult in project elasticsearch by elastic.

the class ReplicaShardAllocator method findMatchingNodes.

private MatchingNodes findMatchingNodes(ShardRouting shard, RoutingAllocation allocation, TransportNodesListShardStoreMetaData.StoreFilesMetaData primaryStore, AsyncShardFetch.FetchResult<NodeStoreFilesMetaData> data, boolean explain) {
    ObjectLongMap<DiscoveryNode> nodesToSize = new ObjectLongHashMap<>();
    Map<String, NodeAllocationResult> nodeDecisions = explain ? new HashMap<>() : null;
    for (Map.Entry<DiscoveryNode, NodeStoreFilesMetaData> nodeStoreEntry : data.getData().entrySet()) {
        DiscoveryNode discoNode = nodeStoreEntry.getKey();
        TransportNodesListShardStoreMetaData.StoreFilesMetaData storeFilesMetaData = nodeStoreEntry.getValue().storeFilesMetaData();
        // we don't have any files at all, it is an empty index
        if (storeFilesMetaData.isEmpty()) {
            continue;
        }
        RoutingNode node = allocation.routingNodes().node(discoNode.getId());
        if (node == null) {
            continue;
        }
        // check if we can allocate on that node...
        // we only check for NO, since if this node is THROTTLING and it has enough "same data"
        // then we will try and assign it next time
        Decision decision = allocation.deciders().canAllocate(shard, node, allocation);
        long matchingBytes = -1;
        if (explain) {
            matchingBytes = computeMatchingBytes(primaryStore, storeFilesMetaData);
            ShardStoreInfo shardStoreInfo = new ShardStoreInfo(matchingBytes);
            nodeDecisions.put(node.nodeId(), new NodeAllocationResult(discoNode, shardStoreInfo, decision));
        }
        if (decision.type() == Decision.Type.NO) {
            continue;
        }
        if (matchingBytes < 0) {
            matchingBytes = computeMatchingBytes(primaryStore, storeFilesMetaData);
        }
        nodesToSize.put(discoNode, matchingBytes);
        if (logger.isTraceEnabled()) {
            if (matchingBytes == Long.MAX_VALUE) {
                logger.trace("{}: node [{}] has same sync id {} as primary", shard, discoNode.getName(), storeFilesMetaData.syncId());
            } else {
                logger.trace("{}: node [{}] has [{}/{}] bytes of re-usable data", shard, discoNode.getName(), new ByteSizeValue(matchingBytes), matchingBytes);
            }
        }
    }
    return new MatchingNodes(nodesToSize, nodeDecisions);
}
Also used : ObjectLongHashMap(com.carrotsearch.hppc.ObjectLongHashMap) DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) ByteSizeValue(org.elasticsearch.common.unit.ByteSizeValue) TransportNodesListShardStoreMetaData(org.elasticsearch.indices.store.TransportNodesListShardStoreMetaData) AllocateUnassignedDecision(org.elasticsearch.cluster.routing.allocation.AllocateUnassignedDecision) Decision(org.elasticsearch.cluster.routing.allocation.decider.Decision) ShardStoreInfo(org.elasticsearch.cluster.routing.allocation.NodeAllocationResult.ShardStoreInfo) RoutingNode(org.elasticsearch.cluster.routing.RoutingNode) HashMap(java.util.HashMap) ObjectLongHashMap(com.carrotsearch.hppc.ObjectLongHashMap) Map(java.util.Map) ObjectLongMap(com.carrotsearch.hppc.ObjectLongMap) NodeAllocationResult(org.elasticsearch.cluster.routing.allocation.NodeAllocationResult) NodeStoreFilesMetaData(org.elasticsearch.indices.store.TransportNodesListShardStoreMetaData.NodeStoreFilesMetaData)

Example 12 with NodeAllocationResult

use of org.elasticsearch.cluster.routing.allocation.NodeAllocationResult in project elasticsearch by elastic.

the class BaseGatewayShardAllocator method buildDecisionsForAllNodes.

/**
     * Builds decisions for all nodes in the cluster, so that the explain API can provide information on
     * allocation decisions for each node, while still waiting to allocate the shard (e.g. due to fetching shard data).
     */
protected List<NodeAllocationResult> buildDecisionsForAllNodes(ShardRouting shard, RoutingAllocation allocation) {
    List<NodeAllocationResult> results = new ArrayList<>();
    for (RoutingNode node : allocation.routingNodes()) {
        Decision decision = allocation.deciders().canAllocate(shard, node, allocation);
        results.add(new NodeAllocationResult(node.node(), null, decision));
    }
    return results;
}
Also used : RoutingNode(org.elasticsearch.cluster.routing.RoutingNode) ArrayList(java.util.ArrayList) NodeAllocationResult(org.elasticsearch.cluster.routing.allocation.NodeAllocationResult) Decision(org.elasticsearch.cluster.routing.allocation.decider.Decision) AllocationDecision(org.elasticsearch.cluster.routing.allocation.AllocationDecision) AllocateUnassignedDecision(org.elasticsearch.cluster.routing.allocation.AllocateUnassignedDecision)

Example 13 with NodeAllocationResult

use of org.elasticsearch.cluster.routing.allocation.NodeAllocationResult in project elasticsearch by elastic.

the class ClusterAllocationExplainIT method testAllocationFilteringOnIndexCreation.

public void testAllocationFilteringOnIndexCreation() throws Exception {
    logger.info("--> starting 2 nodes");
    internalCluster().startNodes(2);
    logger.info("--> creating an index with 1 primary, 0 replicas, with allocation filtering so the primary can't be assigned");
    createIndexAndIndexData(1, 0, Settings.builder().put("index.routing.allocation.include._name", "non_existent_node").build(), ActiveShardCount.NONE);
    boolean includeYesDecisions = randomBoolean();
    boolean includeDiskInfo = randomBoolean();
    ClusterAllocationExplanation explanation = runExplain(true, includeYesDecisions, includeDiskInfo);
    ShardId shardId = explanation.getShard();
    boolean isPrimary = explanation.isPrimary();
    ShardRoutingState shardRoutingState = explanation.getShardState();
    DiscoveryNode currentNode = explanation.getCurrentNode();
    UnassignedInfo unassignedInfo = explanation.getUnassignedInfo();
    ClusterInfo clusterInfo = explanation.getClusterInfo();
    AllocateUnassignedDecision allocateDecision = explanation.getShardAllocationDecision().getAllocateDecision();
    MoveDecision moveDecision = explanation.getShardAllocationDecision().getMoveDecision();
    // verify shard info
    assertEquals("idx", shardId.getIndexName());
    assertEquals(0, shardId.getId());
    assertTrue(isPrimary);
    // verify current node info
    assertNotEquals(ShardRoutingState.STARTED, shardRoutingState);
    assertNull(currentNode);
    // verify unassigned info
    assertNotNull(unassignedInfo);
    assertEquals(Reason.INDEX_CREATED, unassignedInfo.getReason());
    assertEquals(AllocationStatus.DECIDERS_NO, unassignedInfo.getLastAllocationStatus());
    // verify cluster info
    verifyClusterInfo(clusterInfo, includeDiskInfo, 2);
    // verify decision objects
    assertTrue(allocateDecision.isDecisionTaken());
    assertFalse(moveDecision.isDecisionTaken());
    assertEquals(AllocationDecision.NO, allocateDecision.getAllocationDecision());
    assertEquals("cannot allocate because allocation is not permitted to any of the nodes", allocateDecision.getExplanation());
    assertNull(allocateDecision.getAllocationId());
    assertNull(allocateDecision.getTargetNode());
    assertEquals(0L, allocateDecision.getConfiguredDelayInMillis());
    assertEquals(0L, allocateDecision.getRemainingDelayInMillis());
    assertEquals(2, allocateDecision.getNodeDecisions().size());
    for (NodeAllocationResult result : allocateDecision.getNodeDecisions()) {
        assertNotNull(result.getNode());
        assertEquals(AllocationDecision.NO, result.getNodeDecision());
        if (includeYesDecisions) {
            assertThat(result.getCanAllocateDecision().getDecisions().size(), greaterThan(1));
        } else {
            assertEquals(1, result.getCanAllocateDecision().getDecisions().size());
        }
        for (Decision d : result.getCanAllocateDecision().getDecisions()) {
            if (d.label().equals("filter")) {
                assertEquals(Decision.Type.NO, d.type());
                assertEquals("node does not match index setting [index.routing.allocation.include] filters " + "[_name:\"non_existent_node\"]", d.getExplanation());
            }
        }
    }
    // verify JSON output
    try (XContentParser parser = getParser(explanation)) {
        verifyShardInfo(parser, true, includeDiskInfo, ShardRoutingState.UNASSIGNED);
        parser.nextToken();
        assertEquals("can_allocate", parser.currentName());
        parser.nextToken();
        String allocationDecision = parser.text();
        assertTrue(allocationDecision.equals(AllocationDecision.NO.toString()) || allocationDecision.equals(AllocationDecision.AWAITING_INFO.toString()));
        parser.nextToken();
        assertEquals("allocate_explanation", parser.currentName());
        parser.nextToken();
        if (allocationDecision.equals("awaiting_info")) {
            assertEquals("cannot allocate because information about existing shard data is still being retrieved " + "from some of the nodes", parser.text());
        } else {
            assertEquals("cannot allocate because allocation is not permitted to any of the nodes", parser.text());
        }
        Map<String, AllocationDecision> nodeDecisions = new HashMap<>();
        for (String nodeName : internalCluster().getNodeNames()) {
            nodeDecisions.put(nodeName, AllocationDecision.NO);
        }
        verifyNodeDecisions(parser, nodeDecisions, includeYesDecisions, false);
        assertEquals(Token.END_OBJECT, parser.nextToken());
    }
}
Also used : DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) UnassignedInfo(org.elasticsearch.cluster.routing.UnassignedInfo) HashMap(java.util.HashMap) MoveDecision(org.elasticsearch.cluster.routing.allocation.MoveDecision) ShardRoutingState(org.elasticsearch.cluster.routing.ShardRoutingState) Matchers.containsString(org.hamcrest.Matchers.containsString) MoveDecision(org.elasticsearch.cluster.routing.allocation.MoveDecision) AllocationDecision(org.elasticsearch.cluster.routing.allocation.AllocationDecision) AllocateUnassignedDecision(org.elasticsearch.cluster.routing.allocation.AllocateUnassignedDecision) Decision(org.elasticsearch.cluster.routing.allocation.decider.Decision) ShardId(org.elasticsearch.index.shard.ShardId) ClusterInfo(org.elasticsearch.cluster.ClusterInfo) AllocationDecision(org.elasticsearch.cluster.routing.allocation.AllocationDecision) AllocateUnassignedDecision(org.elasticsearch.cluster.routing.allocation.AllocateUnassignedDecision) NodeAllocationResult(org.elasticsearch.cluster.routing.allocation.NodeAllocationResult) XContentParser(org.elasticsearch.common.xcontent.XContentParser)

Example 14 with NodeAllocationResult

use of org.elasticsearch.cluster.routing.allocation.NodeAllocationResult in project elasticsearch by elastic.

the class ClusterAllocationExplainIT method testWorseBalance.

public void testWorseBalance() throws Exception {
    logger.info("--> starting a single node");
    internalCluster().startNode();
    ensureStableCluster(1);
    logger.info("--> creating an index with 5 shards, all allocated to the single node");
    createIndexAndIndexData(5, 0);
    logger.info("--> setting balancing threshold really high, so it won't be met");
    client().admin().cluster().prepareUpdateSettings().setTransientSettings(Settings.builder().put("cluster.routing.allocation.balance.threshold", 1000.0f)).get();
    logger.info("--> starting another node, with the rebalance threshold so high, it should not get any shards");
    internalCluster().startNode();
    ensureStableCluster(2);
    boolean includeYesDecisions = randomBoolean();
    boolean includeDiskInfo = randomBoolean();
    ClusterAllocationExplanation explanation = runExplain(true, includeYesDecisions, includeDiskInfo);
    ShardId shardId = explanation.getShard();
    boolean isPrimary = explanation.isPrimary();
    ShardRoutingState shardRoutingState = explanation.getShardState();
    DiscoveryNode currentNode = explanation.getCurrentNode();
    UnassignedInfo unassignedInfo = explanation.getUnassignedInfo();
    ClusterInfo clusterInfo = explanation.getClusterInfo();
    AllocateUnassignedDecision allocateDecision = explanation.getShardAllocationDecision().getAllocateDecision();
    MoveDecision moveDecision = explanation.getShardAllocationDecision().getMoveDecision();
    // verify shard info
    assertEquals("idx", shardId.getIndexName());
    assertEquals(0, shardId.getId());
    assertTrue(isPrimary);
    // verify current node info
    assertEquals(ShardRoutingState.STARTED, shardRoutingState);
    assertNotNull(currentNode);
    // verify unassigned info
    assertNull(unassignedInfo);
    // verify cluster info
    verifyClusterInfo(clusterInfo, includeDiskInfo, 2);
    // verify decision object
    assertFalse(allocateDecision.isDecisionTaken());
    assertTrue(moveDecision.isDecisionTaken());
    assertEquals(AllocationDecision.NO, moveDecision.getAllocationDecision());
    assertEquals("cannot rebalance as no target node exists that can both allocate this shard and improve the cluster balance", moveDecision.getExplanation());
    assertTrue(moveDecision.canRemain());
    assertFalse(moveDecision.forceMove());
    assertTrue(moveDecision.canRebalanceCluster());
    assertNotNull(moveDecision.getCanRemainDecision());
    assertNull(moveDecision.getTargetNode());
    assertEquals(1, moveDecision.getCurrentNodeRanking());
    // verifying cluster rebalance decision object
    assertNotNull(moveDecision.getClusterRebalanceDecision());
    assertEquals(Decision.Type.YES, moveDecision.getClusterRebalanceDecision().type());
    for (Decision d : moveDecision.getClusterRebalanceDecision().getDecisions()) {
        assertEquals(Decision.Type.YES, d.type());
        assertNotNull(d.getExplanation());
    }
    // verify node decisions
    assertEquals(1, moveDecision.getNodeDecisions().size());
    NodeAllocationResult result = moveDecision.getNodeDecisions().get(0);
    assertNotNull(result.getNode());
    assertEquals(1, result.getWeightRanking());
    assertEquals(AllocationDecision.WORSE_BALANCE, result.getNodeDecision());
    if (includeYesDecisions) {
        assertThat(result.getCanAllocateDecision().getDecisions().size(), greaterThan(0));
    } else {
        assertEquals(0, result.getCanAllocateDecision().getDecisions().size());
    }
    for (Decision d : result.getCanAllocateDecision().getDecisions()) {
        assertEquals(Decision.Type.YES, d.type());
        assertNotNull(d.getExplanation());
    }
    // verify JSON output
    try (XContentParser parser = getParser(explanation)) {
        verifyShardInfo(parser, true, includeDiskInfo, ShardRoutingState.STARTED);
        parser.nextToken();
        assertEquals("can_remain_on_current_node", parser.currentName());
        parser.nextToken();
        assertEquals(AllocationDecision.YES.toString(), parser.text());
        parser.nextToken();
        assertEquals("can_rebalance_cluster", parser.currentName());
        parser.nextToken();
        assertEquals(AllocationDecision.YES.toString(), parser.text());
        parser.nextToken();
        assertEquals("can_rebalance_to_other_node", parser.currentName());
        parser.nextToken();
        assertEquals(AllocationDecision.NO.toString(), parser.text());
        parser.nextToken();
        assertEquals("rebalance_explanation", parser.currentName());
        parser.nextToken();
        assertEquals("cannot rebalance as no target node exists that can both allocate this shard and improve the cluster balance", parser.text());
        verifyNodeDecisions(parser, allNodeDecisions(AllocationDecision.WORSE_BALANCE, true), includeYesDecisions, false);
        assertEquals(Token.END_OBJECT, parser.nextToken());
    }
}
Also used : ShardId(org.elasticsearch.index.shard.ShardId) DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) ClusterInfo(org.elasticsearch.cluster.ClusterInfo) UnassignedInfo(org.elasticsearch.cluster.routing.UnassignedInfo) MoveDecision(org.elasticsearch.cluster.routing.allocation.MoveDecision) AllocateUnassignedDecision(org.elasticsearch.cluster.routing.allocation.AllocateUnassignedDecision) ShardRoutingState(org.elasticsearch.cluster.routing.ShardRoutingState) MoveDecision(org.elasticsearch.cluster.routing.allocation.MoveDecision) AllocationDecision(org.elasticsearch.cluster.routing.allocation.AllocationDecision) AllocateUnassignedDecision(org.elasticsearch.cluster.routing.allocation.AllocateUnassignedDecision) Decision(org.elasticsearch.cluster.routing.allocation.decider.Decision) NodeAllocationResult(org.elasticsearch.cluster.routing.allocation.NodeAllocationResult) XContentParser(org.elasticsearch.common.xcontent.XContentParser)

Example 15 with NodeAllocationResult

use of org.elasticsearch.cluster.routing.allocation.NodeAllocationResult in project elasticsearch by elastic.

the class ClusterAllocationExplainIT method testCannotAllocateStaleReplicaExplanation.

public void testCannotAllocateStaleReplicaExplanation() throws Exception {
    logger.info("--> starting 3 nodes");
    final String masterNode = internalCluster().startNode();
    // start replica node first, so it's path will be used first when we start a node after
    // stopping all of them at end of test.
    final String replicaNode = internalCluster().startNode();
    final String primaryNode = internalCluster().startNode();
    logger.info("--> creating an index with 1 primary and 1 replica");
    createIndexAndIndexData(1, 1, Settings.builder().put("index.routing.allocation.include._name", primaryNode).put("index.routing.allocation.exclude._name", masterNode).build(), ActiveShardCount.ONE);
    client().admin().indices().prepareUpdateSettings("idx").setSettings(Settings.builder().put("index.routing.allocation.include._name", (String) null)).get();
    ensureGreen();
    assertThat(replicaNode().getName(), equalTo(replicaNode));
    assertThat(primaryNodeName(), equalTo(primaryNode));
    logger.info("--> stop node with the replica shard");
    internalCluster().stopRandomNode(InternalTestCluster.nameFilter(replicaNode));
    logger.info("--> index more data, now the replica is stale");
    indexData();
    logger.info("--> stop the node with the primary");
    internalCluster().stopRandomNode(InternalTestCluster.nameFilter(primaryNode));
    logger.info("--> restart the node with the stale replica");
    String restartedNode = internalCluster().startDataOnlyNode();
    // wait for the master to finish processing join.
    ensureClusterSizeConsistency();
    // wait until the system has fetched shard data and we know there is no valid shard copy
    assertBusy(() -> {
        ClusterAllocationExplanation explanation = client().admin().cluster().prepareAllocationExplain().setIndex("idx").setShard(0).setPrimary(true).get().getExplanation();
        assertTrue(explanation.getShardAllocationDecision().getAllocateDecision().isDecisionTaken());
        assertEquals(AllocationDecision.NO_VALID_SHARD_COPY, explanation.getShardAllocationDecision().getAllocateDecision().getAllocationDecision());
    });
    boolean includeYesDecisions = randomBoolean();
    boolean includeDiskInfo = randomBoolean();
    ClusterAllocationExplanation explanation = runExplain(true, includeYesDecisions, includeDiskInfo);
    ShardId shardId = explanation.getShard();
    boolean isPrimary = explanation.isPrimary();
    ShardRoutingState shardRoutingState = explanation.getShardState();
    DiscoveryNode currentNode = explanation.getCurrentNode();
    UnassignedInfo unassignedInfo = explanation.getUnassignedInfo();
    AllocateUnassignedDecision allocateDecision = explanation.getShardAllocationDecision().getAllocateDecision();
    MoveDecision moveDecision = explanation.getShardAllocationDecision().getMoveDecision();
    // verify shard info
    assertEquals("idx", shardId.getIndexName());
    assertEquals(0, shardId.getId());
    assertTrue(isPrimary);
    // verify current node info
    assertEquals(ShardRoutingState.UNASSIGNED, shardRoutingState);
    assertNull(currentNode);
    // verify unassigned info
    assertNotNull(unassignedInfo);
    // verify decision object
    assertTrue(allocateDecision.isDecisionTaken());
    assertFalse(moveDecision.isDecisionTaken());
    assertEquals(AllocationDecision.NO_VALID_SHARD_COPY, allocateDecision.getAllocationDecision());
    assertEquals(2, allocateDecision.getNodeDecisions().size());
    for (NodeAllocationResult nodeAllocationResult : allocateDecision.getNodeDecisions()) {
        if (nodeAllocationResult.getNode().getName().equals(restartedNode)) {
            assertNotNull(nodeAllocationResult.getShardStoreInfo());
            assertNotNull(nodeAllocationResult.getShardStoreInfo().getAllocationId());
            assertFalse(nodeAllocationResult.getShardStoreInfo().isInSync());
            assertNull(nodeAllocationResult.getShardStoreInfo().getStoreException());
        } else {
            assertNotNull(nodeAllocationResult.getShardStoreInfo());
            assertNull(nodeAllocationResult.getShardStoreInfo().getAllocationId());
            assertFalse(nodeAllocationResult.getShardStoreInfo().isInSync());
            assertNull(nodeAllocationResult.getShardStoreInfo().getStoreException());
        }
    }
    // verify JSON output
    try (XContentParser parser = getParser(explanation)) {
        verifyShardInfo(parser, true, includeDiskInfo, ShardRoutingState.UNASSIGNED);
        parser.nextToken();
        assertEquals("can_allocate", parser.currentName());
        parser.nextToken();
        assertEquals(AllocationDecision.NO_VALID_SHARD_COPY.toString(), parser.text());
        parser.nextToken();
        assertEquals("allocate_explanation", parser.currentName());
        parser.nextToken();
        assertEquals("cannot allocate because all found copies of the shard are either stale or corrupt", parser.text());
        verifyStaleShardCopyNodeDecisions(parser, 2, Collections.singleton(restartedNode));
    }
}
Also used : ShardId(org.elasticsearch.index.shard.ShardId) DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) UnassignedInfo(org.elasticsearch.cluster.routing.UnassignedInfo) MoveDecision(org.elasticsearch.cluster.routing.allocation.MoveDecision) AllocateUnassignedDecision(org.elasticsearch.cluster.routing.allocation.AllocateUnassignedDecision) Matchers.containsString(org.hamcrest.Matchers.containsString) ShardRoutingState(org.elasticsearch.cluster.routing.ShardRoutingState) NodeAllocationResult(org.elasticsearch.cluster.routing.allocation.NodeAllocationResult) XContentParser(org.elasticsearch.common.xcontent.XContentParser)

Aggregations

NodeAllocationResult (org.elasticsearch.cluster.routing.allocation.NodeAllocationResult)15 DiscoveryNode (org.elasticsearch.cluster.node.DiscoveryNode)13 AllocateUnassignedDecision (org.elasticsearch.cluster.routing.allocation.AllocateUnassignedDecision)13 Decision (org.elasticsearch.cluster.routing.allocation.decider.Decision)12 UnassignedInfo (org.elasticsearch.cluster.routing.UnassignedInfo)10 ShardRoutingState (org.elasticsearch.cluster.routing.ShardRoutingState)9 AllocationDecision (org.elasticsearch.cluster.routing.allocation.AllocationDecision)9 MoveDecision (org.elasticsearch.cluster.routing.allocation.MoveDecision)9 XContentParser (org.elasticsearch.common.xcontent.XContentParser)9 ShardId (org.elasticsearch.index.shard.ShardId)9 ClusterInfo (org.elasticsearch.cluster.ClusterInfo)8 Matchers.containsString (org.hamcrest.Matchers.containsString)6 HashMap (java.util.HashMap)5 RoutingNode (org.elasticsearch.cluster.routing.RoutingNode)4 ArrayList (java.util.ArrayList)3 ObjectLongHashMap (com.carrotsearch.hppc.ObjectLongHashMap)2 ObjectLongMap (com.carrotsearch.hppc.ObjectLongMap)2 Map (java.util.Map)2 IndexMetaData (org.elasticsearch.cluster.metadata.IndexMetaData)2 NodeGatewayStartedShards (org.elasticsearch.gateway.TransportNodesListGatewayStartedShards.NodeGatewayStartedShards)2