AMBARI-21450 - Fixing Unit Test Logic From trunk Merge (jonathanhurley)

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

Branch: refs/heads/branch-2.6
Commit: 15cd3d8379178006a0ee42b949217fa511351435
Parents: 51e3080
Author: Jonathan Hurley <jhur...@hortonworks.com>
Authored: Mon Jul 24 13:15:01 2017 -0400
Committer: Jonathan Hurley <jhur...@hortonworks.com>
Committed: Mon Jul 24 13:15:09 2017 -0400

----------------------------------------------------------------------
 .../actionmanager/ExecutionCommandWrapper.java  |  11 +-
 .../ambari/server/agent/HeartBeatHandler.java   | 116 ++------
 .../request/eventcreator/HostEventCreator.java  |   6 +-
 .../AmbariManagementControllerImpl.java         | 151 ++++------
 .../server/controller/ClusterRequest.java       |  15 -
 .../server/controller/ClusterResponse.java      | 102 ++-----
 .../server/controller/KerberosHelperImpl.java   | 285 ++++++++++---------
 .../server/controller/ServiceRequest.java       |  24 +-
 .../internal/ClusterResourceProvider.java       |  33 +--
 .../internal/ComponentResourceProvider.java     |  10 +-
 .../internal/ServiceResourceProvider.java       | 104 ++++---
 .../orm/entities/ServiceConfigEntity.java       |  25 +-
 .../upgrades/ComponentVersionCheckAction.java   |   2 +-
 .../serveraction/upgrades/ConfigureAction.java  |  38 ++-
 .../ambari/server/topology/AmbariContext.java   |  26 +-
 .../ExecutionCommandWrapperTest.java            |   1 +
 .../ambari/server/agent/AgentResourceTest.java  |  12 +-
 .../server/api/services/AmbariMetaInfoTest.java |   4 +-
 .../request/creator/HostEventCreatorTest.java   |  10 +-
 .../AmbariCustomCommandExecutionHelperTest.java |   2 +-
 .../AmbariManagementControllerImplTest.java     |  26 +-
 .../AmbariManagementControllerTest.java         | 221 +++++++-------
 .../BackgroundCustomCommandExecutionTest.java   |   2 +-
 .../server/controller/ClusterResponseTest.java  |  18 +-
 ...hYarnCapacitySchedulerReleaseConfigTest.java |   2 +-
 .../internal/ClusterResourceProviderTest.java   | 105 ++++---
 .../internal/JMXHostProviderTest.java           |   3 +-
 .../internal/ServiceResourceProviderTest.java   |   2 +-
 .../ComponentVersionCheckActionTest.java        |   4 +-
 .../upgrades/ConfigureActionTest.java           |  66 +++--
 30 files changed, 652 insertions(+), 774 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/15cd3d83/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
index 91db7d0..e4b2540 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
@@ -26,6 +26,7 @@ import java.util.TreeMap;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ClusterNotFoundException;
+import org.apache.ambari.server.RoleCommand;
 import org.apache.ambari.server.ServiceNotFoundException;
 import org.apache.ambari.server.agent.AgentCommand.AgentCommandType;
 import org.apache.ambari.server.agent.ExecutionCommand;
