@Override
 public void readFrom(StreamInput in) throws IOException {
   clusterName = in.readUTF();
   activePrimaryShards = in.readVInt();
   activeShards = in.readVInt();
   relocatingShards = in.readVInt();
   initializingShards = in.readVInt();
   unassignedShards = in.readVInt();
   numberOfNodes = in.readVInt();
   numberOfDataNodes = in.readVInt();
   status = ClusterHealthStatus.fromValue(in.readByte());
   int size = in.readVInt();
   for (int i = 0; i < size; i++) {
     ClusterIndexHealth indexHealth = readClusterIndexHealth(in);
     indices.put(indexHealth.index(), indexHealth);
   }
   timedOut = in.readBoolean();
   size = in.readVInt();
   if (size == 0) {
     validationFailures = ImmutableList.of();
   } else {
     for (int i = 0; i < size; i++) {
       validationFailures.add(in.readUTF());
     }
   }
 }
  private ClusterHealthResponse clusterHealth(ClusterHealthRequest request) {
    ClusterState clusterState = clusterService.state();
    RoutingTableValidation validation =
        clusterState.routingTable().validate(clusterState.metaData());
    ClusterHealthResponse response =
        new ClusterHealthResponse(clusterName.value(), validation.failures());
    response.numberOfNodes = clusterState.nodes().size();
    response.numberOfDataNodes = clusterState.nodes().dataNodes().size();

    for (String index : clusterState.metaData().concreteIndices(request.indices())) {
      IndexRoutingTable indexRoutingTable = clusterState.routingTable().index(index);
      IndexMetaData indexMetaData = clusterState.metaData().index(index);
      if (indexRoutingTable == null) {
        continue;
      }
      ClusterIndexHealth indexHealth =
          new ClusterIndexHealth(
              index,
              indexMetaData.numberOfShards(),
              indexMetaData.numberOfReplicas(),
              validation.indexFailures(indexMetaData.index()));

      for (IndexShardRoutingTable shardRoutingTable : indexRoutingTable) {
        ClusterShardHealth shardHealth = new ClusterShardHealth(shardRoutingTable.shardId().id());
        for (ShardRouting shardRouting : shardRoutingTable) {
          if (shardRouting.active()) {
            shardHealth.activeShards++;
            if (shardRouting.relocating()) {
              // the shard is relocating, the one he is relocating to will be in initializing state,
              // so we don't count it
              shardHealth.relocatingShards++;
            }
            if (shardRouting.primary()) {
              shardHealth.primaryActive = true;
            }
          } else if (shardRouting.initializing()) {
            shardHealth.initializingShards++;
          } else if (shardRouting.unassigned()) {
            shardHealth.unassignedShards++;
          }
        }
        if (shardHealth.primaryActive) {
          if (shardHealth.activeShards == shardRoutingTable.size()) {
            shardHealth.status = ClusterHealthStatus.GREEN;
          } else {
            shardHealth.status = ClusterHealthStatus.YELLOW;
          }
        } else {
          shardHealth.status = ClusterHealthStatus.RED;
        }
        indexHealth.shards.put(shardHealth.id(), shardHealth);
      }

      for (ClusterShardHealth shardHealth : indexHealth) {
        if (shardHealth.primaryActive()) {
          indexHealth.activePrimaryShards++;
        }
        indexHealth.activeShards += shardHealth.activeShards;
        indexHealth.relocatingShards += shardHealth.relocatingShards;
        indexHealth.initializingShards += shardHealth.initializingShards;
        indexHealth.unassignedShards += shardHealth.unassignedShards;
      }
      // update the index status
      indexHealth.status = ClusterHealthStatus.GREEN;
      if (!indexHealth.validationFailures().isEmpty()) {
        indexHealth.status = ClusterHealthStatus.RED;
      } else if (indexHealth
          .shards()
          .isEmpty()) { // might be since none has been created yet (two phase index creation)
        indexHealth.status = ClusterHealthStatus.RED;
      } else {
        for (ClusterShardHealth shardHealth : indexHealth) {
          if (shardHealth.status() == ClusterHealthStatus.RED) {
            indexHealth.status = ClusterHealthStatus.RED;
            break;
          }
          if (shardHealth.status() == ClusterHealthStatus.YELLOW) {
            indexHealth.status = ClusterHealthStatus.YELLOW;
          }
        }
      }

      response.indices.put(indexHealth.index(), indexHealth);
    }

    for (ClusterIndexHealth indexHealth : response) {
      response.activePrimaryShards += indexHealth.activePrimaryShards;
      response.activeShards += indexHealth.activeShards;
      response.relocatingShards += indexHealth.relocatingShards;
      response.initializingShards += indexHealth.initializingShards;
      response.unassignedShards += indexHealth.unassignedShards;
    }

    response.status = ClusterHealthStatus.GREEN;
    if (!response.validationFailures().isEmpty()) {
      response.status = ClusterHealthStatus.RED;
    } else if (clusterState
        .blocks()
        .hasGlobalBlock(GatewayService.NOT_RECOVERED_FROM_GATEWAY_BLOCK)) {
      response.status = ClusterHealthStatus.RED;
    } else {
      for (ClusterIndexHealth indexHealth : response) {
        if (indexHealth.status() == ClusterHealthStatus.RED) {
          response.status = ClusterHealthStatus.RED;
          break;
        }
        if (indexHealth.status() == ClusterHealthStatus.YELLOW) {
          response.status = ClusterHealthStatus.YELLOW;
        }
      }
    }

    return response;
  }