AMBARI-18335. After upgrading cluster from HDP-2.4.x to HDP-2.5.x and added 
atlas service - missing kafka security properties (rlevas)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7aff03f5
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7aff03f5
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7aff03f5

Branch: refs/heads/branch-2.5
Commit: 7aff03f59d05cec0a491a2a4ab5b79bfaf5dc5f6
Parents: 79afcb9
Author: Robert Levas <rle...@hortonworks.com>
Authored: Fri Sep 9 15:41:15 2016 -0400
Committer: Robert Levas <rle...@hortonworks.com>
Committed: Fri Sep 9 15:41:15 2016 -0400

----------------------------------------------------------------------
 .../upgrades/UpgradeUserKerberosDescriptor.java |  205 ++
 .../kerberos/AbstractKerberosDescriptor.java    |    4 +-
 .../AbstractKerberosDescriptorContainer.java    |   86 +-
 .../KerberosConfigurationDescriptor.java        |   23 +-
 .../state/kerberos/KerberosDescriptor.java      |   32 +-
 .../KerberosDescriptorUpdateHelper.java         |  585 +++++
 .../kerberos/KerberosKeytabDescriptor.java      |   71 +-
 .../kerberos/KerberosPrincipalDescriptor.java   |    4 +-
 .../kerberos/KerberosServiceDescriptor.java     |    4 +-
 .../HBASE/0.96.0.2.0/kerberos.json              |    3 +-
 .../HDP/2.3/upgrades/nonrolling-upgrade-2.5.xml |   10 +
 .../stacks/HDP/2.3/upgrades/upgrade-2.5.xml     |   10 +
 .../HDP/2.4/upgrades/nonrolling-upgrade-2.5.xml |   10 +
 .../stacks/HDP/2.4/upgrades/upgrade-2.5.xml     |   10 +
 .../stacks/HDP/2.5/services/HBASE/kerberos.json |    3 +-
 .../HDP/2.5/upgrades/nonrolling-upgrade-2.5.xml |   10 +
 .../stacks/HDP/2.5/upgrades/upgrade-2.5.xml     |   10 +
 ...rKerberosDescriptorResourceProviderTest.java |  270 +--
 .../KerberosComponentDescriptorTest.java        |   69 +-
 .../KerberosConfigurationDescriptorTest.java    |   56 +-
 .../state/kerberos/KerberosDescriptorTest.java  |  126 +-
 .../KerberosDescriptorUpdateHelperTest.java     | 2272 ++++++++++++++++++
 .../KerberosIdentityDescriptorTest.java         |   88 +-
 .../kerberos/KerberosKeytabDescriptorTest.java  |   33 +-
 .../KerberosPrincipalDescriptorTest.java        |   32 +-
 .../kerberos/KerberosServiceDescriptorTest.java |   70 +-
 26 files changed, 3650 insertions(+), 446 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/UpgradeUserKerberosDescriptor.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/UpgradeUserKerberosDescriptor.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/UpgradeUserKerberosDescriptor.java
