private static void migrateToFullAuto(String dc, String clusterName, HelixAdmin admin, String zkConnectStr,
      String commaSeparatedResources, WagedHelixConfig wagedHelixConfig, boolean setPreferenceList,
      int maxInstancesInOneResourceForFullAuto, boolean dryRun, boolean addConfigs) {
    try {
      ClusterMapConfig config = getClusterMapConfig(clusterName, dc, null);
      try (PropertyStoreToDataNodeConfigAdapter propertyStoreAdapter = new PropertyStoreToDataNodeConfigAdapter(
          zkConnectStr, config)) {
        // Get resources to migrate from user input.
        Set<String> helixResources = admin.getResourcesInCluster(clusterName)
            .stream()
            .filter(s -> s.matches("\\d+"))
            .collect(Collectors.toSet());
        Set<String> resources;
        if (commaSeparatedResources.equalsIgnoreCase(ALL)) {
          resources = helixResources;
        } else {
          resources = Arrays.stream(commaSeparatedResources.replaceAll("\\p{Space}", "").split(","))
              .collect(Collectors.toSet());
          resources.removeIf(resource -> {
            if (!helixResources.contains(resource)) {
              logger.info("Resource {} is not present in data center {}", resource, dc);
              return true;
            }
            return false;
          });
        }

        Map<String, IdealState> resourceToIdealState = new HashMap<>();
        for (String resource : resources) {
          resourceToIdealState.put(resource, admin.getResourceIdealState(clusterName, resource));
        }

        ConfigAccessor configAccessor = new ConfigAccessor(zkConnectStr);

        if (addConfigs) {
          // 1. Update cluster config
          setClusterConfig(clusterName, configAccessor, wagedHelixConfig.getClusterConfigFields(), dryRun);

          // 2. Update instance config for all instances present in each resource
          for (String resource : resources) {
            // a. Get list of instances sharing partitions in this resource
            IdealState idealState = resourceToIdealState.get(resource);
            Set<String> partitions = idealState.getPartitionSet();
            Set<String> instances = new HashSet<>();
            for (String partition : partitions) {
              instances.addAll(idealState.getInstanceSet(partition));
            }
            // b. Update instance config for each instance
            for (String instance : instances) {
              setInstanceConfig(clusterName, instance, resource, configAccessor, propertyStoreAdapter, admin, dryRun);
            }
          }

          // 3. Set resource configs
          for (String resource : resources) {
            setResourceConfig(clusterName, resource, configAccessor, propertyStoreAdapter, admin,
                wagedHelixConfig.clusterConfigFields, setPreferenceList, dryRun);
          }
        } else {
          if (!dryRun) {
            // 4. Enter maintenance mode
            admin.manuallyEnableMaintenanceMode(clusterName, true, "Migrating to Full auto", Collections.emptyMap());
            info("[{}] Enabled maintenance mode for cluster {}", dc.toUpperCase(), clusterName);
          }

          // 5. Update ideal state and enable waged rebalancer
          for (String resource : resources) {
            IdealState idealState = resourceToIdealState.get(resource);
            idealState.setRebalanceMode(IdealState.RebalanceMode.FULL_AUTO);
            // Set resource tag
            idealState.setInstanceGroupTag(getResourceTag(resource));
            // Get number of replicas in first partition
            int numberOfReplicas = idealState.getPreferenceLists().values().iterator().next().size();
            // Set number of replicas
            idealState.setReplicas(String.valueOf(numberOfReplicas));
            // Set minimum active replicas needed. Helix will bring up a new replica if the replica count goes below
            // this value even if we are in delayed rebalancer window.
            if (numberOfReplicas > 1) {
              idealState.setMinActiveReplicas(numberOfReplicas - 1);
            }
            if (!dryRun) {
              admin.updateIdealState(clusterName, resource, idealState);
              info(
                  "Updated ideal state for resource {}. REBALANCE_MODE: {}, INSTANCE_GROUP_TAG: {}, NUM_PARTITIONS: {}, "
                      + "MIN_ACTIVE_REPLICAS: {}", resource, idealState.getRebalanceMode().toString(),
                  idealState.getInstanceGroupTag(), idealState.getReplicas(), idealState.getMinActiveReplicas());
            } else {
              info("Dry run. This will update ideal state for resource {}. REBALANCE_MODE: {}, INSTANCE_GROUP_TAG: {}, "
                      + "NUM_PARTITIONS: {}, MIN_ACTIVE_REPLICAS: {}", resource, idealState.getRebalanceMode().toString(),
                  idealState.getInstanceGroupTag(), idealState.getReplicas(), idealState.getMinActiveReplicas());
            }
          }

          if (!dryRun) {
            admin.enableWagedRebalance(clusterName, new ArrayList<>(resources));
            info("[{}] Enabled waged rebalancer for resources {} in cluster {}", dc.toUpperCase(), resources,
                clusterName);
            // 6. Update the list of resources migrating to full_auto in helix property store. This is used by servers
            // in case we want to fall back to semi_auto later.
            updateAdminConfigForFullAutoMigration(clusterName, dc, resources, zkConnectStr);
            // 7. Exit maintenance mode
            admin.manuallyEnableMaintenanceMode(clusterName, false, "Complete migrating to Full auto",
                Collections.emptyMap());
            info("[{}] Disabled maintenance mode for cluster {}", dc.toUpperCase(), clusterName);
            info("[{}] Successfully migrated resources {} in cluster {} from semi-auto to full-auto", dc.toUpperCase(),
                resources, clusterName);
          }
        }
      }
    } catch (Throwable t) {
      logger.error("Error while migrating resources to full-auto in {}", dc, t);
    }
  }
Convert instance configs to the new DataNodeConfig format and persist them in the property store.
ambry-clustermap/src/main/java/com/github/ambry/clustermap/HelixBootstrapUpgradeUtil.java