public RoutingAllocation.Result reroute(
     ClusterState clusterState, AllocationCommands commands, boolean explain)
     throws ElasticsearchException {
   RoutingNodes routingNodes = clusterState.routingNodes();
   // we don't shuffle the unassigned shards here, to try and get as close as possible to
   // a consistent result of the effect the commands have on the routing
   // this allows systems to dry run the commands, see the resulting cluster state, and act on it
   RoutingAllocation allocation =
       new RoutingAllocation(
           allocationDeciders,
           routingNodes,
           clusterState.nodes(),
           clusterInfoService.getClusterInfo());
   // don't short circuit deciders, we want a full explanation
   allocation.debugDecision(true);
   // we ignore disable allocation, because commands are explicit
   allocation.ignoreDisable(true);
   RoutingExplanations explanations = commands.execute(allocation, explain);
   // we revert the ignore disable flag, since when rerouting, we want the original setting to take
   // place
   allocation.ignoreDisable(false);
   // the assumption is that commands will move / act on shards (or fail through exceptions)
   // so, there will always be shard "movements", so no need to check on reroute
   reroute(allocation);
   return new RoutingAllocation.Result(
       true,
       new RoutingTable.Builder()
           .updateNodes(routingNodes)
           .build()
           .validateRaiseException(clusterState.metaData()),
       explanations);
 }
  @Test
  public void xContent() throws Exception {
    String commands =
        "{\n"
            + "    \"commands\" : [\n"
            + "        {\"allocate\" : {\"index\" : \"test\", \"shard\" : 1, \"node\" : \"node1\", \"allow_primary\" : true}}\n"
            + "       ,{\"move\" : {\"index\" : \"test\", \"shard\" : 3, \"from_node\" : \"node2\", \"to_node\" : \"node3\"}} \n"
            + "       ,{\"cancel\" : {\"index\" : \"test\", \"shard\" : 4, \"node\" : \"node5\", \"allow_primary\" : true}} \n"
            + "    ]\n"
            + "}\n";
    XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(commands);
    // move two tokens, parser expected to be "on" `commands` field
    parser.nextToken();
    parser.nextToken();
    AllocationCommands sCommands = AllocationCommands.fromXContent(parser);

    assertThat(sCommands.commands().size(), equalTo(3));
    assertThat(
        ((AllocateAllocationCommand) (sCommands.commands().get(0))).shardId(),
        equalTo(new ShardId("test", 1)));
    assertThat(
        ((AllocateAllocationCommand) (sCommands.commands().get(0))).node(), equalTo("node1"));
    assertThat(
        ((AllocateAllocationCommand) (sCommands.commands().get(0))).allowPrimary(), equalTo(true));

    assertThat(
        ((MoveAllocationCommand) (sCommands.commands().get(1))).shardId(),
        equalTo(new ShardId("test", 3)));
    assertThat(
        ((MoveAllocationCommand) (sCommands.commands().get(1))).fromNode(), equalTo("node2"));
    assertThat(((MoveAllocationCommand) (sCommands.commands().get(1))).toNode(), equalTo("node3"));

    assertThat(
        ((CancelAllocationCommand) (sCommands.commands().get(2))).shardId(),
        equalTo(new ShardId("test", 4)));
    assertThat(((CancelAllocationCommand) (sCommands.commands().get(2))).node(), equalTo("node5"));
    assertThat(
        ((CancelAllocationCommand) (sCommands.commands().get(2))).allowPrimary(), equalTo(true));
  }
  @Test
  public void serialization() throws Exception {
    AllocationCommands commands =
        new AllocationCommands(
            new AllocateAllocationCommand(new ShardId("test", 1), "node1", true),
            new MoveAllocationCommand(new ShardId("test", 3), "node2", "node3"),
            new CancelAllocationCommand(new ShardId("test", 4), "node5", true));
    BytesStreamOutput bytes = new BytesStreamOutput();
    AllocationCommands.writeTo(commands, bytes);
    AllocationCommands sCommands = AllocationCommands.readFrom(new BytesStreamInput(bytes.bytes()));

    assertThat(sCommands.commands().size(), equalTo(3));
    assertThat(
        ((AllocateAllocationCommand) (sCommands.commands().get(0))).shardId(),
        equalTo(new ShardId("test", 1)));
    assertThat(
        ((AllocateAllocationCommand) (sCommands.commands().get(0))).node(), equalTo("node1"));
    assertThat(
        ((AllocateAllocationCommand) (sCommands.commands().get(0))).allowPrimary(), equalTo(true));

    assertThat(
        ((MoveAllocationCommand) (sCommands.commands().get(1))).shardId(),
        equalTo(new ShardId("test", 3)));
    assertThat(
        ((MoveAllocationCommand) (sCommands.commands().get(1))).fromNode(), equalTo("node2"));
    assertThat(((MoveAllocationCommand) (sCommands.commands().get(1))).toNode(), equalTo("node3"));

    assertThat(
        ((CancelAllocationCommand) (sCommands.commands().get(2))).shardId(),
        equalTo(new ShardId("test", 4)));
    assertThat(((CancelAllocationCommand) (sCommands.commands().get(2))).node(), equalTo("node5"));
    assertThat(
        ((CancelAllocationCommand) (sCommands.commands().get(2))).allowPrimary(), equalTo(true));
  }