http://git-wip-us.apache.org/repos/asf/ambari/blob/4bce5782/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
index 8d0fd0f..d86433f 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
@@ -24,6 +24,7 @@ import java.io.File;
 import java.io.IOException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
@@ -35,6 +36,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.TreeSet;
 import java.util.regex.Matcher;
 
 import org.apache.ambari.annotations.Experimental;
@@ -48,6 +50,7 @@ import org.apache.ambari.server.actionmanager.RequestFactory;
 import org.apache.ambari.server.actionmanager.Stage;
 import org.apache.ambari.server.actionmanager.StageFactory;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import 
org.apache.ambari.server.api.services.stackadvisor.StackAdvisorException;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorHelper;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 import 
org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse;
@@ -92,14 +95,17 @@ import org.apache.ambari.server.stageplanner.RoleGraph;
 import org.apache.ambari.server.stageplanner.RoleGraphFactory;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.ComponentInfo;
 import org.apache.ambari.server.state.Config;
 import org.apache.ambari.server.state.ConfigHelper;
 import org.apache.ambari.server.state.Host;
 import org.apache.ambari.server.state.HostState;
+import org.apache.ambari.server.state.PropertyInfo;
 import org.apache.ambari.server.state.SecurityType;
 import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
+import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.State;
 import org.apache.ambari.server.state.ValueAttributesInfo;
@@ -359,16 +365,16 @@ public class KerberosHelperImpl implements KerberosHelper 
{
     RoleCommandOrder roleCommandOrder = 
ambariManagementController.getRoleCommandOrder(cluster);
     DeleteIdentityHandler handler = new 
DeleteIdentityHandler(customCommandExecutionHelper, 
configuration.getDefaultServerTaskTimeout(), stageFactory, 
ambariManagementController);
     DeleteIdentityHandler.CommandParams commandParameters = new 
DeleteIdentityHandler.CommandParams(
-      components,
-      identities,
-      ambariManagementController.getAuthName(),
-      dataDirectory,
-      kerberosDetails.getDefaultRealm(),
-      kerberosDetails.getKdcType());
+        components,
+        identities,
+        ambariManagementController.getAuthName(),
+        dataDirectory,
+        kerberosDetails.getDefaultRealm(),
+        kerberosDetails.getKdcType());
     OrderedRequestStageContainer stageContainer = new 
OrderedRequestStageContainer(
-      roleGraphFactory,
-      roleCommandOrder,
-      new RequestStageContainer(actionManager.getNextRequestId(), null, 
requestFactory, actionManager));
+        roleGraphFactory,
+        roleCommandOrder,
+        new RequestStageContainer(actionManager.getNextRequestId(), null, 
requestFactory, actionManager));
     handler.addDeleteIdentityStages(cluster, stageContainer, 
commandParameters, kerberosDetails.manageIdentities());
     stageContainer.getRequestStageContainer().persist();
   }
