class PreconfigureKerberosAction extends AbstractUpgradeServerAction {

  @Override
  public CommandReport execute(ConcurrentMap<String, Object> requestSharedDataContext) throws AmbariException, InterruptedException {
    Map<String, String> commandParameters = getCommandParameters();
    if (null == commandParameters || commandParameters.isEmpty()) {
      return createCommandReport(0, HostRoleStatus.FAILED, "{}", "",
          "Unable to change configuration values without command parameters");
    }

    if (!isDowngrade()) {
      String clusterName = commandParameters.get("clusterName");
      Cluster cluster = getClusters().getCluster(clusterName);

      if (cluster.getSecurityType() == SecurityType.KERBEROS) {
        StackId stackId;

        try {
          stackId = getTargetStackId(cluster);
        } catch (AmbariException e) {
          return createCommandReport(0, HostRoleStatus.FAILED, "{}", "", e.getLocalizedMessage());
        }

        if (stackId == null) {
          return createCommandReport(0, HostRoleStatus.FAILED, "{}", "",
              "The target stack Id was not specified.");
        }

        KerberosDescriptor kerberosDescriptor = kerberosHelper.getKerberosDescriptor(KerberosHelper.KerberosDescriptorType.COMPOSITE, cluster, stackId, true);

        // Calculate the current host-specific configurations. These will be used to replace
        // variables within the Kerberos descriptor data
        Map<String, Map<String, String>> configurations = kerberosHelper.calculateConfigurations(cluster, null, kerberosDescriptor, true, false);

        PreconfigureServiceType preconfigureServiceType = getPreconfigureServiceType(configurations);

        if (preconfigureServiceType != PreconfigureServiceType.NONE) {
          Map<String, Map<String, String>> kerberosConfigurations = new HashMap<>();
          Map<String, Set<String>> propertiesToRemove = new HashMap<>();
          Map<String, Set<String>> propertiesToIgnore = new HashMap<>();

          if (preconfigureServiceType == PreconfigureServiceType.ALL) {
            // Force all services to be flagged for pre-configuration...
            Map<String, KerberosServiceDescriptor> serviceDescriptors = kerberosDescriptor.getServices();
            if (serviceDescriptors != null) {
              for (KerberosServiceDescriptor serviceDescriptor : serviceDescriptors.values()) {
                serviceDescriptor.setPreconfigure(true);
              }
            }
          }

          processServiceComponentHosts(cluster, kerberosDescriptor, configurations, kerberosConfigurations, propertiesToIgnore, getDefaultRealm(configurations));

          // Calculate the set of configurations to update and replace any variables
          // using the previously calculated Map of configurations for the host.
          kerberosConfigurations = kerberosHelper.processPreconfiguredServiceConfigurations(kerberosConfigurations, configurations, cluster, kerberosDescriptor);

          Map<String, Set<String>> installedServices = calculateInstalledServices(cluster);

          kerberosHelper.applyStackAdvisorUpdates(cluster, installedServices.keySet(), configurations, kerberosConfigurations,
              propertiesToIgnore, propertiesToRemove, true);

          kerberosHelper.setAuthToLocalRules(cluster, kerberosDescriptor, getDefaultRealm(configurations), installedServices,
              configurations, kerberosConfigurations, true);

          processConfigurationChanges(cluster, stackId, kerberosDescriptor, kerberosConfigurations, propertiesToRemove, configurations);
        } else {
          actionLog.writeStdOut("Skipping: This facility is only available when kerberos-env/preconfigure_services is not \"NONE\"");
        }
      } else {
        actionLog.writeStdOut("Skipping: This facility is only available when Kerberos is enabled");
      }
    } else {
      actionLog.writeStdOut("Skipping: This facility is only available during an upgrade");
    }

    return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", actionLog.getStdOut(), actionLog.getStdErr());
  }

}