new file mode 100644
index 0000000..f1eab38
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/UpgradeUserKerberosDescriptor.java
@@ -0,0 +1,205 @@
+/*
+ * 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.upgrades;
+
+import com.google.inject.Inject;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.actionmanager.HostRoleCommand;
+import org.apache.ambari.server.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.agent.CommandReport;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.orm.dao.ArtifactDAO;
+import org.apache.ambari.server.orm.entities.ArtifactEntity;
+import org.apache.ambari.server.serveraction.AbstractServerAction;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.kerberos.KerberosDescriptor;
+import org.apache.ambari.server.state.kerberos.KerberosDescriptorFactory;
+import org.apache.ambari.server.state.kerberos.KerberosDescriptorUpdateHelper;
+import org.apache.ambari.server.state.stack.upgrade.Direction;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TreeMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Update the user-defined Kerberos Descriptor to work with the current stack.
+ *
+ * @see org.apache.ambari.server.state.kerberos.KerberosDescriptorUpdateHelper
+ */
+public class UpgradeUserKerberosDescriptor extends AbstractServerAction {
+  private static final Logger LOG = 
LoggerFactory.getLogger(UpgradeUserKerberosDescriptor.class);
+
+  /**
+   * The upgrade direction.
+   *
+   * @see Direction
+   */
+  private static final String UPGRADE_DIRECTION_KEY = "upgrade_direction";
+
+  /**
+   * The original "current" stack of the cluster before the upgrade started.
+   * This is the same regardless of whether the current direction is
+   * {@link Direction#UPGRADE} or {@link Direction#DOWNGRADE}.
+   *
+   * @see Direction
+   */
+  private static final String ORIGINAL_STACK_KEY = "original_stack";
+
+  /**
+   * The target upgrade stack before the upgrade started. This is the same
+   * regardless of whether the current direction is {@link Direction#UPGRADE} 
or
+   * {@link Direction#DOWNGRADE}.
+   *
+   * @see Direction
+   */
+  private static final String TARGET_STACK_KEY = "target_stack";
+
+  @Inject
+  private ArtifactDAO artifactDAO;
+
+  @Inject
+  private Clusters clusters;
+
+  @Inject
+  private AmbariMetaInfo ambariMetaInfo;
+
+  @Inject
+  private KerberosDescriptorFactory kerberosDescriptorFactory;
+
+  protected UpgradeUserKerberosDescriptor() {
+  }
+
+  /**
+   * Update Kerberos Descriptor Storm properties when upgrading to Storm 1.0
+   * <p/>
+   * Finds the relevant artifact entities and iterates through them to process 
each independently.
+   */
+  @Override
+  public CommandReport execute(ConcurrentMap<String, Object> 
requestSharedDataContext)
+      throws AmbariException, InterruptedException {
+    HostRoleCommand hostRoleCommand = getHostRoleCommand();
+    String clusterName = 
hostRoleCommand.getExecutionCommandWrapper().getExecutionCommand().getClusterName();
+    Cluster cluster = clusters.getCluster(clusterName);
+    List<String> messages = new ArrayList<String>();
+    List<String> errorMessages = new ArrayList<String>();
+
+    if (cluster != null) {
+      logMessage(messages, "Obtaining the user-defined Kerberos descriptor");
+
+      TreeMap<String, String> foreignKeys = new TreeMap<String, String>();
+      foreignKeys.put("cluster", String.valueOf(cluster.getClusterId()));
+
+      ArtifactEntity entity = 
artifactDAO.findByNameAndForeignKeys("kerberos_descriptor", foreignKeys);
+      KerberosDescriptor userDescriptor = (entity == null) ? null : 
kerberosDescriptorFactory.createInstance(entity.getArtifactData());
+
+      if (userDescriptor != null) {
+        StackId originalStackId = 
getStackIdFromCommandParams(ORIGINAL_STACK_KEY);
+        StackId targetStackId = getStackIdFromCommandParams(TARGET_STACK_KEY);
+        boolean isDowngrade = isDowngrade();
+
+        StackId newVersion = (isDowngrade) ? originalStackId : targetStackId;
+        StackId previousVersion = (isDowngrade) ? targetStackId : 
originalStackId;
+        KerberosDescriptor newDescriptor = null;
+        KerberosDescriptor previousDescriptor = null;
+
+        if (newVersion == null) {
+          logErrorMessage(messages, errorMessages, "The new stack version 
information was not found.");
+        } else {
+          logMessage(messages, String.format("Obtaining new stack Kerberos 
descriptor for %s.", newVersion.toString()));
+          newDescriptor = 
ambariMetaInfo.getKerberosDescriptor(newVersion.getStackName(), 
newVersion.getStackVersion());
+
+          if (newDescriptor == null) {
+            logErrorMessage(messages, errorMessages, String.format("The 
Kerberos descriptor for the new stack version, %s, was not found.", 
newVersion.toString()));
+          }
+        }
+
+        if (previousVersion == null) {
+          logErrorMessage(messages, errorMessages, "The previous stack version 
information was not found.");
+        } else {
+          logMessage(messages, String.format("Obtaining previous stack 
Kerberos descriptor for %s.", previousVersion.toString()));
+          previousDescriptor = 
ambariMetaInfo.getKerberosDescriptor(previousVersion.getStackName(), 
previousVersion.getStackVersion());
+
+          if (newDescriptor == null) {
+            logErrorMessage(messages, errorMessages, String.format("The 
Kerberos descriptor for the previous stack version, %s, was not found.", 
previousVersion.toString()));
+          }
+        }
+
+        if (errorMessages.isEmpty()) {
+          logMessage(messages, "Updating the user-specified Kerberos 
descriptor.");
+
+          KerberosDescriptor updatedDescriptor = 
KerberosDescriptorUpdateHelper.updateUserKerberosDescriptor(
+              previousDescriptor,
+              newDescriptor,
+              userDescriptor);
+
+          logMessage(messages, "Storing updated user-specified Kerberos 
descriptor.");
+
+          entity.setArtifactData(updatedDescriptor.toMap());
+          artifactDAO.merge(entity);
+
+          logMessage(messages, "Successfully updated the user-specified 
Kerberos descriptor.");
+        }
+      } else {
+        logMessage(messages, "A user-specified Kerberos descriptor was not 
found. No updates are necessary.");
+      }
+    } else {
+      logErrorMessage(messages, errorMessages, String.format("The cluster 
named %s was not found.", clusterName));
+    }
+
+    if (!errorMessages.isEmpty()) {
+      logErrorMessage(messages, errorMessages, "No updates have been performed 
due to previous issues.");
+    }
+
+    return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", 
StringUtils.join(messages, "\n"), StringUtils.join(errorMessages, "\n"));
+  }
+
+  /**
+   * Determines if upgrade direction is {@link Direction#UPGRADE} or {@link 
Direction#DOWNGRADE}.
+   *
+   * @return {@code true} if {@link Direction#DOWNGRADE}; {@code false} if 
{@link Direction#UPGRADE}
+   */
+  private boolean isDowngrade() {
+    return 
Direction.DOWNGRADE.name().equalsIgnoreCase(getCommandParameterValue(UPGRADE_DIRECTION_KEY));
+  }
+
+  private StackId getStackIdFromCommandParams(String commandParamKey) {
+    String stackId = getCommandParameterValue(commandParamKey);
+    if (stackId == null) {
+      return null;
+    } else {
+      return new StackId(stackId);
+    }
+  }
+
+  private void logMessage(List<String> messages, String message) {
+    LOG.info(message);
+    messages.add(message);
+  }
+
+  private void logErrorMessage(List<String> messages, List<String> 
errorMessages, String message) {
+    LOG.error(message);
+    messages.add(message);
+    errorMessages.add(message);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptor.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptor.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptor.java
index 84a9111..2112fcc 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptor.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptor.java
@@ -18,8 +18,8 @@
 
 package org.apache.ambari.server.state.kerberos;
 
-import java.util.HashMap;
 import java.util.Map;
+import java.util.TreeMap;
 
 /**
  * AbstractKerberosDescriptor is the base class for all Kerberos*Descriptor 
and associated classes.
@@ -65,7 +65,7 @@ public abstract class AbstractKerberosDescriptor {
    * @return a Map of date representing this AbstractKerberosDescriptor 
implementation
    */
   public Map<String, Object> toMap() {
-    HashMap<String, Object> dataMap = new HashMap<String, Object>();
+    TreeMap<String, Object> dataMap = new TreeMap<String, Object>();
     String name = getName();
 
     if (name != null) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java
index 39ebdaf..ad2437a 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java
@@ -23,12 +23,12 @@ import org.apache.ambari.server.AmbariException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
+import java.util.TreeMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.regex.Pattern;
 
 /**
@@ -165,8 +165,8 @@ public abstract class AbstractKerberosDescriptorContainer 
extends AbstractKerber
 
   /**
    * Returns a specific named child container
-   * @param name the name of the child container to retrieve
    *
+   * @param name the name of the child container to retrieve
    * @return an {@link AbstractKerberosDescriptorContainer}
    */
   public abstract AbstractKerberosDescriptorContainer getChildContainer(String 
name);
@@ -193,6 +193,17 @@ public abstract class AbstractKerberosDescriptorContainer 
extends AbstractKerber
   }
 
   /**
+   * Set the {@link KerberosIdentityDescriptor} for this {@link 
AbstractKerberosDescriptorContainer}.
+   *
+   * @param identities a {@link List} of {@link KerberosIdentityDescriptor}s
+   */
+  public void setIdentities(List<KerberosIdentityDescriptor> identities) {
+    this.identities = (identities == null)
+        ? null
+        : new ArrayList<KerberosIdentityDescriptor>(identities);
+  }
+
+  /**
    * Returns a List of KerberosIdentityDescriptors contained within this
    * AbstractKerberosDescriptorContainer.
    * <p/>
@@ -215,9 +226,9 @@ public abstract class AbstractKerberosDescriptorContainer 
extends AbstractKerber
    *                          (false)
    * @return a List of the requested KerberosIdentityDescriptors
    */
-  public List<KerberosIdentityDescriptor> getIdentities(boolean 
resolveReferences, Map<String,Object> contextForFilter) throws AmbariException {
+  public List<KerberosIdentityDescriptor> getIdentities(boolean 
resolveReferences, Map<String, Object> contextForFilter) throws AmbariException 
{
     if (identities == null) {
-      return Collections.emptyList();
+      return null;
     } else {
       List<KerberosIdentityDescriptor> list = new 
ArrayList<KerberosIdentityDescriptor>();
 
@@ -317,6 +328,18 @@ public abstract class AbstractKerberosDescriptorContainer 
extends AbstractKerber
   }
 
   /**
+   * Sets the {@link Map} of {@link KerberosConfigurationDescriptor}s for this
+   * {@link AbstractKerberosDescriptorContainer}.
+   *
+   * @param configurations a {@link Map} of {@link 
KerberosConfigurationDescriptor}s
+   */
+  public void setConfigurations(Map<String, KerberosConfigurationDescriptor> 
configurations) {
+    this.configurations = (configurations == null)
+        ? null
+        : new TreeMap<String, KerberosConfigurationDescriptor>(configurations);
+  }
+
+  /**
    * Returns a Map of raw KerberosConfigurationDescriptors contained within 
this
    * AbstractKerberosDescriptorContainer.
    * <p/>
@@ -353,7 +376,7 @@ public abstract class AbstractKerberosDescriptorContainer 
extends AbstractKerber
    */
   public Map<String, KerberosConfigurationDescriptor> 
getConfigurations(boolean includeInherited) {
     if (includeInherited) {
-      Map<String, KerberosConfigurationDescriptor> mergedConfigurations = new 
HashMap<String, KerberosConfigurationDescriptor>();
+      Map<String, KerberosConfigurationDescriptor> mergedConfigurations = new 
TreeMap<String, KerberosConfigurationDescriptor>();
       List<Map<String, KerberosConfigurationDescriptor>> configurationSets = 
new ArrayList<Map<String, KerberosConfigurationDescriptor>>();
       AbstractKerberosDescriptor currentDescriptor = this;
 
@@ -417,7 +440,7 @@ public abstract class AbstractKerberosDescriptorContainer 
extends AbstractKerber
       }
 
       if (configurations == null) {
-        configurations = new HashMap<String, 
KerberosConfigurationDescriptor>();
+        configurations = new TreeMap<String, 
KerberosConfigurationDescriptor>();
       }
 
       configurations.put(type, configuration);
@@ -448,7 +471,7 @@ public abstract class AbstractKerberosDescriptorContainer 
extends AbstractKerber
   public void putAuthToLocalProperty(String authToLocalProperty) {
     if (authToLocalProperty != null) {
       if (authToLocalProperties == null) {
-        authToLocalProperties = new HashSet<String>();
+        authToLocalProperties = new TreeSet<String>();
       }
 
       authToLocalProperties.add(authToLocalProperty);
@@ -456,6 +479,17 @@ public abstract class AbstractKerberosDescriptorContainer 
extends AbstractKerber
   }
 
   /**
+   * Sets the set of <code>auth_to_local</code> property names.
+   *
+   * @param authToLocalProperties a Set of String values; or null if not set
+   */
+  public void setAuthToLocalProperties(Set<String> authToLocalProperties) {
+    this.authToLocalProperties = (authToLocalProperties == null)
+        ? null
+        : new TreeSet<String>(authToLocalProperties);
+  }
+
+  /**
    * Gets the set of <code>auth_to_local</code> property names.
    *
    * @return a Set of String values; or null if not set
@@ -582,13 +616,13 @@ public abstract class AbstractKerberosDescriptorContainer 
extends AbstractKerber
     KerberosIdentityDescriptor identityDescriptor = null;
 
     if (path != null) {
-      if(path.startsWith("../")) {
+      if (path.startsWith("../")) {
         // Resolve parent path
         AbstractKerberosDescriptor parent = getParent();
 
         path = path.substring(2);
 
-        while(parent != null) {
+        while (parent != null) {
           String name = parent.getName();
 
           if (name != null) {
@@ -694,24 +728,27 @@ public abstract class AbstractKerberosDescriptorContainer 
extends AbstractKerber
     Map<String, Object> map = super.toMap();
 
     if (identities != null) {
-      List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
+      // Use a TreeMap to force the identities definitions to be ordered by 
name, alphebetically.
+      // This helps with readability and comparisons.
+      Map<String, Map<String, Object>> list = new TreeMap<String, Map<String, 
Object>>();
       for (KerberosIdentityDescriptor identity : identities) {
-        list.add(identity.toMap());
+        list.put(identity.getName(), identity.toMap());
       }
-      map.put(Type.IDENTITY.getDescriptorPluralName(), list);
+      map.put(Type.IDENTITY.getDescriptorPluralName(), list.values());
     }
 
     if (configurations != null) {
-      List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
+      // Use a TreeMap to force the configurations to be ordered by 
configuration type, alphebetically.
+      // This helps with readability and comparisons.
+      Map<String, Map<String, Object>> list = new TreeMap<String, Map<String, 
Object>>();
       for (KerberosConfigurationDescriptor configuration : 
configurations.values()) {
-        list.add(configuration.toMap());
+        list.put(configuration.getType(), configuration.toMap());
       }
-      map.put(Type.CONFIGURATION.getDescriptorPluralName(), list);
+      map.put(Type.CONFIGURATION.getDescriptorPluralName(), list.values());
     }
 
     if (authToLocalProperties != null) {
-      List<String> list = new ArrayList<String>(authToLocalProperties);
-      map.put(Type.AUTH_TO_LOCAL_PROPERTY.getDescriptorPluralName(), list);
+      map.put(Type.AUTH_TO_LOCAL_PROPERTY.getDescriptorPluralName(), 
authToLocalProperties);
     }
 
     return map;
@@ -723,6 +760,9 @@ public abstract class AbstractKerberosDescriptorContainer 
extends AbstractKerber
         ((getIdentities() == null)
             ? 0
             : getIdentities().hashCode()) +
+        ((getAuthToLocalProperties() == null)
+            ? 0
+            : getAuthToLocalProperties().hashCode()) +
         ((getConfigurations() == null)
             ? 0
             : getConfigurations().hashCode());
@@ -743,6 +783,11 @@ public abstract class AbstractKerberosDescriptorContainer 
extends AbstractKerber
                   : getIdentities().equals(descriptor.getIdentities())
           ) &&
           (
+              (getAuthToLocalProperties() == null)
+                  ? (descriptor.getAuthToLocalProperties() == null)
+                  : 
getAuthToLocalProperties().equals(descriptor.getAuthToLocalProperties())
+          ) &&
+          (
               (getConfigurations() == null)
                   ? (descriptor.getConfigurations() == null)
                   : getConfigurations().equals(descriptor.getConfigurations())
@@ -768,7 +813,7 @@ public abstract class AbstractKerberosDescriptorContainer 
extends AbstractKerber
   private KerberosIdentityDescriptor 
dereferenceIdentity(KerberosIdentityDescriptor identity) throws AmbariException 
{
     KerberosIdentityDescriptor dereferencedIdentity = null;
 
-    if(identity != null) {
+    if (identity != null) {
       KerberosIdentityDescriptor referencedIdentity;
       try {
         if (identity.getReference() != null) {
@@ -790,8 +835,7 @@ public abstract class AbstractKerberosDescriptorContainer 
extends AbstractKerber
           dereferencedIdentity = new 
KerberosIdentityDescriptor(referencedIdentity.toMap());
           dereferencedIdentity.update(identity);
         }
-      }
-      else {
+      } else {
         dereferencedIdentity = new 
KerberosIdentityDescriptor(identity.toMap());
       }
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosConfigurationDescriptor.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosConfigurationDescriptor.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosConfigurationDescriptor.java
index 3cdd9908..bc5f936 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosConfigurationDescriptor.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosConfigurationDescriptor.java
@@ -1,4 +1,4 @@
-/**
+/*
  * 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
@@ -18,7 +18,7 @@
 package org.apache.ambari.server.state.kerberos;
 
 
-import java.util.HashMap;
+import java.util.TreeMap;
 import java.util.Map;
 import java.util.Set;
 
@@ -105,6 +105,19 @@ public class KerberosConfigurationDescriptor extends 
AbstractKerberosDescriptor
   }
 
   /**
+   * Set the properties of the configuration data represented by this 
KerberosConfigurationDescriptor
+   *
+   * @param properties a Map of properties
+   */
+  public void setProperties(Map<String, String> properties) {
+    if (properties == null) {
+      this.properties = null;
+    } else {
+      this.properties = new TreeMap<String, String>(properties);
+    }
+  }
+
+  /**
    * Gets the properties of the configuration data represented by this 
KerberosConfigurationDescriptor
    *
    * @return a Map of properties
@@ -137,7 +150,7 @@ public class KerberosConfigurationDescriptor extends 
AbstractKerberosDescriptor
     }
 
     if (properties == null) {
-      properties = new HashMap<String, String>();
+      properties = new TreeMap<String, String>();
     }
 
     properties.put(name, value);
@@ -173,8 +186,8 @@ public class KerberosConfigurationDescriptor extends 
AbstractKerberosDescriptor
    */
   @Override
   public Map<String, Object> toMap() {
-    Map<String, Object> map = new HashMap<String, Object>();
-    map.put(getName(), (properties == null) ? null : new HashMap<String, 
Object>(properties));
+    Map<String, Object> map = new TreeMap<String, Object>();
+    map.put(getName(), (properties == null) ? null : new TreeMap<String, 
Object>(properties));
     return map;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptor.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptor.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptor.java
index 484f65c..e7be589 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptor.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptor.java
@@ -1,4 +1,4 @@
-/**
+/*
  * 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
@@ -20,7 +20,7 @@ package org.apache.ambari.server.state.kerberos;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
+import java.util.TreeMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -147,6 +147,17 @@ public class KerberosDescriptor extends 
AbstractKerberosDescriptorContainer {
   }
 
   /**
+   * Set the KerberosServiceDescriptors in this KerberosDescriptor
+   *
+   * @param services a Map of String to KerberosServiceDescriptor
+   */
+  public void setServices(Map<String, KerberosServiceDescriptor> services) {
+    this.services = (services == null)
+        ? null
+        : new TreeMap<String, KerberosServiceDescriptor>(services);
+  }
+
+  /**
    * Returns a Map of the KerberosServiceDescriptors in this KerberosDescriptor
    *
    * @return a Map of String to KerberosServiceDescriptor
@@ -182,7 +193,7 @@ public class KerberosDescriptor extends 
AbstractKerberosDescriptorContainer {
       }
 
       if (services == null) {
-        services = new HashMap<String, KerberosServiceDescriptor>();
+        services = new TreeMap<String, KerberosServiceDescriptor>();
       }
 
       services.put(name, service);
@@ -193,6 +204,17 @@ public class KerberosDescriptor extends 
AbstractKerberosDescriptorContainer {
   }
 
   /**
+   * Set the Map of properties for this KerberosDescriptor
+   *
+   * @param properties a Map of String to String values
+   */
+  public void setProperties(Map<String, String> properties) {
+    this.properties = (properties == null)
+        ? null
+        : new TreeMap<String, String>(properties);
+  }
+
+  /**
    * Gets the Map of properties for this KerberosDescriptor
    *
    * @return a Map of String to String values
@@ -225,7 +247,7 @@ public class KerberosDescriptor extends 
AbstractKerberosDescriptorContainer {
     }
 
     if (properties == null) {
-      properties = new HashMap<String, String>();
+      properties = new TreeMap<String, String>();
     }
 
     properties.put(name, value);
@@ -304,7 +326,7 @@ public class KerberosDescriptor extends 
AbstractKerberosDescriptorContainer {
     }
 
     if (properties != null) {
-      map.put("properties", new HashMap<String, String>(properties));
+      map.put("properties", new TreeMap<String, String>(properties));
     }
 
     return map;

http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptorUpdateHelper.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptorUpdateHelper.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptorUpdateHelper.java
new file mode 100644
index 0000000..2eef4b9
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptorUpdateHelper.java
@@ -0,0 +1,585 @@
+/*
+ * 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.state.kerberos;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.TreeMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * KerberosDescriptorUpdateHelper provides routines for upgrading the 
user-specified Kerberos descriptor
+ * when changing stacks.
+ * <p>
+ * This implementation should work for stack upgrades and downgrades.
+ */
+public class KerberosDescriptorUpdateHelper {
+  private static final Logger LOG = 
LoggerFactory.getLogger(KerberosDescriptorUpdateHelper.class);
+
+  /**
+   * The entry point into upgrading a user-specified Kerberos descriptor.
+   * <p>
+   * The supplied Kerberos descriptors will remain untouched and new Kerberos 
descriptor instance will
+   * created and returned with the update data.
+   *
+   * @param beginningStackKerberosDescriptor the Kerberos descriptor for the 
previous stack version
+   * @param endingStackKerberosDescriptor    the Kerberos descriptor for the 
new stack version
+   * @param userKerberosDescriptor           the user-specified Kerberos 
descriptor
+   * @return a new Kerberos descriptor containing the updated user-specified 
data
+   */
+  public static KerberosDescriptor 
updateUserKerberosDescriptor(KerberosDescriptor 
beginningStackKerberosDescriptor,
+                                                                
KerberosDescriptor endingStackKerberosDescriptor,
+                                                                
KerberosDescriptor userKerberosDescriptor) {
+    KerberosDescriptor updated = new 
KerberosDescriptor(userKerberosDescriptor.toMap());
+
+    updated.setProperties(processProperties(
+        beginningStackKerberosDescriptor.getProperties(),
+        endingStackKerberosDescriptor.getProperties(),
+        updated.getProperties()));
+
+    updated.setConfigurations(processConfigurations(
+        beginningStackKerberosDescriptor.getConfigurations(),
+        endingStackKerberosDescriptor.getConfigurations(),
+        updated.getConfigurations()));
+
+    updated.setIdentities(processIdentities(
+        beginningStackKerberosDescriptor.getIdentities(),
+        endingStackKerberosDescriptor.getIdentities(),
+        updated.getIdentities()));
+
+    updated.setAuthToLocalProperties(processAuthToLocalProperties(
+        beginningStackKerberosDescriptor.getAuthToLocalProperties(),
+        endingStackKerberosDescriptor.getAuthToLocalProperties(),
+        updated.getAuthToLocalProperties()));
+
+    updated.setServices(processServices(
+        beginningStackKerberosDescriptor.getServices(),
+        endingStackKerberosDescriptor.getServices(),
+        updated.getServices()));
+
+    return updated;
+  }
+
+  /**
+   * Processes the service-level Kerberos descriptors to add, remove, or 
update data in the user-specified
+   * Kerberos descriptor.
+   *
+   * @param previousStackServices a map of {@link KerberosServiceDescriptor}s 
from the previous stack version's Kerberos descriptor
+   * @param newStackServices      a map of {@link KerberosServiceDescriptor}s 
from the new stack version's Kerberos descriptor
+   * @param userServices          a map of {@link KerberosServiceDescriptor}s 
from the user-supplied Kerberos descriptor
+   * @return a map of updated {@link KerberosServiceDescriptor}s
+   */
+  private static Map<String, KerberosServiceDescriptor> 
processServices(Map<String, KerberosServiceDescriptor> previousStackServices,
+                                                                        
Map<String, KerberosServiceDescriptor> newStackServices,
+                                                                        
Map<String, KerberosServiceDescriptor> userServices) {
+    if ((userServices == null) || userServices.isEmpty() || 
((previousStackServices == null) && (newStackServices == null))) {
+      return userServices;
+    }
+
+    Map<String, KerberosServiceDescriptor> updatedServices = new 
TreeMap<String, KerberosServiceDescriptor>();
+
+    if (previousStackServices == null) {
+      previousStackServices = Collections.emptyMap();
+    }
+
+    if (newStackServices == null) {
+      newStackServices = Collections.emptyMap();
+    }
+
+    for (Map.Entry<String, KerberosServiceDescriptor> entry : 
userServices.entrySet()) {
+      String name = entry.getKey();
+      KerberosServiceDescriptor userValue = entry.getValue();
+
+      if (userValue != null) {
+        if (newStackServices.containsKey(name)) {
+          KerberosServiceDescriptor oldValue = previousStackServices.get(name);
+          KerberosServiceDescriptor newValue = newStackServices.get(name);
+
+          LOG.debug("Processing service {} for modifications", name);
+          updatedServices.put(name, processService(oldValue, newValue, 
userValue));
+        } else if (previousStackServices.containsKey(name)) {
+          LOG.debug("Removing service {} from user-specified Kerberos 
Descriptor", name);
+          // Nothing to do here, just don't add it to the updated 
configurations map...
+        } else {
+          LOG.debug("Leaving service {} in user-specified Kerberos Descriptor 
unchanged since it was user-defined.", name);
+          updatedServices.put(name, userValue);
+        }
+      }
+    }
+
+    // Note: there is no need to add service definitions that do not exist 
since they will get
+    // added dynamically when merged with the stack default value.
+
+    return updatedServices;
+  }
+
+  /**
+   * Processes a {@link KerberosServiceDescriptor} to change the user-supplied 
data based on the changes
+   * observed between the previous stack version's data and the new stack 
version's data.
+   *
+   * @param previousStackService a {@link KerberosServiceDescriptor} from the 
previous stack version's Kerberos descriptor
+   * @param newStackService      a {@link KerberosServiceDescriptor} from the 
new stack version's Kerberos descriptor
+   * @param userService          a {@link KerberosServiceDescriptor} from the 
user-specified Kerberos descriptor
+   * @return the updated {@link KerberosServiceDescriptor}
+   */
+  private static KerberosServiceDescriptor 
processService(KerberosServiceDescriptor previousStackService,
+                                                          
KerberosServiceDescriptor newStackService,
+                                                          
KerberosServiceDescriptor userService) {
+
+    KerberosServiceDescriptor updatedService = new 
KerberosServiceDescriptor(userService.toMap());
+
+    updatedService.setAuthToLocalProperties(processAuthToLocalProperties(
+        (previousStackService == null) ? null : 
previousStackService.getAuthToLocalProperties(),
+        (newStackService == null) ? null : 
newStackService.getAuthToLocalProperties(),
+        updatedService.getAuthToLocalProperties()));
+
+    updatedService.setConfigurations(processConfigurations(
+        (previousStackService == null) ? null : 
previousStackService.getConfigurations(),
+        (newStackService == null) ? null : newStackService.getConfigurations(),
+        updatedService.getConfigurations()));
+
+    updatedService.setIdentities(processIdentities(
+        (previousStackService == null) ? null : 
previousStackService.getIdentities(),
+        (newStackService == null) ? null : newStackService.getIdentities(),
+        updatedService.getIdentities()));
+
+    Map<String, KerberosComponentDescriptor> userServiceComponents = 
updatedService.getComponents();
+    Map<String, KerberosComponentDescriptor> newServiceComponents = 
(newStackService == null) ? null : newStackService.getComponents();
+    Map<String, KerberosComponentDescriptor> oldServiceComponents = 
(previousStackService == null) ? null : previousStackService.getComponents();
+
+    if (newServiceComponents == null) {
+      newServiceComponents = Collections.emptyMap();
+    }
+
+    if (oldServiceComponents == null) {
+      oldServiceComponents = Collections.emptyMap();
+    }
+
+    if (userServiceComponents != null) {
+      Iterator<Map.Entry<String, KerberosComponentDescriptor>> iterator = 
userServiceComponents.entrySet().iterator();
+      while (iterator.hasNext()) {
+        Map.Entry<String, KerberosComponentDescriptor> entry = iterator.next();
+        String name = entry.getKey();
+        KerberosComponentDescriptor userValue = entry.getValue();
+
+        if (userValue == null) {
+          iterator.remove();  // This is a bad entry... remove it.
+        } else if (newServiceComponents.containsKey(name)) {
+          KerberosComponentDescriptor oldValue = 
oldServiceComponents.get(name);
+          KerberosComponentDescriptor newValue = 
newServiceComponents.get(name);
+
+          LOG.debug("Processing component {}/{} for modifications", 
updatedService.getName(), name);
+          processComponent(oldValue, newValue, userValue);
+        } else {
+          LOG.debug("Removing component {}/{} from user-specified Kerberos 
Descriptor", updatedService.getName(), name);
+          iterator.remove();
+        }
+      }
+    }
+
+    return updatedService;
+  }
+
+  /**
+   * Processes a {@link KerberosComponentDescriptor} to change the 
user-supplied data based on the changes
+   * observed between the previous stack version's data and the new stack 
version's data.
+   * <p>
+   * The supplied userComponent value is updated in place.
+   *
+   * @param previousStackComponent a {@link KerberosComponentDescriptor} from 
the previous stack version's Kerberos descriptor
+   * @param newStackComponent      a {@link KerberosComponentDescriptor} from 
the new stack version's Kerberos descriptor
+   * @param userComponent          a {@link KerberosComponentDescriptor} from 
the user-specified Kerberos descriptor
+   * @return the updated {@link KerberosComponentDescriptor}
+   */
+  private static KerberosComponentDescriptor 
processComponent(KerberosComponentDescriptor previousStackComponent,
+                                                              
KerberosComponentDescriptor newStackComponent,
+                                                              
KerberosComponentDescriptor userComponent) {
+    userComponent.setAuthToLocalProperties(processAuthToLocalProperties(
+        (previousStackComponent == null) ? null : 
previousStackComponent.getAuthToLocalProperties(),
+        (newStackComponent == null) ? null : 
newStackComponent.getAuthToLocalProperties(),
+        userComponent.getAuthToLocalProperties()));
+
+    userComponent.setConfigurations(processConfigurations(
+        (previousStackComponent == null) ? null : 
previousStackComponent.getConfigurations(),
+        (newStackComponent == null) ? null : 
newStackComponent.getConfigurations(),
+        userComponent.getConfigurations()));
+
+    userComponent.setIdentities(processIdentities(
+        (previousStackComponent == null) ? null : 
previousStackComponent.getIdentities(),
+        (newStackComponent == null) ? null : newStackComponent.getIdentities(),
+        userComponent.getIdentities()));
+
+    return userComponent;
+  }
+
+  /**
+   * Processes a the list of configuration specification 
(<code>&lt;configuration type&gt;/&lt;property name&gt;</code>)
+   * identifying the properties that should be automatically updated with 
generated auth-to-local rules.
+   * <p>
+   * If no user-specified properties are set, <code>null</code> is returned.
+   * <p>
+   * Else the configuration specifications from the previous stack are removed 
from the user-specified
+   * data and the configuration specifications from the new stack are added to 
the user-specified,
+   * leaving the new list of configuration specifications  as well as any 
user-specified changes.
+   *
+   * @param previousStackAuthToLocalProperties the auth-to-local properties 
from the previous stack version's Kerberos descriptor
+   * @param newStackAuthToLocalProperties      the auth-to-local properties 
from the new stack version's Kerberos descriptor
+   * @param userAuthToLocalProperties          the auth-to-local properties 
from the user-specified Kerberos descriptor
+   * @return an updated {@link Set} of configuration specifications
+   */
+  private static Set<String> processAuthToLocalProperties(Set<String> 
previousStackAuthToLocalProperties,
+                                                          Set<String> 
newStackAuthToLocalProperties,
+                                                          Set<String> 
userAuthToLocalProperties) {
+    if (userAuthToLocalProperties == null) {
+      return null;
+    }
+
+    TreeSet<String> updatedAuthToLocalProperties = new 
TreeSet<String>(userAuthToLocalProperties);
+
+    // Remove old configuration specifications, leaving the user-specified 
ones.
+    if (previousStackAuthToLocalProperties != null) {
+      
updatedAuthToLocalProperties.removeAll(previousStackAuthToLocalProperties);
+    }
+
+    // Add the new configuration specifications
+    if (newStackAuthToLocalProperties != null) {
+      updatedAuthToLocalProperties.addAll(newStackAuthToLocalProperties);
+    }
+
+    return updatedAuthToLocalProperties;
+  }
+
+  /**
+   * Processes the identity-level Kerberos descriptors to add, remove, or 
update data in the user-specified
+   * Kerberos descriptor.
+   *
+   * @param previousStackIdentities a map of {@link 
KerberosIdentityDescriptor}s from the previous stack version's Kerberos 
descriptor
+   * @param newStackIdentities      a map of {@link 
KerberosIdentityDescriptor}s from the new stack version's Kerberos descriptor
+   * @param userIdentities          a map of {@link 
KerberosIdentityDescriptor}s from the user-supplied Kerberos descriptor
+   * @return a list of updated {@link KerberosIdentityDescriptor}s
+   */
+  private static List<KerberosIdentityDescriptor> 
processIdentities(List<KerberosIdentityDescriptor> previousStackIdentities,
+                                                                    
List<KerberosIdentityDescriptor> newStackIdentities,
+                                                                    
List<KerberosIdentityDescriptor> userIdentities) {
+
+    if ((userIdentities == null) || userIdentities.isEmpty() || 
((previousStackIdentities == null) && (newStackIdentities == null))) {
+      return userIdentities;
+    }
+
+    // Create maps to make processing easier....
+    Map<String, KerberosIdentityDescriptor> previousStackIdentityMap = 
toMap(previousStackIdentities);
+    Map<String, KerberosIdentityDescriptor> newStackIdentityMap = 
toMap(newStackIdentities);
+    Map<String, KerberosIdentityDescriptor> userStackIdentityMap = 
toMap(userIdentities);
+
+    Map<String, KerberosIdentityDescriptor> updatedIdentities = new 
TreeMap<String, KerberosIdentityDescriptor>();
+
+    if (previousStackIdentityMap == null) {
+      previousStackIdentityMap = Collections.emptyMap();
+    }
+
+    if (newStackIdentityMap == null) {
+      newStackIdentityMap = Collections.emptyMap();
+    }
+
+    // Find identities to modify or remove
+    for (Map.Entry<String, KerberosIdentityDescriptor> entry : 
userStackIdentityMap.entrySet()) {
+      String name = entry.getKey();
+      KerberosIdentityDescriptor userValue = entry.getValue();
+
+      if (userValue != null) {
+        if (newStackIdentityMap.containsKey(name)) {
+          // Modify the new stack identity value by changing on the principal 
value and/or keytab
+          // file value since they are the only fields in this structure that 
should be changed
+          // by a user. However, the new stack identity may have been 
converted to a pure reference
+          // where the user changes will then be ignored.
+          KerberosIdentityDescriptor newValue = newStackIdentityMap.get(name);
+          KerberosIdentityDescriptor previousValue = 
previousStackIdentityMap.get(name);
+
+          updatedIdentities.put(name, processIdentity(previousValue, newValue, 
userValue));
+
+        } else if (previousStackIdentityMap.containsKey(name)) {
+          LOG.debug("Removing identity named {} from user-specified Kerberos 
Descriptor", name);
+          // Nothing to do here, just don't add it to the updated identity 
map...
+        } else {
+          LOG.debug("Leaving identity named {} in user-specified Kerberos 
Descriptor unchanged since it was user-defined.", name);
+          updatedIdentities.put(name, userValue);
+        }
+      }
+    }
+
+    // Note: there is no need to add identity definitions that do not exist 
since they will get
+    // added dynamically when merged with the stack default value.
+
+    return new 
ArrayList<KerberosIdentityDescriptor>(updatedIdentities.values());
+  }
+
+
+  /**
+   * Processes a {@link KerberosIdentityDescriptor} to change the 
user-supplied data based on the changes
+   * observed between the previous stack version's data and the new stack 
version's data.
+   *
+   * @param previousStackIdentity a {@link KerberosIdentityDescriptor} from 
the previous stack version's Kerberos descriptor
+   * @param newStackIdentity      a {@link KerberosIdentityDescriptor} from 
the new stack version's Kerberos descriptor
+   * @param userIdentity          a {@link KerberosIdentityDescriptor} from 
the user-specified Kerberos descriptor
+   * @return a new, updated, {@link KerberosIdentityDescriptor}
+   */
+  private static KerberosIdentityDescriptor 
processIdentity(KerberosIdentityDescriptor previousStackIdentity,
+                                                            
KerberosIdentityDescriptor newStackIdentity,
+                                                            
KerberosIdentityDescriptor userIdentity) {
+
+    KerberosIdentityDescriptor updatedValue = new 
KerberosIdentityDescriptor(newStackIdentity.toMap());
+    KerberosPrincipalDescriptor updatedValuePrincipal = 
updatedValue.getPrincipalDescriptor();
+    KerberosKeytabDescriptor updatedValueKeytab = 
updatedValue.getKeytabDescriptor();
+
+    // If the new identity definition is a reference and no longer has a 
principal definition,
+    // Ignore any user changes to the old principal definition.
+    if (updatedValuePrincipal != null) {
+      KerberosPrincipalDescriptor oldValuePrincipal = 
previousStackIdentity.getPrincipalDescriptor();
+      String previousValuePrincipalValue = null;
+      KerberosPrincipalDescriptor userValuePrincipal = 
userIdentity.getPrincipalDescriptor();
+      String userValuePrincipalValue = null;
+
+      if (oldValuePrincipal != null) {
+        previousValuePrincipalValue = oldValuePrincipal.getValue();
+      }
+
+      if (userValuePrincipal != null) {
+        userValuePrincipalValue = userValuePrincipal.getValue();
+      }
+
+      // If the user changed the stack default, replace the new stack default 
value with the user's
+      // changed value
+      if ((userValuePrincipalValue != null) && 
!userValuePrincipalValue.equals(previousValuePrincipalValue)) {
+        updatedValuePrincipal.setValue(userValuePrincipalValue);
+      }
+    }
+
+    // If the new identity definition is a reference and no longer has a 
keytab definition,
+    // Ignore any user changes to the old keytab definition.
+    if (updatedValueKeytab != null) {
+      KerberosKeytabDescriptor oldValueKeytab = 
previousStackIdentity.getKeytabDescriptor();
+      String previousValueKeytabFile = null;
+      KerberosKeytabDescriptor userValueKeytab = 
userIdentity.getKeytabDescriptor();
+      String userValueKeytabFile = null;
+
+      if (oldValueKeytab != null) {
+        previousValueKeytabFile = oldValueKeytab.getFile();
+      }
+
+      if (userValueKeytab != null) {
+        userValueKeytabFile = userValueKeytab.getFile();
+      }
+
+      // If the user changed the stack default, replace the new stack default 
value with the user's
+      // changed value
+      if ((userValueKeytabFile != null) && 
!userValueKeytabFile.equals(previousValueKeytabFile)) {
+        updatedValueKeytab.setFile(userValueKeytabFile);
+      }
+    }
+
+    // Remove the when clause
+    updatedValue.setWhen(null);
+
+    return updatedValue;
+  }
+
+  /**
+   * Processes the configuration-level Kerberos descriptors to add, remove, or 
update data in the user-specified
+   * Kerberos descriptor.
+   *
+   * @param previousStackConfigurations a map of {@link 
KerberosConfigurationDescriptor}s from the previous stack version's Kerberos 
descriptor
+   * @param newStackConfigurations      a map of {@link 
KerberosConfigurationDescriptor}s from the new stack version's Kerberos 
descriptor
+   * @param userConfigurations          a map of {@link 
KerberosConfigurationDescriptor}s from the user-supplied Kerberos descriptor
+   * @return a map of updated {@link KerberosConfigurationDescriptor}s
+   */
+  private static Map<String, KerberosConfigurationDescriptor> 
processConfigurations(Map<String, KerberosConfigurationDescriptor> 
previousStackConfigurations,
+                                                                               
     Map<String, KerberosConfigurationDescriptor> newStackConfigurations,
+                                                                               
     Map<String, KerberosConfigurationDescriptor> userConfigurations) {
+
+    if ((userConfigurations == null) || ((previousStackConfigurations == null) 
&& (newStackConfigurations == null))) {
+      return userConfigurations;
+    }
+
+    Map<String, KerberosConfigurationDescriptor> updatedConfigurations = new 
TreeMap<String, KerberosConfigurationDescriptor>();
+
+    if (previousStackConfigurations == null) {
+      previousStackConfigurations = Collections.emptyMap();
+    }
+
+    if (newStackConfigurations == null) {
+      newStackConfigurations = Collections.emptyMap();
+    }
+
+    // Find configurations to modify or remove
+    for (Map.Entry<String, KerberosConfigurationDescriptor> entry : 
userConfigurations.entrySet()) {
+      String name = entry.getKey();
+      KerberosConfigurationDescriptor userValue = entry.getValue();
+
+      if (userValue != null) {
+        if (newStackConfigurations.containsKey(name)) {
+          KerberosConfigurationDescriptor oldValue = 
previousStackConfigurations.get(name);
+          KerberosConfigurationDescriptor newValue = 
newStackConfigurations.get(name);
+
+          LOG.debug("Processing configuration type {} for modifications", 
name);
+          updatedConfigurations.put(name, processConfiguration(oldValue, 
newValue, userValue));
+        } else if (previousStackConfigurations.containsKey(name)) {
+          LOG.debug("Removing configuration type {} from user-specified 
Kerberos Descriptor", name);
+          // Nothing to do here, just don't add it to the updated 
configurations map...
+        } else {
+          LOG.debug("Leaving configuration type {} in user-specified Kerberos 
Descriptor unchanged since it was user-defined.", name);
+          updatedConfigurations.put(name, userValue);
+        }
+      }
+    }
+
+    // Note: there is no need to add configuration definitions that do not 
exist in the user-specified
+    // descriptor since they will get added dynamically when merged with the 
stack default value.
+
+    return updatedConfigurations;
+  }
+
+  /**
+   * Processes a {@link KerberosConfigurationDescriptor} to change the 
user-supplied data based on the changes
+   * observed between the previous stack version's data and the new stack 
version's data.
+   *
+   * @param previousStackConfiguration a {@link 
KerberosConfigurationDescriptor} from the previous stack version's Kerberos 
descriptor
+   * @param newStackConfiguration      a {@link 
KerberosConfigurationDescriptor} from the new stack version's Kerberos 
descriptor
+   * @param userConfiguration          a {@link 
KerberosConfigurationDescriptor} from the user-specified Kerberos descriptor
+   * @return an updated {@link KerberosConfigurationDescriptor}
+   */
+  private static KerberosConfigurationDescriptor 
processConfiguration(KerberosConfigurationDescriptor previousStackConfiguration,
+                                                                      
KerberosConfigurationDescriptor newStackConfiguration,
+                                                                      
KerberosConfigurationDescriptor userConfiguration) {
+
+    KerberosConfigurationDescriptor updatedValue = new 
KerberosConfigurationDescriptor((userConfiguration == null) ? null : 
userConfiguration.toMap());
+
+    Map<String, String> previousValue = (previousStackConfiguration == null) ? 
null : previousStackConfiguration.getProperties();
+    Map<String, String> newValue = (newStackConfiguration == null) ? null : 
newStackConfiguration.getProperties();
+    Map<String, String> userValue = updatedValue.getProperties();
+
+    updatedValue.setProperties(processProperties(previousValue, newValue, 
userValue));
+
+    return updatedValue;
+  }
+
+  /**
+   * Processes a map of global or configuration properties to change the 
user-supplied data based on
+   * the changes observed between the previous stack version's data and the 
new stack version's data.
+   * <p>
+   * If a property exists in both the previous and new stacks, and the user 
has not changed it; then
+   * the value of the property will be updated to the new stack version's 
value.  Else, if the user
+   * changed the value, the changed value will be left as-is.
+   * <p>
+   * If a property exists only in the previous stack, then it will be removed.
+   * <p>
+   * If a property exists only in the new stack, then it will be added.
+   *
+   * @param previousStackProperties properties from the previous stack 
version's Kerberos descriptor
+   * @param newStackProperties      properties from the new stack version's 
Kerberos descriptor
+   * @param userProperties          properties from the user-specified 
Kerberos descriptor
+   * @return a new map of updated properties
+   */
+  private static Map<String, String> processProperties(Map<String, String> 
previousStackProperties,
+                                                       Map<String, String> 
newStackProperties,
+                                                       Map<String, String> 
userProperties) {
+
+    if ((previousStackProperties == null) && (newStackProperties == null)) {
+      return userProperties;
+    } else {
+      Map<String, String> updatedProperties = new TreeMap<String, String>();
+      if (userProperties != null) {
+        updatedProperties.putAll(userProperties);
+      }
+
+      if (previousStackProperties == null) {
+        previousStackProperties = Collections.emptyMap();
+      }
+
+      if (newStackProperties == null) {
+        newStackProperties = Collections.emptyMap();
+      }
+
+      // Find properties to modify and remove
+      for (Map.Entry<String, String> entry : 
previousStackProperties.entrySet()) {
+        String name = entry.getKey();
+
+        if (newStackProperties.containsKey(name)) {
+          String previousValue = entry.getValue();
+          String newValue = newStackProperties.get(name);
+          String userValue = updatedProperties.get(name);
+
+          // See if the user property should be modified...
+          // Test if the old property value is different than the new property 
value and that the user did
+          // not update the value from the old default. If the user updated 
the value, then it would be
+          // risky to change it to the new stack default value.
+          if (((previousValue == null) ? (newValue != null) : 
!previousValue.equals(newValue)) &&
+              ((previousValue == null) ? (userValue == null) : 
previousValue.equals(userValue))) {
+            LOG.debug("Modifying property named {} from user-specified 
Kerberos Descriptor", name);
+            updatedProperties.put(name, newValue);
+          }
+        } else {
+          LOG.debug("Removing property named {} from user-specified Kerberos 
Descriptor", name);
+          updatedProperties.remove(name);
+        }
+      }
+
+      // Find properties to add
+      for (Map.Entry<String, String> entry : newStackProperties.entrySet()) {
+        String name = entry.getKey();
+
+        if (!previousStackProperties.containsKey(name) && 
!updatedProperties.containsKey(name)) {
+          // A new property was found, add it...
+          LOG.debug("Adding property named {} to user-specified Kerberos 
Descriptor", name);
+          updatedProperties.put(name, entry.getValue());
+        }
+      }
+
+      return updatedProperties;
+    }
+  }
+
+  /**
+   * A convenience method used to change a list of {@link 
KerberosIdentityDescriptor} items into a map
+   * of identity names or {@link 
org.apache.ambari.server.api.services.HostKerberosIdentityService}
+   * items.
+   *
+   * @param identities a list of {@link KerberosIdentityDescriptor}s
+   * @return a map of identity names or {@link 
org.apache.ambari.server.api.services.HostKerberosIdentityService}
+   */
+  private static Map<String, KerberosIdentityDescriptor> 
toMap(List<KerberosIdentityDescriptor> identities) {
+    if (identities == null) {
+      return null;
+    } else {
+      Map<String, KerberosIdentityDescriptor> map = new TreeMap<String, 
KerberosIdentityDescriptor>();
+
+      for (KerberosIdentityDescriptor identity : identities) {
+        map.put(identity.getName(), identity);
+      }
+
+      return map;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosKeytabDescriptor.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosKeytabDescriptor.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosKeytabDescriptor.java
index 7ce1c9f..ccb4efe 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosKeytabDescriptor.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosKeytabDescriptor.java
@@ -1,4 +1,4 @@
-/**
+/*
  * 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
@@ -17,8 +17,8 @@
  */
 package org.apache.ambari.server.state.kerberos;
 
-import java.util.HashMap;
 import java.util.Map;
+import java.util.TreeMap;
 
 /**
  * KerberosKeytabDescriptor is an implementation of an 
AbstractKerberosDescriptor that
@@ -157,13 +157,13 @@ public class KerberosKeytabDescriptor extends 
AbstractKerberosDescriptor {
   /**
    * Creates a new KerberosKeytabDescriptor
    *
-   * @param file the path to the keytab file
-   * @param ownerName the local username of the file owner
-   * @param ownerAccess the file access privileges for the file owner ("r", 
"rw", "")
-   * @param groupName the local group name with privileges to access the file
-   * @param groupAccess the file access privileges for the group ("r", "rw", 
"")
+   * @param file          the path to the keytab file
+   * @param ownerName     the local username of the file owner
+   * @param ownerAccess   the file access privileges for the file owner ("r", 
"rw", "")
+   * @param groupName     the local group name with privileges to access the 
file
+   * @param groupAccess   the file access privileges for the group ("r", "rw", 
"")
    * @param configuration the configuration used to store the principal name
-   * @param cachable true if the keytab may be cached by Ambari; otherwise 
false
+   * @param cachable      true if the keytab may be cached by Ambari; 
otherwise false
    */
   public KerberosKeytabDescriptor(String file, String ownerName, String 
ownerAccess, String groupName,
                                   String groupAccess, String configuration, 
boolean cachable) {
@@ -175,6 +175,7 @@ public class KerberosKeytabDescriptor extends 
AbstractKerberosDescriptor {
     setConfiguration(configuration);
     setCachable(cachable);
   }
+
   /**
    * Creates a new KerberosKeytabDescriptor
    * <p/>
@@ -416,21 +417,53 @@ public class KerberosKeytabDescriptor extends 
AbstractKerberosDescriptor {
    */
   @Override
   public Map<String, Object> toMap() {
-    Map<String, Object> map = new HashMap<String, Object>();
+    Map<String, Object> map = new TreeMap<String, Object>();
+
+    String data;
 
-    map.put("file", getFile());
+    data = getFile();
+    map.put("file", data);
 
-    map.put("owner", new HashMap<String, Object>() {{
-      put("name", getOwnerName());
-      put("access", getOwnerAccess());
-    }});
+    // Build file owner map
+    Map<String, String> owner = new TreeMap<String, String>();
+
+    data = getOwnerName();
+    if (data != null) {
+      owner.put("name", data);
+    }
+
+    data = getOwnerAccess();
+    if (data != null) {
+      owner.put("access", data);
+    }
+
+    if (!owner.isEmpty()) {
+      map.put("owner", owner);
+    }
+    // Build file owner map (end)
 
-    map.put("group", new HashMap<String, Object>() {{
-      put("name", getGroupName());
-      put("access", getGroupAccess());
-    }});
+    // Build file owner map
+    Map<String, String> group = new TreeMap<String, String>();
 
-    map.put("configuration", getConfiguration());
+    data = getGroupName();
+    if (data != null) {
+      group.put("name", data);
+    }
+
+    data = getGroupAccess();
+    if (data != null) {
+      group.put("access", data);
+    }
+
+    if (!owner.isEmpty()) {
+      map.put("group", group);
+    }
+    // Build file owner map (end)
+
+    data = getConfiguration();
+    if (data != null) {
+      map.put("configuration", data);
+    }
 
     return map;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosPrincipalDescriptor.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosPrincipalDescriptor.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosPrincipalDescriptor.java
index 0156e4a..83dd953 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosPrincipalDescriptor.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosPrincipalDescriptor.java
@@ -17,7 +17,7 @@
  */
 package org.apache.ambari.server.state.kerberos;
 
-import java.util.HashMap;
+import java.util.TreeMap;
 import java.util.Map;
 
 /**
@@ -267,7 +267,7 @@ public class KerberosPrincipalDescriptor extends 
AbstractKerberosDescriptor {
    */
   @Override
   public Map<String, Object> toMap() {
-    Map<String, Object> map = new HashMap<String, Object>();
+    Map<String, Object> map = new TreeMap<String, Object>();
 
     map.put("value", getValue());
     map.put("type", KerberosPrincipalType.translate(getType()));

http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosServiceDescriptor.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosServiceDescriptor.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosServiceDescriptor.java
index 72dbcfe..0f14ca6 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosServiceDescriptor.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosServiceDescriptor.java
@@ -20,7 +20,7 @@ package org.apache.ambari.server.state.kerberos;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
+import java.util.TreeMap;
 import java.util.List;
 import java.util.Map;
 
@@ -196,7 +196,7 @@ public class KerberosServiceDescriptor extends 
AbstractKerberosDescriptorContain
       }
 
       if (components == null) {
-        components = new HashMap<String, KerberosComponentDescriptor>();
+        components = new TreeMap<String, KerberosComponentDescriptor>();
       }
 
       components.put(name, component);

http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/resources/common-services/HBASE/0.96.0.2.0/kerberos.json
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/common-services/HBASE/0.96.0.2.0/kerberos.json
 
b/ambari-server/src/main/resources/common-services/HBASE/0.96.0.2.0/kerberos.json
index d569447..636d36e 100644
--- 
a/ambari-server/src/main/resources/common-services/HBASE/0.96.0.2.0/kerberos.json
+++ 
b/ambari-server/src/main/resources/common-services/HBASE/0.96.0.2.0/kerberos.json
@@ -104,7 +104,8 @@
           "name": "PHOENIX_QUERY_SERVER",
           "identities": [
             {
-              "name": "/spnego",
+              "name": "phoenix_spnego",
+              "reference": "/spnego",
               "principal": {
                 "configuration": 
"hbase-site/phoenix.queryserver.kerberos.principal"
               },

http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.5.xml
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.5.xml
 
b/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.5.xml
index f5f06c0..ff4ed18 100644
--- 
a/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.5.xml
+++ 
b/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.5.xml
@@ -449,6 +449,16 @@
     </group>
 
     <!--
+    After processing this group, the user-specified Kerberos descriptor will 
be updated to work with
+    the new stack-level Kerberos descriptor.
+    -->
+    <group xsi:type="cluster" name="UPDATE_KERBEROS_DESCRIPTORS" title="Update 
Kerberos Descriptors">
+      <execute-stage title="Update the user-specified Kerberos descriptor" 
service="" component="">
+        <task xsi:type="server_action" 
class="org.apache.ambari.server.serveraction.upgrades.UpgradeUserKerberosDescriptor"/>
+      </execute-stage>
+    </group>
+
+    <!--
     Invoke "hdp-select set all" to change any components we may have missed
     that are installed on the hosts but not known by Ambari.
     -->

http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.5.xml
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.5.xml 
b/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.5.xml
index 09bd2ac..46e11e4 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.5.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.5.xml
@@ -197,6 +197,16 @@
       </execute-stage>
     </group>
 
+    <!--
+    After processing this group, the user-specified Kerberos descriptor will 
be updated to work with
+    the new stack-level Kerberos descriptor.
+    -->
+    <group xsi:type="cluster" name="UPDATE_KERBEROS_DESCRIPTORS" title="Update 
Kerberos Descriptors">
+      <execute-stage title="Update the user-specified Kerberos descriptor" 
service="" component="">
+        <task xsi:type="server_action" 
class="org.apache.ambari.server.serveraction.upgrades.UpgradeUserKerberosDescriptor"/>
+      </execute-stage>
+    </group>
+
     <group name="CORE_MASTER" title="Core Masters">
       <service-check>false</service-check>
       <service name="HDFS">

http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/nonrolling-upgrade-2.5.xml
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/nonrolling-upgrade-2.5.xml
 
b/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/nonrolling-upgrade-2.5.xml
index 1cc9529..3478603 100644
--- 
a/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/nonrolling-upgrade-2.5.xml
+++ 
b/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/nonrolling-upgrade-2.5.xml
@@ -405,6 +405,16 @@
     </group>
 
     <!--
+    After processing this group, the user-specified Kerberos descriptor will 
be updated to work with
+    the new stack-level Kerberos descriptor.
+    -->
+    <group xsi:type="cluster" name="UPDATE_KERBEROS_DESCRIPTORS" title="Update 
Kerberos Descriptors">
+      <execute-stage title="Update the user-specified Kerberos descriptor" 
service="" component="">
+        <task xsi:type="server_action" 
class="org.apache.ambari.server.serveraction.upgrades.UpgradeUserKerberosDescriptor"/>
+      </execute-stage>
+    </group>
+
+    <!--
     Invoke "hdp-select set all" to change any components we may have missed
     that are installed on the hosts but not known by Ambari.
     -->

http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.5.xml
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.5.xml 
b/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.5.xml
index f20ad06..8a7f0fa 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.5.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.5.xml
@@ -183,6 +183,16 @@
       </execute-stage>
     </group>
 
+    <!--
+    After processing this group, the user-specified Kerberos descriptor will 
be updated to work with
+    the new stack-level Kerberos descriptor.
+    -->
+    <group xsi:type="cluster" name="UPDATE_KERBEROS_DESCRIPTORS" title="Update 
Kerberos Descriptors">
+      <execute-stage title="Update the user-specified Kerberos descriptor" 
service="" component="">
+        <task xsi:type="server_action" 
class="org.apache.ambari.server.serveraction.upgrades.UpgradeUserKerberosDescriptor"/>
+      </execute-stage>
+    </group>
+
     <group name="CORE_MASTER" title="Core Masters">
       <service-check>false</service-check>
       <service name="HDFS">

http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/resources/stacks/HDP/2.5/services/HBASE/kerberos.json
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/stacks/HDP/2.5/services/HBASE/kerberos.json 
b/ambari-server/src/main/resources/stacks/HDP/2.5/services/HBASE/kerberos.json
index 501bcd3..9ed40ef 100644
--- 
a/ambari-server/src/main/resources/stacks/HDP/2.5/services/HBASE/kerberos.json
+++ 
b/ambari-server/src/main/resources/stacks/HDP/2.5/services/HBASE/kerberos.json
@@ -142,7 +142,8 @@
           "name": "PHOENIX_QUERY_SERVER",
           "identities": [
             {
-              "name": "/spnego",
+              "name": "phoenix_spnego",
+              "reference": "/spnego",
               "principal": {
                 "configuration": 
"hbase-site/phoenix.queryserver.kerberos.principal"
               },

http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/nonrolling-upgrade-2.5.xml
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/nonrolling-upgrade-2.5.xml
 
b/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/nonrolling-upgrade-2.5.xml
index cbab386..a54c830 100644
--- 
a/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/nonrolling-upgrade-2.5.xml
+++ 
b/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/nonrolling-upgrade-2.5.xml
@@ -295,6 +295,16 @@
     </group>
 
     <!--
+    After processing this group, the user-specified Kerberos descriptor will 
be updated to work with
+    the new stack-level Kerberos descriptor.
+    -->
+    <group xsi:type="cluster" name="UPDATE_KERBEROS_DESCRIPTORS" title="Update 
Kerberos Descriptors">
+      <execute-stage title="Update the user-specified Kerberos descriptor" 
service="" component="">
+        <task xsi:type="server_action" 
class="org.apache.ambari.server.serveraction.upgrades.UpgradeUserKerberosDescriptor"/>
+      </execute-stage>
+    </group>
+
+    <!--
     Invoke "hdp-select set all" to change any components we may have missed
     that are installed on the hosts but not known by Ambari.
     -->

http://git-wip-us.apache.org/repos/asf/ambari/blob/7aff03f5/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/upgrade-2.5.xml
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/upgrade-2.5.xml 
b/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/upgrade-2.5.xml
index 60e81c0..e3e632b 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/upgrade-2.5.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/upgrade-2.5.xml
@@ -148,6 +148,16 @@
       </service>
     </group>
 
+    <!--
+    After processing this group, the user-specified Kerberos descriptor will 
be updated to work with
+    the new stack-level Kerberos descriptor.
+    -->
+    <group xsi:type="cluster" name="UPDATE_KERBEROS_DESCRIPTORS" title="Update 
Kerberos Descriptors">
+      <execute-stage title="Update the user-specified Kerberos descriptor" 
service="" component="">
+        <task xsi:type="server_action" 
class="org.apache.ambari.server.serveraction.upgrades.UpgradeUserKerberosDescriptor"/>
+      </execute-stage>
+    </group>
+
     <group name="CORE_MASTER" title="Core Masters">
       <service-check>false</service-check>
       <service name="HDFS">

Reply via email to