@@ -376,45 +382,43 @@ public class KerberosHelperImpl implements KerberosHelper 
{
   @Override
   public void configureServices(Cluster cluster, Map<String, 
Collection<String>> serviceFilter)
       throws AmbariException, KerberosInvalidConfigurationException {
-    Map<String, Map<String, String>> existingConfigurations = 
calculateExistingConfigurations(cluster, null);
-    Map<String, Set<String>> installedServices = new HashMap<>();
-    Set<String> previouslyExistingServices = new HashSet<>();
-
-    // Calculate the map of installed services to installed components
-    Map<String, Service> clusterServices = cluster.getServices();
-    if(clusterServices != null) {
-      for (Service clusterService : clusterServices.values()) {
-        Set<String> installedComponents = 
installedServices.get(clusterService.getName());
-        if (installedComponents == null) {
-          installedComponents = new HashSet<>();
-          installedServices.put(clusterService.getName(), installedComponents);
-        }
+    final Map<String, Set<String>> installedServices = new HashMap<>();
+    final Set<String> previouslyExistingServices = new HashSet<>();
+
+    // Calculate the map of installed services to installed components.
+    // We can create the map in the "shouldIncludeCommand" Command to avoid 
having to iterate
+    // over the returned ServiceComponentHost List.
+    getServiceComponentHosts(cluster,
+        new Command<Boolean, ServiceComponentHost>() {
+          @Override
+          public Boolean invoke(ServiceComponentHost sch) throws 
AmbariException {
+            if (sch != null) {
+              String serviceName = sch.getServiceName();
+
+              Set<String> installedComponents = 
installedServices.get(serviceName);
+              if (installedComponents == null) {
+                installedComponents = new HashSet<>();
+                installedServices.put(serviceName, installedComponents);
+              }
+              installedComponents.add(sch.getServiceComponentName());
 
-        Map<String, ServiceComponent> clusterServiceComponents = 
clusterService.getServiceComponents();
-        if (clusterServiceComponents != null) {
-          for (ServiceComponent clusterServiceComponent : 
clusterServiceComponents.values()) {
-            installedComponents.add(clusterServiceComponent.getName());
-
-            // Determine if this component was PREVIOUSLY installed, which 
implies that its containing service was PREVIOUSLY installed
-            if 
(!previouslyExistingServices.contains(clusterService.getName())) {
-              Map<String, ServiceComponentHost> clusterServiceComponentHosts = 
clusterServiceComponent.getServiceComponentHosts();
-              if (clusterServiceComponentHosts != null) {
-                for (ServiceComponentHost clusterServiceComponentHost : 
clusterServiceComponentHosts.values()) {
-                  if 
(PREVIOUSLY_INSTALLED_STATES.contains(clusterServiceComponentHost.getState())) {
-                    previouslyExistingServices.add(clusterService.getName());
-                    break;
-                  }
-                }
+              // Determine if this component was PREVIOUSLY installed, which 
implies that its containing service was PREVIOUSLY installed
+              if (!previouslyExistingServices.contains(serviceName) && 
PREVIOUSLY_INSTALLED_STATES.contains(sch.getState())) {
+                previouslyExistingServices.add(serviceName);
               }
+
+              return true;
             }
+
+            return false;
           }
-        }
-      }
-    }
+        });
 
+    Map<String, Map<String, String>> existingConfigurations = 
calculateExistingConfigurations(cluster, null);
     Map<String, Map<String, String>> updates = 
getServiceConfigurationUpdates(cluster,
         existingConfigurations, installedServices, serviceFilter, 
previouslyExistingServices, true, true);
 
+    // Store the updates...
     for (Map.Entry<String, Map<String, String>> entry : updates.entrySet()) {
       configHelper.updateConfigType(cluster, cluster.getDesiredStackVersion(),
           ambariManagementController, entry.getKey(), entry.getValue(), null,
@@ -434,7 +438,7 @@ public class KerberosHelperImpl implements KerberosHelper {
 
     Map<String, Map<String, String>> kerberosConfigurations = new HashMap<>();
     KerberosDetails kerberosDetails = getKerberosDetails(cluster, null);
-    KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster);
+    KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster, 
false);
 
     Map<String, String> kerberosDescriptorProperties = 
kerberosDescriptor.getProperties();
     Map<String, Map<String, String>> configurations = 
addAdditionalConfigurations(cluster,
@@ -442,10 +446,10 @@ public class KerberosHelperImpl implements KerberosHelper 
{
 
     Map<String, Set<String>> propertiesToIgnore = new HashMap<>();
 
-    // If Ambari is managing it own identities then add AMBARI to the set of 
installed servcie so
+    // If Ambari is managing it own identities then add AMBARI to the set of 
installed service so
     // that its Kerberos descriptor entries will be included.
-    if (createAmbariIdentities(existingConfigurations.get("kerberos-env"))) {
-      installedServices = new HashMap<>(installedServices);
+    if (createAmbariIdentities(existingConfigurations.get(KERBEROS_ENV))) {
+      installedServices = new HashMap<String, Set<String>>(installedServices);
       installedServices.put("AMBARI", Collections.singleton("AMBARI_SERVER"));
     }
 
@@ -482,7 +486,7 @@ public class KerberosHelperImpl implements KerberosHelper {
                   processIdentityConfigurations(identityConfigurations, 
kerberosConfigurations, configurations, propertiesToIgnore);
 
                   mergeConfigurations(kerberosConfigurations,
-                      
componentDescriptor.getConfigurations(!servicePreviouslyExisted), 
configurations);
+                      
componentDescriptor.getConfigurations(!servicePreviouslyExisted), 
configurations, null);
                 }
               }
             }
@@ -491,14 +495,134 @@ public class KerberosHelperImpl implements 
KerberosHelper {
       }
     }
 
-    setAuthToLocalRules(kerberosDescriptor, kerberosDetails.getDefaultRealm(), 
installedServices, configurations, kerberosConfigurations);
+    setAuthToLocalRules(cluster, kerberosDescriptor, 
kerberosDetails.getDefaultRealm(), installedServices, configurations, 
kerberosConfigurations, false);
 
     return (applyStackAdvisorUpdates)
         ? applyStackAdvisorUpdates(cluster, installedServices.keySet(), 
configurations, kerberosConfigurations, propertiesToIgnore,
-      new HashMap<>(), kerberosEnabled)
+        new HashMap<>(), kerberosEnabled)
         : kerberosConfigurations;
   }
 
+  /**
+   * Adds host assignments, recommended by the Stack Advisor, to the 
configuration map (clusterHostInfo)
+   * for the components specified in the component filter 
<code>componentFilter</code> (or all if the
+   * component filter is <code>null</code>).
+   *
+   * @param cluster         the cluster
+   * @param services        the relevant services to consider
+   * @param componentFilter the set of components to add to the 
clusterHostInfo structure
+   * @param configurations  the configurations map to update
+   * @throws AmbariException if an error occurs
+   */
+  private void applyStackAdvisorHostRecommendations(Cluster cluster,
+                                                    Set<String> services,
+                                                    Set<String> 
componentFilter,
+                                                    Map<String, Map<String, 
String>> configurations)
+      throws AmbariException {
+    StackId stackVersion = cluster.getCurrentStackVersion();
+    List<String> hostNames = new ArrayList<>();
+
+    Collection<Host> hosts = cluster.getHosts();
+    if (hosts != null) {
+      for (Host host : hosts) {
+        hostNames.add(host.getHostName());
+      }
+    }
+
+    StackAdvisorRequest request = 
StackAdvisorRequest.StackAdvisorRequestBuilder
+        .forStack(stackVersion.getStackName(), stackVersion.getStackVersion())
+        .forServices(services)
+        .forHosts(hostNames)
+        .withComponentHostsMap(cluster.getServiceComponentHostMap(null, 
services))
+        .ofType(StackAdvisorRequest.StackAdvisorRequestType.HOST_GROUPS)
+        .build();
+
+    try {
+      RecommendationResponse response = stackAdvisorHelper.recommend(request);
+
+      RecommendationResponse.Recommendation recommendation = (response == 
null) ? null : response.getRecommendations();
+      RecommendationResponse.Blueprint blueprint = (recommendation == null) ? 
null : recommendation.getBlueprint();
+      Set<RecommendationResponse.HostGroup> hostGroups = (blueprint == null) ? 
null : blueprint.getHostGroups();
+
+
+      if (hostGroups != null) {
+        RecommendationResponse.BlueprintClusterBinding blueprintBinding = 
recommendation.getBlueprintClusterBinding();
+        Map<String, RecommendationResponse.BindingHostGroup> bindingMap = new 
HashMap<>();
+        if (blueprintBinding != null) {
+          Set<RecommendationResponse.BindingHostGroup> bindingHostGroups = 
blueprintBinding.getHostGroups();
+          if (bindingHostGroups != null) {
+            for (RecommendationResponse.BindingHostGroup bindingHostGroup : 
bindingHostGroups) {
+              bindingMap.put(bindingHostGroup.getName(), bindingHostGroup);
+            }
+          }
+        }
+
+        // Get (and created if needed) the clusterHostInfo map
+        Map<String, String> clusterHostInfoMap = 
configurations.get("clusterHostInfo");
+        if (clusterHostInfoMap == null) {
+          clusterHostInfoMap = new HashMap<>();
+          configurations.put("clusterHostInfo", clusterHostInfoMap);
+        }
+
+        Map<String, String> componentToClusterInfoMap = 
StageUtils.getComponentToClusterInfoKeyMap();
+
+        // Iterate through the recommendations to find the recommended host 
assignments
+        for (RecommendationResponse.HostGroup hostGroup : hostGroups) {
+          Set<Map<String, String>> components = hostGroup.getComponents();
+
+          if (components != null) {
+            RecommendationResponse.BindingHostGroup binding = 
bindingMap.get(hostGroup.getName());
+
+            if (binding != null) {
+              Set<Map<String, String>> hostGroupHosts = binding.getHosts();
+
+              if (hostGroupHosts != null) {
+                for (Map<String, String> component : components) {
+                  String componentName = component.get("name");
+
+                  // If the component filter is null or the current component 
is found in the filter,
+                  // include it in the map
+                  if ((componentFilter == null) || 
componentFilter.contains(componentName)) {
+                    String key = componentToClusterInfoMap.get(componentName);
+
+                    if (StringUtils.isEmpty(key)) {
+                      // If not found in the componentToClusterInfoMap, then 
keys are assumed to be
+                      // in the form of <component_name>_hosts (lowercase)
+                      key = componentName.toLowerCase() + "_hosts";
+                    }
+
+                    Set<String> fqdns = new TreeSet<>();
+
+                    // Values are a comma-delimited list of hosts.
+                    // If a value exists, split it and add the tokens to the 
set
+                    if (!StringUtils.isEmpty(clusterHostInfoMap.get(key))) {
+                      
fqdns.addAll(Arrays.asList(clusterHostInfoMap.get(key).split(",")));
+                    }
+
+                    // Add the set of hosts for the current host group
+                    for (Map<String, String> hostGroupHost : hostGroupHosts) {
+                      String fqdn = hostGroupHost.get("fqdn");
+
+                      if (!StringUtils.isEmpty(fqdn)) {
+                        fqdns.add(fqdn);
+                      }
+                    }
+
+                    // create the comma-delimited list of hosts
+                    clusterHostInfoMap.put(key, StringUtils.join(fqdns, ','));
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    } catch (StackAdvisorException e) {
+      LOG.error("Failed to obtain the recommended host groups for the 
preconfigured components.", e);
+      throw new AmbariException(e.getMessage(), e);
+    }
+  }
+
   @Override
   public Map<String, Map<String, String>> applyStackAdvisorUpdates(Cluster 
cluster, Set<String> services,
                                                                    Map<String, 
Map<String, String>> existingConfigurations,
@@ -568,9 +692,16 @@ public class KerberosHelperImpl implements KerberosHelper {
       }
 
       Set<StackId> visitedStacks = new HashSet<>();
+      Map<String, Service> installedServices = cluster.getServices();
 
       for (String serviceName : services) {
-        Service service = cluster.getService(serviceName);
+        Service service = installedServices.get(serviceName);
+
+        // Skip services that are not really installed
+        if (service == null) {
+          continue;
+        }
+
         StackId stackId = service.getDesiredStackId();
 
         if (visitedStacks.contains(stackId)) {
@@ -579,7 +710,7 @@ public class KerberosHelperImpl implements KerberosHelper {
 
         StackAdvisorRequest request = 
StackAdvisorRequest.StackAdvisorRequestBuilder
             .forStack(stackId.getStackName(), stackId.getStackVersion())
-            .forServices(new ArrayList<>(services))
+            .forServices(services)
             .forHosts(hostNames)
             .withComponentHostsMap(cluster.getServiceComponentHostMap(null, 
services))
             .withConfigurations(requestConfigurations)
@@ -647,7 +778,7 @@ public class KerberosHelperImpl implements KerberosHelper {
                     "\n\tConfigType: {}\n\tProperty: {}\n\tValue: {}",
                 configType, propertyName, recommendedValue);
 
-            if(kerberosConfigProperties == null) {
+            if (kerberosConfigProperties == null) {
               kerberosConfigProperties = new HashMap<>();
               kerberosConfigurations.put(configType, kerberosConfigProperties);
             }
@@ -723,7 +854,7 @@ public class KerberosHelperImpl implements KerberosHelper {
 
     // Only perform this task if Ambari manages Kerberos identities
     if (kerberosDetails.manageIdentities()) {
-      KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster);
+      KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster, 
false);
 
       Map<String, String> kerberosDescriptorProperties = 
kerberosDescriptor.getProperties();
       Map<String, Map<String, String>> configurations = 
addAdditionalConfigurations(cluster,
@@ -947,16 +1078,18 @@ public class KerberosHelperImpl implements 
KerberosHelper {
   }
 
   @Override
-  public void setAuthToLocalRules(KerberosDescriptor kerberosDescriptor, 
String realm,
+  public void setAuthToLocalRules(Cluster cluster,
+                                  KerberosDescriptor kerberosDescriptor, 
String realm,
                                   Map<String, Set<String>> installedServices,
                                   Map<String, Map<String, String>> 
existingConfigurations,
-                                  Map<String, Map<String, String>> 
kerberosConfigurations)
+                                  Map<String, Map<String, String>> 
kerberosConfigurations,
+                                  boolean includePreconfigureData)
       throws AmbariException {
 
     boolean processAuthToLocalRules = true;
-    Map<String, String> kerberosEnvProperties = 
existingConfigurations.get("kerberos-env");
-    if (kerberosEnvProperties.containsKey("manage_auth_to_local")) {
-      processAuthToLocalRules = 
Boolean.valueOf(kerberosEnvProperties.get("manage_auth_to_local"));
+    Map<String, String> kerberosEnvProperties = 
existingConfigurations.get(KERBEROS_ENV);
+    if (kerberosEnvProperties.containsKey(MANAGE_AUTH_TO_LOCAL_RULES)) {
+      processAuthToLocalRules = 
Boolean.valueOf(kerberosEnvProperties.get(MANAGE_AUTH_TO_LOCAL_RULES));
     }
 
     if (kerberosDescriptor != null && processAuthToLocalRules) {
@@ -966,7 +1099,7 @@ public class KerberosHelperImpl implements KerberosHelper {
 
       // a flag to be used by the AuthToLocalBuilder marking whether the 
default realm rule should contain the //L option, indicating username case 
insensitive behaviour
       // the 'kerberos-env' structure is expected to be available here as it 
was previously validated
-      boolean caseInsensitiveUser = 
Boolean.valueOf(existingConfigurations.get("kerberos-env").get("case_insensitive_username_rules"));
+      boolean caseInsensitiveUser = 
Boolean.valueOf(existingConfigurations.get(KERBEROS_ENV).get(CASE_INSENSITIVE_USERNAME_RULES));
 
       // Additional realms that need to be handled according to the Kerberos 
Descriptor
       String additionalRealms = 
kerberosDescriptor.getProperty("additional_realms");
@@ -976,43 +1109,69 @@ public class KerberosHelperImpl implements 
KerberosHelper {
       filterContext.put("configurations", existingConfigurations);
       filterContext.put("services", installedServices.keySet());
 
-      // Determine which properties need to be set
       AuthToLocalBuilder authToLocalBuilder = new AuthToLocalBuilder(realm, 
additionalRealms, caseInsensitiveUser);
-      addIdentities(authToLocalBuilder, kerberosDescriptor.getIdentities(true, 
filterContext), null, existingConfigurations);
 
+      // Add in the default configurations for the services that need to be 
preconfigured. These
+      // configurations may be needed while calculating the auth-to-local 
rules.
+      Map<String, Map<String, String>> replacements = (includePreconfigureData)
+          ? 
addConfigurationsForPreProcessedServices(deepCopy(existingConfigurations), 
cluster, kerberosDescriptor, false)
+          : existingConfigurations;
+
+      // Process top-level identities
+      addIdentities(authToLocalBuilder, kerberosDescriptor.getIdentities(true, 
filterContext), null, replacements);
+
+      // Determine which properties need to be set
       authToLocalProperties = kerberosDescriptor.getAuthToLocalProperties();
       if (authToLocalProperties != null) {
         authToLocalPropertiesToSet.addAll(authToLocalProperties);
       }
 
-      for(Map.Entry<String, Set<String>> installedService: 
installedServices.entrySet()) {
-        String serviceName = installedService.getKey();
+      // Iterate through the services in the Kerberos descriptor. If a found 
service is installed
+      // or marked to be preconfigured, add the relevant data to the 
auth-to-local rules.
+      Map<String, KerberosServiceDescriptor> serviceDescriptors = 
kerberosDescriptor.getServices();
+      if (serviceDescriptors != null) {
+        for (KerberosServiceDescriptor serviceDescriptor : 
serviceDescriptors.values()) {
+          String serviceName = serviceDescriptor.getName();
+          boolean preconfigure = includePreconfigureData && 
serviceDescriptor.shouldPreconfigure();
+          boolean explicitlyAdded = installedServices.containsKey(serviceName);
+
+          // Add this service's identities if we are implicitly 
preconfigurring the service or if the
+          // service has been explicitly added to the cluster
+          if (preconfigure || explicitlyAdded) {
+            LOG.info("Adding identities for service {} to auth to local 
mapping [{}]",
+                serviceName,
+                (explicitlyAdded) ? "explicit" : "preconfigured");
 
-        KerberosServiceDescriptor serviceDescriptor = 
kerberosDescriptor.getService(serviceName);
-        if(serviceDescriptor != null) {
-          LOG.info("Adding identities for service {} to auth to local 
mapping", installedService);
+            // Process the service-level Kerberos descriptor
+            addIdentities(authToLocalBuilder, 
serviceDescriptor.getIdentities(true, filterContext), null, replacements);
 
-          // Process the service-level Kerberos descriptor
-          addIdentities(authToLocalBuilder, 
serviceDescriptor.getIdentities(true, filterContext), null, 
existingConfigurations);
+            authToLocalProperties = 
serviceDescriptor.getAuthToLocalProperties();
+            if (authToLocalProperties != null) {
+              authToLocalPropertiesToSet.addAll(authToLocalProperties);
+            }
 
-          authToLocalProperties = serviceDescriptor.getAuthToLocalProperties();
-          if (authToLocalProperties != null) {
-            authToLocalPropertiesToSet.addAll(authToLocalProperties);
-          }
+            // Process the relevant component-level Kerberos descriptors
+            Map<String, KerberosComponentDescriptor> componentDescriptors = 
serviceDescriptor.getComponents();
+            if (componentDescriptors != null) {
+              Set<String> installedServiceComponents = 
installedServices.get(serviceName);
+              // Ensure installedComponents is not null....
+              if (installedServiceComponents == null) {
+                installedServiceComponents = Collections.emptySet();
+              }
 
-          // Process the relevant component-level Kerberos descriptors
-          Set<String> installedComponents = installedService.getValue();
-          if(installedComponents != null) {
-            for (String installedComponent : installedComponents) {
-              KerberosComponentDescriptor componentDescriptor = 
serviceDescriptor.getComponent(installedComponent);
+              for (KerberosComponentDescriptor componentDescriptor : 
componentDescriptors.values()) {
+                String componentName = componentDescriptor.getName();
 
-              if (componentDescriptor != null) {
-                LOG.info("Adding identities for component {} to auth to local 
mapping", installedComponent);
-                addIdentities(authToLocalBuilder, 
componentDescriptor.getIdentities(true, filterContext), null, 
existingConfigurations);
+                // Add this component's identities if we are implicitly 
preconfiguring the parent
+                // service or if the component has been explicitly added to 
the cluster
+                if (preconfigure || 
(installedServiceComponents.contains(componentName))) {
+                  LOG.info("Adding identities for component {} to auth to 
local mapping", componentName);
+                  addIdentities(authToLocalBuilder, 
componentDescriptor.getIdentities(true, filterContext), null, replacements);
 
-                authToLocalProperties = 
componentDescriptor.getAuthToLocalProperties();
-                if (authToLocalProperties != null) {
-                  authToLocalPropertiesToSet.addAll(authToLocalProperties);
+                  authToLocalProperties = 
componentDescriptor.getAuthToLocalProperties();
+                  if (authToLocalProperties != null) {
+                    authToLocalPropertiesToSet.addAll(authToLocalProperties);
+                  }
                 }
               }
             }
@@ -1065,63 +1224,82 @@ public class KerberosHelperImpl implements 
KerberosHelper {
 
 
   @Override
-  public List<ServiceComponentHost> getServiceComponentHostsToProcess(Cluster 
cluster,
-                                                                      
KerberosDescriptor kerberosDescriptor,
-                                                                      
Map<String, ? extends Collection<String>> serviceComponentFilter,
-                                                                      
Collection<String> hostFilter, Collection<String> identityFilter,
-                                                                      
Command<Boolean, ServiceComponentHost> shouldProcessCommand)
+  public List<ServiceComponentHost> getServiceComponentHostsToProcess(final 
Cluster cluster,
+                                                                      final 
KerberosDescriptor kerberosDescriptor,
+                                                                      final 
Map<String, ? extends Collection<String>> serviceComponentFilter,
+                                                                      final 
Collection<String> hostFilter, Collection<String> identityFilter,
+                                                                      final 
Command<Boolean, ServiceComponentHost> shouldProcessCommand)
       throws AmbariException {
-    List<ServiceComponentHost> serviceComponentHostsToProcess = new 
ArrayList<>();
-    Map<String, Service> services = cluster.getServices();
-
-    if ((services != null) && !services.isEmpty()) {
-      Collection<Host> hosts = cluster.getHosts();
-
-      if ((hosts != null) && !hosts.isEmpty()) {
-        // Iterate over the hosts in the cluster to find the components 
installed in each.  For each
-        // component (aka service component host - sch) determine the 
configuration updates and
-        // and the principals an keytabs to create.
-        for (Host host : hosts) {
-          String hostname = host.getHostName();
-
-          // Filter hosts as needed....
-          if ((hostFilter == null) || hostFilter.contains(hostname)) {
-            // Get a list of components on the current host
-            List<ServiceComponentHost> serviceComponentHosts = 
cluster.getServiceComponentHosts(hostname);
-
-            if ((serviceComponentHosts != null) && 
!serviceComponentHosts.isEmpty()) {
-
-              // Iterate over the components installed on the current host to 
get the service and
-              // component-level Kerberos descriptors in order to determine 
which principals,
-              // keytab files, and configurations need to be created or 
updated.
-              for (ServiceComponentHost sch : serviceComponentHosts) {
-                String serviceName = sch.getServiceName();
-                String componentName = sch.getServiceComponentName();
-
-                // If there is no filter or the filter contains the current 
service name...
-                if ((serviceComponentFilter == null) || 
serviceComponentFilter.containsKey(serviceName)) {
-                  Collection<String> componentFilter = (serviceComponentFilter 
== null) ? null : serviceComponentFilter.get(serviceName);
-                  KerberosServiceDescriptor serviceDescriptor = 
kerberosDescriptor.getService(serviceName);
-
-                  if (serviceDescriptor != null) {
-                    // If there is no filter or the filter contains the 
current component name,
-                    // test to see if this component should be processed by 
querying the handler...
-                    if (((componentFilter == null) || 
componentFilter.contains(componentName)) && shouldProcessCommand.invoke(sch)) {
-                      serviceComponentHostsToProcess.add(sch);
-                    }
-                  }
-                }
+    return getServiceComponentHosts(cluster, new Command<Boolean, 
ServiceComponentHost>() {
+      @Override
+      public Boolean invoke(ServiceComponentHost sch) throws AmbariException {
+        if (sch != null) {
+          // Check the host filter
+          if ((hostFilter == null) || hostFilter.contains(sch.getHostName())) {
+            String serviceName = sch.getServiceName();
+
+            // Check the service filter
+            if ((serviceComponentFilter == null) || 
serviceComponentFilter.containsKey(serviceName)) {
+              KerberosServiceDescriptor serviceDescriptor = 
kerberosDescriptor.getService(serviceName);
+
+              if (serviceDescriptor != null) {
+                Collection<String> componentFilter = (serviceComponentFilter 
== null) ? null : serviceComponentFilter.get(serviceName);
+
+                // Check the service/component filter and the 
shouldProcessCommand
+                return (((componentFilter == null) || 
componentFilter.contains(sch.getServiceComponentName())) &&
+                    ((shouldProcessCommand == null) || 
shouldProcessCommand.invoke(sch)));
               }
             }
           }
         }
+
+        return false;
+      }
+    });
+  }
+
+  /**
+   * Find the {@link ServiceComponentHost}s for the cluster, filtering using 
the
+   * supplied "should include" command (<code>shouldIncludeCommand</code>).
+   * <p>
+   * If <code>shouldIncludeCommand</code> is <code>null/code>, no filtering 
will be performed causing
+   * all found {@link ServiceComponentHost}s to be returned.
+   *
+   * @param cluster              the cluster
+   * @param shouldIncludeCommand the filtering logic
+   * @return a list of (filtered) {@link ServiceComponentHost}s
+   * @throws AmbariException if an error occurs
+   */
+  private List<ServiceComponentHost> getServiceComponentHosts(Cluster cluster,
+                                                              Command<Boolean, 
ServiceComponentHost> shouldIncludeCommand)
+      throws AmbariException {
+    List<ServiceComponentHost> serviceComponentHostsToProcess = new 
ArrayList<>();
+    // Get the hosts in the cluster
+    Collection<Host> hosts = cluster.getHosts();
+
+    if ((hosts != null) && !hosts.isEmpty()) {
+      // Iterate over the hosts in the cluster to find the components 
installed in each.
+      for (Host host : hosts) {
+        String hostname = host.getHostName();
+
+        // Get a list of components on the current host
+        List<ServiceComponentHost> serviceComponentHosts = 
cluster.getServiceComponentHosts(hostname);
+
+        if ((serviceComponentHosts != null) && 
!serviceComponentHosts.isEmpty()) {
+          // Iterate over the components installed on the current host and 
execute the shouldIncludeCommand
+          // Command (if supplied) to get the desired ServiceComponentHost 
instances.
+          for (ServiceComponentHost sch : serviceComponentHosts) {
+            if ((shouldIncludeCommand == null) || 
shouldIncludeCommand.invoke(sch)) {
+              serviceComponentHostsToProcess.add(sch);
+            }
+          }
+        }
       }
     }
 
     return serviceComponentHostsToProcess;
   }
 
-
   @Override
   public Set<String> getHostsWithValidKerberosClient(Cluster cluster)
       throws AmbariException {
@@ -1140,41 +1318,30 @@ public class KerberosHelperImpl implements 
KerberosHelper {
   }
 
   @Override
-  public KerberosDescriptor getKerberosDescriptor(Cluster cluster) throws 
AmbariException {
-    return getKerberosDescriptor(KerberosDescriptorType.COMPOSITE, cluster, 
false, null);
+  public KerberosDescriptor getKerberosDescriptor(Cluster cluster, boolean 
includePreconfigureData) throws AmbariException {
+    return getKerberosDescriptor(KerberosDescriptorType.COMPOSITE, cluster, 
false, null, includePreconfigureData);
   }
 
   @Override
   public KerberosDescriptor getKerberosDescriptor(KerberosDescriptorType 
kerberosDescriptorType, Cluster cluster,
-                                                  boolean evaluateWhenClauses, 
Collection<String> additionalServices)
+                                                  boolean evaluateWhenClauses, 
Collection<String> additionalServices,
+                                                  boolean 
includePreconfigureData)
       throws AmbariException {
-    KerberosDescriptor kerberosDescriptor;
 
     KerberosDescriptor stackDescriptor = (kerberosDescriptorType == 
KerberosDescriptorType.STACK || kerberosDescriptorType == 
KerberosDescriptorType.COMPOSITE)
-        ? getKerberosDescriptorFromStack(cluster)
+        ? getKerberosDescriptorFromStack(cluster, includePreconfigureData)
         : null;
 
     KerberosDescriptor userDescriptor = (kerberosDescriptorType == 
KerberosDescriptorType.USER || kerberosDescriptorType == 
KerberosDescriptorType.COMPOSITE)
         ? getKerberosDescriptorUpdates(cluster)
         : null;
 
-    if (stackDescriptor == null) {
-      if (userDescriptor == null) {
-        return new KerberosDescriptor();  // return an empty Kerberos 
descriptor since we have no data
-      } else {
-        kerberosDescriptor = userDescriptor;
-      }
-    } else {
-      if (userDescriptor != null) {
-        stackDescriptor.update(userDescriptor);
-      }
-      kerberosDescriptor = stackDescriptor;
-    }
+    KerberosDescriptor kerberosDescriptor = 
combineKerberosDescriptors(stackDescriptor, userDescriptor);
 
     if (evaluateWhenClauses) {
       Set<String> services = new HashSet<>(cluster.getServices().keySet());
 
-      if(additionalServices != null) {
+      if (additionalServices != null) {
         services.addAll(additionalServices);
       }
 
@@ -1220,7 +1387,8 @@ public class KerberosHelperImpl implements KerberosHelper 
{
   @Override
   public Map<String, Map<String, String>> mergeConfigurations(Map<String, 
Map<String, String>> configurations,
                                                               Map<String, 
KerberosConfigurationDescriptor> updates,
-                                                              Map<String, 
Map<String, String>> replacements)
+                                                              Map<String, 
Map<String, String>> replacements,
+                                                              Set<String> 
configurationTypeFilter)
       throws AmbariException {
 
     if ((updates != null) && !updates.isEmpty()) {
@@ -1230,11 +1398,59 @@ public class KerberosHelperImpl implements 
KerberosHelper {
 
       for (Map.Entry<String, KerberosConfigurationDescriptor> entry : 
updates.entrySet()) {
         String type = entry.getKey();
-        KerberosConfigurationDescriptor configurationDescriptor = 
entry.getValue();
 
-        if (configurationDescriptor != null) {
-          Map<String, String> updatedProperties = 
configurationDescriptor.getProperties();
-          mergeConfigurations(configurations, type, updatedProperties, 
replacements);
+        if ((configurationTypeFilter == null) || 
(configurationTypeFilter.contains(type))) {
+          KerberosConfigurationDescriptor configurationDescriptor = 
entry.getValue();
+
+          if (configurationDescriptor != null) {
+            Map<String, String> updatedProperties = 
configurationDescriptor.getProperties();
+            mergeConfigurations(configurations, type, updatedProperties, 
replacements);
+          }
+        }
+      }
+    }
+
+    return configurations;
+  }
+
+  @Override
+  public Map<String, Map<String, String>> 
processPreconfiguredServiceConfigurations(Map<String, Map<String, String>> 
configurations,
+                                                                               
     Map<String, Map<String, String>> replacements,
+                                                                               
     Cluster cluster,
+                                                                               
     KerberosDescriptor kerberosDescriptor)
+      throws AmbariException {
+
+    // Ensure the Kerberos descriptor exists....
+    if (kerberosDescriptor == null) {
+      kerberosDescriptor = getKerberosDescriptor(cluster, true);
+    }
+
+    Map<String, KerberosServiceDescriptor> serviceDescriptors = 
kerberosDescriptor.getServices();
+
+    if (serviceDescriptors != null) {
+      if (configurations == null) {
+        configurations = new HashMap<>();
+      }
+
+      // Add in the default configurations for the services that need to be 
preconfigured. These
+      // configurations may be needed while calculating the auth-to-local 
rules.
+      Map<String, Map<String, String>> replacementsWithDefaults = 
addConfigurationsForPreProcessedServices(deepCopy(replacements), cluster, 
kerberosDescriptor, true);
+
+      Map<String, Service> existingServices = cluster.getServices();
+
+      for (KerberosServiceDescriptor serviceDescriptor : 
serviceDescriptors.values()) {
+        String serviceName = serviceDescriptor.getName();
+        boolean shouldPreconfigure = serviceDescriptor.shouldPreconfigure();
+
+        if (!existingServices.containsKey(serviceName) && shouldPreconfigure) {
+          configurations = mergeConfigurations(configurations, 
serviceDescriptor.getConfigurations(), replacementsWithDefaults, 
replacements.keySet());
+
+          Map<String, KerberosComponentDescriptor> componentDescriptors = 
serviceDescriptor.getComponents();
+          if (componentDescriptors != null) {
+            for (KerberosComponentDescriptor componentDescriptor : 
componentDescriptors.values()) {
+              configurations = mergeConfigurations(configurations, 
componentDescriptor.getConfigurations(), replacementsWithDefaults, 
replacements.keySet());
+            }
+          }
         }
       }
     }
@@ -1318,16 +1534,15 @@ public class KerberosHelperImpl implements 
KerberosHelper {
   @Override
   public Map<String, Map<String, String>> calculateConfigurations(Cluster 
cluster, String hostname,
                                                                   Map<String, 
String> kerberosDescriptorProperties)
-      throws AmbariException
-  {
+      throws AmbariException {
     return addAdditionalConfigurations(cluster,
-      calculateExistingConfigurations(cluster, hostname),
-      hostname, kerberosDescriptorProperties);
+        calculateExistingConfigurations(cluster, hostname),
+        hostname, kerberosDescriptorProperties);
   }
 
   private Map<String, String> principalNames(Cluster cluster, Map<String, 
Map<String, String>> configuration) throws AmbariException {
     Map<String, String> result = new HashMap<>();
-    for (Map.Entry<String, String> each : 
getKerberosDescriptor(cluster).principals().entrySet()) {
+    for (Map.Entry<String, String> each : getKerberosDescriptor(cluster, 
false).principals().entrySet()) {
       result.put(each.getKey(), 
variableReplacementHelper.replaceVariables(each.getValue(), configuration));
     }
     return result;
@@ -1355,12 +1570,11 @@ public class KerberosHelperImpl implements 
KerberosHelper {
 
     // Only calculate the active identities if the kerberos-env configurtaion 
is available.  Else
     // important information like the realm will be missing 
(kerberos-env/realm)
-    Config kerberosEnvConfig = cluster.getDesiredConfigByType("kerberos-env");
-    if(kerberosEnvConfig == null) {
+    Config kerberosEnvConfig = cluster.getDesiredConfigByType(KERBEROS_ENV);
+    if (kerberosEnvConfig == null) {
       LOG.debug("Calculating the active identities for {} is being skipped 
since the kerberos-env configuration is not available",
           clusterName, cluster.getSecurityType().name(), 
SecurityType.KERBEROS.name());
-    }
-    else {
+    } else {
       Collection<String> hosts;
       String ambariServerHostname = StageUtils.getHostName();
 
@@ -1383,7 +1597,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
       }
 
       if (!hosts.isEmpty()) {
-        KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster);
+        KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster, 
false);
 
         if (kerberosDescriptor != null) {
           Map<String, String> kerberosDescriptorProperties = 
kerberosDescriptor.getProperties();
@@ -1410,7 +1624,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
             if (hostname.equals(ambariServerHostname)) {
               // Determine if we should _calculate_ the Ambari service 
identities.
               // If kerberos-env/create_ambari_principal is not set to false 
the identity should be calculated.
-              if(createAmbariIdentities(kerberosEnvConfig.getProperties())) {
+              if (createAmbariIdentities(kerberosEnvConfig.getProperties())) {
                 List<KerberosIdentityDescriptor> ambariIdentities = 
getAmbariServerIdentities(kerberosDescriptor);
                 if (ambariIdentities != null) {
                   identities.addAll(ambariIdentities);
@@ -1743,7 +1957,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
                                final Handler handler)
       throws AmbariException, KerberosOperationException {
 
-    final KerberosDescriptor kerberosDescriptor = 
getKerberosDescriptor(cluster);
+    final KerberosDescriptor kerberosDescriptor = 
getKerberosDescriptor(cluster, false);
 
     List<ServiceComponentHost> schToProcess = 
getServiceComponentHostsToProcess(
         cluster,
@@ -1751,7 +1965,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
         serviceComponentFilter,
         hostFilter,
         identityFilter,
-      arg -> true);
+        arg -> true);
 
 
     // While iterating over all the ServiceComponentHosts find hosts that have 
KERBEROS_CLIENT
@@ -1791,7 +2005,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
     Map<String, Set<String>> clusterHostInfo = 
StageUtils.getClusterHostInfo(cluster);
     String clusterHostInfoJson = StageUtils.getGson().toJson(clusterHostInfo);
 
-    @Experimental(feature=ExperimentalFeature.MULTI_SERVICE, comment="The 
cluster stack id is deprecated")
+    @Experimental(feature = ExperimentalFeature.MULTI_SERVICE, comment = "The 
cluster stack id is deprecated")
     Map<String, String> hostParams = 
customCommandExecutionHelper.createDefaultHostParams(cluster, 
cluster.getDesiredStackVersion());
     String hostParamsJson = StageUtils.getGson().toJson(hostParams);
     String ambariServerHostname = StageUtils.getHostName();
@@ -1855,7 +2069,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
       }
 
       List<ServiceComponentHost> serviceComponentHostsToProcess = new 
ArrayList<>();
-      KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster);
+      KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster, 
false);
       KerberosIdentityDataFileWriter kerberosIdentityDataFileWriter = null;
 
       Map<String, String> kerberosDescriptorProperties = 
kerberosDescriptor.getProperties();
@@ -1965,7 +2179,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
       Map<String, Set<String>> clusterHostInfo = 
StageUtils.getClusterHostInfo(cluster);
       String clusterHostInfoJson = 
StageUtils.getGson().toJson(clusterHostInfo);
 
-      @Experimental(feature=ExperimentalFeature.MULTI_SERVICE, comment="The 
cluster stack id is deprecated")
+      @Experimental(feature = ExperimentalFeature.MULTI_SERVICE, comment = 
"The cluster stack id is deprecated")
       Map<String, String> hostParams = 
customCommandExecutionHelper.createDefaultHostParams(cluster, 
cluster.getDesiredStackVersion());
       String hostParamsJson = StageUtils.getGson().toJson(hostParams);
       String ambariServerHostname = StageUtils.getHostName();
@@ -2037,7 +2251,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
       throw new AmbariException(message);
     }
 
-    Config configKerberosEnv = cluster.getDesiredConfigByType("kerberos-env");
+    Config configKerberosEnv = cluster.getDesiredConfigByType(KERBEROS_ENV);
     if (configKerberosEnv == null) {
       String message = "The 'kerberos-env' configuration is not available";
       LOG.error(message);
@@ -2052,14 +2266,14 @@ public class KerberosHelperImpl implements 
KerberosHelper {
     }
 
     kerberosDetails.setSecurityType(cluster.getSecurityType());
-    kerberosDetails.setDefaultRealm(kerberosEnvProperties.get("realm"));
+    kerberosDetails.setDefaultRealm(kerberosEnvProperties.get(DEFAULT_REALM));
 
     kerberosDetails.setKerberosEnvProperties(kerberosEnvProperties);
 
     // If set, override the manage identities behavior
     kerberosDetails.setManageIdentities(manageIdentities);
 
-    String kdcTypeProperty = kerberosEnvProperties.get("kdc_type");
+    String kdcTypeProperty = kerberosEnvProperties.get(KDC_TYPE);
     if ((kdcTypeProperty == null) && kerberosDetails.manageIdentities()) {
       String message = "The 'kerberos-env/kdc_type' value must be set to a 
valid KDC type";
       LOG.error(message);
@@ -2253,12 +2467,12 @@ public class KerberosHelperImpl implements 
KerberosHelper {
   /**
    * Creates a new stage
    *
-   * @param id              the new stage's id
-   * @param cluster         the relevant Cluster
-   * @param requestId       the relevant request Id
-   * @param requestContext  a String describing the stage
-   * @param commandParams   JSON-encoded command parameters
-   * @param hostParams      JSON-encoded host parameters
+   * @param id             the new stage's id
+   * @param cluster        the relevant Cluster
+   * @param requestId      the relevant request Id
+   * @param requestContext a String describing the stage
+   * @param commandParams  JSON-encoded command parameters
+   * @param hostParams     JSON-encoded host parameters
    * @return a newly created Stage
    */
   private Stage createNewStage(long id, Cluster cluster, long requestId,
@@ -2302,7 +2516,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
                                         Map<String, String> commandParameters, 
String commandDetail,
                                         Integer timeout) throws 
AmbariException {
 
-    Stage stage = createNewStage(id, cluster, requestId, requestContext,  
commandParams, hostParams);
+    Stage stage = createNewStage(id, cluster, requestId, requestContext, 
commandParams, hostParams);
     stage.addServerActionCommand(actionClass.getName(), null, 
Role.AMBARI_SERVER_ACTION,
         RoleCommand.EXECUTE, cluster.getClusterName(), event, 
commandParameters, commandDetail,
         ambariManagementController.findConfigurationTagsWithOverrides(cluster, 
null), timeout,
@@ -2628,11 +2842,12 @@ public class KerberosHelperImpl implements 
KerberosHelper {
    * Get the default Kerberos descriptor from the stack, which is the same as 
the value from
    * 
<code>stacks/:stackName/versions/:version/artifacts/kerberos_descriptor</code>
    *
-   * @param cluster the cluster
+   * @param cluster                 the cluster
+   * @param includePreconfigureData <code>true</code> to include the 
preconfigure data; otherwise false
    * @return a Kerberos Descriptor
    * @throws AmbariException if an error occurs while retrieving the Kerberos 
descriptor
    */
-  private KerberosDescriptor getKerberosDescriptorFromStack(Cluster cluster) 
throws AmbariException {
+  private KerberosDescriptor getKerberosDescriptorFromStack(Cluster cluster, 
boolean includePreconfigureData) throws AmbariException {
     // !!! FIXME in a per-service view, what does this become?
     Set<StackId> stackIds = new HashSet<>();
 
@@ -2649,14 +2864,14 @@ public class KerberosHelperImpl implements 
KerberosHelper {
     // -------------------------------
     // Get the default Kerberos descriptor from the stack, which is the same 
as the value from
     // stacks/:stackName/versions/:version/artifacts/kerberos_descriptor
-    return ambariMetaInfo.getKerberosDescriptor(stackId.getStackName(), 
stackId.getStackVersion());
+    return ambariMetaInfo.getKerberosDescriptor(stackId.getStackName(), 
stackId.getStackVersion(), includePreconfigureData);
     // -------------------------------
   }
 
   /**
    * Recursively walk the Kerberos descriptor tree to find all Kerberos 
identity definitions and
    * determine which should be filtered out.
-   *
+   * <p>
    * No actual filtering is performed while processing since any referenced 
Kerberos identities need
    * to be accessible throughout the process. So a map of container path to a 
list of identities is
    * created an returned
@@ -2668,14 +2883,14 @@ public class KerberosHelperImpl implements 
KerberosHelper {
    * @return
    * @throws AmbariException
    */
-  private Map<String,Set<String>> processWhenClauses(String currentPath, 
AbstractKerberosDescriptorContainer container, Map<String, Object> context, 
Map<String,Set<String>> identitiesToRemove) throws AmbariException {
+  private Map<String, Set<String>> processWhenClauses(String currentPath, 
AbstractKerberosDescriptorContainer container, Map<String, Object> context, 
Map<String, Set<String>> identitiesToRemove) throws AmbariException {
 
     // Get the list of this container's identities.
     // Do not filter these identities using 
KerberosIdentityDescriptor#shouldInclude since we will do
     // that later.
     List<KerberosIdentityDescriptor> identities = 
container.getIdentities(true, null);
 
-    if((identities != null) && !identities.isEmpty()) {
+    if ((identities != null) && !identities.isEmpty()) {
       Set<String> set = null;
 
       for (KerberosIdentityDescriptor identity : identities) {
@@ -2691,8 +2906,8 @@ public class KerberosHelperImpl implements KerberosHelper 
{
     }
 
     Collection<? extends AbstractKerberosDescriptorContainer> children = 
container.getChildContainers();
-    if(children != null) {
-      for(AbstractKerberosDescriptorContainer child: children) {
+    if (children != null) {
+      for (AbstractKerberosDescriptorContainer child : children) {
         identitiesToRemove = processWhenClauses(currentPath + "/" + 
child.getName(), child, context, identitiesToRemove);
       }
     }
@@ -2749,6 +2964,142 @@ public class KerberosHelperImpl implements 
KerberosHelper {
 
   }
 
+  /**
+   * Gathers the Kerberos-related configurations for services not yet 
installed, but flagged to be
+   * preconfigured.
+   * <p>
+   * Only existing configuration types will be updated, new types will not be 
added since they are
+   * expected only when the relevant service has been installed. This is to 
help reduce the number
+   * of service restarts when new services are added to clusters where 
Kerberos has been enabled.
+   * <p>
+   * If desired, the Stack Advisor will be invoked to request recommended 
hosts for the component.
+   * This is needed to fill out the clusterHostInfo structure in the 
configuration map. For example,
+   * <code>clusterHostInfo/knox_gateway_hosts</code>
+   *
+   * @param configurations           the existing configurations (updated 
in-place)
+   * @param cluster                  the cluster
+   * @param kerberosDescriptor       the kerberos descriptor
+   * @param calculateClusterHostInfo true, to query the Stack Advisor for 
recommended hosts for the
+   *                                 preconfigured services and components; 
false, otherwise
+   * @return the updated configuration map
+   * @throws AmbariException if an error occurs
+   */
+  private Map<String, Map<String, String>> 
addConfigurationsForPreProcessedServices(Map<String, Map<String, String>> 
configurations,
+                                                                               
     Cluster cluster,
+                                                                               
     KerberosDescriptor kerberosDescriptor,
+                                                                               
     boolean calculateClusterHostInfo)
+      throws AmbariException {
+
+    Map<String, KerberosServiceDescriptor> serviceDescriptorMap = 
kerberosDescriptor.getServices();
+
+    if (serviceDescriptorMap != null) {
+      Map<String, Service> existingServices = cluster.getServices();
+      Set<String> allServices = new HashSet<>(existingServices.keySet());
+      Set<String> componentFilter = new HashSet<>();
+      StackId stackVersion = cluster.getCurrentStackVersion();
+
+      for (KerberosServiceDescriptor serviceDescriptor : 
serviceDescriptorMap.values()) {
+        String serviceName = serviceDescriptor.getName();
+        boolean shouldPreconfigure = serviceDescriptor.shouldPreconfigure();
+
+        if (shouldPreconfigure && !existingServices.containsKey(serviceName)) {
+          if (ambariMetaInfo.isValidService(stackVersion.getStackName(), 
stackVersion.getStackVersion(), serviceName)) {
+            ServiceInfo serviceInfo = 
ambariMetaInfo.getService(stackVersion.getStackName(), 
stackVersion.getStackVersion(), serviceName);
+
+            Collection<PropertyInfo> servicePropertiesInfos = 
serviceInfo.getProperties();
+            if (servicePropertiesInfos != null) {
+              Map<String, Map<String, String>> propertiesToAdd = new 
HashMap<>();
+
+              for (PropertyInfo propertyInfo : servicePropertiesInfos) {
+                String type = 
ConfigHelper.fileNameToConfigType(propertyInfo.getFilename());
+
+                Map<String, String> map = propertiesToAdd.get(type);
+                if (map == null) {
+                  map = new HashMap<>();
+                  propertiesToAdd.put(type, map);
+                }
+                map.put(propertyInfo.getName(), propertyInfo.getValue());
+              }
+
+              for (Map.Entry<String, Map<String, String>> entry : 
propertiesToAdd.entrySet()) {
+                if (!configurations.containsKey(entry.getKey())) {
+                  configurations.put(entry.getKey(), entry.getValue());
+                }
+              }
+            }
+
+            // This is only needed if the Stack Advisor is being called to get 
recommended host
+            // for components
+            if (calculateClusterHostInfo) {
+              // Add the service to preconfigure to the all services set for 
use later
+              allServices.add(serviceName);
+
+              // Add the components for the service to preconfigure to the 
component filter
+              List<ComponentInfo> componentInfos = serviceInfo.getComponents();
+              if (componentInfos != null) {
+                for (ComponentInfo componentInfo : componentInfos) {
+                  componentFilter.add(componentInfo.getName());
+                }
+              }
+            }
+          }
+        }
+      }
+
+      if (calculateClusterHostInfo && (allServices.size() > 
existingServices.size())) {
+        applyStackAdvisorHostRecommendations(cluster, allServices, 
componentFilter, configurations);
+      }
+    }
+
+    return configurations;
+  }
+
+  /**
+   * Combines a stack-level Kerberos descriptor with a user-suppled Kerberos 
descriptor to creae a
+   * composite {@link KerberosDescriptor} using the following logic:
+   * <p>
+   * <ul>
+   * <li>
+   * If both the stack-level and the user-supplied Kerberos descriptors are 
<code>null</code>,
+   * return an empty {@link KerberosDescriptor}.
+   * </li>
+   * <li>
+   * If the stack-level Kerberos descriptor is <code>null</code> and the 
user-supplied Kerberos
+   * descriptor is <code>non-null</code>, return the user-supplied Kerberos 
descriptor.
+   * </li>
+   * <li>
+   * If the stack-level Kerberos descriptor is <code>non-null</code> and the 
user-supplied
+   * Kerberos descriptor is <code>null</code>, return the stack-level Kerberos 
descriptor.
+   * </li>
+   * <li>
+   * If neither the stack-level nor the user-supplied Kerberos descriptors are 
<code>null</code>,
+   * return the stack-level Kerberos descriptor that has been updated using 
data from the
+   * user-supplied Kerberos descriptor.
+   * </li>
+   * </ul>
+   *
+   * @param stackDescriptor the stack-level Keberos descriptor
+   * @param userDescriptor  the user-supplied Kerberos descriptor
+   * @return a KerberosDescriptor
+   */
+  private KerberosDescriptor combineKerberosDescriptors(KerberosDescriptor 
stackDescriptor, KerberosDescriptor userDescriptor) {
+    KerberosDescriptor kerberosDescriptor;
+    if (stackDescriptor == null) {
+      if (userDescriptor == null) {
+        return new KerberosDescriptor();  // return an empty Kerberos 
descriptor since we have no data
+      } else {
+        kerberosDescriptor = userDescriptor;
+      }
+    } else {
+      if (userDescriptor != null) {
+        stackDescriptor.update(userDescriptor);
+      }
+      kerberosDescriptor = stackDescriptor;
+    }
+
+    return kerberosDescriptor;
+  }
+
   /* 
********************************************************************************************
    * Helper classes and enums
    * 
********************************************************************************************
 *\
@@ -2994,7 +3345,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
           hostParamsJson);
 
       Collection<ServiceComponentHost> filteredComponents = 
filterServiceComponentHostsForHosts(
-        new ArrayList<>(serviceComponentHosts), hostsWithValidKerberosClient);
+          new ArrayList<>(serviceComponentHosts), 
hostsWithValidKerberosClient);
 
       if (!filteredComponents.isEmpty()) {
         List<String> hostsToUpdate = createUniqueHostList(filteredComponents, 
Collections.singleton(HostState.HEALTHY));
@@ -3005,7 +3356,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
 
         ActionExecutionContext actionExecContext = new ActionExecutionContext(
             cluster.getClusterName(),
-          SET_KEYTAB,
+            SET_KEYTAB,
             requestResourceFilters,
             requestParams);
         
customCommandExecutionHelper.addExecutionCommandsToStage(actionExecContext, 
stage,
@@ -3024,14 +3375,14 @@ public class KerberosHelperImpl implements 
KerberosHelper {
      */
     public void addCheckMissingKeytabsStage(Cluster cluster, String 
clusterHostInfoJson, String hostParamsJson, 
ServiceComponentHostServerActionEvent event, Map<String, String> 
commandParameters, RoleCommandOrder roleCommandOrder, RequestStageContainer 
requestStageContainer, List<ServiceComponentHost> serviceComponentHosts) throws 
AmbariException {
       Stage stage = createNewStage(requestStageContainer.getLastStageId(),
-        cluster,
-        requestStageContainer.getId(),
-        "Checking keytabs",
-        StageUtils.getGson().toJson(commandParameters),
-        hostParamsJson);
+          cluster,
+          requestStageContainer.getId(),
+          "Checking keytabs",
+          StageUtils.getGson().toJson(commandParameters),
+          hostParamsJson);
 
       Collection<ServiceComponentHost> filteredComponents = 
filterServiceComponentHostsForHosts(
-        new ArrayList<>(serviceComponentHosts), 
getHostsWithValidKerberosClient(cluster));
+          new ArrayList<>(serviceComponentHosts), 
getHostsWithValidKerberosClient(cluster));
 
       List<String> hostsToUpdate = createUniqueHostList(filteredComponents, 
Collections.singleton(HostState.HEALTHY));
       Map<String, String> requestParams = new HashMap<>();
@@ -3040,10 +3391,10 @@ public class KerberosHelperImpl implements 
KerberosHelper {
       requestResourceFilters.add(reqResFilter);
 
       ActionExecutionContext actionExecContext = new ActionExecutionContext(
-        cluster.getClusterName(),
-        CHECK_KEYTABS,
-        requestResourceFilters,
-        requestParams);
+          cluster.getClusterName(),
+          CHECK_KEYTABS,
+          requestResourceFilters,
+          requestParams);
       
customCommandExecutionHelper.addExecutionCommandsToStage(actionExecContext, 
stage, requestParams, null);
       RoleGraph roleGraph = roleGraphFactory.createNew(roleCommandOrder);
       roleGraph.build(stage);
@@ -3079,19 +3430,18 @@ public class KerberosHelperImpl implements 
KerberosHelper {
     }
 
     void addDisableSecurityHookStage(Cluster cluster,
-                                            String clusterHostInfoJson,
-                                            String hostParamsJson,
-                                            Map<String, String> 
commandParameters,
-                                            RoleCommandOrder roleCommandOrder,
-                                            RequestStageContainer 
requestStageContainer)
-      throws AmbariException
-    {
+                                     String clusterHostInfoJson,
+                                     String hostParamsJson,
+                                     Map<String, String> commandParameters,
+                                     RoleCommandOrder roleCommandOrder,
+                                     RequestStageContainer 
requestStageContainer)
+        throws AmbariException {
       Stage stage = createNewStage(requestStageContainer.getLastStageId(),
-        cluster,
-        requestStageContainer.getId(),
-        "Disable security",
-        StageUtils.getGson().toJson(commandParameters),
-        hostParamsJson);
+          cluster,
+          requestStageContainer.getId(),
+          "Disable security",
+          StageUtils.getGson().toJson(commandParameters),
+          hostParamsJson);
       addDisableSecurityCommandToAllServices(cluster, stage);
       RoleGraph roleGraph = roleGraphFactory.createNew(roleCommandOrder);
       roleGraph.build(stage);
@@ -3103,27 +3453,26 @@ public class KerberosHelperImpl implements 
KerberosHelper {
     private void addDisableSecurityCommandToAllServices(Cluster cluster, Stage 
stage) throws AmbariException {
       for (Service service : cluster.getServices().values()) {
         for (ServiceComponent component : 
service.getServiceComponents().values()) {
-            if (!component.getServiceComponentHosts().isEmpty()) {
-              String firstHost = 
component.getServiceComponentHosts().keySet().iterator().next(); // it is only 
necessary to send it to one host
-              ActionExecutionContext exec = new ActionExecutionContext(
+          if (!component.getServiceComponentHosts().isEmpty()) {
+            String firstHost = 
component.getServiceComponentHosts().keySet().iterator().next(); // it is only 
necessary to send it to one host
+            ActionExecutionContext exec = new ActionExecutionContext(
                 cluster.getClusterName(),
                 "DISABLE_SECURITY",
                 singletonList(new RequestResourceFilter(service.getName(), 
component.getName(), singletonList(firstHost))),
                 Collections.emptyMap());
-              customCommandExecutionHelper.addExecutionCommandsToStage(exec, 
stage, Collections.emptyMap(), null);
+            customCommandExecutionHelper.addExecutionCommandsToStage(exec, 
stage, Collections.emptyMap(), null);
           }
         }
       }
     }
 
     void addStopZookeeperStage(Cluster cluster,
-                                      String clusterHostInfoJson,
-                                      String hostParamsJson,
-                                      Map<String, String> commandParameters,
-                                      RoleCommandOrder roleCommandOrder,
-                                      RequestStageContainer 
requestStageContainer)
-      throws AmbariException
-    {
+                               String clusterHostInfoJson,
+                               String hostParamsJson,
+                               Map<String, String> commandParameters,
+                               RoleCommandOrder roleCommandOrder,
+                               RequestStageContainer requestStageContainer)
+        throws AmbariException {
       Service zookeeper;
       try {
         zookeeper = cluster.getService("ZOOKEEPER");
@@ -3131,19 +3480,19 @@ public class KerberosHelperImpl implements 
KerberosHelper {
         return;
       }
       Stage stage = createNewStage(requestStageContainer.getLastStageId(),
-        cluster,
-        requestStageContainer.getId(),
-        "Stopping ZooKeeper",
-        StageUtils.getGson().toJson(commandParameters),
-        hostParamsJson);
+          cluster,
+          requestStageContainer.getId(),
+          "Stopping ZooKeeper",
+          StageUtils.getGson().toJson(commandParameters),
+          hostParamsJson);
       for (ServiceComponent component : 
zookeeper.getServiceComponents().values()) {
-          Set<String> hosts = component.getServiceComponentHosts().keySet();
-          ActionExecutionContext exec = new ActionExecutionContext(
+        Set<String> hosts = component.getServiceComponentHosts().keySet();
+        ActionExecutionContext exec = new ActionExecutionContext(
             cluster.getClusterName(),
             "STOP",
             singletonList(new RequestResourceFilter(zookeeper.getName(), 
component.getName(), new ArrayList<>(hosts))),
             Collections.emptyMap());
-          customCommandExecutionHelper.addExecutionCommandsToStage(exec, 
stage, Collections.emptyMap(), null);
+        customCommandExecutionHelper.addExecutionCommandsToStage(exec, stage, 
Collections.emptyMap(), null);
       }
       RoleGraph roleGraph = roleGraphFactory.createNew(roleCommandOrder);
       roleGraph.build(stage);
@@ -3168,7 +3517,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
           hostParamsJson);
 
       Collection<ServiceComponentHost> filteredComponents = 
filterServiceComponentHostsForHosts(
-        new ArrayList<>(serviceComponentHosts), hostsWithValidKerberosClient);
+          new ArrayList<>(serviceComponentHosts), 
hostsWithValidKerberosClient);
 
       if (!filteredComponents.isEmpty()) {
         List<String> hostsToUpdate = createUniqueHostList(filteredComponents, 
Collections.singleton(HostState.HEALTHY));
@@ -3181,7 +3530,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
 
           ActionExecutionContext actionExecContext = new 
ActionExecutionContext(
               cluster.getClusterName(),
-            REMOVE_KEYTAB,
+              REMOVE_KEYTAB,
               requestResourceFilters,
               requestParams);
           
customCommandExecutionHelper.addExecutionCommandsToStage(actionExecContext, 
stage,
@@ -3325,6 +3674,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
       commandParameters.put(KerberosServerAction.UPDATE_CONFIGURATIONS, 
"true");
       commandParameters.put(KerberosServerAction.DEFAULT_REALM, 
kerberosDetails.getDefaultRealm());
       commandParameters.put(KerberosServerAction.INCLUDE_AMBARI_IDENTITY, 
(kerberosDetails.createAmbariPrincipal()) ? "true" : "false");
+      commandParameters.put(KerberosServerAction.PRECONFIGURE_SERVICES, 
kerberosDetails.getPreconfigureServices());
 
       if (dataDirectory != null) {
         commandParameters.put(KerberosServerAction.DATA_DIRECTORY, 
dataDirectory.getAbsolutePath());
@@ -3431,10 +3781,10 @@ public class KerberosHelperImpl implements 
KerberosHelper {
       }
 
       addDisableSecurityHookStage(cluster, clusterHostInfoJson, 
hostParamsJson, commandParameters,
-        roleCommandOrder, requestStageContainer);
+          roleCommandOrder, requestStageContainer);
 
       addStopZookeeperStage(cluster, clusterHostInfoJson, hostParamsJson, 
commandParameters,
-        roleCommandOrder, requestStageContainer);
+          roleCommandOrder, requestStageContainer);
 
       // *****************************************************************
       // Create stage to prepare operations
@@ -3580,7 +3930,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
 
         if (!regenerateAllKeytabs) {
           addCheckMissingKeytabsStage(cluster, clusterHostInfoJson, 
hostParamsJson, event,
-            commandParameters, roleCommandOrder, requestStageContainer, 
serviceComponentHosts);
+              commandParameters, roleCommandOrder, requestStageContainer, 
serviceComponentHosts);
         }
 
         // *****************************************************************
@@ -3752,5 +4102,9 @@ public class KerberosHelperImpl implements KerberosHelper 
{
       return (kerberosEnvProperties == null) ||
           
!"false".equalsIgnoreCase(kerberosEnvProperties.get(CREATE_AMBARI_PRINCIPAL));
     }
+
+    public String getPreconfigureServices() {
+      return (kerberosEnvProperties == null) ? "" : 
kerberosEnvProperties.get(PRECONFIGURE_SERVICES);
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4bce5782/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java
index 91a84ea..b4e1027 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java
@@ -538,7 +538,7 @@ public class BlueprintConfigurationProcessor {
       String clusterName = 
clusterTopology.getAmbariContext().getClusterName(clusterTopology.getClusterId());
       Cluster cluster = 
clusterTopology.getAmbariContext().getController().getClusters().getCluster(clusterName);
       authToLocalPerClusterMap = new HashMap<>();
-      
authToLocalPerClusterMap.put(Long.valueOf(clusterTopology.getClusterId()), 
clusterTopology.getAmbariContext().getController().getKerberosHelper().getKerberosDescriptor(cluster).getAllAuthToLocalProperties());
+      
authToLocalPerClusterMap.put(Long.valueOf(clusterTopology.getClusterId()), 
clusterTopology.getAmbariContext().getController().getKerberosHelper().getKerberosDescriptor(cluster,
 false).getAllAuthToLocalProperties());
       } catch (AmbariException e) {
         LOG.error("Error while getting authToLocal properties. ", e);
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4bce5782/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterKerberosDescriptorResourceProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterKerberosDescriptorResourceProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterKerberosDescriptorResourceProvider.java
index 59bd96a..2678d55 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterKerberosDescriptorResourceProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterKerberosDescriptorResourceProvider.java
@@ -158,7 +158,8 @@ public class ClusterKerberosDescriptorResourceProvider 
extends ReadOnlyResourceP
           kerberosDescriptor = 
kerberosHelper.getKerberosDescriptor(kerberosDescriptorType,
               cluster,
               getEvaluateWhen(requestInfoProperties),
-              getAdditionalServices(requestInfoProperties));
+              getAdditionalServices(requestInfoProperties),
+              false);
         } catch (AmbariException e) {
           throw new SystemException("An unexpected error occurred building the 
cluster's composite Kerberos Descriptor", e);
         }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4bce5782/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackVersionResourceProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackVersionResourceProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackVersionResourceProvider.java
index 64ead40..094c75b 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackVersionResourceProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackVersionResourceProvider.java
@@ -19,10 +19,7 @@
 
 package org.apache.ambari.server.controller.internal;
 
-import java.io.File;
-import java.io.IOException;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Map;
@@ -42,12 +39,6 @@ import org.apache.ambari.server.controller.spi.Resource.Type;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
-import org.apache.ambari.server.state.kerberos.KerberosDescriptor;
-import org.apache.ambari.server.state.kerberos.KerberosDescriptorFactory;
-import org.apache.ambari.server.state.kerberos.KerberosServiceDescriptor;
-import 
org.apache.ambari.server.state.kerberos.KerberosServiceDescriptorFactory;
-
-import com.google.inject.Inject;
 
 @StaticallyInject
 public class StackVersionResourceProvider extends ReadOnlyResourceProvider {
@@ -67,18 +58,6 @@ public class StackVersionResourceProvider extends 
ReadOnlyResourceProvider {
   private static Set<String> pkPropertyIds = new HashSet<>(
     Arrays.asList(new String[]{STACK_NAME_PROPERTY_ID, 
STACK_VERSION_PROPERTY_ID}));
 
-  /**
-   * KerberosDescriptorFactory used to create KerberosDescriptor instances
-   */
-  @Inject
-  private static KerberosDescriptorFactory kerberosDescriptorFactory;
-
-  /**
-   * KerberosServiceDescriptorFactory used to create KerberosServiceDescriptor 
instances
-   */
-  @Inject
-  private static KerberosServiceDescriptorFactory 
kerberosServiceDescriptorFactory;
-
   protected StackVersionResourceProvider(Set<String> propertyIds,
       Map<Type, String> keyPropertyIds,
       AmbariManagementController managementController) {
@@ -153,51 +132,6 @@ public class StackVersionResourceProvider extends 
ReadOnlyResourceProvider {
     return resources;
   }
 
-  /**
-   * Given data from a StackVersionResponse build a complete Kerberos 
descriptor hierarchy.
-   *
-   * @param stackVersionResponse the StackVersionResponse instance containing 
the details of the
-   *                             stack and the relevant Kerberos descriptor 
files
-   * @return a KerberosDescriptor containing the complete hierarchy for the 
stack
-   * @throws IOException     if the specified File is not found or not a 
readable
-   * @throws AmbariException if the specified File does not contain valid 
JSON-encoded Kerberos
-   *                         descriptor
-   */
-  private KerberosDescriptor buildKerberosDescriptor(StackVersionResponse 
stackVersionResponse)
-      throws IOException {
-    KerberosDescriptor kerberosDescriptor = null;
-
-    // Process the stack-level Kerberos descriptor file
-    File stackKerberosDescriptorFile = 
stackVersionResponse.getStackKerberosDescriptorFile();
-    if (stackKerberosDescriptorFile != null) {
-      kerberosDescriptor = 
kerberosDescriptorFactory.createInstance(stackKerberosDescriptorFile);
-    }
-
-    // Process the service-level Kerberos descriptor files
-    Collection<File> serviceDescriptorFiles = 
stackVersionResponse.getServiceKerberosDescriptorFiles();
-    if ((serviceDescriptorFiles != null) && !serviceDescriptorFiles.isEmpty()) 
{
-      // Make sure kerberosDescriptor is not null. This will be the case if 
there is no stack-level
-      // Kerberos descriptor file.
-      if (kerberosDescriptor == null) {
-        kerberosDescriptor = new KerberosDescriptor();
-      }
-
-      // For each service-level Kerberos descriptor file, parse into an array 
of KerberosServiceDescriptors
-      // and then append each to the KerberosDescriptor hierarchy.
-      for (File file : serviceDescriptorFiles) {
-        KerberosServiceDescriptor[] serviceDescriptors = 
kerberosServiceDescriptorFactory.createInstances(file);
-
-        if (serviceDescriptors != null) {
-          for (KerberosServiceDescriptor serviceDescriptor : 
serviceDescriptors) {
-            kerberosDescriptor.putService(serviceDescriptor);
-          }
-        }
-      }
-    }
-
-    return kerberosDescriptor;
-  }
-
   private StackVersionRequest getRequest(Map<String, Object> properties) {
     return new StackVersionRequest(
         (String) properties.get(STACK_NAME_PROPERTY_ID),

http://git-wip-us.apache.org/repos/asf/ambari/blob/4bce5782/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/RemovableIdentities.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/RemovableIdentities.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/RemovableIdentities.java
index d4bb501..66bf7b3 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/RemovableIdentities.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/RemovableIdentities.java
@@ -58,7 +58,7 @@ public class RemovableIdentities {
     if (cluster.getSecurityType() != SecurityType.KERBEROS) {
       return RemovableIdentities.none();
     }
-    KerberosServiceDescriptor serviceDescriptor = 
kerberosHelper.getKerberosDescriptor(cluster).getService(event.getServiceName());
+    KerberosServiceDescriptor serviceDescriptor = 
kerberosHelper.getKerberosDescriptor(cluster, 
false).getService(event.getServiceName());
     if (serviceDescriptor == null) {
       return RemovableIdentities.none();
     }
@@ -77,7 +77,7 @@ public class RemovableIdentities {
     if (cluster.getSecurityType() != SecurityType.KERBEROS) {
       return RemovableIdentities.none();
     }
-    KerberosServiceDescriptor serviceDescriptor = 
kerberosHelper.getKerberosDescriptor(cluster).getService(event.getServiceName());
+    KerberosServiceDescriptor serviceDescriptor = 
kerberosHelper.getKerberosDescriptor(cluster, 
false).getService(event.getServiceName());
     if (serviceDescriptor == null) {
       return RemovableIdentities.none();
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/4bce5782/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/UsedIdentities.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/UsedIdentities.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/UsedIdentities.java
index 46f5642..2f0974e 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/UsedIdentities.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/UsedIdentities.java
@@ -50,7 +50,7 @@ public class UsedIdentities {
    */
   public static UsedIdentities populate(Cluster cluster, ServiceExclude 
serviceExclude, ComponentExclude componentExclude, KerberosHelper 
kerberosHelper) throws AmbariException {
     List<KerberosIdentityDescriptor> result = new ArrayList<>();
-    KerberosDescriptor root = kerberosHelper.getKerberosDescriptor(cluster);
+    KerberosDescriptor root = kerberosHelper.getKerberosDescriptor(cluster, 
false);
     result.addAll(nullToEmpty(root.getIdentities()));
     for (Service service : cluster.getServices().values()) {
       if (serviceExclude.shouldExclude(service.getName())) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/4bce5782/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinitionManager.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinitionManager.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinitionManager.java
index 1f2d26f..dde2647 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinitionManager.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/customactions/ActionDefinitionManager.java
@@ -34,8 +34,8 @@ import javax.xml.bind.Unmarshaller;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.actionmanager.ActionType;
 import org.apache.ambari.server.actionmanager.TargetHostType;
-import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.security.authorization.RoleAuthorization;
+import org.apache.ambari.server.stack.StackDirectory;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -93,7 +93,7 @@ public class ActionDefinitionManager {
     }
 
     File[] customActionDefinitionFiles
-        = customActionDefinitionRoot.listFiles(AmbariMetaInfo.FILENAME_FILTER);
+        = customActionDefinitionRoot.listFiles(StackDirectory.FILENAME_FILTER);
 
     if (customActionDefinitionFiles != null) {
       for (File definitionFile : customActionDefinitionFiles) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/4bce5782/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerAction.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerAction.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerAction.java
index dd2b223..d6b8ffc 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerAction.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerAction.java
@@ -152,7 +152,7 @@ public abstract class AbstractPrepareKerberosServerAction 
extends KerberosServer
               // Calculate the set of configurations to update and replace any 
variables
               // using the previously calculated Map of configurations for the 
host.
               kerberosHelper.mergeConfigurations(kerberosConfigurations,
-                  componentDescriptor.getConfigurations(true), 
currentConfigurations);
+                  componentDescriptor.getConfigurations(true), 
currentConfigurations, null);
 
               // Add component-level principals (and keytabs)
               kerberosHelper.addIdentities(kerberosIdentityDataFileWriter, 
componentIdentities,

http://git-wip-us.apache.org/repos/asf/ambari/blob/4bce5782/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
index 2e331bb..c86ffa3 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
@@ -135,6 +135,12 @@ public abstract class KerberosServerAction extends 
AbstractServerAction {
   */
   public static final String INCLUDE_AMBARI_IDENTITY = 
"include_ambari_identity";
 
+  /**
+   * Keys used in CommandParams from ExecutionCommand to declare how to 
pre-configure services.
+   * Expected values are, "ALL", "DEFAULT", and "NONE".
+   */
+  public static final String PRECONFIGURE_SERVICES = "preconfigure_services";
+
   private static final Logger LOG = 
LoggerFactory.getLogger(KerberosServerAction.class);
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/4bce5782/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PreconfigureServiceType.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PreconfigureServiceType.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PreconfigureServiceType.java
new file mode 100644
index 0000000..c843b14
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PreconfigureServiceType.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.serveraction.kerberos;
+
+/**
+ * PreconfigureServiceType enumerates the ways in which services may be 
pre-configured.
+ */
+public enum PreconfigureServiceType {
+  /**
+   * Preconfigure services that have been explicitly flagged.
+   * <p>
+   * For example, in the Kerberos descriptor using
+   * <code>
+   * "preconfigure" : true
+   * </code>
+   * <p>
+   * For example, declared in the stack-specific kerberos_preconfigure.json 
file
+   */
+  DEFAULT,
+
+  /**
+   * Preconfigure all services, flagged or not.
+   */
+  ALL,
+
+  /**
+   * Do not preconfiure any services, even if flagged.
+   */
+  NONE
+}

Reply via email to