@@ -224,8 +225,14 @@ public class ExecutionCommandWrapper {
         Map<String, String> commandParams = 
executionCommand.getCommandParams();
 
         if (null != repositoryVersion) {
-          commandParams.put(KeyNames.VERSION, repositoryVersion.getVersion());
-          executionCommand.getHostLevelParams().put(KeyNames.CURRENT_VERSION, 
repositoryVersion.getVersion());
+          // only set the version if it's not set and this is NOT an install
+          // command
+          if (!commandParams.containsKey(KeyNames.VERSION)
+              && executionCommand.getRoleCommand() != RoleCommand.INSTALL) {
+            commandParams.put(KeyNames.VERSION, 
repositoryVersion.getVersion());
+            
executionCommand.getHostLevelParams().put(KeyNames.CURRENT_VERSION, 
repositoryVersion.getVersion());
+
+          }
 
           StackId stackId = repositoryVersion.getStackId();
           StackInfo stackInfo = ambariMetaInfo.getStack(stackId.getStackName(),

http://git-wip-us.apache.org/repos/asf/ambari/blob/15cd3d83/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
index d3ea24b..5d4b338 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.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
@@ -22,9 +22,7 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -33,51 +31,22 @@ import java.util.regex.Pattern;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.HostNotFoundException;
-import org.apache.ambari.server.Role;
-import org.apache.ambari.server.RoleCommand;
-import org.apache.ambari.server.ServiceComponentHostNotFoundException;
-import org.apache.ambari.server.ServiceComponentNotFoundException;
-import org.apache.ambari.server.ServiceNotFoundException;
 import org.apache.ambari.server.actionmanager.ActionManager;
-import org.apache.ambari.server.actionmanager.HostRoleCommand;
-import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
-import org.apache.ambari.server.controller.MaintenanceStateHelper;
-import org.apache.ambari.server.events.ActionFinalReportReceivedEvent;
-import org.apache.ambari.server.events.AlertEvent;
-import org.apache.ambari.server.events.AlertReceivedEvent;
-import org.apache.ambari.server.events.HostComponentVersionAdvertisedEvent;
-import org.apache.ambari.server.events.publishers.AlertEventPublisher;
-import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
-import org.apache.ambari.server.events.publishers.VersionEventPublisher;
-import org.apache.ambari.server.metadata.ActionMetadata;
-import org.apache.ambari.server.orm.dao.HostDAO;
-import org.apache.ambari.server.orm.dao.KerberosPrincipalHostDAO;
-import org.apache.ambari.server.orm.entities.HostEntity;
 import 
org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFileReader;
 import 
org.apache.ambari.server.serveraction.kerberos.KerberosIdentityDataFileReaderFactory;
 import org.apache.ambari.server.serveraction.kerberos.KerberosServerAction;
 import org.apache.ambari.server.state.AgentVersion;
-import org.apache.ambari.server.state.Alert;
 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.ConfigHelper;
 import org.apache.ambari.server.state.Host;
-import org.apache.ambari.server.state.HostHealthStatus;
-import org.apache.ambari.server.state.HostHealthStatus.HealthStatus;
 import org.apache.ambari.server.state.HostState;
-import org.apache.ambari.server.state.MaintenanceState;
-import org.apache.ambari.server.state.SecurityState;
-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.StackInfo;
-import org.apache.ambari.server.state.State;
-import org.apache.ambari.server.state.UpgradeState;
 import org.apache.ambari.server.state.alert.AlertDefinition;
 import org.apache.ambari.server.state.alert.AlertDefinitionHash;
 import org.apache.ambari.server.state.fsm.InvalidStateTransitionException;
@@ -85,26 +54,14 @@ import 
org.apache.ambari.server.state.host.HostHealthyHeartbeatEvent;
 import org.apache.ambari.server.state.host.HostRegistrationRequestEvent;
 import org.apache.ambari.server.state.host.HostStatusUpdatesReceivedEvent;
 import org.apache.ambari.server.state.host.HostUnhealthyHeartbeatEvent;
-import org.apache.ambari.server.state.scheduler.RequestExecution;
-import org.apache.ambari.server.state.stack.upgrade.Direction;
-import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
-import 
org.apache.ambari.server.state.svccomphost.ServiceComponentHostOpFailedEvent;
-import 
org.apache.ambari.server.state.svccomphost.ServiceComponentHostOpInProgressEvent;
-import 
org.apache.ambari.server.state.svccomphost.ServiceComponentHostOpSucceededEvent;
-import 
org.apache.ambari.server.state.svccomphost.ServiceComponentHostStartedEvent;
-import 
org.apache.ambari.server.state.svccomphost.ServiceComponentHostStoppedEvent;
 import org.apache.ambari.server.utils.StageUtils;
 import org.apache.ambari.server.utils.VersionUtils;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.gson.Gson;
-import com.google.gson.JsonSyntaxException;
-import com.google.gson.annotations.SerializedName;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
 import com.google.inject.Singleton;
@@ -129,9 +86,6 @@ public class HeartBeatHandler {
   private HeartbeatProcessor heartbeatProcessor;
 
   @Inject
-  private Injector injector;
-
-  @Inject
   private Configuration config;
 
   @Inject
@@ -152,9 +106,9 @@ public class HeartBeatHandler {
   @Inject
   private KerberosIdentityDataFileReaderFactory 
kerberosIdentityDataFileReaderFactory;
 
-  private Map<String, Long> hostResponseIds = new ConcurrentHashMap<String, 
Long>();
+  private Map<String, Long> hostResponseIds = new ConcurrentHashMap<>();
 
-  private Map<String, HeartBeatResponse> hostResponses = new 
ConcurrentHashMap<String, HeartBeatResponse>();
+  private Map<String, HeartBeatResponse> hostResponses = new 
ConcurrentHashMap<>();
 
   @Inject
   public HeartBeatHandler(Clusters fsm, ActionQueue aq, ActionManager am,
@@ -201,10 +155,7 @@ public class HeartBeatHandler {
       return createRegisterCommand();
     }
 
-    LOG.debug("Received heartbeat from host"
-        + ", hostname=" + hostname
-        + ", currentResponseId=" + currentResponseId
-        + ", receivedResponseId=" + heartbeat.getResponseId());
+    LOG.debug("Received heartbeat from host, hostname={}, 
currentResponseId={}, receivedResponseId={}", hostname, currentResponseId, 
heartbeat.getResponseId());
 
     if (heartbeat.getResponseId() == currentResponseId - 1) {
       HeartBeatResponse heartBeatResponse = hostResponses.get(hostname);
@@ -279,11 +230,10 @@ public class HeartBeatHandler {
       return createRegisterCommand();
     }
 
-    /**
+    /*
      * A host can belong to only one cluster. Though 
getClustersForHost(hostname)
      * returns a set of clusters, it will have only one entry.
      *
-     *
      * TODO: Handle the case when a host is a part of multiple clusters.
      */
     Set<Cluster> clusters = clusterFsm.getClustersForHost(hostname);
@@ -296,7 +246,7 @@ public class HeartBeatHandler {
         response.setRecoveryConfig(rc);
 
         if (response.getRecoveryConfig() != null) {
-          LOG.info("Recovery configuration set to {}", 
response.getRecoveryConfig().toString());
+          LOG.info("Recovery configuration set to {}", 
response.getRecoveryConfig());
         }
       }
     }
@@ -315,7 +265,7 @@ public class HeartBeatHandler {
 
 
   protected void processRecoveryReport(RecoveryReport recoveryReport, String 
hostname) throws AmbariException {
-    LOG.debug("Received recovery report: " + recoveryReport.toString());
+    LOG.debug("Received recovery report: {}", recoveryReport);
     Host host = clusterFsm.getHost(hostname);
     host.setRecoveryReport(recoveryReport);
   }
@@ -330,7 +280,7 @@ public class HeartBeatHandler {
       for (AgentCommand ac : cmds) {
         try {
           if (LOG.isDebugEnabled()) {
-            LOG.debug("Sending command string = " + 
StageUtils.jaxbToString(ac));
+            LOG.debug("Sending command string = {}", 
StageUtils.jaxbToString(ac));
           }
         } catch (Exception e) {
           throw new AmbariException("Could not get jaxb string for command", 
e);
@@ -493,10 +443,10 @@ public class HeartBeatHandler {
 
     response.setAgentConfig(config.getAgentConfigsMap());
     if(response.getAgentConfig() != null) {
-      LOG.debug("Agent configuration map set to " + response.getAgentConfig());
+      LOG.debug("Agent configuration map set to {}", 
response.getAgentConfig());
     }
 
-    /**
+    /*
      * A host can belong to only one cluster. Though 
getClustersForHost(hostname)
      * returns a set of clusters, it will have only one entry.
      *
@@ -511,7 +461,7 @@ public class HeartBeatHandler {
       response.setRecoveryConfig(rc);
 
       if(response.getRecoveryConfig() != null) {
-        LOG.info("Recovery configuration set to " + 
response.getRecoveryConfig().toString());
+        LOG.info("Recovery configuration set to " + 
response.getRecoveryConfig());
       }
     }
 
@@ -542,7 +492,7 @@ public class HeartBeatHandler {
     }
 
     if(actionQueue.hasPendingTask(hostname)) {
-      LOG.debug("Host " + hostname + " has pending tasks");
+      LOG.debug("Host {} has pending tasks", hostname);
       response.setHasPendingTasks(true);
     }
   }
@@ -558,36 +508,26 @@ public class HeartBeatHandler {
     ComponentsResponse response = new ComponentsResponse();
 
     Cluster cluster = clusterFsm.getCluster(clusterName);
-    StackId stackId = cluster.getCurrentStackVersion();
-    if (stackId == null) {
-      throw new AmbariException("Cannot provide stack components map. " +
-        "Stack hasn't been selected yet.");
-    }
-    StackInfo stack = ambariMetaInfo.getStack(stackId.getStackName(),
-        stackId.getStackVersion());
 
-    response.setClusterName(clusterName);
-    response.setStackName(stackId.getStackName());
-    response.setStackVersion(stackId.getStackVersion());
-    response.setComponents(getComponentsMap(stack));
+    Map<String, Map<String, String>> componentsMap = new HashMap<>();
 
-    return response;
-  }
+    for (org.apache.ambari.server.state.Service service : 
cluster.getServices().values()) {
+      componentsMap.put(service.getName(), new HashMap<String, String>());
 
-  private Map<String, Map<String, String>> getComponentsMap(StackInfo stack) {
-    Map<String, Map<String, String>> result = new HashMap<String, Map<String, 
String>>();
+      for (ServiceComponent component : 
service.getServiceComponents().values()) {
+        StackId stackId = component.getDesiredStackId();
 
-    for (ServiceInfo service : stack.getServices()) {
-      Map<String, String> components = new HashMap<String, String>();
+        ComponentInfo componentInfo = ambariMetaInfo.getComponent(
+            stackId.getStackName(), stackId.getStackVersion(), 
service.getName(), component.getName());
 
-      for (ComponentInfo component : service.getComponents()) {
-        components.put(component.getName(), component.getCategory());
+        componentsMap.get(service.getName()).put(component.getName(), 
componentInfo.getCategory());
       }
-
-      result.put(service.getName(), components);
     }
 
-    return result;
+    response.setClusterName(clusterName);
+    response.setComponents(componentsMap);
+
+    return response;
   }
 
   /**
@@ -606,7 +546,7 @@ public class HeartBeatHandler {
       return null;
     }
 
-    List<AlertDefinitionCommand> commands = new 
ArrayList<AlertDefinitionCommand>();
+    List<AlertDefinitionCommand> commands = new ArrayList<>();
 
     // for every cluster this host is a member of, build the command
     for (Cluster cluster : hostClusters) {
@@ -662,7 +602,7 @@ public class HeartBeatHandler {
                 File keytabFile = new File(dataDir + File.separator + hostName 
+ File.separator + sha1Keytab);
 
                 if (keytabFile.canRead()) {
-                  Map<String, String> keytabMap = new HashMap<String, 
String>();
+                  Map<String, String> keytabMap = new HashMap<>();
                   String principal = 
record.get(KerberosIdentityDataFileReader.PRINCIPAL);
                   String isService = 
record.get(KerberosIdentityDataFileReader.SERVICE);
 
@@ -690,7 +630,7 @@ public class HeartBeatHandler {
                 }
               }
             } else if ("REMOVE_KEYTAB".equalsIgnoreCase(command)) {
-              Map<String, String> keytabMap = new HashMap<String, String>();
+              Map<String, String> keytabMap = new HashMap<>();
 
               keytabMap.put(KerberosIdentityDataFileReader.HOSTNAME, hostName);
               keytabMap.put(KerberosIdentityDataFileReader.SERVICE, 
record.get(KerberosIdentityDataFileReader.SERVICE));
@@ -722,4 +662,4 @@ public class HeartBeatHandler {
     heartbeatMonitor.shutdown();
     heartbeatProcessor.stopAsync();
   }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/15cd3d83/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/HostEventCreator.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/HostEventCreator.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/HostEventCreator.java
index d05fe9d..1abb0d9 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/HostEventCreator.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/HostEventCreator.java
@@ -59,7 +59,7 @@ public class HostEventCreator implements 
RequestAuditEventCreator {
   /**
    * Pattern to retrieve hostname from url
    */
-  private static final Pattern HOSTNAME_PATTERN = Pattern.compile(".*" + 
HostResourceProvider.HOST_NAME_PROPERTY_ID + "\\s*=\\s*([^&\\s]+).*");
+  private static final Pattern HOSTNAME_PATTERN = Pattern.compile(".*" + 
HostResourceProvider.HOST_HOST_NAME_PROPERTY_ID + "\\s*=\\s*([^&\\s]+).*");
 
   /**
    * {@inheritDoc}
@@ -109,7 +109,7 @@ public class HostEventCreator implements 
RequestAuditEventCreator {
           .withResultStatus(result.getStatus())
           .withUrl(request.getURI())
           .withRemoteIp(request.getRemoteAddress())
-          
.withHostName(RequestAuditEventCreatorHelper.getNamedProperty(request, 
HostResourceProvider.HOST_NAME_PROPERTY_ID))
+          
.withHostName(RequestAuditEventCreatorHelper.getNamedProperty(request, 
HostResourceProvider.HOST_HOST_NAME_PROPERTY_ID))
           .build();
       case QUERY_POST:
         return AddComponentToHostRequestAuditEvent.builder()
@@ -157,4 +157,4 @@ public class HostEventCreator implements 
RequestAuditEventCreator {
     }
     return null;
   }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/15cd3d83/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index becf596..16b4917 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -204,6 +204,7 @@ import org.apache.ambari.server.utils.SecretReference;
 import org.apache.ambari.server.utils.StageUtils;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.BooleanUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.math.NumberUtils;
 import org.apache.http.client.utils.URIBuilder;
@@ -453,18 +454,6 @@ public class AmbariManagementControllerImpl implements 
AmbariManagementControlle
       throw new StackAccessException("stackName=" + stackId.getStackName() + 
", stackVersion=" + stackId.getStackVersion());
     }
 
-    RepositoryVersionEntity versionEntity = null;
-
-    if (null != request.getRepositoryVersion()) {
-      versionEntity = repositoryVersionDAO.findByStackAndVersion(stackId,
-          request.getRepositoryVersion());
-
-      if (null == versionEntity) {
-        throw new AmbariException(String.format("Tried to create a cluster on 
version %s, but that version doesn't exist",
-            request.getRepositoryVersion()));
-      }
-    }
-
     // FIXME add support for desired configs at cluster level
 
     boolean foundInvalidHosts = false;
@@ -756,22 +745,21 @@ public class AmbariManagementControllerImpl implements 
AmbariManagementControlle
   @Override
   public void registerRackChange(String clusterName) throws AmbariException {
     Cluster cluster = clusters.getCluster(clusterName);
-    StackId stackId = cluster.getCurrentStackVersion();
 
-    Set<String> rackSensitiveServices =
-        ambariMetaInfo.getRackSensitiveServicesNames(stackId.getStackName(), 
stackId.getStackVersion());
+    for (Service service : cluster.getServices().values()) {
+      ServiceInfo serviceInfo = ambariMetaInfo.getService(service);
+
+      if 
(!BooleanUtils.toBoolean(serviceInfo.isRestartRequiredAfterRackChange())) {
+        continue;
+      }
 
-    Map<String, Service> services = cluster.getServices();
+      Map<String, ServiceComponent> serviceComponents = 
service.getServiceComponents();
 
-    for (Service service : services.values()) {
-      if(rackSensitiveServices.contains(service.getName())) {
-        Map<String, ServiceComponent> serviceComponents = 
service.getServiceComponents();
-        for (ServiceComponent serviceComponent : serviceComponents.values()) {
-          Map<String, ServiceComponentHost> schMap = 
serviceComponent.getServiceComponentHosts();
-          for (Entry<String, ServiceComponentHost> sch : schMap.entrySet()) {
-            ServiceComponentHost serviceComponentHost = sch.getValue();
-            serviceComponentHost.setRestartRequired(true);
-          }
+      for (ServiceComponent serviceComponent : serviceComponents.values()) {
+        Map<String, ServiceComponentHost> schMap = 
serviceComponent.getServiceComponentHosts();
+        for (Entry<String, ServiceComponentHost> sch : schMap.entrySet()) {
+          ServiceComponentHost serviceComponentHost = sch.getValue();
+          serviceComponentHost.setRestartRequired(true);
         }
       }
     }
@@ -1048,10 +1036,8 @@ public class AmbariManagementControllerImpl implements 
AmbariManagementControlle
     Set<ClusterResponse> response = new HashSet<>();
 
     if (LOG.isDebugEnabled()) {
-      LOG.debug("Received a getClusters request"
-        + ", clusterName=" + request.getClusterName()
-        + ", clusterId=" + request.getClusterId()
-        + ", stackInfo=" + request.getStackVersion());
+      LOG.debug("Received a getClusters request, clusterName={}, clusterId={}, 
stackInfo={}",
+        request.getClusterName(), request.getClusterId(), 
request.getStackVersion());
     }
 
     Cluster singleCluster = null;
@@ -1159,20 +1145,13 @@ public class AmbariManagementControllerImpl implements 
AmbariManagementControlle
     }
 
     if (request.getComponentName() != null) {
-      if (request.getServiceName() == null
-          || request.getServiceName().isEmpty()) {
-        StackId stackId = cluster.getDesiredStackVersion();
-        String serviceName =
-            ambariMetaInfo.getComponentToService(stackId.getStackName(),
-                stackId.getStackVersion(), request.getComponentName());
-        if (LOG.isDebugEnabled()) {
-          LOG.debug("Looking up service name for component"
-              + ", componentName=" + request.getComponentName()
-              + ", serviceName=" + serviceName
-              + ", stackInfo=" + stackId.getStackId());
-        }
-        if (serviceName == null
-            || serviceName.isEmpty()) {
+      if (StringUtils.isBlank(request.getServiceName())) {
+
+        // !!! FIXME the assumption that a component is unique across all 
stacks is a ticking
+        // time bomb.  Blueprints are making this assumption.
+        String serviceName = findServiceName(cluster, 
request.getComponentName());
+
+        if (StringUtils.isBlank(serviceName)) {
           LOG.error("Unable to find service for component {}", 
request.getComponentName());
           throw new ServiceComponentHostNotFoundException(
               cluster.getClusterName(), null, request.getComponentName(), 
request.getHostname());
@@ -1897,7 +1876,8 @@ public class AmbariManagementControllerImpl implements 
AmbariManagementControlle
       }
 
       ClusterResponse clusterResponse =
-          new ClusterResponse(cluster.getClusterId(), 
cluster.getClusterName(), null, null, null, null, null, null);
+          new ClusterResponse(cluster.getClusterId(), 
cluster.getClusterName(), null, null, null, 0,
+              null, null);
 
       Map<String, Collection<ServiceConfigVersionResponse>> map =
         new HashMap<>();
@@ -3468,24 +3448,7 @@ public class AmbariManagementControllerImpl implements 
AmbariManagementControlle
 
   @Override
   public String findServiceName(Cluster cluster, String componentName) throws 
AmbariException {
-    StackId stackId = cluster.getDesiredStackVersion();
-    String serviceName =
-        ambariMetaInfo.getComponentToService(stackId.getStackName(),
-            stackId.getStackVersion(), componentName);
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("Looking up service name for component"
-          + ", componentName=" + componentName
-          + ", serviceName=" + serviceName);
-    }
-
-    if (serviceName == null
-        || serviceName.isEmpty()) {
-      throw new AmbariException("Could not find service for component"
-          + ", componentName=" + componentName
-          + ", clusterName=" + cluster.getClusterName()
-          + ", stackInfo=" + stackId.getStackId());
-    }
-    return serviceName;
+    return cluster.getServiceByComponentName(componentName).getName();
   }
 
   /**
@@ -5256,52 +5219,52 @@ public class AmbariManagementControllerImpl implements 
AmbariManagementControlle
   @SuppressWarnings("unchecked")
   @Override
   public void initializeWidgetsAndLayouts(Cluster cluster, Service service) 
throws AmbariException {
-    StackId stackId = cluster.getDesiredStackVersion();
     Type widgetLayoutType = new TypeToken<Map<String, 
List<WidgetLayout>>>(){}.getType();
 
-    try {
-      Map<String, Object> widgetDescriptor = null;
-      StackInfo stackInfo = ambariMetaInfo.getStack(stackId.getStackName(), 
stackId.getStackVersion());
-      if (service != null) {
-        // Service widgets
-        ServiceInfo serviceInfo = stackInfo.getService(service.getName());
-        File widgetDescriptorFile = serviceInfo.getWidgetsDescriptorFile();
-        if (widgetDescriptorFile != null && widgetDescriptorFile.exists()) {
-          try {
-            widgetDescriptor = gson.fromJson(new 
FileReader(widgetDescriptorFile), widgetLayoutType);
-          } catch (Exception ex) {
-            String msg = "Error loading widgets from file: " + 
widgetDescriptorFile;
-            LOG.error(msg, ex);
-            throw new AmbariException(msg);
-          }
-        }
-      } else {
-        // Cluster level widgets
+    Set<File> widgetDescriptorFiles = new HashSet<>();
+
+    if (null != service) {
+      ServiceInfo serviceInfo = ambariMetaInfo.getService(service);
+      File widgetDescriptorFile = serviceInfo.getWidgetsDescriptorFile();
+      if (widgetDescriptorFile != null && widgetDescriptorFile.exists()) {
+        widgetDescriptorFiles.add(widgetDescriptorFile);
+      }
+    } else {
+      Set<StackId> stackIds = new HashSet<>();
+
+      for (Service svc : cluster.getServices().values()) {
+        stackIds.add(svc.getDesiredStackId());
+      }
+
+      for (StackId stackId : stackIds) {
+        StackInfo stackInfo = ambariMetaInfo.getStack(stackId);
+
         String widgetDescriptorFileLocation = 
stackInfo.getWidgetsDescriptorFileLocation();
         if (widgetDescriptorFileLocation != null) {
           File widgetDescriptorFile = new File(widgetDescriptorFileLocation);
           if (widgetDescriptorFile.exists()) {
-            try {
-              widgetDescriptor = gson.fromJson(new 
FileReader(widgetDescriptorFile), widgetLayoutType);
-            } catch (Exception ex) {
-              String msg = "Error loading widgets from file: " + 
widgetDescriptorFile;
-              LOG.error(msg, ex);
-              throw new AmbariException(msg);
-            }
+            widgetDescriptorFiles.add(widgetDescriptorFile);
           }
         }
       }
-      if (widgetDescriptor != null) {
-        LOG.debug("Loaded widget descriptor: " + widgetDescriptor);
+    }
+
+    for (File widgetDescriptorFile : widgetDescriptorFiles) {
+      Map<String, Object> widgetDescriptor = null;
+
+      try {
+        widgetDescriptor = gson.fromJson(new FileReader(widgetDescriptorFile), 
widgetLayoutType);
+
         for (Object artifact : widgetDescriptor.values()) {
           List<WidgetLayout> widgetLayouts = (List<WidgetLayout>) artifact;
           createWidgetsAndLayouts(cluster, widgetLayouts);
         }
+
+      } catch (Exception ex) {
+        String msg = "Error loading widgets from file: " + 
widgetDescriptorFile;
+        LOG.error(msg, ex);
+        throw new AmbariException(msg);
       }
-    } catch (Exception e) {
-      throw new AmbariException("Error creating stack widget artifacts. " +
-        (service != null ? "Service: " + service.getName() + ", " : "") +
-        "Cluster: " + cluster.getClusterName(), e);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/15cd3d83/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterRequest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterRequest.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterRequest.java
index 4d4fd59..aea2072 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterRequest.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterRequest.java
@@ -240,19 +240,4 @@ public class ClusterRequest {
   public void setServiceConfigVersionRequest(ServiceConfigVersionRequest 
serviceConfigVersionRequest) {
     this.serviceConfigVersionRequest = serviceConfigVersionRequest;
   }
-
-  /**
-   * @param version the repo version to use
-   */
-  public void setRepositoryVersion(String version) {
-    repositoryVersion = version;
-  }
-
-  /**
-   * @return the repo version to use
-   */
-  public String getRepositoryVersion() {
-    return repositoryVersion;
-  }
-
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/15cd3d83/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterResponse.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterResponse.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterResponse.java
index c7577ee..968dbba 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterResponse.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterResponse.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,6 +20,7 @@ package org.apache.ambari.server.controller;
 
 import java.util.Collection;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 
 import org.apache.ambari.server.state.ClusterHealthReport;
@@ -29,38 +30,23 @@ import org.apache.ambari.server.state.State;
 
 public class ClusterResponse {
 
-  private final Long clusterId;
-
+  private final long clusterId;
   private final String clusterName;
-
   private final Set<String> hostNames;
-
   private final String desiredStackVersion;
+  private final State provisioningState;
+  private final SecurityType securityType;
+  private final int totalHosts;
 
   private Map<String, DesiredConfig> desiredConfigs;
-
   private Map<String, Collection<ServiceConfigVersionResponse>> 
desiredServiceConfigVersions;
-
-  private String provisioningState;
-
-  /**
-   * The cluster's security.
-   * <p/>
-   * See {@link org.apache.ambari.server.state.SecurityType} for relevant 
values.
-   */
-  private String securityType;
-
-  private Integer totalHosts;
-
   private ClusterHealthReport clusterHealthReport;
+  private Map<String, String> credentialStoreServiceProperties;
 
-  private Map<String, String> credentialStoreServiceProperties = null;
-
-  public ClusterResponse(Long clusterId, String clusterName,
-                         State provisioningState, SecurityType securityType, 
Set<String> hostNames, Integer totalHosts,
+  public ClusterResponse(long clusterId, String clusterName,
+                         State provisioningState, SecurityType securityType, 
Set<String> hostNames, int totalHosts,
                          String desiredStackVersion, ClusterHealthReport 
clusterHealthReport) {
 
-    super();
     this.clusterId = clusterId;
     this.clusterName = clusterName;
     this.hostNames = hostNames;
@@ -69,13 +55,15 @@ public class ClusterResponse {
     this.clusterHealthReport = clusterHealthReport;
 
     if (null != provisioningState) {
-      this.provisioningState = provisioningState.name();
+      this.provisioningState = provisioningState;
+    } else {
+      this.provisioningState = State.UNKNOWN;
     }
 
     if (null == securityType) {
-      this.securityType = SecurityType.NONE.name();
+      this.securityType = SecurityType.NONE;
     } else {
-      this.securityType = securityType.name();
+      this.securityType = securityType;
     }
   }
 
@@ -94,19 +82,12 @@ public class ClusterResponse {
   }
 
   /**
-   * @return the host names
-   */
-  public Set<String> getHostNames() {
-    return hostNames;
-  }
-
-  /**
    * Gets whether the cluster is still initializing or has finished with its
    * deployment requests.
    *
    * @return either {@code INIT} or {@code INSTALLED}, never {@code null}.
    */
-  public String getProvisioningState() {
+  public State getProvisioningState() {
     return provisioningState;
   }
 
@@ -117,31 +98,19 @@ public class ClusterResponse {
    *
    * @return the cluster's security type
    */
-  public String getSecurityType() {
+  public SecurityType getSecurityType() {
     return securityType;
   }
 
-  /**
-   * Sets the cluster's security type.
-   * <p/>
-   * See {@link org.apache.ambari.server.state.SecurityType} for relevant 
values.
-   *
-   * @param securityType a String declaring the cluster's security type
-   */
-  public void setSecurityType(String securityType) {
-    this.securityType = securityType;
-  }
-
   @Override
   public String toString() {
     StringBuilder sb = new StringBuilder();
-    sb.append("{"
-        + " clusterName=" + clusterName
-        + ", clusterId=" + clusterId
-        + ", provisioningState=" + provisioningState
-        + ", desiredStackVersion=" + desiredStackVersion
-        + ", totalHosts=" + totalHosts
-        + ", hosts=[");
+    sb.append("{ clusterName=").append(clusterName)
+      .append(", clusterId=").append(clusterId)
+      .append(", provisioningState=").append(provisioningState)
+      .append(", desiredStackVersion=").append(desiredStackVersion)
+      .append(", totalHosts=").append(totalHosts)
+      .append(", hosts=[");
 
     if (hostNames != null) {
       int i = 0;
@@ -153,9 +122,7 @@ public class ClusterResponse {
         sb.append(hostName);
       }
     }
-    sb.append("]"
-        + ", clusterHealthReport= " + clusterHealthReport
-        + "}");
+    sb.append("], clusterHealthReport= 
").append(clusterHealthReport).append("}");
     return sb.toString();
   }
 
@@ -168,25 +135,15 @@ public class ClusterResponse {
       return false;
     }
 
-    ClusterResponse that = (ClusterResponse) o;
-
-    if (clusterId != null ?
-        !clusterId.equals(that.clusterId) : that.clusterId != null) {
-      return false;
-    }
-    if (clusterName != null ?
-        !clusterName.equals(that.clusterName) : that.clusterName != null) {
-      return false;
-    }
+    ClusterResponse other = (ClusterResponse) o;
 
-    return true;
+    return Objects.equals(clusterId, other.clusterId) &&
+      Objects.equals(clusterName, other.clusterName);
   }
 
   @Override
   public int hashCode() {
-    int result = clusterId != null ? clusterId.intValue() : 0;
-    result = 71 * result + (clusterName != null ? clusterName.hashCode() : 0);
-    return result;
+    return Objects.hash(clusterId, clusterName);
   }
 
   /**
@@ -196,9 +153,6 @@ public class ClusterResponse {
     return desiredStackVersion;
   }
 
-  /**
-   * @param configs
-   */
   public void setDesiredConfigs(Map<String, DesiredConfig> configs) {
     desiredConfigs = configs;
   }
@@ -239,4 +193,4 @@ public class ClusterResponse {
   public Map<String, String> getCredentialStoreServiceProperties() {
     return credentialStoreServiceProperties;
   }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/15cd3d83/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 3097a07..86ddc5f 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
@@ -60,7 +60,6 @@ import org.apache.ambari.server.orm.entities.ArtifactEntity;
 import org.apache.ambari.server.security.credential.Credential;
 import org.apache.ambari.server.security.credential.PrincipalKeyCredential;
 import org.apache.ambari.server.security.encryption.CredentialStoreService;
-import org.apache.ambari.server.serveraction.ActionLog;
 import org.apache.ambari.server.serveraction.ServerAction;
 import org.apache.ambari.server.serveraction.kerberos.CleanupServerAction;
 import 
org.apache.ambari.server.serveraction.kerberos.ConfigureAmbariIdentitiesServerAction;
@@ -129,7 +128,7 @@ import com.google.inject.persist.Transactional;
 @Singleton
 public class KerberosHelperImpl implements KerberosHelper {
 
-  private static final String BASE_LOG_DIR = "/tmp/ambari";
+  public static final String BASE_LOG_DIR = "/tmp/ambari";
 
   private static final Logger LOG = 
LoggerFactory.getLogger(KerberosHelperImpl.class);
 
@@ -338,7 +337,8 @@ public class KerberosHelperImpl implements KerberosHelper {
         existingConfigurations, installedServices, serviceFilter, 
previouslyExistingServices, true, true);
 
     for (Map.Entry<String, Map<String, String>> entry : updates.entrySet()) {
-      configHelper.updateConfigType(cluster, cluster.getDesiredStackVersion(), 
ambariManagementController, entry.getKey(), entry.getValue(), null,
+      configHelper.updateConfigType(cluster, cluster.getDesiredStackVersion(),
+          ambariManagementController, entry.getKey(), entry.getValue(), null,
           ambariManagementController.getAuthName(), "Enabling Kerberos for 
added components");
     }
   }
@@ -420,55 +420,6 @@ public class KerberosHelperImpl implements KerberosHelper {
         : kerberosConfigurations;
   }
 
-  /**
-   * Processes the configuration values related to a particular Kerberos 
descriptor identity definition
-   * by:
-   * <ol>
-   * <li>
-   * merging the declared properties and their values from 
<code>identityConfigurations</code> with the set of
-   * Kerberos-related configuration updates in 
<code>kerberosConfigurations</code>, using the existing cluster
-   * configurations in <code>configurations</code>
-   * </li>
-   * <li>
-   * ensuring that these properties are not overwritten by recommendations by 
the stack advisor later
-   * in the workflow by adding them to the <code>propertiesToIgnore</code> map
-   * </li>
-   * </ol>
-   *
-   * @param identityConfigurations a map of config-types to property 
name/value pairs to process
-   * @param kerberosConfigurations a map of config-types to property 
name/value pairs to be applied
-   *                               as configuration updates
-   * @param configurations         a map of config-types to property 
name/value pairs representing
-   *                               the existing configurations for the cluster
-   * @param propertiesToIgnore     a map of config-types to property names to 
be ignored while
-   *                               processing stack advisor recommendations
-   * @throws AmbariException
-   */
-  private void processIdentityConfigurations(Map<String, Map<String, String>> 
identityConfigurations,
-                                             Map<String, Map<String, String>> 
kerberosConfigurations,
-                                             Map<String, Map<String, String>> 
configurations,
-                                             Map<String, Set<String>> 
propertiesToIgnore)
-      throws AmbariException {
-    if (identityConfigurations != null) {
-      for (Map.Entry<String, Map<String, String>> identitiyEntry : 
identityConfigurations.entrySet()) {
-        String configType = identitiyEntry.getKey();
-        Map<String, String> properties = identitiyEntry.getValue();
-
-        mergeConfigurations(kerberosConfigurations, configType, 
identitiyEntry.getValue(), configurations);
-
-        if ((properties != null) && !properties.isEmpty()) {
-          Set<String> propertyNames = propertiesToIgnore.get(configType);
-          if (propertyNames == null) {
-            propertyNames = new HashSet<>();
-            propertiesToIgnore.put(configType, propertyNames);
-          }
-          propertyNames.addAll(properties.keySet());
-        }
-      }
-    }
-
-  }
-
   @Override
   public Map<String, Map<String, String>> applyStackAdvisorUpdates(Cluster 
cluster, Set<String> services,
                                                                    Map<String, 
Map<String, String>> existingConfigurations,
@@ -477,8 +428,6 @@ public class KerberosHelperImpl implements KerberosHelper {
                                                                    Map<String, 
Set<String>> propertiesToRemove,
                                                                    boolean 
kerberosEnabled) throws AmbariException {
 
-    StackId stackVersion = cluster.getCurrentStackVersion();
-
     List<String> hostNames = new ArrayList<>();
     Collection<Host> hosts = cluster.getHosts();
 
@@ -539,44 +488,58 @@ public class KerberosHelperImpl implements KerberosHelper 
{
         }
       }
 
-      StackAdvisorRequest request = 
StackAdvisorRequest.StackAdvisorRequestBuilder
-          .forStack(stackVersion.getStackName(), 
stackVersion.getStackVersion())
-          .forServices(new ArrayList<>(services))
-          .forHosts(hostNames)
-          .withComponentHostsMap(cluster.getServiceComponentHostMap(null, 
services))
-          .withConfigurations(requestConfigurations)
-          .ofType(StackAdvisorRequest.StackAdvisorRequestType.CONFIGURATIONS)
-          .build();
+      Set<StackId> visitedStacks = new HashSet<>();
 
-      try {
-        RecommendationResponse response = 
stackAdvisorHelper.recommend(request);
-
-        RecommendationResponse.Recommendation recommendation = (response == 
null) ? null : response.getRecommendations();
-        RecommendationResponse.Blueprint blueprint = (recommendation == null) 
? null : recommendation.getBlueprint();
-        Map<String, RecommendationResponse.BlueprintConfigurations> 
configurations = (blueprint == null) ? null : blueprint.getConfigurations();
-
-        if (configurations != null) {
-          for (Map.Entry<String, 
RecommendationResponse.BlueprintConfigurations> configuration : 
configurations.entrySet()) {
-            String configType = configuration.getKey();
-            Map<String, String> recommendedConfigProperties = 
configuration.getValue().getProperties();
-            Map<String, ValueAttributesInfo> 
recommendedConfigPropertyAttributes = 
configuration.getValue().getPropertyAttributes();
-            Map<String, String> existingConfigProperties = 
(existingConfigurations == null) ? null : 
existingConfigurations.get(configType);
-            Map<String, String> kerberosConfigProperties = 
kerberosConfigurations.get(configType);
-            Set<String> ignoreProperties = (propertiesToIgnore == null) ? null 
: propertiesToIgnore.get(configType);
-
-            addRecommendedPropertiesForConfigType(kerberosConfigurations, 
configType, recommendedConfigProperties,
-                existingConfigProperties, kerberosConfigProperties, 
ignoreProperties);
-
-            if (recommendedConfigPropertyAttributes != null) {
-              removeRecommendedPropertiesForConfigType(configType, 
recommendedConfigPropertyAttributes,
-                  existingConfigProperties, kerberosConfigurations, 
ignoreProperties, propertiesToRemove);
+      for (String serviceName : services) {
+        Service service = cluster.getService(serviceName);
+        StackId stackId = service.getDesiredStackId();
+
+        if (visitedStacks.contains(stackId)) {
+          continue;
+        }
+
+        StackAdvisorRequest request = 
StackAdvisorRequest.StackAdvisorRequestBuilder
+            .forStack(stackId.getStackName(), stackId.getStackVersion())
+            .forServices(new ArrayList<>(services))
+            .forHosts(hostNames)
+            .withComponentHostsMap(cluster.getServiceComponentHostMap(null, 
services))
+            .withConfigurations(requestConfigurations)
+            .ofType(StackAdvisorRequest.StackAdvisorRequestType.CONFIGURATIONS)
+            .build();
+
+        try {
+          RecommendationResponse response = 
stackAdvisorHelper.recommend(request);
+
+          RecommendationResponse.Recommendation recommendation = (response == 
null) ? null : response.getRecommendations();
+          RecommendationResponse.Blueprint blueprint = (recommendation == 
null) ? null : recommendation.getBlueprint();
+          Map<String, RecommendationResponse.BlueprintConfigurations> 
configurations = (blueprint == null) ? null : blueprint.getConfigurations();
+
+          if (configurations != null) {
+            for (Map.Entry<String, 
RecommendationResponse.BlueprintConfigurations> configuration : 
configurations.entrySet()) {
+              String configType = configuration.getKey();
+              Map<String, String> recommendedConfigProperties = 
configuration.getValue().getProperties();
+              Map<String, ValueAttributesInfo> 
recommendedConfigPropertyAttributes = 
configuration.getValue().getPropertyAttributes();
+              Map<String, String> existingConfigProperties = 
(existingConfigurations == null) ? null : 
existingConfigurations.get(configType);
+              Map<String, String> kerberosConfigProperties = 
kerberosConfigurations.get(configType);
+              Set<String> ignoreProperties = (propertiesToIgnore == null) ? 
null : propertiesToIgnore.get(configType);
+
+              addRecommendedPropertiesForConfigType(kerberosConfigurations, 
configType, recommendedConfigProperties,
+                  existingConfigProperties, kerberosConfigProperties, 
ignoreProperties);
+
+              if (recommendedConfigPropertyAttributes != null) {
+                removeRecommendedPropertiesForConfigType(configType, 
recommendedConfigPropertyAttributes,
+                    existingConfigProperties, kerberosConfigurations, 
ignoreProperties, propertiesToRemove);
+              }
             }
           }
+
+        } catch (Exception e) {
+          throw new AmbariException(e.getMessage(), e);
         }
 
-      } catch (Exception e) {
-        throw new AmbariException(e.getMessage(), e);
+        visitedStacks.add(stackId);
       }
+
     }
 
     return kerberosConfigurations;
@@ -817,7 +780,7 @@ public class KerberosHelperImpl implements KerberosHelper {
    * @param kerberosDetails      a KerberosDetails containing information 
about relevant Kerberos configuration
    * @param updateJAASFile       true to update Ambari's JAAS file; false 
otherwise
    * @throws AmbariException
-   * @see ConfigureAmbariIdentitiesServerAction#configureJAAS(String, String, 
ActionLog)
+   * @see ConfigureAmbariIdentitiesServerAction#configureJAAS(String, String, 
org.apache.ambari.server.serveraction.ActionLog)
    */
   private void installAmbariIdentity(KerberosIdentityDescriptor 
ambariServerIdentity,
                                      Keytab keytab, Map<String, Map<String, 
String>> configurations,
@@ -1754,6 +1717,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
     // Gather data needed to create stages and tasks...
     Map<String, Set<String>> clusterHostInfo = 
StageUtils.getClusterHostInfo(cluster);
     String clusterHostInfoJson = StageUtils.getGson().toJson(clusterHostInfo);
+
     Map<String, String> hostParams = 
customCommandExecutionHelper.createDefaultHostParams(cluster, 
cluster.getDesiredStackVersion());
     String hostParamsJson = StageUtils.getGson().toJson(hostParams);
     String ambariServerHostname = StageUtils.getHostName();
@@ -1954,6 +1918,7 @@ public class KerberosHelperImpl implements KerberosHelper 
{
       // Gather data needed to create stages and tasks...
       Map<String, Set<String>> clusterHostInfo = 
StageUtils.getClusterHostInfo(cluster);
       String clusterHostInfoJson = 
StageUtils.getGson().toJson(clusterHostInfo);
+
       Map<String, String> hostParams = 
customCommandExecutionHelper.createDefaultHostParams(cluster, 
cluster.getDesiredStackVersion());
       String hostParamsJson = StageUtils.getGson().toJson(hostParams);
       String ambariServerHostname = StageUtils.getHostName();
@@ -2108,43 +2073,6 @@ public class KerberosHelperImpl implements 
KerberosHelper {
     }
   }
 
-  /**
-   * Creates a temporary file within the system temporary directory
-   * <p/>
-   * The resulting file is to be removed by the caller when desired.
-   *
-   * @return a File pointing to the new temporary file, or null if one was not 
created
-   * @throws AmbariException if a new temporary directory cannot be created
-   */
-  protected File createTemporaryFile() throws AmbariException {
-    try {
-      return File.createTempFile("tmp", ".tmp", 
getConfiguredTemporaryDirectory());
-    } catch (IOException e) {
-      String message = "Failed to create a temporary file.";
-      LOG.error(message, e);
-      throw new AmbariException(message, e);
-    }
-  }
-
-  /**
-   * Gets the configured temporary directory.
-   *
-   * @return a File pointing to the configured temporary directory
-   * @throws IOException
-   */
-  protected File getConfiguredTemporaryDirectory() throws IOException {
-    String tempDirectoryPath = configuration.getServerTempDir();
-
-    if (StringUtils.isEmpty(tempDirectoryPath)) {
-      tempDirectoryPath = System.getProperty("java.io.tmpdir");
-    }
-
-    if (tempDirectoryPath == null) {
-      throw new IOException("The System property 'java.io.tmpdir' does not 
specify a temporary directory");
-    }
-
-    return new File(tempDirectoryPath);
-  }
 
   /**
    * Merges the specified configuration property in a map of configuration 
types.
@@ -2237,6 +2165,43 @@ public class KerberosHelperImpl implements 
KerberosHelper {
     }
   }
 
+  /**
+   * Creates a temporary file within the system temporary directory
+   * <p/>
+   * The resulting file is to be removed by the caller when desired.
+   *
+   * @return a File pointing to the new temporary file, or null if one was not 
created
+   * @throws AmbariException if a new temporary directory cannot be created
+   */
+  protected File createTemporaryFile() throws AmbariException {
+    try {
+      return File.createTempFile("tmp", ".tmp", 
getConfiguredTemporaryDirectory());
+    } catch (IOException e) {
+      String message = "Failed to create a temporary file.";
+      LOG.error(message, e);
+      throw new AmbariException(message, e);
+    }
+  }
+
+  /**
+   * Gets the configured temporary directory.
+   *
+   * @return a File pointing to the configured temporary directory
+   * @throws IOException
+   */
+  protected File getConfiguredTemporaryDirectory() throws IOException {
+    String tempDirectoryPath = configuration.getServerTempDir();
+
+    if (StringUtils.isEmpty(tempDirectoryPath)) {
+      tempDirectoryPath = System.getProperty("java.io.tmpdir");
+    }
+
+    if (tempDirectoryPath == null) {
+      throw new IOException("The System property 'java.io.tmpdir' does not 
specify a temporary directory");
+    }
+
+    return new File(tempDirectoryPath);
+  }
 
   /**
    * Creates a new stage
@@ -2245,7 +2210,6 @@ public class KerberosHelperImpl implements KerberosHelper 
{
    * @param cluster         the relevant Cluster
    * @param requestId       the relevant request Id
    * @param requestContext  a String describing the stage
-   * @param clusterHostInfo JSON-encoded clusterHostInfo structure
    * @param commandParams   JSON-encoded command parameters
    * @param hostParams      JSON-encoded host parameters
    * @return a newly created Stage
@@ -2273,7 +2237,6 @@ public class KerberosHelperImpl implements KerberosHelper 
{
    * @param cluster           the relevant Cluster
    * @param requestId         the relevant request Id
    * @param requestContext    a String describing the stage
-   * @param clusterHostInfo   JSON-encoded clusterHostInfo structure
    * @param commandParams     JSON-encoded command parameters
    * @param hostParams        JSON-encoded host parameters
    * @param actionClass       The ServeAction class that implements the action 
to invoke
@@ -2429,9 +2392,9 @@ public class KerberosHelperImpl implements KerberosHelper 
{
    * @param componentName      the name of a component for which to find 
results, null indicates all
    *                           components
    * @param kerberosDescriptor the relevant Kerberos Descriptor
+   *                           requested service component
    * @param filterContext      the context to use for filtering identities 
based on the state of the cluster
    * @return a list of KerberosIdentityDescriptors representing the active 
identities for the
-   * requested service component
    * @throws AmbariException if an error occurs processing the cluster's 
active identities
    */
   private List<KerberosIdentityDescriptor> getActiveIdentities(Cluster cluster,
@@ -2623,7 +2586,18 @@ public class KerberosHelperImpl implements 
KerberosHelper {
    * @throws AmbariException if an error occurs while retrieving the Kerberos 
descriptor
    */
   private KerberosDescriptor getKerberosDescriptorFromStack(Cluster cluster) 
throws AmbariException {
-    StackId stackId = cluster.getCurrentStackVersion();
+    // !!! FIXME in a per-service view, what does this become?
+    Set<StackId> stackIds = new HashSet<>();
+
+    for (Service service : cluster.getServices().values()) {
+      stackIds.add(service.getDesiredStackId());
+    }
+
+    if (1 != stackIds.size()) {
+      throw new AmbariException("Services are deployed from multiple stacks 
and cannot determine a unique one.");
+    }
+
+    StackId stackId = stackIds.iterator().next();
 
     // -------------------------------
     // Get the default Kerberos descriptor from the stack, which is the same 
as the value from
@@ -2679,6 +2653,55 @@ public class KerberosHelperImpl implements 
KerberosHelper {
     return identitiesToRemove;
   }
 
+  /**
+   * Processes the configuration values related to a particular Kerberos 
descriptor identity definition
+   * by:
+   * <ol>
+   * <li>
+   * merging the declared properties and their values from 
<code>identityConfigurations</code> with the set of
+   * Kerberos-related configuration updates in 
<code>kerberosConfigurations</code>, using the existing cluster
+   * configurations in <code>configurations</code>
+   * </li>
+   * <li>
+   * ensuring that these properties are not overwritten by recommendations by 
the stack advisor later
+   * in the workflow by adding them to the <code>propertiesToIgnore</code> map
+   * </li>
+   * </ol>
+   *
+   * @param identityConfigurations a map of config-types to property 
name/value pairs to process
+   * @param kerberosConfigurations a map of config-types to property 
name/value pairs to be applied
+   *                               as configuration updates
+   * @param configurations         a map of config-types to property 
name/value pairs representing
+   *                               the existing configurations for the cluster
+   * @param propertiesToIgnore     a map of config-types to property names to 
be ignored while
+   *                               processing stack advisor recommendations
+   * @throws AmbariException
+   */
+  private void processIdentityConfigurations(Map<String, Map<String, String>> 
identityConfigurations,
+                                             Map<String, Map<String, String>> 
kerberosConfigurations,
+                                             Map<String, Map<String, String>> 
configurations,
+                                             Map<String, Set<String>> 
propertiesToIgnore)
+      throws AmbariException {
+    if (identityConfigurations != null) {
+      for (Map.Entry<String, Map<String, String>> identitiyEntry : 
identityConfigurations.entrySet()) {
+        String configType = identitiyEntry.getKey();
+        Map<String, String> properties = identitiyEntry.getValue();
+
+        mergeConfigurations(kerberosConfigurations, configType, 
identitiyEntry.getValue(), configurations);
+
+        if ((properties != null) && !properties.isEmpty()) {
+          Set<String> propertyNames = propertiesToIgnore.get(configType);
+          if (propertyNames == null) {
+            propertyNames = new HashSet<>();
+            propertiesToIgnore.put(configType, propertyNames);
+          }
+          propertyNames.addAll(properties.keySet());
+        }
+      }
+    }
+
+  }
+
   /* 
********************************************************************************************
    * Helper classes and enums
    * 
********************************************************************************************
 *\
@@ -2959,7 +2982,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));
@@ -3100,7 +3123,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));
@@ -3768,4 +3791,4 @@ public class KerberosHelperImpl implements KerberosHelper 
{
           
!"false".equalsIgnoreCase(kerberosEnvProperties.get(CREATE_AMBARI_PRINCIPAL));
     }
   }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/15cd3d83/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
index 1a6a040..2094a34 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
@@ -28,26 +28,24 @@ public class ServiceRequest {
   private String credentialStoreEnabled; // CREATE/UPDATE/GET
   private String credentialStoreSupported; //GET
 
-  private String desiredStack;
-  private String desiredRepositoryVersion;
+  private Long desiredRepositoryVersionId;
   /**
    * Short-lived object that gets set while validating a request
    */
   private RepositoryVersionEntity resolvedRepository;
 
-  public ServiceRequest(String clusterName, String serviceName, String 
desiredStack,
-      String desiredRepositoryVersion, String desiredState) {
-    this(clusterName, serviceName, desiredStack, desiredRepositoryVersion, 
desiredState, null);
+  public ServiceRequest(String clusterName, String serviceName,
+      Long desiredRepositoryVersionId, String desiredState) {
+    this(clusterName, serviceName, desiredRepositoryVersionId, desiredState, 
null);
   }
 
-  public ServiceRequest(String clusterName, String serviceName, String 
desiredStack,
-      String desiredRepositoryVersion, String desiredState, String 
credentialStoreEnabled) {
+  public ServiceRequest(String clusterName, String serviceName,
+      Long desiredRepositoryVersionId, String desiredState, String 
credentialStoreEnabled) {
     this.clusterName = clusterName;
     this.serviceName = serviceName;
     this.desiredState = desiredState;
 
-    this.desiredStack = desiredStack;
-    this.desiredRepositoryVersion = desiredRepositoryVersion;
+    this.desiredRepositoryVersionId = desiredRepositoryVersionId;
 
     this.credentialStoreEnabled = credentialStoreEnabled;
     // Credential store supported cannot be changed after
@@ -83,12 +81,8 @@ public class ServiceRequest {
     this.desiredState = desiredState;
   }
 
-  public String getDesiredStack() {
-    return desiredStack;
-  }
-
-  public String getDesiredRepositoryVersion() {
-    return desiredRepositoryVersion;
+  public Long getDesiredRepositoryVersionId() {
+    return desiredRepositoryVersionId;
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/15cd3d83/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
index 577659d..83df6aa 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
@@ -116,12 +116,12 @@ public class ClusterResourceProvider extends 
AbstractControllerResourceProvider
    * The cluster primary key properties.
    */
   private static Set<String> pkPropertyIds =
-      new HashSet<String>(Arrays.asList(new String[]{CLUSTER_ID_PROPERTY_ID}));
+      new HashSet<>(Arrays.asList(new String[]{CLUSTER_ID_PROPERTY_ID}));
 
   /**
    * The key property ids for a cluster resource.
    */
-  private static Map<Resource.Type, String> keyPropertyIds = new 
HashMap<Resource.Type, String>();
+  private static Map<Resource.Type, String> keyPropertyIds = new HashMap<>();
   static {
     keyPropertyIds.put(Resource.Type.Cluster, CLUSTER_NAME_PROPERTY_ID);
   }
@@ -129,7 +129,7 @@ public class ClusterResourceProvider extends 
AbstractControllerResourceProvider
   /**
    * The property ids for a cluster resource.
    */
-  private static Set<String> propertyIds = new HashSet<String>();
+  private static Set<String> propertyIds = new HashSet<>();
 
   /**
    * Used to serialize to/from json.
@@ -237,7 +237,7 @@ public class ClusterResourceProvider extends 
AbstractControllerResourceProvider
   public Set<Resource> getResources(Request request, Predicate predicate)
       throws SystemException, UnsupportedPropertyException, 
NoSuchResourceException, NoSuchParentResourceException {
 
-    final Set<ClusterRequest> requests = new HashSet<ClusterRequest>();
+    final Set<ClusterRequest> requests = new HashSet<>();
 
     if (predicate == null) {
       requests.add(getRequest(Collections.<String, Object>emptyMap()));
@@ -257,7 +257,7 @@ public class ClusterResourceProvider extends 
AbstractControllerResourceProvider
       }
     });
 
-    Set<Resource> resources = new HashSet<Resource>();
+    Set<Resource> resources = new HashSet<>();
     if (LOG.isDebugEnabled()) {
       LOG.debug("Found clusters matching getClusters request"
           + ", clusterResponseCount=" + responses.size());
@@ -297,7 +297,7 @@ public class ClusterResourceProvider extends 
AbstractControllerResourceProvider
   protected RequestStatus updateResourcesAuthorized(final Request request, 
Predicate predicate)
       throws SystemException, UnsupportedPropertyException, 
NoSuchResourceException, NoSuchParentResourceException {
 
-    final Set<ClusterRequest>   requests = new HashSet<ClusterRequest>();
+    final Set<ClusterRequest>   requests = new HashSet<>();
     RequestStatusResponse       response;
 
     for (Map<String, Object> requestPropertyMap : request.getProperties()) {
@@ -321,7 +321,7 @@ public class ClusterResourceProvider extends 
AbstractControllerResourceProvider
       if (updateResults != null) {
         Map<String, Collection<ServiceConfigVersionResponse>> 
serviceConfigVersions = updateResults.getDesiredServiceConfigVersions();
         if (serviceConfigVersions != null) {
-          associatedResources = new HashSet<Resource>();
+          associatedResources = new HashSet<>();
           for (Collection<ServiceConfigVersionResponse> scvCollection : 
serviceConfigVersions.values()) {
             for (ServiceConfigVersionResponse serviceConfigVersionResponse : 
scvCollection) {
               Resource resource = new 
ResourceImpl(Resource.Type.ServiceConfigVersion);
@@ -401,9 +401,9 @@ public class ClusterResourceProvider extends 
AbstractControllerResourceProvider
   private ClusterRequest getRequest(Map<String, Object> properties) {
     SecurityType securityType;
     String requestedSecurityType = (String) 
properties.get(CLUSTER_SECURITY_TYPE_PROPERTY_ID);
-    if(requestedSecurityType == null)
+    if(requestedSecurityType == null) {
       securityType = null;
-    else {
+    } else {
       try {
         securityType = 
SecurityType.valueOf(requestedSecurityType.toUpperCase());
       } catch (IllegalArgumentException e) {
@@ -420,16 +420,13 @@ public class ClusterResourceProvider extends 
AbstractControllerResourceProvider
         null,
         getSessionAttributes(properties));
 
-    if (properties.containsKey(CLUSTER_REPO_VERSION)) {
-      cr.setRepositoryVersion(properties.get(CLUSTER_REPO_VERSION).toString());
-    }
-
     List<ConfigurationRequest> configRequests = 
getConfigurationRequests("Clusters", properties);
 
     ServiceConfigVersionRequest serviceConfigVersionRequest = 
getServiceConfigVersionRequest("Clusters", properties);
 
-    if (!configRequests.isEmpty())
+    if (!configRequests.isEmpty()) {
       cr.setDesiredConfig(configRequests);
+    }
 
     if (serviceConfigVersionRequest != null) {
       cr.setServiceConfigVersionRequest(serviceConfigVersionRequest);
@@ -447,7 +444,7 @@ public class ClusterResourceProvider extends 
AbstractControllerResourceProvider
    * @return the map of session attributes
    */
   private Map<String, Object> getSessionAttributes(Map<String, Object> 
properties) {
-    Map<String, Object> sessionAttributes = new HashMap<String, Object>();
+    Map<String, Object> sessionAttributes = new HashMap<>();
 
     for (Map.Entry<String, Object> entry : properties.entrySet()) {
 
@@ -475,11 +472,11 @@ public class ClusterResourceProvider extends 
AbstractControllerResourceProvider
         serviceConfigVersionRequest =
             (serviceConfigVersionRequest ==null ) ? new 
ServiceConfigVersionRequest() : serviceConfigVersionRequest;
 
-        if (propName.equals("service_name"))
+        if (propName.equals("service_name")) {
           
serviceConfigVersionRequest.setServiceName(entry.getValue().toString());
-        else if (propName.equals("service_config_version"))
+        } else if (propName.equals("service_config_version")) {
           
serviceConfigVersionRequest.setVersion(Long.valueOf(entry.getValue().toString()));
-        else if (propName.equals("service_config_version_note")) {
+        } else if (propName.equals("service_config_version_note")) {
           serviceConfigVersionRequest.setNote(entry.getValue().toString());
         }
       }

http://git-wip-us.apache.org/repos/asf/ambari/blob/15cd3d83/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
index 9137799..c02dcb0 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
@@ -224,7 +224,9 @@ public class ComponentResourceProvider extends 
AbstractControllerResourceProvide
       setResourceProperty(resource, COMPONENT_INIT_COUNT_PROPERTY_ID, 
response.getServiceComponentStateCount().get("initCount"), requestedIds);
       setResourceProperty(resource, COMPONENT_UNKNOWN_COUNT_PROPERTY_ID, 
response.getServiceComponentStateCount().get("unknownCount"), requestedIds);
       setResourceProperty(resource, COMPONENT_RECOVERY_ENABLED_ID, 
String.valueOf(response.isRecoveryEnabled()), requestedIds);
-
+      setResourceProperty(resource, COMPONENT_DESIRED_STACK, 
response.getDesiredStackId(), requestedIds);
+      setResourceProperty(resource, COMPONENT_DESIRED_VERSION, 
response.getDesiredVersion(), requestedIds);
+      setResourceProperty(resource, COMPONENT_REPOSITORY_STATE, 
response.getRepositoryState(), requestedIds);
       resources.add(resource);
     }
     return resources;
@@ -436,7 +438,6 @@ public class ComponentResourceProvider extends 
AbstractControllerResourceProvide
     return response;
   }
 
-  // Get the components for the given request.
   private Set<ServiceComponentResponse> getComponents(ServiceComponentRequest 
request) throws AmbariException {
 
     final AmbariMetaInfo ambariMetaInfo = 
getManagementController().getAmbariMetaInfo();
@@ -446,7 +447,6 @@ public class ComponentResourceProvider extends 
AbstractControllerResourceProvide
     Set<ServiceComponentResponse> response = new HashSet<>();
     String category = null;
 
-    StackId stackId = cluster.getDesiredStackVersion();
 
     if (request.getComponentName() != null) {
       setServiceNameIfAbsent(request, cluster, ambariMetaInfo);
@@ -455,6 +455,8 @@ public class ComponentResourceProvider extends 
AbstractControllerResourceProvide
       ServiceComponent sc = s.getServiceComponent(request.getComponentName());
       ServiceComponentResponse serviceComponentResponse = 
sc.convertToResponse();
 
+      StackId stackId = sc.getDesiredStackId();
+
       try {
         ComponentInfo componentInfo = 
ambariMetaInfo.getComponent(stackId.getStackName(),
             stackId.getStackVersion(), s.getName(), 
request.getComponentName());
@@ -486,6 +488,8 @@ public class ComponentResourceProvider extends 
AbstractControllerResourceProvide
           continue;
         }
 
+        StackId stackId = sc.getDesiredStackId();
+
         ServiceComponentResponse serviceComponentResponse = 
sc.convertToResponse();
         try {
           ComponentInfo componentInfo = 
ambariMetaInfo.getComponent(stackId.getStackName(),

http://git-wip-us.apache.org/repos/asf/ambari/blob/15cd3d83/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
index dcaaad9..b1f00e6 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
@@ -74,7 +74,6 @@ 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.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.Validate;
 
@@ -110,8 +109,8 @@ public class ServiceResourceProvider extends 
AbstractControllerResourceProvider
   public static final String SERVICE_DESIRED_STACK_PROPERTY_ID = 
PropertyHelper.getPropertyId(
       "ServiceInfo", "desired_stack");
 
-  public static final String SERVICE_DESIRED_REPO_VERSION_PROPERTY_ID = 
PropertyHelper.getPropertyId(
-      "ServiceInfo", "desired_repository_version");
+  public static final String SERVICE_DESIRED_REPO_VERSION_ID_PROPERTY_ID = 
PropertyHelper.getPropertyId(
+      "ServiceInfo", "desired_repository_version_id");
 
   protected static final String SERVICE_REPOSITORY_STATE = 
"ServiceInfo/repository_state";
 
@@ -145,7 +144,7 @@ public class ServiceResourceProvider extends 
AbstractControllerResourceProvider
     PROPERTY_IDS.add(SERVICE_CREDENTIAL_STORE_ENABLED_PROPERTY_ID);
     PROPERTY_IDS.add(SERVICE_ATTRIBUTES_PROPERTY_ID);
     PROPERTY_IDS.add(SERVICE_DESIRED_STACK_PROPERTY_ID);
-    PROPERTY_IDS.add(SERVICE_DESIRED_REPO_VERSION_PROPERTY_ID);
+    PROPERTY_IDS.add(SERVICE_DESIRED_REPO_VERSION_ID_PROPERTY_ID);
     PROPERTY_IDS.add(SERVICE_REPOSITORY_STATE);
 
     PROPERTY_IDS.add(QUERY_PARAMETERS_RUN_SMOKE_TEST_ID);
@@ -252,11 +251,17 @@ public class ServiceResourceProvider extends 
AbstractControllerResourceProvider
       setResourceProperty(resource, 
SERVICE_CREDENTIAL_STORE_ENABLED_PROPERTY_ID,
           String.valueOf(response.isCredentialStoreEnabled()), requestedIds);
 
-      setResourceProperty(resource, SERVICE_DESIRED_STACK_PROPERTY_ID,
-          response.getDesiredStackId(), requestedIds);
+      RepositoryVersionEntity repoVersion = repositoryVersionDAO.findByPK(
+          response.getDesiredRepositoryVersionId());
 
-      setResourceProperty(resource, SERVICE_DESIRED_REPO_VERSION_PROPERTY_ID,
-          response.getDesiredRepositoryVersion(), requestedIds);
+      // !!! TODO is the UI using this?
+      if (null != repoVersion) {
+        setResourceProperty(resource, SERVICE_DESIRED_STACK_PROPERTY_ID, 
repoVersion.getStackId(),
+            requestedIds);
+      }
+
+      setResourceProperty(resource, 
SERVICE_DESIRED_REPO_VERSION_ID_PROPERTY_ID,
+          response.getDesiredRepositoryVersionId(), requestedIds);
 
       setResourceProperty(resource, SERVICE_REPOSITORY_STATE,
           response.getRepositoryVersionState(), requestedIds);
@@ -382,13 +387,13 @@ public class ServiceResourceProvider extends 
AbstractControllerResourceProvider
    * @return the service request object
    */
   private ServiceRequest getRequest(Map<String, Object> properties) {
-    String desiredStack = 
(String)properties.get(SERVICE_DESIRED_STACK_PROPERTY_ID);
-    String desiredRepositoryVersion = 
(String)properties.get(SERVICE_DESIRED_REPO_VERSION_PROPERTY_ID);
+
+    String desiredRepoId = (String) 
properties.get(SERVICE_DESIRED_REPO_VERSION_ID_PROPERTY_ID);
 
     ServiceRequest svcRequest = new ServiceRequest(
         (String) properties.get(SERVICE_CLUSTER_NAME_PROPERTY_ID),
         (String) properties.get(SERVICE_SERVICE_NAME_PROPERTY_ID),
-        desiredStack, desiredRepositoryVersion,
+        null == desiredRepoId ? null : Long.valueOf(desiredRepoId),
         (String) properties.get(SERVICE_SERVICE_STATE_PROPERTY_ID),
         (String) properties.get(SERVICE_CREDENTIAL_STORE_ENABLED_PROPERTY_ID));
 
@@ -420,14 +425,10 @@ public class ServiceResourceProvider extends 
AbstractControllerResourceProvider
     for (ServiceRequest request : requests) {
       Cluster cluster = clusters.getCluster(request.getClusterName());
 
-      String desiredStack = request.getDesiredStack();
-
       RepositoryVersionEntity repositoryVersion = 
request.getResolvedRepository();
 
       if (null == repositoryVersion) {
-        throw new AmbariException(String.format("Could not find any 
repositories defined by %s", desiredStack));
-      } else {
-        desiredStack = repositoryVersion.getStackId().toString();
+        throw new AmbariException("Could not find any repository on the 
request.");
       }
 
       Service s = cluster.addService(request.getServiceName(), 
repositoryVersion);
@@ -1009,7 +1010,7 @@ public class ServiceResourceProvider extends 
AbstractControllerResourceProvider
   }
 
   private void validateCreateRequests(Set<ServiceRequest> requests, Clusters 
clusters)
-          throws AuthorizationException, AmbariException {
+      throws AuthorizationException, AmbariException {
 
     AmbariMetaInfo ambariMetaInfo = 
getManagementController().getAmbariMetaInfo();
     Map<String, Set<String>> serviceNames = new HashMap<>();
@@ -1022,10 +1023,12 @@ public class ServiceResourceProvider extends 
AbstractControllerResourceProvider
       Validate.notEmpty(serviceName, "Service name should be provided when 
creating a service");
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug("Received a createService request, clusterName={}, 
serviceName={}, request={}", clusterName, serviceName, request);
+        LOG.debug("Received a createService request, clusterName={}, 
serviceName={}, request={}",
+            clusterName, serviceName, request);
       }
 
-      if(!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, 
getClusterResourceId(clusterName), 
RoleAuthorization.SERVICE_ADD_DELETE_SERVICES)) {
+      if (!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, 
getClusterResourceId(clusterName),
+          RoleAuthorization.SERVICE_ADD_DELETE_SERVICES)) {
         throw new AuthorizationException("The user is not authorized to create 
services");
       }
 
@@ -1043,8 +1046,8 @@ public class ServiceResourceProvider extends 
AbstractControllerResourceProvider
       if (StringUtils.isNotEmpty(request.getDesiredState())) {
         State state = State.valueOf(request.getDesiredState());
         if (!state.isValidDesiredState() || state != State.INIT) {
-          throw new IllegalArgumentException("Invalid desired state"
-                  + " only INIT state allowed during creation"
+          throw new IllegalArgumentException(
+              "Invalid desired state" + " only INIT state allowed during 
creation"
                   + ", providedDesiredState=" + request.getDesiredState());
         }
       }
@@ -1053,7 +1056,8 @@ public class ServiceResourceProvider extends 
AbstractControllerResourceProvider
       try {
         cluster = clusters.getCluster(clusterName);
       } catch (ClusterNotFoundException e) {
-        throw new ParentObjectNotFoundException("Attempted to add a service to 
a cluster which doesn't exist", e);
+        throw new ParentObjectNotFoundException(
+            "Attempted to add a service to a cluster which doesn't exist", e);
       }
       try {
         Service s = cluster.getService(serviceName);
@@ -1066,40 +1070,28 @@ public class ServiceResourceProvider extends 
AbstractControllerResourceProvider
         // Expected
       }
 
-      String desiredStack = request.getDesiredStack();
-      StackId stackId = new StackId(desiredStack);
-
-      String desiredRepositoryVersion = request.getDesiredRepositoryVersion();
-      RepositoryVersionEntity repositoryVersion = null;
-      if (StringUtils.isNotBlank(desiredRepositoryVersion)){
-        repositoryVersion = 
repositoryVersionDAO.findByVersion(desiredRepositoryVersion);
+      Long desiredRepositoryVersion = request.getDesiredRepositoryVersionId();
+      if (null == desiredRepositoryVersion) {
+        throw new IllegalArgumentException(String.format("%s is required when 
adding a service.",
+            SERVICE_DESIRED_REPO_VERSION_ID_PROPERTY_ID));
       }
 
-      if (null == repositoryVersion) {
-        // !!! FIXME hack until the UI always sends the repository
-        if (null == desiredStack) {
-          desiredStack = cluster.getDesiredStackVersion().toString();
-        }
-
-        List<RepositoryVersionEntity> allVersions = 
repositoryVersionDAO.findByStack(new StackId(desiredStack));
-
-        if (CollectionUtils.isNotEmpty(allVersions)) {
-          repositoryVersion = allVersions.get(0);
-        }
-      }
+      RepositoryVersionEntity repositoryVersion = 
repositoryVersionDAO.findByPK(
+          desiredRepositoryVersion);
 
       if (null == repositoryVersion) {
-        throw new AmbariException(String.format("Could not find any 
repositories defined by %s", desiredStack));
-      } else {
-        stackId = repositoryVersion.getStackId();
+        throw new IllegalArgumentException(String.format(
+            "Could not find any repositories defined by %d", 
desiredRepositoryVersion));
       }
 
+      StackId stackId = repositoryVersion.getStackId();
+
       request.setResolvedRepository(repositoryVersion);
 
-      if (!ambariMetaInfo.isValidService(stackId.getStackName(),
-              stackId.getStackVersion(), request.getServiceName())) {
-        throw new IllegalArgumentException("Unsupported or invalid service in 
stack, clusterName=" + clusterName
-                + ", serviceName=" + serviceName + ", stackInfo=" + 
stackId.getStackId());
+      if (!ambariMetaInfo.isValidService(stackId.getStackName(), 
stackId.getStackVersion(),
+          request.getServiceName())) {
+        throw new IllegalArgumentException("Unsupported or invalid service in 
stack, clusterName="
+            + clusterName + ", serviceName=" + serviceName + ", stackInfo=" + 
stackId.getStackId());
       }
 
       // validate the credential store input provided
@@ -1109,25 +1101,25 @@ public class ServiceResourceProvider extends 
AbstractControllerResourceProvider
       if (StringUtils.isNotEmpty(request.getCredentialStoreEnabled())) {
         boolean credentialStoreEnabled = 
Boolean.parseBoolean(request.getCredentialStoreEnabled());
         if (!serviceInfo.isCredentialStoreSupported() && 
credentialStoreEnabled) {
-          throw new IllegalArgumentException("Invalid arguments, cannot enable 
credential store " +
-              "as it is not supported by the service. Service=" + 
request.getServiceName());
-        }
+          throw new IllegalArgumentException("Invalid arguments, cannot enable 
credential store "
+              + "as it is not supported by the service. Service=" + 
request.getServiceName());
+    }
       }
     }
     // ensure only a single cluster update
     if (serviceNames.size() != 1) {
-      throw new IllegalArgumentException("Invalid arguments, updates allowed"
-              + "on only one cluster at a time");
+      throw new IllegalArgumentException(
+          "Invalid arguments, updates allowed" + "on only one cluster at a 
time");
     }
 
     // Validate dups
     if (!duplicates.isEmpty()) {
       String clusterName = requests.iterator().next().getClusterName();
-      String msg = "Attempted to create a service which already exists: "
-              + ", clusterName=" + clusterName  + " serviceName=" + 
StringUtils.join(duplicates, ",");
+      String msg = "Attempted to create a service which already exists: " + ", 
clusterName="
+          + clusterName + " serviceName=" + StringUtils.join(duplicates, ",");
 
       throw new DuplicateResourceException(msg);
     }
 
-  }
+}
 }
\ No newline at end of file

Reply via email to