private boolean maybeVerifyResourcesAreFullAutoCompatible(String dcName, String clusterName, HelixAdmin helixAdmin,
      int maxInstancesInOneResourceForFullAuto) {
    List<String> resourceNames = helixAdmin.getResourcesInCluster(clusterName);
    if (resourceNames == null || resourceNames.isEmpty()) {
      info(
          "[{}] There is no resource found for this cluster {}, max instance in one resource is {}, resource should {} be full auto compatible",
          dcName.toUpperCase(), clusterName, maxInstancesInOneResourceForFullAuto,
          maxInstancesInOneResourceForFullAuto > 0 ? "" : "NOT");
      return maxInstancesInOneResourceForFullAuto > 0;
    }
    boolean allResourceFullAutoCompatible =
        resourceNames.stream().filter(rn -> rn.matches("\\d+")).mapToInt(Integer::parseInt)
        .allMatch(i -> i >= FULL_AUTO_COMPATIBLE_RESOURCE_NAME_START_NUMBER);
    boolean allResourceNotFullAutoCompatible = resourceNames.stream()
        .filter(rn -> rn.matches("\\d+"))
        .mapToInt(Integer::parseInt)
        .allMatch(i -> i < FULL_AUTO_COMPATIBLE_RESOURCE_NAME_START_NUMBER);
    // When there is mixed of new and old resources, it means we are in the middle of resource reconstruction.
    // We don't want to do any changes to the helix cluster map if that's the case. Since a partition can belong
    // to more than one resources, we would remove partitions from one of them and that would cause troubles.
    // DON'T continue when there is mixed of new and old resources.
    ensureOrThrow(allResourceFullAutoCompatible || allResourceNotFullAutoCompatible,
        "Resource has to be all greater than " + FULL_AUTO_COMPATIBLE_RESOURCE_NAME_START_NUMBER
            + " or all less than it");
    if (!allResourceFullAutoCompatible) {
      info("[{}] Resources are not FULL_AUTO compatible in cluster {}", dcName.toUpperCase(), clusterName);
      return false;
    }
    if (maxInstancesInOneResourceForFullAuto <= 0) {
      ensureOrThrow(!anyResourceInFullAuto(dcName), "There are resources in FULL AUTO for dc " + dcName
          + ", but maxInstancesInOneResourceForFullAuto is not a valid number");
      warning("****************************************");
      warning(
          "[{}] Cluster {} is in FULL_AUTO compatible mode, but max instances in one resource [{}] is not a valid number for FULL_AUTO",
          dcName.toUpperCase(), clusterName, maxInstancesInOneResourceForFullAuto);
      warning("Will not verify resources");
      return false;
    }

    if (!dcToResourceIdToIdealState.containsKey(dcName)) {
      fetchResourceInformationFromHelix(dcName);
    }
    Map<Integer, IdealState> resourceIdToIdealState = dcToResourceIdToIdealState.get(dcName);
    TreeMap<Integer, Set<String>> resourceIdToInstances = dcToResourceIdToInstances.get(dcName);
    Map<String, Set<Integer>> instanceToResourceIds = dcToInstanceToResourceIds.get(dcName);
    // Now verify
    // 1. all resources should have less than the maxInstanceInResource
    // 2. all instances should only have one resource, or if they have more than one, the these resources should have
    //    the same set of hosts, and different resource should have different number of replicas for each partition.
    //    For example, if hostA belongs to resource 10000 and 10001, then resource 10000 and 10001 should have the same
    //    set of the hosts. And all the partitions in resource 10000 should have same number of replicas, all the
    //    partitions in resource 10001 should have same number of replicas, but the number should be different from
    //    resource 10000
    for (Map.Entry<Integer, IdealState> ent : resourceIdToIdealState.entrySet()) {
      if (!isIdealStateInFullAuto(ent.getValue())) {
        Set<String> instances = resourceIdToInstances.get(ent.getKey());
        ensureOrThrow(maxInstancesInOneResourceForFullAuto >= instances.size(),
            "Resource " + ent.getKey() + " has " + instances.size()
                + " instances, but we are expecting less than or equal to " + maxInstancesInOneResourceForFullAuto
                + ": " + instances);
      }
    }

    for (Map.Entry<String, Set<Integer>> ent : instanceToResourceIds.entrySet()) {
      // If an instance only has partitions from one resource, then it's compatible
      if (ent.getValue().size() == 1) {
        continue;
      }
      // if All resources are already on FULL AUTO, don't have to verify
      if (ent.getValue()
          .stream()
          .map(resourceId -> resourceIdToIdealState.get(resourceId))
          .allMatch(this::isIdealStateInFullAuto)) {
        continue;
      }
      // if only some resources are in FULL AUTO, then this is wrong
      if (ent.getValue()
          .stream()
          .map(resourceId -> resourceIdToIdealState.get(resourceId))
          .anyMatch(this::isIdealStateInFullAuto)) {
        ensureOrThrow(false, "Not all resources " + ent.getValue() + " for instance " + " enabled FULL AUTO");
      }

      // instance has partitions from multiple resources, make sure different resources have different number of replicas.
      Set<Integer> numberReplicasInResource = ent.getValue()
          .stream()
          .map(resourceIdToIdealState::get)
          .map(state -> numReplicasForIdealState(dcName, state))
          .collect(Collectors.toSet());
      ensureOrThrow(numberReplicasInResource.size() == ent.getValue().size(),
          "Instance " + ent.getKey() + " in DC " + dcName + " has multiple resources having same number of replicas: "
              + ent.getValue());

      // make sure different resources has the same set of instances
      Set<String> instancesToCompare = null;
      int firstResourceId = -1;
      for (int resourceId : ent.getValue()) {
        Set<String> instances = resourceIdToInstances.get(resourceId);
        if (instancesToCompare == null) {
          instancesToCompare = instances;
          firstResourceId = resourceId;
        } else {
          if (instances.size() == instancesToCompare.size()) {
            ensureOrThrow(instances.equals(instancesToCompare),
                "Instance " + ent.getKey() + " belongs to multiple resource, but resource " + firstResourceId
                    + " doesn't have the same set of instances as resource " + resourceId);
          } else if (instances.size() < instancesToCompare.size()) {
            ensureOrThrow(instancesToCompare.containsAll(instances),
                "Instance " + ent.getKey() + " belongs to multiple resource, but resource " + firstResourceId
                    + " doesn't contain all the instances in resource " + resourceId);
          } else {
            ensureOrThrow(instances.containsAll(instancesToCompare),
                "Instance " + ent.getKey() + " belongs to multiple resource, but resource " + resourceId
                    + " doesn't contain all the instances in resource " + firstResourceId);
            firstResourceId = resourceId;
            instancesToCompare = instances;
          }
        }
      }
    }

    info("[{}] Successfully verified resources are FULL_AUTO compatible for cluster {}", dcName.toUpperCase(),
        clusterName);
    return true;
  }
If the resources are reconstructed to be FULL_AUTO compatible, then make sure that each instance only has partitions
from one resource.
@param dcName the datacenter whose information is to be verified.
@param clusterName the cluster to be verified.
ambry-clustermap/src/main/java/com/github/ambry/clustermap/HelixBootstrapUpgradeUtil.java