@Override
    public long createStages(Cluster cluster,
                             String clusterHostInfoJson, String hostParamsJson,
                             ServiceComponentHostServerActionEvent event,
                             RoleCommandOrder roleCommandOrder, KerberosDetails kerberosDetails,
                             File dataDirectory, RequestStageContainer requestStageContainer,
                             List<ServiceComponentHost> serviceComponentHosts,
                             Map<String, ? extends Collection<String>> serviceComponentFilter,
                             Set<String> hostFilter, Collection<String> identityFilter, Set<String> hostsWithValidKerberosClient)
      throws AmbariException {
      // If there are principals and keytabs to process, setup the following sages:
      //  1) prepare identities
      //  2) generate principals
      //  3) generate keytab files
      //  4) distribute keytab files
      //  5) update configurations (optional)

      // If a RequestStageContainer does not already exist, create a new one...
      if (requestStageContainer == null) {
        requestStageContainer = new RequestStageContainer(
          actionManager.getNextRequestId(),
          null,
          requestFactory,
          actionManager);
      }


      boolean processAmbariIdentity = includeAmbariIdentity;
      Map<String, String> commandParameters = new HashMap<>();
      commandParameters.put(KerberosServerAction.AUTHENTICATED_USER_NAME, ambariManagementController.getAuthName());
      commandParameters.put(KerberosServerAction.DEFAULT_REALM, kerberosDetails.getDefaultRealm());
      if (dataDirectory != null) {
        commandParameters.put(KerberosServerAction.DATA_DIRECTORY, dataDirectory.getAbsolutePath());
      }
      if (serviceComponentFilter != null) {
        commandParameters.put(KerberosServerAction.SERVICE_COMPONENT_FILTER, StageUtils.getGson().toJson(serviceComponentFilter));

        processAmbariIdentity = serviceComponentFilter.containsKey(RootService.AMBARI.name()) &&
          ((serviceComponentFilter.get(RootService.AMBARI.name()) == null) || serviceComponentFilter.get(RootService.AMBARI.name()).contains("*") || serviceComponentFilter.get("AMBARI").contains(RootComponent.AMBARI_SERVER.name()));
      }
      if (hostFilter != null) {
        commandParameters.put(KerberosServerAction.HOST_FILTER, StageUtils.getGson().toJson(hostFilter));

        processAmbariIdentity = hostFilter.contains("*") || hostFilter.contains(StageUtils.getHostName());
      }
      if (identityFilter != null) {
        commandParameters.put(KerberosServerAction.IDENTITY_FILTER, StageUtils.getGson().toJson(identityFilter));
      }

      commandParameters.put(KerberosServerAction.OPERATION_TYPE, (operationType == null) ? KerberosServerAction.OperationType.DEFAULT.name() : operationType.name());
      commandParameters.put(KerberosServerAction.INCLUDE_AMBARI_IDENTITY, (processAmbariIdentity) ? "true" : "false");

      if (updateConfigurationPolicy != UpdateConfigurationPolicy.NONE) {
        commandParameters.put(KerberosServerAction.UPDATE_CONFIGURATION_NOTE, "Updated Kerberos-related configurations");
        commandParameters.put(KerberosServerAction.UPDATE_CONFIGURATION_POLICY, updateConfigurationPolicy.name());
      }

      List<String> hostsToInclude = calculateHosts(cluster, serviceComponentHosts, hostsWithValidKerberosClient, forceAllHosts);

      // *****************************************************************
      // Create stage to create principals
      addPrepareKerberosIdentitiesStage(cluster, clusterHostInfoJson, hostParamsJson, event,
        commandParameters, roleCommandOrder, requestStageContainer);

      if (kerberosDetails.manageIdentities()) {
        commandParameters.put(KerberosServerAction.KDC_TYPE, kerberosDetails.getKdcType().name());

        if (operationType != KerberosServerAction.OperationType.RECREATE_ALL) {
          addCheckMissingKeytabsStage(cluster, clusterHostInfoJson, hostParamsJson,
            commandParameters, roleCommandOrder, requestStageContainer, hostsToInclude);
        }

        // *****************************************************************
        // Create stage to create principals
        addCreatePrincipalsStage(cluster, clusterHostInfoJson, hostParamsJson, event,
          commandParameters, roleCommandOrder, requestStageContainer);

        // *****************************************************************
        // Create stage to generate keytabs
        addCreateKeytabFilesStage(cluster, clusterHostInfoJson, hostParamsJson, event,
          commandParameters, roleCommandOrder, requestStageContainer);

        // *****************************************************************
        // Create stage to distribute and configure keytab for Ambari server and configure JAAS
        if (processAmbariIdentity && kerberosDetails.createAmbariPrincipal()) {
          addConfigureAmbariIdentityStage(cluster, clusterHostInfoJson, hostParamsJson, event, commandParameters,
            roleCommandOrder, requestStageContainer);
        }

        // *****************************************************************
        // Create stage to distribute keytabs
        addDistributeKeytabFilesStage(cluster, clusterHostInfoJson, hostParamsJson, commandParameters,
          roleCommandOrder, requestStageContainer, hostsToInclude);
      }

      if (updateConfigurationPolicy != UpdateConfigurationPolicy.NONE) {
        // *****************************************************************
        // Create stage to update configurations of services
        addUpdateConfigurationsStage(cluster, clusterHostInfoJson, hostParamsJson, event, commandParameters,
          roleCommandOrder, requestStageContainer);
      }

      return requestStageContainer.getLastStageId();
    }
CreatePrincipalsAndKeytabsHandler constructor to set whether this instance should be used to
regenerate all keytabs or just the ones that have not been distributed

@param operationType             The type of Kerberos operation being performed
@param updateConfigurationPolicy The policy to use when updating configurations
                                 (<code>true</code>) or ignore any potential configuration changes
@param forceAllHosts             A boolean value indicating whether to include all hosts (<code>true</code>)
                                 when setting up agent-side tasks or to select only the hosts found to be
                                 relevant (<code>false</code>)
@param includeAmbariIdentity     A boolean value indicating whether to include Ambari server
                                 identity (<code>true</code>) or ignore it (<code>false</code>)
ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java