use of org.opensearch.cluster.routing.allocation.RerouteExplanation in project OpenSearch by opensearch-project.
the class CancelAllocationCommand method execute.
@Override
public RerouteExplanation execute(RoutingAllocation allocation, boolean explain) {
DiscoveryNode discoNode = allocation.nodes().resolveNode(node);
ShardRouting shardRouting = null;
RoutingNodes routingNodes = allocation.routingNodes();
RoutingNode routingNode = routingNodes.node(discoNode.getId());
IndexMetadata indexMetadata = null;
if (routingNode != null) {
indexMetadata = allocation.metadata().index(index());
if (indexMetadata == null) {
throw new IndexNotFoundException(index());
}
ShardId shardId = new ShardId(indexMetadata.getIndex(), shardId());
shardRouting = routingNode.getByShardId(shardId);
}
if (shardRouting == null) {
if (explain) {
return new RerouteExplanation(this, allocation.decision(Decision.NO, "cancel_allocation_command", "can't cancel " + shardId + ", failed to find it on node " + discoNode));
}
throw new IllegalArgumentException("[cancel_allocation] can't cancel " + shardId + ", failed to find it on node " + discoNode);
}
if (shardRouting.primary() && allowPrimary == false) {
if ((shardRouting.initializing() && shardRouting.relocatingNodeId() != null) == false) {
// only allow cancelling initializing shard of primary relocation without allowPrimary flag
if (explain) {
return new RerouteExplanation(this, allocation.decision(Decision.NO, "cancel_allocation_command", "can't cancel " + shardId + " on node " + discoNode + ", shard is primary and " + shardRouting.state().name().toLowerCase(Locale.ROOT)));
}
throw new IllegalArgumentException("[cancel_allocation] can't cancel " + shardId + " on node " + discoNode + ", shard is primary and " + shardRouting.state().name().toLowerCase(Locale.ROOT));
}
}
routingNodes.failShard(LogManager.getLogger(CancelAllocationCommand.class), shardRouting, new UnassignedInfo(UnassignedInfo.Reason.REROUTE_CANCELLED, null), indexMetadata, allocation.changes());
// TODO: We don't have to remove a cancelled shard from in-sync set once we have a strict resync implementation.
allocation.removeAllocationId(shardRouting);
return new RerouteExplanation(this, allocation.decision(Decision.YES, "cancel_allocation_command", "shard " + shardId + " on node " + discoNode + " can be cancelled"));
}
use of org.opensearch.cluster.routing.allocation.RerouteExplanation in project OpenSearch by opensearch-project.
the class MoveAllocationCommand method execute.
@Override
public RerouteExplanation execute(RoutingAllocation allocation, boolean explain) {
DiscoveryNode fromDiscoNode = allocation.nodes().resolveNode(fromNode);
DiscoveryNode toDiscoNode = allocation.nodes().resolveNode(toNode);
Decision decision = null;
boolean found = false;
RoutingNode fromRoutingNode = allocation.routingNodes().node(fromDiscoNode.getId());
if (fromRoutingNode == null && !fromDiscoNode.isDataNode()) {
throw new IllegalArgumentException("[move_allocation] can't move [" + index + "][" + shardId + "] from " + fromDiscoNode + " to " + toDiscoNode + ": source [" + fromDiscoNode.getName() + "] is not a data node.");
}
RoutingNode toRoutingNode = allocation.routingNodes().node(toDiscoNode.getId());
if (toRoutingNode == null && !toDiscoNode.isDataNode()) {
throw new IllegalArgumentException("[move_allocation] can't move [" + index + "][" + shardId + "] from " + fromDiscoNode + " to " + toDiscoNode + ": source [" + toDiscoNode.getName() + "] is not a data node.");
}
for (ShardRouting shardRouting : fromRoutingNode) {
if (!shardRouting.shardId().getIndexName().equals(index)) {
continue;
}
if (shardRouting.shardId().id() != shardId) {
continue;
}
found = true;
// TODO we can possibly support also relocating cases, where we cancel relocation and move...
if (!shardRouting.started()) {
if (explain) {
return new RerouteExplanation(this, allocation.decision(Decision.NO, "move_allocation_command", "shard " + shardId + " has not been started"));
}
throw new IllegalArgumentException("[move_allocation] can't move " + shardId + ", shard is not started (state = " + shardRouting.state() + "]");
}
decision = allocation.deciders().canAllocate(shardRouting, toRoutingNode, allocation);
if (decision.type() == Decision.Type.NO) {
if (explain) {
return new RerouteExplanation(this, decision);
}
throw new IllegalArgumentException("[move_allocation] can't move " + shardId + ", from " + fromDiscoNode + ", to " + toDiscoNode + ", since its not allowed, reason: " + decision);
}
if (decision.type() == Decision.Type.THROTTLE) {
// its being throttled, maybe have a flag to take it into account and fail? for now, just do it since the "user" wants it...
}
allocation.routingNodes().relocateShard(shardRouting, toRoutingNode.nodeId(), allocation.clusterInfo().getShardSize(shardRouting, ShardRouting.UNAVAILABLE_EXPECTED_SHARD_SIZE), allocation.changes());
}
if (!found) {
if (explain) {
return new RerouteExplanation(this, allocation.decision(Decision.NO, "move_allocation_command", "shard " + shardId + " not found"));
}
throw new IllegalArgumentException("[move_allocation] can't move " + shardId + ", failed to find it on node " + fromDiscoNode);
}
return new RerouteExplanation(this, decision);
}
use of org.opensearch.cluster.routing.allocation.RerouteExplanation in project OpenSearch by opensearch-project.
the class ClusterRerouteResponseTests method testToXContent.
public void testToXContent() throws IOException {
DiscoveryNode node0 = new DiscoveryNode("node0", new TransportAddress(TransportAddress.META_ADDRESS, 9000), Version.CURRENT);
DiscoveryNodes nodes = new DiscoveryNodes.Builder().add(node0).masterNodeId(node0.getId()).build();
IndexMetadata indexMetadata = IndexMetadata.builder("index").settings(Settings.builder().put(IndexSettings.INDEX_CHECK_ON_STARTUP.getKey(), true).put(IndexSettings.MAX_SCRIPT_FIELDS_SETTING.getKey(), 10).put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1).put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0).put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT).build()).build();
ImmutableOpenMap.Builder<String, IndexMetadata> openMapBuilder = ImmutableOpenMap.builder();
openMapBuilder.put("index", indexMetadata);
Metadata metadata = Metadata.builder().indices(openMapBuilder.build()).build();
ClusterState clusterState = ClusterState.builder(new ClusterName("test")).nodes(nodes).metadata(metadata).build();
RoutingExplanations routingExplanations = new RoutingExplanations();
routingExplanations.add(new RerouteExplanation(new AllocateReplicaAllocationCommand("index", 0, "node0"), Decision.YES));
ClusterRerouteResponse clusterRerouteResponse = new ClusterRerouteResponse(true, clusterState, routingExplanations);
{
XContentBuilder builder = JsonXContent.contentBuilder().prettyPrint();
clusterRerouteResponse.toXContent(builder, ToXContent.EMPTY_PARAMS);
assertEquals("{\n" + " \"acknowledged\" : true,\n" + " \"state\" : {\n" + " \"cluster_uuid\" : \"_na_\",\n" + " \"version\" : 0,\n" + " \"state_uuid\" : \"" + clusterState.stateUUID() + "\",\n" + " \"master_node\" : \"node0\",\n" + " \"blocks\" : { },\n" + " \"nodes\" : {\n" + " \"node0\" : {\n" + " \"name\" : \"\",\n" + " \"ephemeral_id\" : \"" + node0.getEphemeralId() + "\",\n" + " \"transport_address\" : \"0.0.0.0:9000\",\n" + " \"attributes\" : { }\n" + " }\n" + " },\n" + " \"metadata\" : {\n" + " \"cluster_uuid\" : \"_na_\",\n" + " \"cluster_uuid_committed\" : false,\n" + " \"cluster_coordination\" : {\n" + " \"term\" : 0,\n" + " \"last_committed_config\" : [ ],\n" + " \"last_accepted_config\" : [ ],\n" + " \"voting_config_exclusions\" : [ ]\n" + " },\n" + " \"templates\" : { },\n" + " \"indices\" : {\n" + " \"index\" : {\n" + " \"version\" : 1,\n" + " \"mapping_version\" : 1,\n" + " \"settings_version\" : 1,\n" + " \"aliases_version\" : 1,\n" + " \"routing_num_shards\" : 1,\n" + " \"state\" : \"open\",\n" + " \"settings\" : {\n" + " \"index\" : {\n" + " \"shard\" : {\n" + " \"check_on_startup\" : \"true\"\n" + " },\n" + " \"number_of_shards\" : \"1\",\n" + " \"number_of_replicas\" : \"0\",\n" + " \"version\" : {\n" + " \"created\" : \"" + Version.CURRENT.id + "\"\n" + " },\n" + " \"max_script_fields\" : \"10\"\n" + " }\n" + " },\n" + " \"mappings\" : { },\n" + " \"aliases\" : [ ],\n" + " \"primary_terms\" : {\n" + " \"0\" : 0\n" + " },\n" + " \"in_sync_allocations\" : {\n" + " \"0\" : [ ]\n" + " },\n" + " \"rollover_info\" : { },\n" + " \"system\" : false\n" + " }\n" + " },\n" + " \"index-graveyard\" : {\n" + " \"tombstones\" : [ ]\n" + " }\n" + " },\n" + " \"routing_table\" : {\n" + " \"indices\" : { }\n" + " },\n" + " \"routing_nodes\" : {\n" + " \"unassigned\" : [ ],\n" + " \"nodes\" : {\n" + " \"node0\" : [ ]\n" + " }\n" + " }\n" + " }\n" + "}", Strings.toString(builder));
}
{
XContentBuilder builder = JsonXContent.contentBuilder().prettyPrint();
Map<String, String> params = new HashMap<>();
params.put("explain", "true");
params.put("metric", "version,master_node");
clusterRerouteResponse.toXContent(builder, new ToXContent.MapParams(params));
assertEquals("{\n" + " \"acknowledged\" : true,\n" + " \"state\" : {\n" + " \"cluster_uuid\" : \"_na_\",\n" + " \"version\" : 0,\n" + " \"state_uuid\" : \"" + clusterState.stateUUID() + "\",\n" + " \"master_node\" : \"node0\"\n" + " },\n" + " \"explanations\" : [\n" + " {\n" + " \"command\" : \"allocate_replica\",\n" + " \"parameters\" : {\n" + " \"index\" : \"index\",\n" + " \"shard\" : 0,\n" + " \"node\" : \"node0\"\n" + " },\n" + " \"decisions\" : [\n" + " {\n" + " \"decider\" : null,\n" + " \"decision\" : \"YES\",\n" + " \"explanation\" : \"none\"\n" + " }\n" + " ]\n" + " }\n" + " ]\n" + "}", Strings.toString(builder));
}
{
XContentBuilder builder = JsonXContent.contentBuilder().prettyPrint();
Map<String, String> params = new HashMap<>();
params.put("metric", "metadata");
params.put("settings_filter", "index.number*,index.version.created");
clusterRerouteResponse.toXContent(builder, new ToXContent.MapParams(params));
assertEquals("{\n" + " \"acknowledged\" : true,\n" + " \"state\" : {\n" + " \"cluster_uuid\" : \"_na_\",\n" + " \"metadata\" : {\n" + " \"cluster_uuid\" : \"_na_\",\n" + " \"cluster_uuid_committed\" : false,\n" + " \"cluster_coordination\" : {\n" + " \"term\" : 0,\n" + " \"last_committed_config\" : [ ],\n" + " \"last_accepted_config\" : [ ],\n" + " \"voting_config_exclusions\" : [ ]\n" + " },\n" + " \"templates\" : { },\n" + " \"indices\" : {\n" + " \"index\" : {\n" + " \"version\" : 1,\n" + " \"mapping_version\" : 1,\n" + " \"settings_version\" : 1,\n" + " \"aliases_version\" : 1,\n" + " \"routing_num_shards\" : 1,\n" + " \"state\" : \"open\",\n" + " \"settings\" : {\n" + " \"index\" : {\n" + " \"max_script_fields\" : \"10\",\n" + " \"shard\" : {\n" + " \"check_on_startup\" : \"true\"\n" + " }\n" + " }\n" + " },\n" + " \"mappings\" : { },\n" + " \"aliases\" : [ ],\n" + " \"primary_terms\" : {\n" + " \"0\" : 0\n" + " },\n" + " \"in_sync_allocations\" : {\n" + " \"0\" : [ ]\n" + " },\n" + " \"rollover_info\" : { },\n" + " \"system\" : false\n" + " }\n" + " },\n" + " \"index-graveyard\" : {\n" + " \"tombstones\" : [ ]\n" + " }\n" + " }\n" + " }\n" + "}", Strings.toString(builder));
}
}
use of org.opensearch.cluster.routing.allocation.RerouteExplanation in project OpenSearch by opensearch-project.
the class ClusterRerouteIT method testRerouteExplain.
public void testRerouteExplain() {
Settings commonSettings = Settings.builder().build();
logger.info("--> starting a node");
String node_1 = internalCluster().startNode(commonSettings);
assertThat(cluster().size(), equalTo(1));
ClusterHealthResponse healthResponse = client().admin().cluster().prepareHealth().setWaitForNodes("1").execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
logger.info("--> create an index with 1 shard");
createIndex("test", Settings.builder().put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1).put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0).build());
if (randomBoolean()) {
assertAcked(client().admin().indices().prepareClose("test"));
}
ensureGreen("test");
logger.info("--> disable allocation");
Settings newSettings = Settings.builder().put(CLUSTER_ROUTING_ALLOCATION_ENABLE_SETTING.getKey(), Allocation.NONE.name()).build();
client().admin().cluster().prepareUpdateSettings().setTransientSettings(newSettings).execute().actionGet();
logger.info("--> starting a second node");
String node_2 = internalCluster().startNode(commonSettings);
assertThat(cluster().size(), equalTo(2));
healthResponse = client().admin().cluster().prepareHealth().setWaitForNodes("2").execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
logger.info("--> try to move the shard from node1 to node2");
MoveAllocationCommand cmd = new MoveAllocationCommand("test", 0, node_1, node_2);
ClusterRerouteResponse resp = client().admin().cluster().prepareReroute().add(cmd).setExplain(true).execute().actionGet();
RoutingExplanations e = resp.getExplanations();
assertThat(e.explanations().size(), equalTo(1));
RerouteExplanation explanation = e.explanations().get(0);
assertThat(explanation.command().name(), equalTo(cmd.name()));
assertThat(((MoveAllocationCommand) explanation.command()).shardId(), equalTo(cmd.shardId()));
assertThat(((MoveAllocationCommand) explanation.command()).fromNode(), equalTo(cmd.fromNode()));
assertThat(((MoveAllocationCommand) explanation.command()).toNode(), equalTo(cmd.toNode()));
assertThat(explanation.decisions().type(), equalTo(Decision.Type.YES));
}
use of org.opensearch.cluster.routing.allocation.RerouteExplanation in project OpenSearch by opensearch-project.
the class AllocateEmptyPrimaryAllocationCommand method execute.
@Override
public RerouteExplanation execute(RoutingAllocation allocation, boolean explain) {
final DiscoveryNode discoNode;
try {
discoNode = allocation.nodes().resolveNode(node);
} catch (IllegalArgumentException e) {
return explainOrThrowRejectedCommand(explain, allocation, e);
}
final RoutingNodes routingNodes = allocation.routingNodes();
RoutingNode routingNode = routingNodes.node(discoNode.getId());
if (routingNode == null) {
return explainOrThrowMissingRoutingNode(allocation, explain, discoNode);
}
try {
allocation.routingTable().shardRoutingTable(index, shardId).primaryShard();
} catch (IndexNotFoundException | ShardNotFoundException e) {
return explainOrThrowRejectedCommand(explain, allocation, e);
}
ShardRouting shardRouting = null;
for (ShardRouting shard : allocation.routingNodes().unassigned()) {
if (shard.getIndexName().equals(index) && shard.getId() == shardId && shard.primary()) {
shardRouting = shard;
break;
}
}
if (shardRouting == null) {
return explainOrThrowRejectedCommand(explain, allocation, "primary [" + index + "][" + shardId + "] is already assigned");
}
if (shardRouting.recoverySource().getType() != RecoverySource.Type.EMPTY_STORE && acceptDataLoss == false) {
String dataLossWarning = "allocating an empty primary for [" + index + "][" + shardId + "] can result in data loss. Please confirm by setting the accept_data_loss parameter to true";
return explainOrThrowRejectedCommand(explain, allocation, dataLossWarning);
}
UnassignedInfo unassignedInfoToUpdate = null;
if (shardRouting.unassignedInfo().getReason() != UnassignedInfo.Reason.FORCED_EMPTY_PRIMARY) {
String unassignedInfoMessage = "force empty allocation from previous reason " + shardRouting.unassignedInfo().getReason() + ", " + shardRouting.unassignedInfo().getMessage();
unassignedInfoToUpdate = new UnassignedInfo(UnassignedInfo.Reason.FORCED_EMPTY_PRIMARY, unassignedInfoMessage, shardRouting.unassignedInfo().getFailure(), 0, System.nanoTime(), System.currentTimeMillis(), false, shardRouting.unassignedInfo().getLastAllocationStatus(), Collections.emptySet());
}
initializeUnassignedShard(allocation, routingNodes, routingNode, shardRouting, unassignedInfoToUpdate, EmptyStoreRecoverySource.INSTANCE);
return new RerouteExplanation(this, allocation.decision(Decision.YES, name() + " (allocation command)", "ignore deciders"));
}
Aggregations