Browse Source

Merge branch 'trunk' into branch-alerts-dev

Conflicts:
	ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java
	ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
	ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java
	ambari-server/src/main/java/org/apache/ambari/server/utils/StageUtils.java
	ambari-server/src/test/java/org/apache/ambari/server/utils/TestStageUtils.java
Jonathan Hurley 11 years ago
parent
commit
ae8f1e77ea
100 changed files with 1815 additions and 607 deletions
  1. 0 7
      ambari-agent/conf/unix/install-helper.sh
  2. 10 1
      ambari-agent/pom.xml
  3. 0 3
      ambari-server/conf/unix/install-helper.sh
  4. 33 0
      ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionScheduler.java
  5. 30 2
      ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
  6. 3 1
      ambari-server/src/main/java/org/apache/ambari/server/actionmanager/StageFactory.java
  7. 1 1
      ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java
  8. 8 4
      ambari-server/src/main/java/org/apache/ambari/server/api/resources/RequestResourceDefinition.java
  9. 5 5
      ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceConfigVersionResourceDefinition.java
  10. 18 0
      ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
  11. 9 5
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelper.java
  12. 0 116
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelper.java.orig
  13. 73 0
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorResponse.java
  14. 3 2
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/GetComponentLayoutRecommnedationCommand.java
  15. 3 2
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/GetComponentLayoutValidationCommand.java
  16. 6 12
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/GetConfigurationRecommnedationCommand.java
  17. 3 2
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/GetConfigurationValidationCommand.java
  18. 27 3
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
  19. 2 36
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/recommendations/RecommendationResponse.java
  20. 2 13
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/validations/ValidationResponse.java
  21. 9 0
      ambari-server/src/main/java/org/apache/ambari/server/api/util/StackExtensionHelper.java
  22. 2 7
      ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java
  23. 12 22
      ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
  24. 105 79
      ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
  25. 15 13
      ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterRequest.java
  26. 6 3
      ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterResponse.java
  27. 9 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigGroupRequest.java
  28. 6 5
      ambari-server/src/main/java/org/apache/ambari/server/controller/HostRequest.java
  29. 23 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionRequest.java
  30. 11 2
      ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionResponse.java
  31. 29 4
      ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceComponentResponse.java
  32. 13 3
      ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java
  33. 61 31
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractResourceProvider.java
  34. 25 12
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BaseBlueprintProcessor.java
  35. 3 2
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java
  36. 92 34
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
  37. 4 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigGroupResourceProvider.java
  38. 27 27
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
  39. 2 2
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RecommendationResourceProvider.java
  40. 7 5
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceConfigVersionResourceProvider.java
  41. 9 13
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackServiceComponentResourceProvider.java
  42. 9 13
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackServiceResourceProvider.java
  43. 2 2
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ValidationResourceProvider.java
  44. 8 1
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java
  45. 3 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewVersionResourceProvider.java
  46. 40 1
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceConfigDAO.java
  47. 53 21
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java
  48. 28 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StageEntity.java
  49. 31 8
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java
  50. 2 1
      ambari-server/src/main/java/org/apache/ambari/server/stageplanner/RoleGraph.java
  51. 8 7
      ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
  52. 11 3
      ambari-server/src/main/java/org/apache/ambari/server/state/ComponentInfo.java
  53. 8 7
      ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
  54. 9 0
      ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
  55. 90 29
      ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
  56. 2 1
      ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
  57. 15 4
      ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java
  58. 9 4
      ambari-server/src/main/java/org/apache/ambari/server/utils/StageUtils.java
  59. 15 0
      ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
  60. 14 0
      ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
  61. 3 2
      ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
  62. 3 2
      ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
  63. 3 2
      ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
  64. 3 2
      ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
  65. 4 3
      ambari-server/src/main/resources/custom_actions/check_host.py
  66. 5 2
      ambari-server/src/main/resources/properties.json
  67. 2 3
      ambari-server/src/main/resources/scripts/stack_advisor.py
  68. 2 1
      ambari-server/src/main/resources/stacks/HDP/1.3.2/hooks/before-ANY/scripts/params.py
  69. 1 1
      ambari-server/src/main/resources/stacks/HDP/1.3.2/hooks/before-INSTALL/scripts/params.py
  70. 3 0
      ambari-server/src/main/resources/stacks/HDP/1.3.2/services/GANGLIA/metainfo.xml
  71. 4 0
      ambari-server/src/main/resources/stacks/HDP/1.3.2/services/HBASE/metainfo.xml
  72. 5 0
      ambari-server/src/main/resources/stacks/HDP/1.3.2/services/HDFS/metainfo.xml
  73. 10 1
      ambari-server/src/main/resources/stacks/HDP/1.3.2/services/HIVE/metainfo.xml
  74. 1 1
      ambari-server/src/main/resources/stacks/HDP/1.3.2/services/HIVE/package/scripts/params.py
  75. 5 0
      ambari-server/src/main/resources/stacks/HDP/1.3.2/services/MAPREDUCE/metainfo.xml
  76. 2 0
      ambari-server/src/main/resources/stacks/HDP/1.3.2/services/NAGIOS/metainfo.xml
  77. 3 0
      ambari-server/src/main/resources/stacks/HDP/1.3.2/services/OOZIE/metainfo.xml
  78. 2 0
      ambari-server/src/main/resources/stacks/HDP/1.3.2/services/PIG/metainfo.xml
  79. 2 0
      ambari-server/src/main/resources/stacks/HDP/1.3.2/services/SQOOP/metainfo.xml
  80. 3 1
      ambari-server/src/main/resources/stacks/HDP/1.3.2/services/WEBHCAT/metainfo.xml
  81. 3 0
      ambari-server/src/main/resources/stacks/HDP/1.3.2/services/ZOOKEEPER/metainfo.xml
  82. 519 0
      ambari-server/src/main/resources/stacks/HDP/1.3.2/services/stack_advisor.py
  83. 25 0
      ambari-server/src/main/resources/stacks/HDP/1.3.3/services/stack_advisor.py
  84. 25 0
      ambari-server/src/main/resources/stacks/HDP/1.3/services/stack_advisor.py
  85. 2 1
      ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-ANY/scripts/params.py
  86. 1 1
      ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-INSTALL/scripts/params.py
  87. 2 0
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/FLUME/metainfo.xml
  88. 3 0
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/GANGLIA/metainfo.xml
  89. 4 0
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HBASE/metainfo.xml
  90. 7 0
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HDFS/metainfo.xml
  91. 10 1
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HIVE/metainfo.xml
  92. 1 1
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HIVE/package/scripts/params.py
  93. 2 0
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/NAGIOS/metainfo.xml
  94. 3 0
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/OOZIE/metainfo.xml
  95. 2 0
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/PIG/metainfo.xml
  96. 2 0
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/SQOOP/metainfo.xml
  97. 3 1
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/WEBHCAT/metainfo.xml
  98. 7 0
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/YARN/metainfo.xml
  99. 2 0
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/ZOOKEEPER/metainfo.xml
  100. 63 0
      ambari-server/src/main/resources/stacks/HDP/2.1.GlusterFS/services/FALCON/configuration/falcon-env.xml

+ 0 - 7
ambari-agent/conf/unix/install-helper.sh

@@ -51,13 +51,6 @@ do_install(){
 }
 
 do_remove(){
-  if [ -d "$COMMON_DIR" ]; then  # common dir exists
-    rm -f "$COMMON_DIR"
-  fi
-
-  if [ -d "$RESOURCE_MANAGEMENT_DIR" ]; then  # resource_management dir exists
-    rm -f "$RESOURCE_MANAGEMENT_DIR"
-  fi
 
   if [ -f "$PYTHON_WRAPER_TARGET" ]; then
     rm -f "$PYTHON_WRAPER_TARGET"

+ 10 - 1
ambari-agent/pom.xml

@@ -49,6 +49,7 @@
     <ambari.server.module>../ambari-server</ambari.server.module>
     <target.cache.dir>${project.build.directory}/cache/</target.cache.dir>
     <resource.keeper.script>${ambari.server.module}/src/main/python/ambari_server/resourceFilesKeeper.py</resource.keeper.script>
+    <init.d.dir>/etc/rc.d/init.d</init.d.dir>
   </properties>
   <build>
     <plugins>
@@ -349,7 +350,7 @@
               <groupname>root</groupname>
             </mapping>
             <mapping>
-              <directory>/etc/rc.d/init.d</directory>
+              <directory>${init.d.dir}</directory>
               <filemode>755</filemode>
               <username>root</username>
               <groupname>root</groupname>
@@ -667,4 +668,12 @@
       </extension>
     </extensions>
   </build>
+  <profiles>
+    <profile>
+      <id>suse11</id>
+      <properties>
+        <init.d.dir>/etc/init.d</init.d.dir>
+      </properties>
+    </profile>
+  </profiles>
 </project>

+ 0 - 3
ambari-server/conf/unix/install-helper.sh

@@ -51,9 +51,6 @@ do_install(){
 
 do_remove(){
 
-  rm -rf "$COMMON_DIR"
-  rm -rf "$RESOURCE_MANAGEMENT_DIR"
-
   if [ -f "$PYTHON_WRAPER_TARGET" ]; then
     rm -f "$PYTHON_WRAPER_TARGET"
   fi

+ 33 - 0
ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionScheduler.java

@@ -121,6 +121,8 @@ class ActionScheduler implements Runnable {
   private boolean activeAwakeRequest = false;
   //Cache for clusterHostinfo, key - stageId-requestId
   private Cache<String, Map<String, Set<String>>> clusterHostInfoCache;
+  private Cache<String, Map<String, String>> commandParamsStageCache;
+  private Cache<String, Map<String, String>> hostParamsStageCache;
 
   public ActionScheduler(long sleepTimeMilliSec, long actionTimeoutMilliSec,
       ActionDBAccessor db, ActionQueue actionQueue, Clusters fsmObject,
@@ -138,6 +140,12 @@ class ActionScheduler implements Runnable {
     this.clusterHostInfoCache = CacheBuilder.newBuilder().
         expireAfterAccess(5, TimeUnit.MINUTES).
         build();
+    this.commandParamsStageCache = CacheBuilder.newBuilder().
+      expireAfterAccess(5, TimeUnit.MINUTES).
+      build();
+    this.hostParamsStageCache = CacheBuilder.newBuilder().
+      expireAfterAccess(5, TimeUnit.MINUTES).
+      build();
     this.configuration = configuration;
   }
 
@@ -748,6 +756,31 @@ class ActionScheduler implements Runnable {
     }
 
     cmd.setClusterHostInfo(clusterHostInfo);
+ 
+    //Try to get commandParams from cache and merge them with command-level parameters
+    Map<String, String> commandParams = commandParamsStageCache.getIfPresent(stagePk);
+
+    if (commandParams == null){
+      Type type = new TypeToken<Map<String, String>>() {}.getType();
+      commandParams = StageUtils.getGson().fromJson(s.getCommandParamsStage(), type);
+      commandParamsStageCache.put(stagePk, commandParams);
+    }
+    Map<String, String> commandParamsCmd = cmd.getCommandParams();
+    commandParamsCmd.putAll(commandParams);
+    cmd.setCommandParams(commandParamsCmd);
+
+
+    //Try to get hostParams from cache and merge them with command-level parameters
+    Map<String, String> hostParams = hostParamsStageCache.getIfPresent(stagePk);
+    if (hostParams == null) {
+      Type type = new TypeToken<Map<String, String>>() {}.getType();
+      hostParams = StageUtils.getGson().fromJson(s.getHostParamsStage(), type);
+      hostParamsStageCache.put(stagePk, hostParams);
+    }
+    Map<String, String> hostParamsCmd = cmd.getHostLevelParams();
+    hostParamsCmd.putAll(hostParams);
+    cmd.setHostLevelParams(hostParamsCmd);
+
 
     commandsToUpdate.add(cmd);
   }

+ 30 - 2
ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java

@@ -39,7 +39,6 @@ import org.apache.ambari.server.orm.entities.StageEntity;
 import org.apache.ambari.server.serveraction.ServerAction;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.ServiceComponentHostEvent;
-import org.apache.ambari.server.state.fsm.event.Event;
 import org.apache.ambari.server.state.svccomphost.ServiceComponentHostUpgradeEvent;
 import org.apache.ambari.server.utils.StageUtils;
 import org.apache.commons.lang.StringUtils;
@@ -63,6 +62,8 @@ public class Stage {
   private final String logDir;
   private final String requestContext;
   private String clusterHostInfo;
+  private String commandParamsStage;
+  private String hostParamsStage;
 
   private int stageTimeout = -1;
 
@@ -83,7 +84,9 @@ public class Stage {
       @Assisted("clusterName") @Nullable String clusterName,
       @Assisted("clusterId") long clusterId,
       @Assisted("requestContext") @Nullable String requestContext,
-      @Assisted("clusterHostInfo") String clusterHostInfo) {
+      @Assisted("clusterHostInfo") String clusterHostInfo,
+      @Assisted("commandParamsStage") String commandParamsStage,
+      @Assisted("hostParamsStage") String hostParamsStage) {
     this.wrappersLoaded = true;
     this.requestId = requestId;
     this.logDir = logDir;
@@ -91,6 +94,8 @@ public class Stage {
     this.clusterId = clusterId;
     this.requestContext = requestContext == null ? "" : requestContext;
     this.clusterHostInfo = clusterHostInfo;
+    this.commandParamsStage = commandParamsStage;
+    this.hostParamsStage = hostParamsStage;
   }
 
   @AssistedInject
@@ -113,6 +118,8 @@ public class Stage {
     
     requestContext = stageEntity.getRequestContext();
     clusterHostInfo = stageEntity.getClusterHostInfo();
+    commandParamsStage = stageEntity.getCommandParamsStage();
+    hostParamsStage = stageEntity.getHostParamsStage();
 
 
     List<Long> taskIds = hostRoleCommandDAO.findTaskIdsByStage(requestId, stageId);
@@ -147,6 +154,8 @@ public class Stage {
     stageEntity.setHostRoleCommands(new ArrayList<HostRoleCommandEntity>());
     stageEntity.setRoleSuccessCriterias(new ArrayList<RoleSuccessCriteriaEntity>());
     stageEntity.setClusterHostInfo(clusterHostInfo);
+    stageEntity.setCommandParamsStage(commandParamsStage);
+    stageEntity.setHostParamsStage(hostParamsStage);
 
     for (Role role : successFactors.keySet()) {
       RoleSuccessCriteriaEntity roleSuccessCriteriaEntity = new RoleSuccessCriteriaEntity();
@@ -198,6 +207,23 @@ public class Stage {
   public void setClusterHostInfo(String clusterHostInfo) {
     this.clusterHostInfo = clusterHostInfo;
   }
+ 
+  public String getCommandParamsStage() {
+    return commandParamsStage;
+  }
+
+  public void setCommandParamsStage(String commandParamsStage) {
+    this.commandParamsStage = commandParamsStage;
+  }
+
+  public String getHostParamsStage() {
+    return hostParamsStage;
+  }
+
+  public void setHostParamsStage(String hostParamsStage) {
+    this.hostParamsStage = hostParamsStage;
+  }
+
 
   public synchronized void setStageId(long stageId) {
     if (this.stageId != -1) {
@@ -539,6 +565,8 @@ public class Stage {
     builder.append("logDir=" + logDir+"\n");
     builder.append("requestContext="+requestContext+"\n");
     builder.append("clusterHostInfo="+clusterHostInfo+"\n");
+    builder.append("commandParamsStage="+commandParamsStage+"\n");
+    builder.append("hostParamsStage="+hostParamsStage+"\n");
     builder.append("Success Factors:\n");
     for (Role r : successFactors.keySet()) {
       builder.append("  role: "+r+", factor: "+successFactors.get(r)+"\n");

+ 3 - 1
ambari-server/src/main/java/org/apache/ambari/server/actionmanager/StageFactory.java

@@ -29,7 +29,9 @@ public interface StageFactory {
       @Assisted("clusterName") String clusterName,
       @Assisted("clusterId") long clusterId,
       @Assisted("requestContext") String requestContext,
-      @Assisted("clusterHostInfo") String clusterHostInfo);
+      @Assisted("clusterHostInfo") String clusterHostInfo,
+      @Assisted("commandParamsStage") String commandParamsStage,
+      @Assisted("hostParamsStage") String hostParamsStage);
 
   Stage createExisting(StageEntity stageEntity);
 }

+ 1 - 1
ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java

@@ -83,7 +83,7 @@ public class ExecutionCommand extends AgentCommand {
   private Set<String> forceRefreshConfigTags = new HashSet<String>();
 
   @SerializedName("commandParams")
-  private Map<String, String> commandParams;
+  private Map<String, String> commandParams = new HashMap<String, String>();
 
   @SerializedName("serviceName")
   private String serviceName;

+ 8 - 4
ambari-server/src/main/java/org/apache/ambari/server/api/resources/RequestResourceDefinition.java

@@ -83,15 +83,19 @@ public class RequestResourceDefinition extends BaseResourceDefinition {
         sb.append(href);
         sb.append('/').append(requestId);
       } else {
-        // split the href up into its parts, intercepting "clusers" in order
+        // split the href up into its parts, intercepting "clusters" in order
         // to rewrite the href to be scoped for requests
         String[] tokens = href.split("/");
 
-        for (int i = 0; i < tokens.length; ++i) {
+        Integer tokenCount = tokens.length;
+        for (int i = 0; i < tokenCount; ++i) {
           String fragment = tokens[i];
-          sb.append(fragment).append('/');
+          sb.append(fragment);
+          if (i < tokenCount - 1 ) {
+            sb.append('/');
+          }
 
-          if ("clusters".equals(fragment) && i + 1 < tokens.length) {
+          if ("clusters".equals(fragment) && i + 1 < tokenCount) {
             String clusterName = tokens[i + 1];
             sb.append(clusterName).append("/");
             sb.append("requests/").append(requestId);

+ 5 - 5
ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceConfigVersionResourceDefinition.java

@@ -43,12 +43,12 @@ public class ServiceConfigVersionResourceDefinition extends BaseResourceDefiniti
 
   @Override
   public String getPluralName() {
-    return "serviceconfigversions";
+    return "service_config_versions";
   }
 
   @Override
   public String getSingularName() {
-    return "serviceconfigversion";
+    return "service_config_version";
   }
 
   private class HrefProcessor extends BaseHrefPostProcessor {
@@ -66,10 +66,10 @@ public class ServiceConfigVersionResourceDefinition extends BaseResourceDefiniti
         idx = href.indexOf("/", idx) + 1;
 
         String serviceName = (String) resultNode.getObject().getPropertyValue("service_name");
-        Long version = (Long) resultNode.getObject().getPropertyValue("serviceconfigversion");
+        Long version = (Long) resultNode.getObject().getPropertyValue("service_config_version");
         href = href.substring(0, idx)
-            + "configurations/serviceconfigversions?service_name="
-            + serviceName + "&serviceconfigversion=" + version;
+            + "configurations/service_config_versions?service_name="
+            + serviceName + "&service_config_version=" + version;
 
         resultNode.setProperty("href", href);
       } else {

+ 18 - 0
ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java

@@ -677,6 +677,24 @@ public class AmbariMetaInfo {
     return stackInfoResult;
   }
 
+  public List<String> getStackParentVersions(String stackName, String version) {
+    List<String> parents = new ArrayList<String>();
+    try {
+      StackInfo stackInfo = getStackInfo(stackName, version);
+      if (stackInfo != null) {
+        String parentVersion = stackInfo.getParentStackVersion();
+        if (parentVersion != null) {
+          parents.add(parentVersion);
+          parents.addAll(getStackParentVersions(stackName, parentVersion));
+        }
+      }
+    } catch (AmbariException e) {
+      // parent was not found. just returning empty list
+    } finally {
+      return parents;
+    }
+  }
+
   public Set<PropertyInfo> getProperties(String stackName, String version, String serviceName)
       throws AmbariException {
 

+ 9 - 5
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelper.java

@@ -21,6 +21,7 @@ package org.apache.ambari.server.api.services.stackadvisor;
 import java.io.File;
 import java.io.IOException;
 
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest.StackAdvisorRequestType;
 import org.apache.ambari.server.api.services.stackadvisor.commands.GetComponentLayoutRecommnedationCommand;
 import org.apache.ambari.server.api.services.stackadvisor.commands.GetComponentLayoutValidationCommand;
@@ -39,16 +40,19 @@ public class StackAdvisorHelper {
 
   private File recommendationsDir;
   private String stackAdvisorScript;
+  private final AmbariMetaInfo metaInfo;
 
   /* Monotonically increasing requestid */
   private int requestId = 0;
   private StackAdvisorRunner saRunner;
 
   @Inject
-  public StackAdvisorHelper(Configuration conf, StackAdvisorRunner saRunner) throws IOException {
+  public StackAdvisorHelper(Configuration conf, StackAdvisorRunner saRunner,
+                            AmbariMetaInfo metaInfo) throws IOException {
     this.recommendationsDir = conf.getRecommendationsDir();
     this.stackAdvisorScript = conf.getStackAdvisorScript();
     this.saRunner = saRunner;
+    this.metaInfo = metaInfo;
   }
 
   /**
@@ -74,10 +78,10 @@ public class StackAdvisorHelper {
     StackAdvisorCommand<ValidationResponse> command;
     if (requestType == StackAdvisorRequestType.HOST_GROUPS) {
       command = new GetComponentLayoutValidationCommand(recommendationsDir, stackAdvisorScript,
-          requestId, saRunner);
+          requestId, saRunner, metaInfo);
     } else if (requestType == StackAdvisorRequestType.CONFIGURATIONS) {
       command = new GetConfigurationValidationCommand(recommendationsDir, stackAdvisorScript,
-          requestId, saRunner);
+          requestId, saRunner, metaInfo);
     } else {
       throw new StackAdvisorException(String.format("Unsupported request type, type=%s",
           requestType));
@@ -109,10 +113,10 @@ public class StackAdvisorHelper {
     StackAdvisorCommand<RecommendationResponse> command;
     if (requestType == StackAdvisorRequestType.HOST_GROUPS) {
       command = new GetComponentLayoutRecommnedationCommand(recommendationsDir, stackAdvisorScript,
-          requestId, saRunner);
+          requestId, saRunner, metaInfo);
     } else if (requestType == StackAdvisorRequestType.CONFIGURATIONS) {
       command = new GetConfigurationRecommnedationCommand(recommendationsDir, stackAdvisorScript,
-          requestId, saRunner);
+          requestId, saRunner, metaInfo);
     } else {
       throw new StackAdvisorException(String.format("Unsupported request type, type=%s",
           requestType));

+ 0 - 116
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelper.java.orig

@@ -1,116 +0,0 @@
-/**
- * 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.api.services.stackadvisor;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest.StackAdvisorRequestType;
-import org.apache.ambari.server.api.services.stackadvisor.commands.GetComponentLayoutRecommnedationCommand;
-import org.apache.ambari.server.api.services.stackadvisor.commands.GetComponentLayoutValidationCommand;
-import org.apache.ambari.server.api.services.stackadvisor.commands.StackAdvisorCommand;
-import org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse;
-import org.apache.ambari.server.api.services.stackadvisor.validations.ValidationResponse;
-import org.apache.ambari.server.configuration.Configuration;
-
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-
-@Singleton
-public class StackAdvisorHelper {
-
-  private File recommendationsDir;
-  private String stackAdvisorScript;
-
-  /* Monotonically increasing requestid */
-  private int requestId = 0;
-  private StackAdvisorRunner saRunner;
-
-  @Inject
-  public StackAdvisorHelper(Configuration conf, StackAdvisorRunner saRunner) throws IOException {
-    this.recommendationsDir = conf.getRecommendationsDir();
-    this.stackAdvisorScript = conf.getStackAdvisorScript();
-    this.saRunner = saRunner;
-  }
-
-  /**
-   * Returns validation (component-layout or configurations) result for the
-   * request.
-   * 
-   * @param validationRequest the validation request
-   * @return {@link ValidationResponse} instance
-   * @throws StackAdvisorException in case of stack advisor script errors
-   */
-  public synchronized ValidationResponse validate(StackAdvisorRequest request)
-      throws StackAdvisorException {
-    requestId += 1;
-
-    StackAdvisorCommand<ValidationResponse> command = createValidationCommand(request
-        .getRequestType());
-
-    return command.invoke(request);
-  }
-
-  StackAdvisorCommand<ValidationResponse> createValidationCommand(
-      StackAdvisorRequestType requestType) throws StackAdvisorException {
-    StackAdvisorCommand<ValidationResponse> command;
-    if (requestType == StackAdvisorRequestType.HOST_GROUPS) {
-      command = new GetComponentLayoutValidationCommand(recommendationsDir, stackAdvisorScript,
-          requestId, saRunner);
-    } else {
-      throw new StackAdvisorException(String.format("Unsupported request type, type=%s",
-          requestType));
-    }
-
-    return command;
-  }
-
-  /**
-   * Returns recommendation (component-layout or configurations) based on the
-   * request.
-   * 
-   * @param request the recommendation request
-   * @return {@link RecommendationResponse} instance
-   * @throws StackAdvisorException in case of stack advisor script errors
-   */
-  public synchronized RecommendationResponse recommend(StackAdvisorRequest request)
-      throws StackAdvisorException {
-    requestId += 1;
-
-    StackAdvisorCommand<RecommendationResponse> command = createRecommendationCommand(request
-        .getRequestType());
-
-    return command.invoke(request);
-  }
-
-  StackAdvisorCommand<RecommendationResponse> createRecommendationCommand(
-      StackAdvisorRequestType requestType) throws StackAdvisorException {
-    StackAdvisorCommand<RecommendationResponse> command;
-    if (requestType == StackAdvisorRequestType.HOST_GROUPS) {
-      command = new GetComponentLayoutRecommnedationCommand(recommendationsDir, stackAdvisorScript,
-          requestId, saRunner);
-    } else {
-      throw new StackAdvisorException(String.format("Unsupported request type, type=%s",
-          requestType));
-    }
-
-    return command;
-  }
-
-}

+ 73 - 0
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorResponse.java

@@ -0,0 +1,73 @@
+/**
+ * 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.api.services.stackadvisor;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * Abstract stack advisor response POJO.
+ */
+public abstract class StackAdvisorResponse {
+
+  private int id;
+
+  @JsonProperty("Versions")
+  private Version version;
+
+  public int getId() {
+    return id;
+  }
+
+  public void setId(int id) {
+    this.id = id;
+  }
+
+  public Version getVersion() {
+    return version;
+  }
+
+  public void setVersion(Version version) {
+    this.version = version;
+  }
+
+  public static class Version {
+    @JsonProperty("stack_name")
+    private String stackName;
+
+    @JsonProperty("stack_version")
+    private String stackVersion;
+
+    public String getStackName() {
+      return stackName;
+    }
+
+    public void setStackName(String stackName) {
+      this.stackName = stackName;
+    }
+
+    public String getStackVersion() {
+      return stackVersion;
+    }
+
+    public void setStackVersion(String stackVersion) {
+      this.stackVersion = stackVersion;
+    }
+  }
+
+}

+ 3 - 2
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/GetComponentLayoutRecommnedationCommand.java

@@ -20,6 +20,7 @@ package org.apache.ambari.server.api.services.stackadvisor.commands;
 
 import java.io.File;
 
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorException;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
@@ -33,8 +34,8 @@ public class GetComponentLayoutRecommnedationCommand extends
     StackAdvisorCommand<RecommendationResponse> {
 
   public GetComponentLayoutRecommnedationCommand(File recommendationsDir,
-      String stackAdvisorScript, int requestId, StackAdvisorRunner saRunner) {
-    super(recommendationsDir, stackAdvisorScript, requestId, saRunner);
+      String stackAdvisorScript, int requestId, StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
+    super(recommendationsDir, stackAdvisorScript, requestId, saRunner, metaInfo);
   }
 
   @Override

+ 3 - 2
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/GetComponentLayoutValidationCommand.java

@@ -20,6 +20,7 @@ package org.apache.ambari.server.api.services.stackadvisor.commands;
 
 import java.io.File;
 
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorException;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
@@ -31,8 +32,8 @@ import org.apache.ambari.server.api.services.stackadvisor.validations.Validation
 public class GetComponentLayoutValidationCommand extends StackAdvisorCommand<ValidationResponse> {
 
   public GetComponentLayoutValidationCommand(File recommendationsDir, String stackAdvisorScript,
-      int requestId, StackAdvisorRunner saRunner) {
-    super(recommendationsDir, stackAdvisorScript, requestId, saRunner);
+      int requestId, StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
+    super(recommendationsDir, stackAdvisorScript, requestId, saRunner, metaInfo);
   }
 
   @Override

+ 6 - 12
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/GetConfigurationRecommnedationCommand.java

@@ -18,6 +18,7 @@
 
 package org.apache.ambari.server.api.services.stackadvisor.commands;
 
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorException;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
@@ -37,9 +38,9 @@ import java.util.Set;
 public class GetConfigurationRecommnedationCommand extends
     StackAdvisorCommand<RecommendationResponse> {
 
-  public GetConfigurationRecommnedationCommand(File recommendationsDir,
-                                               String stackAdvisorScript, int requestId, StackAdvisorRunner saRunner) {
-    super(recommendationsDir, stackAdvisorScript, requestId, saRunner);
+  public GetConfigurationRecommnedationCommand(File recommendationsDir, String stackAdvisorScript, int requestId,
+                                               StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
+    super(recommendationsDir, stackAdvisorScript, requestId, saRunner, metaInfo);
   }
 
   @Override
@@ -55,12 +56,6 @@ public class GetConfigurationRecommnedationCommand extends
     }
   }
 
-  @Override
-  protected StackAdvisorData adjust(StackAdvisorData data, StackAdvisorRequest request) {
-    // do nothing
-    return data;
-  }
-
   @Override
   protected RecommendationResponse updateResponse(StackAdvisorRequest request, RecommendationResponse response) {
     response.getRecommendations().getBlueprint().setHostGroups(processHostGroups(request));
@@ -68,10 +63,9 @@ public class GetConfigurationRecommnedationCommand extends
     return response;
   }
 
-  private Set<HostGroup> processHostGroups(StackAdvisorRequest request) {
-
+  protected Set<HostGroup> processHostGroups(StackAdvisorRequest request) {
     Set<HostGroup> resultSet = new HashSet<HostGroup>();
-    for (Map.Entry<String, Set<String>> componentHost : request.getComponentHostsMap().entrySet()) {
+    for (Map.Entry<String, Set<String>> componentHost : request.getHostComponents().entrySet()) {
       String hostGroupName = componentHost.getKey();
       Set<String> components = componentHost.getValue();
       if (hostGroupName != null && components != null) {

+ 3 - 2
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/GetConfigurationValidationCommand.java

@@ -20,6 +20,7 @@ package org.apache.ambari.server.api.services.stackadvisor.commands;
 
 import java.io.File;
 
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorException;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
@@ -31,8 +32,8 @@ import org.apache.ambari.server.api.services.stackadvisor.validations.Validation
 public class GetConfigurationValidationCommand extends StackAdvisorCommand<ValidationResponse> {
 
   public GetConfigurationValidationCommand(File recommendationsDir, String stackAdvisorScript,
-      int requestId, StackAdvisorRunner saRunner) {
-    super(recommendationsDir, stackAdvisorScript, requestId, saRunner);
+      int requestId, StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
+    super(recommendationsDir, stackAdvisorScript, requestId, saRunner, metaInfo);
   }
 
   @Override

+ 27 - 3
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java

@@ -35,12 +35,14 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 
 import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.api.services.BaseService;
 import org.apache.ambari.server.api.services.LocalUriInfo;
 import org.apache.ambari.server.api.services.Request;
 import org.apache.ambari.server.api.services.StacksService.StackUriInfo;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorException;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
+import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorResponse;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.commons.collections.CollectionUtils;
@@ -52,11 +54,12 @@ import org.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jackson.map.SerializationConfig;
 import org.codehaus.jackson.node.ArrayNode;
 import org.codehaus.jackson.node.ObjectNode;
+import org.codehaus.jackson.node.TextNode;
 
 /**
  * Parent for all commands.
  */
-public abstract class StackAdvisorCommand<T> extends BaseService {
+public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extends BaseService {
 
   /**
    * Type of response object provided by extending classes when
@@ -89,9 +92,11 @@ public abstract class StackAdvisorCommand<T> extends BaseService {
 
   protected ObjectMapper mapper;
 
+  private final AmbariMetaInfo metaInfo;
+
   @SuppressWarnings("unchecked")
   public StackAdvisorCommand(File recommendationsDir, String stackAdvisorScript, int requestId,
-      StackAdvisorRunner saRunner) {
+      StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
     this.type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
         .getActualTypeArguments()[0];
 
@@ -102,6 +107,7 @@ public abstract class StackAdvisorCommand<T> extends BaseService {
     this.stackAdvisorScript = stackAdvisorScript;
     this.requestId = requestId;
     this.saRunner = saRunner;
+    this.metaInfo = metaInfo;
   }
 
   protected abstract StackAdvisorCommandType getCommandType();
@@ -133,6 +139,7 @@ public abstract class StackAdvisorCommand<T> extends BaseService {
     try {
       ObjectNode root = (ObjectNode) this.mapper.readTree(data.servicesJSON);
 
+      populateStackHierarchy(root);
       populateComponentHostsMap(root, request.getComponentHostsMap());
       populateConfigurations(root, request.getConfigurations());
 
@@ -166,6 +173,18 @@ public abstract class StackAdvisorCommand<T> extends BaseService {
     }
   }
 
+  protected void populateStackHierarchy(ObjectNode root) {
+    ObjectNode version = (ObjectNode) root.get("Versions");
+    TextNode stackName = (TextNode) version.get("stack_name");
+    TextNode stackVersion = (TextNode) version.get("stack_version");
+    ObjectNode stackHierarchy = version.putObject("stack_hierarchy");
+    stackHierarchy.put("stack_name", stackName);
+    ArrayNode parents = stackHierarchy.putArray("stack_versions");
+    for (String parentVersion : metaInfo.getStackParentVersions(stackName.asText(), stackVersion.asText())) {
+      parents.add(parentVersion);
+    }
+  }
+
   private void populateComponentHostsMap(ObjectNode root, Map<String, Set<String>> componentHostsMap) {
     ArrayNode services = (ArrayNode) root.get(SERVICES_PROPETRY);
     Iterator<JsonNode> servicesIter = services.getElements();
@@ -215,7 +234,7 @@ public abstract class StackAdvisorCommand<T> extends BaseService {
       String result = FileUtils.readFileToString(new File(requestDirectory, getResultFileName()));
 
       T response = this.mapper.readValue(result, this.type);
-      return updateResponse(request, response);
+      return updateResponse(request, setRequestId(response));
     } catch (Exception e) {
       String message = "Error occured during stack advisor command invocation";
       LOG.warn(message, e);
@@ -225,6 +244,11 @@ public abstract class StackAdvisorCommand<T> extends BaseService {
 
   protected abstract T updateResponse(StackAdvisorRequest request, T response);
 
+  private T setRequestId(T response) {
+    response.setId(requestId);
+    return response;
+  }
+
   /**
    * Create request id directory for each call
    */

+ 2 - 36
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/recommendations/RecommendationResponse.java

@@ -21,15 +21,13 @@ package org.apache.ambari.server.api.services.stackadvisor.recommendations;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorResponse;
 import org.codehaus.jackson.annotate.JsonProperty;
 
 /**
  * Recommendation response POJO.
  */
-public class RecommendationResponse {
-
-  @JsonProperty("Versions")
-  private Version version;
+public class RecommendationResponse extends StackAdvisorResponse {
 
   @JsonProperty
   private Set<String> hosts;
@@ -40,14 +38,6 @@ public class RecommendationResponse {
   @JsonProperty
   private Recommendation recommendations;
 
-  public Version getVersion() {
-    return version;
-  }
-
-  public void setVersion(Version version) {
-    this.version = version;
-  }
-
   public Set<String> getHosts() {
     return hosts;
   }
@@ -72,30 +62,6 @@ public class RecommendationResponse {
     this.recommendations = recommendations;
   }
 
-  public static class Version {
-    @JsonProperty("stack_name")
-    private String stackName;
-
-    @JsonProperty("stack_version")
-    private String stackVersion;
-
-    public String getStackName() {
-      return stackName;
-    }
-
-    public void setStackName(String stackName) {
-      this.stackName = stackName;
-    }
-
-    public String getStackVersion() {
-      return stackVersion;
-    }
-
-    public void setStackVersion(String stackVersion) {
-      this.stackVersion = stackVersion;
-    }
-  }
-
   public static class Recommendation {
     @JsonProperty
     private Blueprint blueprint;

+ 2 - 13
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/validations/ValidationResponse.java

@@ -20,28 +20,17 @@ package org.apache.ambari.server.api.services.stackadvisor.validations;
 
 import java.util.Set;
 
-import org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse.Version;
+import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorResponse;
 import org.codehaus.jackson.annotate.JsonProperty;
 
 /**
  * Validation response POJO.
  */
-public class ValidationResponse {
-
-  @JsonProperty("Versions")
-  private Version version;
+public class ValidationResponse extends StackAdvisorResponse {
 
   @JsonProperty
   private Set<ValidationItem> items;
 
-  public Version getVersion() {
-    return version;
-  }
-
-  public void setVersion(Version version) {
-    this.version = version;
-  }
-
   public Set<ValidationItem> getItems() {
     return items;
   }

+ 9 - 0
ambari-server/src/main/java/org/apache/ambari/server/api/util/StackExtensionHelper.java

@@ -138,6 +138,10 @@ public class StackExtensionHelper {
     mergedServiceInfo.setName(childService.getName());
     mergedServiceInfo.setComment(childService.getComment());
     mergedServiceInfo.setVersion(childService.getVersion());
+    mergedServiceInfo.setDisplayName(
+        childService.getDisplayName() != null ?
+            childService.getDisplayName() :
+            parentService.getDisplayName());
     mergedServiceInfo.setConfigDependencies(
         childService.getConfigDependencies() != null ?
             childService.getConfigDependencies() :
@@ -306,10 +310,15 @@ public class StackExtensionHelper {
       result.setCommandScript(parent.getCommandScript());
     }
     //keep the same semantic as for ServiceInfo
+    result.setDisplayName(
+        child.getDisplayName() != null ?
+            child.getDisplayName() : parent.getDisplayName());
+
     result.setConfigDependencies(
         child.getConfigDependencies() != null ?
             child.getConfigDependencies() : parent.getConfigDependencies());
 
+
 //    HashSet downloadSource = child.getDownloadSource();
 //    if (downloadSource != null) {
 //      result.setDownloadSource(child.getDownloadSource());

+ 2 - 7
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java

@@ -20,7 +20,6 @@ package org.apache.ambari.server.controller;
 
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.COMMAND_TIMEOUT;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.COMPONENT_CATEGORY;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_LOCATION;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT_TYPE;
 
@@ -206,12 +205,10 @@ public class AmbariActionExecutionHelper {
    * Add tasks to the stage based on the requested action execution
    * @param actionContext the context associated with the action
    * @param stage stage into which tasks must be inserted
-   * @param hostLevelParams host level params to send with the command
    * @throws AmbariException
    */
   public void addExecutionCommandsToStage(
-          final ActionExecutionContext actionContext,
-          Stage stage, Map<String, String> hostLevelParams)
+          final ActionExecutionContext actionContext, Stage stage)
       throws AmbariException {
 
     String actionName = actionContext.getActionName();
@@ -337,9 +334,8 @@ public class AmbariActionExecutionHelper {
         configTags = managementController.findConfigurationTagsWithOverrides(cluster, hostName);
       }
 
-      Map<String, String> commandParams = actionContext.getParameters();
+      Map<String, String> commandParams = new TreeMap<String, String>();
       commandParams.put(COMMAND_TIMEOUT, actionContext.getTimeout().toString());
-      commandParams.put(JDK_LOCATION, managementController.getJdkResourceUrl());
       commandParams.put(SCRIPT, actionName + ".py");
       commandParams.put(SCRIPT_TYPE, TYPE_PYTHON);
 
@@ -353,7 +349,6 @@ public class AmbariActionExecutionHelper {
       execCmd.setConfigurations(configurations);
       execCmd.setConfigurationAttributes(configurationAttributes);
       execCmd.setConfigurationTags(configTags);
-      execCmd.setHostLevelParams(hostLevelParams);
       execCmd.setCommandParams(commandParams);
       execCmd.setServiceName(serviceName == null || serviceName.isEmpty() ?
         resourceFilter.getServiceName() : serviceName);

+ 12 - 22
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java

@@ -22,7 +22,6 @@ import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.COMMAND_T
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.COMPONENT_CATEGORY;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.CUSTOM_COMMAND;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.HOOKS_FOLDER;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_LOCATION;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.REPO_INFO;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT_TYPE;
@@ -204,7 +203,7 @@ public class AmbariCustomCommandExecutionHelper {
 
   private void addCustomCommandAction(final ActionExecutionContext actionExecutionContext,
                                       final RequestResourceFilter resourceFilter,
-                                      Stage stage, Map<String, String> hostLevelParams,
+                                      Stage stage,
                                       Map<String, String> additionalCommandParams,
                                       String commandDetail)
                                       throws AmbariException {
@@ -290,6 +289,8 @@ public class AmbariCustomCommandExecutionHelper {
       if(actionExecutionContext.getParameters() != null && actionExecutionContext.getParameters().containsKey(KeyNames.REFRESH_ADITIONAL_COMPONENT_TAGS)){
         execCmd.setForceRefreshConfigTags(parseAndValidateComponentsMapping(actionExecutionContext.getParameters().get(KeyNames.REFRESH_ADITIONAL_COMPONENT_TAGS)));
       }
+ 
+      Map<String, String> hostLevelParams = new TreeMap<String, String>();
 
       hostLevelParams.put(CUSTOM_COMMAND, commandName);
       // Set parameters required for re-installing clients on restart
@@ -330,7 +331,6 @@ public class AmbariCustomCommandExecutionHelper {
       }
 
       commandParams.put(COMMAND_TIMEOUT, commandTimeout);
-      commandParams.put(JDK_LOCATION, managementController.getJdkResourceUrl());
 
       commandParams.put(SERVICE_PACKAGE_FOLDER,
           serviceInfo.getServicePackageFolder());
@@ -357,7 +357,7 @@ public class AmbariCustomCommandExecutionHelper {
 
   /**
    * splits the passed commaseparated value and returns it as set
-   * @param comma separated list
+   * @param commaSeparatedTags separated list
    * @return set of items or null
    * @throws AmbariException
    */
@@ -372,7 +372,7 @@ public class AmbariCustomCommandExecutionHelper {
   private void findHostAndAddServiceCheckAction(
           final ActionExecutionContext actionExecutionContext,
           final RequestResourceFilter resourceFilter,
-          Stage stage, Map<String, String> hostLevelParams)
+          Stage stage)
           throws AmbariException {
 
     String clusterName = actionExecutionContext.getClusterName();
@@ -438,8 +438,7 @@ public class AmbariCustomCommandExecutionHelper {
     }
 
     addServiceCheckAction(stage, hostName, smokeTestRole, nowTimestamp,
-        serviceName, componentName, actionParameters,
-        hostLevelParams);
+        serviceName, componentName, actionParameters);
   }
 
   /**
@@ -452,8 +451,7 @@ public class AmbariCustomCommandExecutionHelper {
                                     long nowTimestamp,
                                     String serviceName,
                                     String componentName,
-                                    Map<String, String> actionParameters,
-                                    Map<String, String> hostLevelParams)
+                                    Map<String, String> actionParameters)
                                     throws AmbariException {
 
     String clusterName = stage.getClusterName();
@@ -496,11 +494,6 @@ public class AmbariCustomCommandExecutionHelper {
     execCmd.setClusterHostInfo(
         StageUtils.getClusterHostInfo(clusters.getHostsForCluster(clusterName), cluster));
 
-    if (hostLevelParams == null) {
-      hostLevelParams = new TreeMap<String, String>();
-    }
-    execCmd.setHostLevelParams(hostLevelParams);
-
     Map<String, String> commandParams = new TreeMap<String, String>();
 
     String commandTimeout = configs.getDefaultAgentTaskTimeout();
@@ -525,7 +518,6 @@ public class AmbariCustomCommandExecutionHelper {
     }
 
     commandParams.put(COMMAND_TIMEOUT, commandTimeout);
-    commandParams.put(JDK_LOCATION, managementController.getJdkResourceUrl());
 
     commandParams.put(SERVICE_PACKAGE_FOLDER,
         serviceInfo.getServicePackageFolder());
@@ -557,7 +549,7 @@ public class AmbariCustomCommandExecutionHelper {
    */
   private void addDecommissionAction(final ActionExecutionContext actionExecutionContext,
                                      final RequestResourceFilter resourceFilter,
-                                     Stage stage, Map<String, String> hostLevelParams)
+                                     Stage stage)
                                      throws AmbariException {
 
     String clusterName = actionExecutionContext.getClusterName();
@@ -741,7 +733,7 @@ public class AmbariCustomCommandExecutionHelper {
       if (!serviceName.equals(Service.Type.HBASE.name()) || hostName.equals(primaryCandidate)) {
         commandParams.put(UPDATE_EXCLUDE_FILE_ONLY, "false");
         addCustomCommandAction(commandContext, commandFilter, stage,
-          hostLevelParams, commandParams, commandDetail.toString());
+          commandParams, commandDetail.toString());
       }
     }
   }
@@ -800,12 +792,10 @@ public class AmbariCustomCommandExecutionHelper {
    * Other than Service_Check and Decommission all other commands are pass-through
    * @param actionExecutionContext received request to execute a command
    * @param stage the initial stage for task creation
-   * @param hostLevelParams specific parameters for the hosts
    * @throws AmbariException
    */
   public void addExecutionCommandsToStage(ActionExecutionContext actionExecutionContext,
                                           Stage stage,
-                                          Map<String, String> hostLevelParams,
                                           Map<String, String> requestParams)
                                           throws AmbariException {
 
@@ -819,9 +809,9 @@ public class AmbariCustomCommandExecutionHelper {
 
       if (actionExecutionContext.getActionName().contains(SERVICE_CHECK_COMMAND_NAME)) {
         findHostAndAddServiceCheckAction(actionExecutionContext,
-          resourceFilter, stage, hostLevelParams);
+          resourceFilter, stage);
       } else if (actionExecutionContext.getActionName().equals(DECOMMISSION_COMMAND_NAME)) {
-        addDecommissionAction(actionExecutionContext, resourceFilter, stage, hostLevelParams);
+        addDecommissionAction(actionExecutionContext, resourceFilter, stage);
       } else if (isValidCustomCommand(actionExecutionContext, resourceFilter)) {
         String commandDetail = getReadableCustomCommandDetail(actionExecutionContext, resourceFilter);
 
@@ -838,7 +828,7 @@ public class AmbariCustomCommandExecutionHelper {
           actionExecutionContext.getParameters().put(KeyNames.REFRESH_ADITIONAL_COMPONENT_TAGS, requestParams.get(KeyNames.REFRESH_ADITIONAL_COMPONENT_TAGS));
         }
         addCustomCommandAction(actionExecutionContext, resourceFilter, stage,
-          hostLevelParams, extraParams, commandDetail);
+          extraParams, commandDetail);
       } else {
         throw new AmbariException("Unsupported action " +
           actionExecutionContext.getActionName());

+ 105 - 79
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java

@@ -18,13 +18,49 @@
 
 package org.apache.ambari.server.controller;
 
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.gson.Gson;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Singleton;
-import com.google.inject.persist.Transactional;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_DRIVER;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_PASSWORD;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_URL;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_USERNAME;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.COMMAND_TIMEOUT;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.DB_DRIVER_FILENAME;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.DB_NAME;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.HOOKS_FOLDER;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JAVA_HOME;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JCE_NAME;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_LOCATION;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_NAME;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.MYSQL_JDBC_URL;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.ORACLE_JDBC_URL;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.PACKAGE_LIST;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.REPO_INFO;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT_TYPE;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_PACKAGE_FOLDER;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_REPO_INFO;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.STACK_NAME;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.STACK_VERSION;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.concurrent.TimeUnit;
+
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ClusterNotFoundException;
 import org.apache.ambari.server.DuplicateResourceException;
@@ -101,46 +137,15 @@ import org.apache.commons.lang.math.NumberUtils;
 import org.apache.http.client.utils.URIBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import java.io.File;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumMap;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.concurrent.TimeUnit;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_DRIVER;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_PASSWORD;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_URL;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_USERNAME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.COMMAND_TIMEOUT;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.DB_DRIVER_FILENAME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.DB_NAME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.HOOKS_FOLDER;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JAVA_HOME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JCE_NAME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_LOCATION;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_NAME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.MYSQL_JDBC_URL;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.ORACLE_JDBC_URL;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.PACKAGE_LIST;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.REPO_INFO;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT_TYPE;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_PACKAGE_FOLDER;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_REPO_INFO;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.STACK_NAME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.STACK_VERSION;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.collect.Multimaps;
+import com.google.gson.Gson;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
 
 @Singleton
 public class AmbariManagementControllerImpl implements AmbariManagementController {
@@ -652,7 +657,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     if(request.getType().equals(Configuration.GLOBAL_CONFIG_TAG)) {
       Map<String, Map<String, String>> configTypes = new HashMap<String, Map<String, String>>();
       configTypes.put(Configuration.GLOBAL_CONFIG_TAG, request.getProperties());
-      configHelper.moveDeprecatedGlobals(cluster.getCurrentStackVersion(), configTypes);
+      configHelper.moveDeprecatedGlobals(cluster.getCurrentStackVersion(), configTypes, cluster.getClusterName());
 
       for(Map.Entry<String, Map<String, String>> configType : configTypes.entrySet()) {
         String configTypeName = configType.getKey();
@@ -673,7 +678,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
         if (config != null) {
           String authName = getAuthName();
 
-          if (cluster.addDesiredConfig(authName, config) != null) {
+          if (cluster.addDesiredConfig(authName, Collections.singleton(config)) != null) {
             LOG.info("cluster '" + cluster.getClusterName() + "' "
                     + "changed by: '" + authName + "'; "
                     + "type='" + config.getType() + "' "
@@ -798,13 +803,16 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     }
   }
 
-  private Stage createNewStage(long id, Cluster cluster, long requestId, String requestContext, String clusterHostInfo) {
+  private Stage createNewStage(long id, Cluster cluster, long requestId,
+                               String requestContext, String clusterHostInfo,
+                               String commandParamsStage, String hostParamsStage) {
     String logDir = BASE_LOG_DIR + File.pathSeparator + requestId;
     Stage stage =
         stageFactory.createNew(requestId, logDir,
             null == cluster ? null : cluster.getClusterName(),
             null == cluster ? -1L : cluster.getClusterId(),
-            requestContext, clusterHostInfo);
+            requestContext, clusterHostInfo, commandParamsStage,
+            hostParamsStage);
     stage.setStageId(id);
     return stage;
   }
@@ -1145,14 +1153,21 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
 
     final Cluster cluster = clusters.getCluster(request.getClusterName());
     //save data to return configurations created
-    ConfigurationResponse configurationResponse = null;
+    List<ConfigurationResponse> configurationResponses =
+      new LinkedList<ConfigurationResponse>();
     ServiceConfigVersionResponse serviceConfigVersionResponse = null;
 
+    if (request.getDesiredConfig() != null && request.getServiceConfigVersionRequest() != null) {
+      String msg = "Unable to set desired configs and rollback at same time, request = " + request.toString();
+      LOG.error(msg);
+      throw new IllegalArgumentException(msg);
+    }
+
     // set or create configuration mapping (and optionally create the map of properties)
     if (null != request.getDesiredConfig()) {
-      ConfigurationRequest cr = request.getDesiredConfig();
-
-      Config oldConfig = cluster.getDesiredConfigByType(cr.getType());
+      Set<Config> configs = new HashSet<Config>();
+      String note = null;
+      for (ConfigurationRequest cr: request.getDesiredConfig()) {
 
       if (null != cr.getProperties()) {
         // !!! empty property sets are supported, and need to be able to use
@@ -1167,21 +1182,23 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
               request.getClusterName()));
 
           cr.setClusterName(cluster.getClusterName());
-          configurationResponse = createConfiguration(cr);
+          configurationResponses.add(createConfiguration(cr));
         }
       }
-
-      Config baseConfig = cluster.getConfig(cr.getType(), cr.getVersionTag());
-      if (null != baseConfig) {
+        note = cr.getServiceConfigVersionNote();
+        configs.add(cluster.getConfig(cr.getType(), cr.getVersionTag()));
+      }
+      if (!configs.isEmpty()) {
         String authName = getAuthName();
-        serviceConfigVersionResponse = cluster.addDesiredConfig(authName, baseConfig, cr.getServiceConfigVersionNote());
+        serviceConfigVersionResponse = cluster.addDesiredConfig(authName, configs, note);
         if (serviceConfigVersionResponse != null) {
           Logger logger = LoggerFactory.getLogger("configchange");
-          logger.info("cluster '" + request.getClusterName() + "' "
-              + "changed by: '" + authName + "'; "
-              + "type='" + baseConfig.getType() + "' "
-              + "tag='" + baseConfig.getTag() + "'"
-              + (null == oldConfig ? "" : " from='"+ oldConfig.getTag() + "'"));
+          for (Config config: configs) {
+            logger.info("cluster '" + request.getClusterName() + "' "
+                + "changed by: '" + authName + "'; "
+                + "type='" + config.getType() + "' "
+                + "tag='" + config.getTag() + "'");
+          }
         }
       }
     }
@@ -1249,21 +1266,24 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
         throw new IllegalArgumentException(msg);
       }
 
-      cluster.setServiceConfigVersion(serviceConfigVersionRequest.getServiceName(),
+      serviceConfigVersionResponse = cluster.setServiceConfigVersion(serviceConfigVersionRequest.getServiceName(),
           serviceConfigVersionRequest.getVersion(), getAuthName(),
           serviceConfigVersionRequest.getNote());
     }
 
     if (serviceConfigVersionResponse != null) {
-      if (configurationResponse != null) {
-        serviceConfigVersionResponse.setConfigurations(Collections.singletonList(configurationResponse));
+      if (!configurationResponses.isEmpty()) {
+        serviceConfigVersionResponse.setConfigurations(configurationResponses);
       }
 
       ClusterResponse clusterResponse =
           new ClusterResponse(cluster.getClusterId(), cluster.getClusterName(), null, null, null, null, null);
 
-      clusterResponse.setDesiredServiceConfigVersions(
-          Collections.singletonMap(serviceConfigVersionResponse.getServiceName(), serviceConfigVersionResponse));
+      Map<String, Collection<ServiceConfigVersionResponse>> map =
+        new HashMap<String, Collection<ServiceConfigVersionResponse>>();
+      map.put(serviceConfigVersionResponse.getServiceName(), Collections.singletonList(serviceConfigVersionResponse));
+
+      clusterResponse.setDesiredServiceConfigVersions(map);
 
       //workaround to be able to retrieve update results in resource provider
       //as this method only expected to return request response
@@ -1582,7 +1602,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
         + ", repoInfo=" + repoInfo);
     }
 
-    Map<String, String> hostParams = createDefaultHostParams(cluster);
+    Map<String, String> hostParams = new TreeMap<String, String>();
     hostParams.put(REPO_INFO, repoInfo);
     hostParams.putAll(getRcaParameters());
 
@@ -1731,9 +1751,11 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
           clusters.getHostsForCluster(cluster.getClusterName()), cluster);
 
       String clusterHostInfoJson = StageUtils.getGson().toJson(clusterHostInfo);
+      String HostParamsJson = StageUtils.getGson().toJson(createDefaultHostParams(cluster));
 
       Stage stage = createNewStage(requestStages.getLastStageId() + 1, cluster,
-          requestStages.getId(), requestProperties.get(REQUEST_CONTEXT_PROPERTY), clusterHostInfoJson);
+          requestStages.getId(), requestProperties.get(REQUEST_CONTEXT_PROPERTY),
+          clusterHostInfoJson, "{}", HostParamsJson);
 
       //HACK
       String jobtrackerHost = getJobTrackerHost(cluster);
@@ -1945,7 +1967,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
 
         customCommandExecutionHelper.addServiceCheckAction(stage, clientHost,
           smokeTestRole, nowTimestamp, serviceName,
-          null, null, createDefaultHostParams(cluster));
+          null, null);
       }
 
       RoleCommandOrder rco = getRoleCommandOrder(cluster);
@@ -2947,24 +2969,28 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       actionExecutionHelper.validateAction(actionRequest);
     }
 
-    Map<String, String> params = new HashMap<String, String>();
+    Map<String, String> commandParamsStage = StageUtils.getCommandParamsStage(actionExecContext);
+    Map<String, String> hostParamsStage = new HashMap<String, String>();
     Map<String, Set<String>> clusterHostInfo;
     String clusterHostInfoJson = "{}";
 
     if (null != cluster) {
       clusterHostInfo = StageUtils.getClusterHostInfo(
         clusters.getHostsForCluster(cluster.getClusterName()), cluster);
-      params = createDefaultHostParams(cluster);
+      hostParamsStage = createDefaultHostParams(cluster);
       clusterHostInfoJson = StageUtils.getGson().toJson(clusterHostInfo);
     }
 
-    Stage stage = createNewStage(0, cluster, actionManager.getNextRequestId(), requestContext, clusterHostInfoJson);
+    String hostParamsStageJson = StageUtils.getGson().toJson(hostParamsStage);
+    String commandParamsStageJson = StageUtils.getGson().toJson(commandParamsStage);
+
+    Stage stage = createNewStage(0, cluster, actionManager.getNextRequestId(), requestContext,
+      clusterHostInfoJson, commandParamsStageJson, hostParamsStageJson);
 
     if (actionRequest.isCommand()) {
-      customCommandExecutionHelper.addExecutionCommandsToStage(actionExecContext, stage,
-          params, requestProperties);
+      customCommandExecutionHelper.addExecutionCommandsToStage(actionExecContext, stage, requestProperties);
     } else {
-      actionExecutionHelper.addExecutionCommandsToStage(actionExecContext, stage, params);
+      actionExecutionHelper.addExecutionCommandsToStage(actionExecContext, stage);
     }
 
     RoleGraph rg;

+ 15 - 13
ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterRequest.java

@@ -18,6 +18,7 @@
 
 package org.apache.ambari.server.controller;
 
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -35,7 +36,7 @@ public class ClusterRequest {
   
   Set<String> hostNames; // CREATE/UPDATE
   
-  private ConfigurationRequest config = null;
+  private List<ConfigurationRequest> configs = null;
 
   private ServiceConfigVersionRequest serviceConfigVersionRequest = null;
 
@@ -128,30 +129,31 @@ public class ClusterRequest {
   }
   
   /**
-   * Sets the config request (if any)
+   * Sets the configs requests (if any)
    * @param configRequest
    */
-  public void setDesiredConfig(ConfigurationRequest configRequest) {
-    config = configRequest;
+  public void setDesiredConfig(List<ConfigurationRequest> configRequest) {
+    configs = configRequest;
   }
   
   /**
    * Gets any configuration-based request (if any).
-   * @return the configuration request, or <code>null</code> if none is set.
+   * @return the list of configuration requests,
+   * or <code>null</code> if none is set.
    */
-  public ConfigurationRequest getDesiredConfig() {
-    return config;
+  public List<ConfigurationRequest> getDesiredConfig() {
+    return configs;
   }
 
   @Override
   public String toString() {
     StringBuilder sb = new StringBuilder();
-    sb.append("{"
-        + " clusterName=" + clusterName
-        + ", clusterId=" + clusterId
-        + ", provisioningState=" + provisioningState
-        + ", stackVersion=" + stackVersion
-        + ", hosts=[");
+    sb.append("{" + " clusterName=").append(clusterName)
+        .append(", clusterId=").append(clusterId)
+        .append(", provisioningState=").append(provisioningState)
+        .append(", stackVersion=").append(stackVersion)
+        .append(", desired_scv=").append(serviceConfigVersionRequest)
+        .append(", hosts=[");
     if (hostNames != null) {
       int i = 0;
       for (String hostName : hostNames) {

+ 6 - 3
ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterResponse.java

@@ -18,9 +18,12 @@
 
 package org.apache.ambari.server.controller;
 
+import java.util.Collection;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.collect.Multimap;
 import org.apache.ambari.server.state.DesiredConfig;
 import org.apache.ambari.server.state.State;
 import org.apache.ambari.server.state.ClusterHealthReport;
@@ -37,7 +40,7 @@ public class ClusterResponse {
 
   private Map<String, DesiredConfig> desiredConfigs;
 
-  private Map<String, ServiceConfigVersionResponse> desiredServiceConfigVersions;
+  private Map<String, Collection<ServiceConfigVersionResponse>> desiredServiceConfigVersions;
   
   private String provisioningState;
 
@@ -180,11 +183,11 @@ public class ClusterResponse {
     return clusterHealthReport;
   }
 
-  public Map<String, ServiceConfigVersionResponse> getDesiredServiceConfigVersions() {
+  public Map<String, Collection<ServiceConfigVersionResponse>> getDesiredServiceConfigVersions() {
     return desiredServiceConfigVersions;
   }
 
-  public void setDesiredServiceConfigVersions(Map<String, ServiceConfigVersionResponse> desiredServiceConfigVersions) {
+  public void setDesiredServiceConfigVersions(Map<String, Collection<ServiceConfigVersionResponse>> desiredServiceConfigVersions) {
     this.desiredServiceConfigVersions = desiredServiceConfigVersions;
   }
 }

+ 9 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigGroupRequest.java

@@ -29,6 +29,7 @@ public class ConfigGroupRequest {
   private String groupName;
   private String tag;
   private String description;
+  private String serviceConfigVersionNote;
   private Set<String> hosts;
   private Map<String, Config> configs;
 
@@ -99,4 +100,12 @@ public class ConfigGroupRequest {
   public void setId(Long id) {
     this.id = id;
   }
+
+  public String getServiceConfigVersionNote() {
+    return serviceConfigVersionNote;
+  }
+
+  public void setServiceConfigVersionNote(String serviceConfigVersionNote) {
+    this.serviceConfigVersionNote = serviceConfigVersionNote;
+  }
 }

+ 6 - 5
ambari-server/src/main/java/org/apache/ambari/server/controller/HostRequest.java

@@ -18,6 +18,7 @@
 
 package org.apache.ambari.server.controller;
 
+import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
@@ -28,7 +29,7 @@ public class HostRequest {
   private String clusterName; // CREATE/UPDATE
   private Map<String, String> hostAttributes; // CREATE/UPDATE
   private String rackInfo;
-  private ConfigurationRequest desiredConfig; // UPDATE
+  private List<ConfigurationRequest> desiredConfigs; // UPDATE
   private String maintenanceState; // UPDATE
 
   public HostRequest(String hostname, String clusterName, Map<String, String> hostAttributes) {
@@ -77,12 +78,12 @@ public class HostRequest {
     publicHostname = name;
   }
   
-  public void setDesiredConfig(ConfigurationRequest request) {
-    desiredConfig = request;
+  public void setDesiredConfigs(List<ConfigurationRequest> request) {
+    desiredConfigs = request;
   }
   
-  public ConfigurationRequest getDesiredConfig() {
-    return desiredConfig;
+  public List<ConfigurationRequest> getDesiredConfigs() {
+    return desiredConfigs;
   }
   
   public void setMaintenanceState(String state) {

+ 23 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionRequest.java

@@ -26,6 +26,7 @@ public class ServiceConfigVersionRequest {
   private Long applyTime;
   private String userName;
   private String note;
+  private Boolean isCurrent;
 
   public ServiceConfigVersionRequest() {
   }
@@ -94,4 +95,26 @@ public class ServiceConfigVersionRequest {
   public void setNote(String note) {
     this.note = note;
   }
+
+  public Boolean getIsCurrent() {
+    return isCurrent;
+  }
+
+  public void setIsCurrent(Boolean isCurrent) {
+    this.isCurrent = isCurrent;
+  }
+
+  @Override
+  public String toString() {
+    return "ServiceConfigVersionRequest{" +
+        "clusterName='" + clusterName + '\'' +
+        ", serviceName='" + serviceName + '\'' +
+        ", version=" + version +
+        ", createTime=" + createTime +
+        ", applyTime=" + applyTime +
+        ", userName='" + userName + '\'' +
+        ", note='" + note + '\'' +
+        ", isCurrent=" + isCurrent +
+        '}';
+  }
 }

+ 11 - 2
ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceConfigVersionResponse.java

@@ -19,7 +19,6 @@
 package org.apache.ambari.server.controller;
 
 
-import org.apache.ambari.server.state.Config;
 import org.codehaus.jackson.annotate.JsonProperty;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 
@@ -34,6 +33,7 @@ public class ServiceConfigVersionResponse {
   private String groupName;
   private String userName;
   private String note;
+  private Boolean isCurrent = false;
   private List<ConfigurationResponse> configurations;
   private List<String> hosts;
 
@@ -46,7 +46,7 @@ public class ServiceConfigVersionResponse {
     this.serviceName = serviceName;
   }
 
-  @JsonProperty("serviceconfigversion")
+  @JsonProperty("service_config_version")
   public Long getVersion() {
     return version;
   }
@@ -130,5 +130,14 @@ public class ServiceConfigVersionResponse {
   public void setGroupId(Long groupId) {
     this.groupId = groupId;
   }
+
+  @JsonProperty("is_current")
+  public Boolean getIsCurrent() {
+    return isCurrent;
+  }
+
+  public void setIsCurrent(Boolean isCurrent) {
+    this.isCurrent = isCurrent;
+  }
 }
 

+ 29 - 4
ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceComponentResponse.java

@@ -18,14 +18,14 @@
 
 package org.apache.ambari.server.controller;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
 import org.apache.ambari.server.state.AutoDeployInfo;
 import org.apache.ambari.server.state.ComponentInfo;
 import org.apache.ambari.server.state.CustomCommandDefinition;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 /**
  * Stack service component response.
  */
@@ -50,6 +50,11 @@ public class StackServiceComponentResponse {
    */
   private String componentName;
 
+  /**
+   * component display name
+   */
+  private String componentDisplayName;
+
   /**
    * component category
    */
@@ -89,6 +94,7 @@ public class StackServiceComponentResponse {
    */
   public StackServiceComponentResponse(ComponentInfo component) {
     componentName = component.getName();
+    componentDisplayName = component.getDisplayName();
     componentCategory = component.getCategory();
     isClient = component.isClient();
     isMaster = component.isMaster();
@@ -179,6 +185,25 @@ public class StackServiceComponentResponse {
     this.componentName = componentName;
   }
 
+  /**
+   * Get component display name.
+   *
+   * @return component display name
+   */
+
+  public String getComponentDisplayName() {
+    return componentDisplayName;
+  }
+
+  /**
+   * Set component display name.
+   *
+   * @param componentDisplayName  component display name
+   */
+  public void setComponentDisplayName(String componentDisplayName) {
+    this.componentDisplayName = componentDisplayName;
+  }
+
   /**
    * Get component category.
    *

+ 13 - 3
ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java

@@ -18,19 +18,20 @@
 
 package org.apache.ambari.server.controller;
 
+import org.apache.ambari.server.state.CustomCommandDefinition;
+import org.apache.ambari.server.state.ServiceInfo;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.ambari.server.state.CustomCommandDefinition;
-import org.apache.ambari.server.state.ServiceInfo;
-
 public class StackServiceResponse {
 
   private String stackName;
   private String stackVersion;
   private String serviceName;
+  private String serviceDisplayName;
   private String userName;
   private String comments;
   private String serviceVersion;
@@ -48,6 +49,7 @@ public class StackServiceResponse {
    */
   public StackServiceResponse(ServiceInfo service) {
     serviceName = service.getName();
+    serviceDisplayName = service.getDisplayName();
     userName = null;
     comments = service.getComment();
     serviceVersion = service.getVersion();
@@ -91,6 +93,14 @@ public class StackServiceResponse {
     this.serviceName = serviceName;
   }
 
+  public String getServiceDisplayName() {
+    return serviceDisplayName;
+  }
+
+  public void setServiceDisplayName(String serviceDisplayName) {
+    this.serviceDisplayName = serviceDisplayName;
+  }
+
   public String getUserName() {
     return userName;
   }

+ 61 - 31
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractResourceProvider.java

@@ -20,6 +20,7 @@ package org.apache.ambari.server.controller.internal;
 
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -343,50 +344,79 @@ public abstract class AbstractResourceProvider extends BaseProvider implements R
    *    whose category is the parent and marked as a desired config.
    * @param properties  the properties on the request.
    */
-  protected ConfigurationRequest getConfigurationRequest(String parentCategory, Map<String, Object> properties) {
+  protected List<ConfigurationRequest> getConfigurationRequests(String parentCategory, Map<String, Object> properties) {
+
+    List<ConfigurationRequest> configs = new LinkedList<ConfigurationRequest>();
+
+    String desiredConfigKey = parentCategory + "/desired_config";
+    // Multiple configs to be updated
+    if (properties.containsKey(desiredConfigKey)
+      && properties.get(desiredConfigKey) instanceof Set) {
+
+      Set<Map<String, Object>> configProperties =
+        (Set<Map<String, Object>>) properties.get(desiredConfigKey);
+      for (Map<String, Object> value: configProperties) {
+        ConfigurationRequest newConfig = new ConfigurationRequest();
+
+        for (Entry<String, Object> e : value.entrySet()) {
+          String propName =
+            PropertyHelper.getPropertyName(desiredConfigKey + '/' + e.getKey());
+          String absCatategory =
+            PropertyHelper.getPropertyCategory(desiredConfigKey + '/' + e.getKey());
+          parseProperties(newConfig, absCatategory, propName, e.getValue().toString());
+        }
+        configs.add(newConfig);
+      }
+      return configs;
+    }
 
     ConfigurationRequest config = null;
-
     // as a convenience, allow consumers to specify name/value overrides in this
     // call instead of forcing a cluster call to do that work
     for (Entry<String, Object> entry : properties.entrySet()) {
       String absCategory = PropertyHelper.getPropertyCategory(entry.getKey());
       String propName = PropertyHelper.getPropertyName(entry.getKey());
 
-      if (absCategory.startsWith(parentCategory + "/desired_config")) {
+      if (absCategory.startsWith(desiredConfigKey)) {
         config = (null == config) ? new ConfigurationRequest() : config;
 
-        if (propName.equals("type"))
-          config.setType(entry.getValue().toString());
-        else if (propName.equals("tag"))
-          config.setVersionTag(entry.getValue().toString());
-        else if (propName.equals("selected")) {
-          config.setSelected(Boolean.parseBoolean(entry.getValue().toString()));
-        }
-        else if (propName.equals("service_config_version_note")) {
-          config.setServiceConfigVersionNote(entry.getValue().toString());
-        }
-        else if (absCategory.endsWith("/properties")) {
-          config.getProperties().put(propName, entry.getValue().toString());
-        }
-        else if (propertiesAttributesPattern.matcher(absCategory).matches()) {
-          String attributeName = absCategory.substring(absCategory.lastIndexOf('/') + 1);
-          Map<String, Map<String, String>> configAttributesMap = config.getPropertiesAttributes();
-          if (null == configAttributesMap) {
-            configAttributesMap = new HashMap<String, Map<String,String>>();
-            config.setPropertiesAttributes(configAttributesMap);
-          }
-          Map<String, String> attributesMap = configAttributesMap.get(attributeName);
-          if (null == attributesMap) {
-            attributesMap = new HashMap<String, String>();
-            configAttributesMap.put(attributeName, attributesMap);
-          }
-          attributesMap.put(PropertyHelper.getPropertyName(entry.getKey()), entry.getValue().toString());
-        }
+        parseProperties(config, absCategory, propName, entry.getValue().toString());
       }
     }
+    if (config != null) {
+      configs.add(config);
+    }
+    return configs;
+  }
 
-    return config;
+  private void parseProperties(ConfigurationRequest config, String absCategory, String propName, String propValue) {
+    if (propName.equals("type"))
+      config.setType(propValue);
+    else if (propName.equals("tag"))
+      config.setVersionTag(propValue);
+    else if (propName.equals("selected")) {
+      config.setSelected(Boolean.parseBoolean(propValue));
+    }
+    else if (propName.equals("service_config_version_note")) {
+      config.setServiceConfigVersionNote(propValue);
+    }
+    else if (absCategory.endsWith("/properties")) {
+      config.getProperties().put(propName, propValue);
+    }
+    else if (propertiesAttributesPattern.matcher(absCategory).matches()) {
+      String attributeName = absCategory.substring(absCategory.lastIndexOf('/') + 1);
+      Map<String, Map<String, String>> configAttributesMap = config.getPropertiesAttributes();
+      if (null == configAttributesMap) {
+        configAttributesMap = new HashMap<String, Map<String,String>>();
+        config.setPropertiesAttributes(configAttributesMap);
+      }
+      Map<String, String> attributesMap = configAttributesMap.get(attributeName);
+      if (null == attributesMap) {
+        attributesMap = new HashMap<String, String>();
+        configAttributesMap.put(attributeName, attributesMap);
+      }
+      attributesMap.put(propName, propValue);
+    }
   }
 
   // get the resources (id fields only) for the given predicate.

+ 25 - 12
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BaseBlueprintProcessor.java

@@ -106,7 +106,7 @@ public abstract class BaseBlueprintProcessor extends AbstractControllerResourceP
     Map<String, HostGroupImpl> mapHostGroups = new HashMap<String, HostGroupImpl>();
 
     for (HostGroupEntity hostGroup : blueprint.getHostGroups()) {
-      mapHostGroups.put(hostGroup.getName(), new HostGroupImpl(hostGroup, stack));
+      mapHostGroups.put(hostGroup.getName(), new HostGroupImpl(hostGroup, stack, this));
     }
     return mapHostGroups;
   }
@@ -123,7 +123,7 @@ public abstract class BaseBlueprintProcessor extends AbstractControllerResourceP
   protected Stack parseStack(BlueprintEntity blueprint) throws SystemException {
     Stack stack;
     try {
-      stack = new Stack(blueprint.getStackName(), blueprint.getStackVersion());
+      stack = new Stack(blueprint.getStackName(), blueprint.getStackVersion(), getManagementController());
     } catch (StackAccessException e) {
       throw new IllegalArgumentException("Invalid stack information provided for cluster.  " +
           "stack name: " + blueprint.getStackName() +
@@ -148,7 +148,7 @@ public abstract class BaseBlueprintProcessor extends AbstractControllerResourceP
    * @throws IllegalArgumentException when validation fails
    */
   protected BlueprintEntity validateTopology(BlueprintEntity blueprint) throws AmbariException {
-    Stack stack = new Stack(blueprint.getStackName(), blueprint.getStackVersion());
+    Stack stack = new Stack(blueprint.getStackName(), blueprint.getStackVersion(), getManagementController());
     Map<String, HostGroupImpl> hostGroupMap = parseBlueprintHostGroups(blueprint, stack);
     Collection<HostGroupImpl> hostGroups = hostGroupMap.values();
     Map<String, Map<String, String>> clusterConfig = processBlueprintConfigurations(blueprint, null);
@@ -455,7 +455,7 @@ public abstract class BaseBlueprintProcessor extends AbstractControllerResourceP
   /**
    * Encapsulates stack information.
    */
-  protected class Stack {
+  protected static class Stack {
     /**
      * Stack name
      */
@@ -514,6 +514,12 @@ public abstract class BaseBlueprintProcessor extends AbstractControllerResourceP
     private Map<String, Map<String, Map<String, ConfigProperty>>> serviceConfigurations =
         new HashMap<String, Map<String, Map<String, ConfigProperty>>>();
 
+
+    /**
+     * Ambari Management Controller, used to obtain Stack definitions
+     */
+    private final AmbariManagementController ambariManagementController;
+
     /**
      * Contains a configuration property's value and attributes.
      */
@@ -553,11 +559,12 @@ public abstract class BaseBlueprintProcessor extends AbstractControllerResourceP
      * @throws AmbariException an exception occurred getting stack information
      *                         for the specified name and version
      */
-    public Stack(String name, String version) throws AmbariException {
+    public Stack(String name, String version, AmbariManagementController ambariManagementController) throws AmbariException {
       this.name = name;
       this.version = version;
+      this.ambariManagementController = ambariManagementController;
 
-      Set<StackServiceResponse> stackServices = getManagementController().getStackServices(
+      Set<StackServiceResponse> stackServices = ambariManagementController.getStackServices(
           Collections.singleton(new StackServiceRequest(name, version, null)));
 
       for (StackServiceResponse stackService : stackServices) {
@@ -767,7 +774,7 @@ public abstract class BaseBlueprintProcessor extends AbstractControllerResourceP
     private void parseComponents(String service) throws AmbariException{
       Collection<String> componentSet = new HashSet<String>();
 
-      Set<StackServiceComponentResponse> components = getManagementController().getStackComponents(
+      Set<StackServiceComponentResponse> components = ambariManagementController.getStackComponents(
           Collections.singleton(new StackServiceComponentRequest(name, version, service, null)));
 
       // stack service components
@@ -807,7 +814,7 @@ public abstract class BaseBlueprintProcessor extends AbstractControllerResourceP
 
       serviceConfigurations.put(service, mapServiceConfig);
 
-      Set<StackConfigurationResponse> serviceConfigs = getManagementController().getStackConfigurations(
+      Set<StackConfigurationResponse> serviceConfigs = ambariManagementController.getStackConfigurations(
           Collections.singleton(new StackConfigurationRequest(name, version, service, null)));
 
       for (StackConfigurationResponse config : serviceConfigs) {
@@ -846,7 +853,7 @@ public abstract class BaseBlueprintProcessor extends AbstractControllerResourceP
   /**
    * Host group representation.
    */
-  protected class HostGroupImpl implements HostGroup {
+  protected static class HostGroupImpl implements HostGroup {
     /**
      * Host group entity
      */
@@ -879,15 +886,21 @@ public abstract class BaseBlueprintProcessor extends AbstractControllerResourceP
      */
     private Stack stack;
 
+    /**
+     * The Blueprint processor associated with this HostGroupImpl instance
+     */
+    private final BaseBlueprintProcessor blueprintProcessor;
+
     /**
      * Constructor.
      *
      * @param hostGroup  host group
      * @param stack      stack
      */
-    public HostGroupImpl(HostGroupEntity hostGroup, Stack stack) {
+    public HostGroupImpl(HostGroupEntity hostGroup, Stack stack, BaseBlueprintProcessor blueprintProcessor) {
       this.hostGroup = hostGroup;
       this.stack = stack;
+      this.blueprintProcessor = blueprintProcessor;
       parseComponents();
       parseConfigurations();
     }
@@ -1009,14 +1022,14 @@ public abstract class BaseBlueprintProcessor extends AbstractControllerResourceP
           boolean           resolved        = false;
 
           if (dependencyScope.equals("cluster")) {
-            Collection<String> missingDependencyInfo = verifyComponentCardinalityCount(entity, hostGroups,
+            Collection<String> missingDependencyInfo = blueprintProcessor.verifyComponentCardinalityCount(entity, hostGroups,
                 componentName, new Cardinality("1+"), autoDeployInfo, stack, clusterConfig);
             resolved = missingDependencyInfo.isEmpty();
           } else if (dependencyScope.equals("host")) {
             if (components.contains(component) || (autoDeployInfo != null && autoDeployInfo.isEnabled())) {
               resolved = true;
               if (addComponent(componentName)) {
-                addComponentToBlueprint(hostGroup.getBlueprintEntity(), getEntity().getName(), componentName);
+                blueprintProcessor.addComponentToBlueprint(hostGroup.getBlueprintEntity(), getEntity().getName(), componentName);
               }
             }
           }

+ 3 - 2
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java

@@ -150,7 +150,8 @@ public class BlueprintConfigurationProcessor {
           for (HostGroup group : hostGroups) {
             Collection<String> hosts = group.getHostInfo();
             for (String host : hosts) {
-              if (propValue.contains(host)) {    //todo: need to use regular expression to avoid matching a host which is a superset.  Can this be fixed???
+              //todo: need to use regular expression to avoid matching a host which is a superset.
+              if (propValue.contains(host)) {
                 matchedHost = true;
                 typeProperties.put(propertyName, propValue.replace(
                     host, "%HOSTGROUP::" + group.getName() + "%"));
@@ -697,4 +698,4 @@ public class BlueprintConfigurationProcessor {
     hbaseEnvMap.put("hbase_master_heapsize", new MPropertyUpdater());
     hbaseEnvMap.put("hbase_regionserver_heapsize", new MPropertyUpdater());
   }
-}
+}

+ 92 - 34
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java

@@ -23,6 +23,7 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -63,7 +64,7 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor {
   protected static final String CLUSTER_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "version");
   protected static final String CLUSTER_PROVISIONING_STATE_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "provisioning_state");
   protected static final String CLUSTER_DESIRED_CONFIGS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "desired_configs");
-  protected static final String CLUSTER_DESIRED_SERVICE_CONFIG_VERSIONS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "desired_serviceconfigversions");
+  protected static final String CLUSTER_DESIRED_SERVICE_CONFIG_VERSIONS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "desired_service_config_versions");
   protected static final String CLUSTER_TOTAL_HOSTS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "total_hosts");
   protected static final String CLUSTER_HEALTH_REPORT_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "health_report");
   protected static final String BLUEPRINT_PROPERTY_ID = PropertyHelper.getPropertyId(null, "blueprint");
@@ -172,7 +173,8 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor {
       setResourceProperty(resource, CLUSTER_NAME_PROPERTY_ID, clusterName, requestedIds);
       setResourceProperty(resource, CLUSTER_PROVISIONING_STATE_PROPERTY_ID, response.getProvisioningState(), requestedIds);
       setResourceProperty(resource, CLUSTER_DESIRED_CONFIGS_PROPERTY_ID, response.getDesiredConfigs(), requestedIds);
-      setResourceProperty(resource, CLUSTER_DESIRED_SERVICE_CONFIG_VERSIONS_PROPERTY_ID, response.getDesiredServiceConfigVersions(), requestedIds);
+      setResourceProperty(resource, CLUSTER_DESIRED_SERVICE_CONFIG_VERSIONS_PROPERTY_ID,
+        response.getDesiredServiceConfigVersions(), requestedIds);
       setResourceProperty(resource, CLUSTER_TOTAL_HOSTS_PROPERTY_ID, response.getTotalHosts(), requestedIds);
       setResourceProperty(resource, CLUSTER_HEALTH_REPORT_PROPERTY_ID, response.getClusterHealthReport(), requestedIds);
 
@@ -218,24 +220,29 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor {
     for (ClusterRequest clusterRequest : requests) {
       ClusterResponse updateResults = getManagementController().getClusterUpdateResults(clusterRequest);
       if (updateResults != null) {
-        Map<String, ServiceConfigVersionResponse> serviceConfigVersions = updateResults.getDesiredServiceConfigVersions();
+        Map<String, Collection<ServiceConfigVersionResponse>> serviceConfigVersions = updateResults.getDesiredServiceConfigVersions();
         if (serviceConfigVersions != null) {
           associatedResources = new HashSet<Resource>();
-          for (Map.Entry<String, ServiceConfigVersionResponse> stringServiceConfigVersionResponseEntry : serviceConfigVersions.entrySet()) {
-            Resource resource = new ResourceImpl(Resource.Type.ServiceConfigVersion);
-            ServiceConfigVersionResponse serviceConfigVersionResponse = stringServiceConfigVersionResponseEntry.getValue();
-            resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID,
-              serviceConfigVersionResponse.getServiceName());
-            resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_PROPERTY_ID,
-              serviceConfigVersionResponse.getVersion());
-            resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID,
-              serviceConfigVersionResponse.getNote());
-            if (serviceConfigVersionResponse.getConfigurations() != null) {
-              resource.setProperty(
+          for (Collection<ServiceConfigVersionResponse> scvCollection : serviceConfigVersions.values()) {
+            for (ServiceConfigVersionResponse serviceConfigVersionResponse : scvCollection) {
+              Resource resource = new ResourceImpl(Resource.Type.ServiceConfigVersion);
+              resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID,
+                serviceConfigVersionResponse.getServiceName());
+              resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_PROPERTY_ID,
+                serviceConfigVersionResponse.getVersion());
+              resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID,
+                serviceConfigVersionResponse.getNote());
+              resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_GROUP_ID_PROPERTY_ID,
+                  serviceConfigVersionResponse.getGroupId());
+              resource.setProperty(ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_GROUP_NAME_PROPERTY_ID,
+                  serviceConfigVersionResponse.getGroupName());
+              if (serviceConfigVersionResponse.getConfigurations() != null) {
+                resource.setProperty(
                   ServiceConfigVersionResourceProvider.SERVICE_CONFIG_VERSION_CONFIGURATIONS_PROPERTY_ID,
                   serviceConfigVersionResponse.getConfigurations());
+              }
+              associatedResources.add(resource);
             }
-            associatedResources.add(resource);
           }
 
         }
@@ -302,6 +309,16 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor {
   }
 
 
+  /**
+   * Package-level access for cluster config
+   * @return cluster config map
+   */
+  Map<String, Map<String, String>> getClusterConfigurations() {
+    return mapClusterConfigurations;
+  }
+
+
+
   // ----- utility methods ---------------------------------------------------
 
   /**
@@ -319,12 +336,12 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor {
         (String) properties.get(CLUSTER_VERSION_PROPERTY_ID),
         null);
 
-    ConfigurationRequest configRequest = getConfigurationRequest("Clusters", properties);
+    List<ConfigurationRequest> configRequests = getConfigurationRequests("Clusters", properties);
 
     ServiceConfigVersionRequest serviceConfigVersionRequest = getServiceConfigVersionRequest("Clusters", properties);
 
-    if (null != configRequest)
-      cr.setDesiredConfig(configRequest);
+    if (!configRequests.isEmpty())
+      cr.setDesiredConfig(configRequests);
 
     if (serviceConfigVersionRequest != null) {
       cr.setServiceConfigVersionRequest(serviceConfigVersionRequest);
@@ -343,13 +360,13 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor {
       String absCategory = PropertyHelper.getPropertyCategory(entry.getKey());
       String propName = PropertyHelper.getPropertyName(entry.getKey());
 
-      if (absCategory.startsWith(parentCategory + "/desired_serviceconfigversions")) {
+      if (absCategory.startsWith(parentCategory + "/desired_service_config_version")) {
         serviceConfigVersionRequest =
             (serviceConfigVersionRequest ==null ) ? new ServiceConfigVersionRequest() : serviceConfigVersionRequest;
 
         if (propName.equals("service_name"))
           serviceConfigVersionRequest.setServiceName(entry.getValue().toString());
-        else if (propName.equals("serviceconfigversion"))
+        else if (propName.equals("service_config_version"))
           serviceConfigVersionRequest.setVersion(Long.valueOf(entry.getValue().toString()));
         else if (propName.equals("service_config_version_note")) {
           serviceConfigVersionRequest.setNote(entry.getValue().toString());
@@ -843,7 +860,7 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor {
 
     BlueprintConfigurationProcessor configurationProcessor = new BlueprintConfigurationProcessor(mapClusterConfigurations);
     configurationProcessor.doUpdateForClusterCreate(blueprintHostGroups);
-    setMissingConfigurations();
+    setMissingConfigurations(blueprintHostGroups);
   }
 
   /**
@@ -853,9 +870,9 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor {
    * @param blueprintConfigurations  map of blueprint configurations keyed by type
    */
   private void handleGlobalsBackwardsCompability(Stack stack,
-      Map<String, Map<String, String>> blueprintConfigurations) {
+      Map<String, Map<String, String>> blueprintConfigurations, String clusterName) {
     StackId stackId = new StackId(stack.getName(), stack.getVersion());
-    configHelper.moveDeprecatedGlobals(stackId, blueprintConfigurations);
+    configHelper.moveDeprecatedGlobals(stackId, blueprintConfigurations, clusterName);
   }
 
   /**
@@ -907,14 +924,29 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor {
   /**
    * Explicitly set any properties that are required but not currently provided in the stack definition.
    */
-  private void setMissingConfigurations() {
+  void setMissingConfigurations(Map<String, HostGroupImpl> blueprintHostGroups) {
     // AMBARI-5206
     final Map<String , String> userProps = new HashMap<String , String>();
-    userProps.put("oozie_user", "oozie-env");
-    userProps.put("hive_user", "hive-env");
-    userProps.put("hcat_user", "hive-env");
-    userProps.put("hbase_user", "hbase-env");
-    userProps.put("falcon_user", "falcon-env");
+
+    // only add user properties to the map for
+    // services actually included in the blueprint definition
+    if (isServiceIncluded("OOZIE", blueprintHostGroups)) {
+      userProps.put("oozie_user", "oozie-env");
+    }
+
+    if (isServiceIncluded("HIVE", blueprintHostGroups)) {
+      userProps.put("hive_user", "hive-env");
+      userProps.put("hcat_user", "hive-env");
+    }
+
+    if (isServiceIncluded("HBASE", blueprintHostGroups)) {
+      userProps.put("hbase_user", "hbase-env");
+    }
+
+    if (isServiceIncluded("FALCON", blueprintHostGroups)) {
+      userProps.put("falcon_user", "falcon-env");
+    }
+
 
     String proxyUserHosts  = "hadoop.proxyuser.%s.hosts";
     String proxyUserGroups = "hadoop.proxyuser.%s.groups";
@@ -922,14 +954,40 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor {
     for (String property : userProps.keySet()) {
       String configType = userProps.get(property);
       Map<String, String> configs = mapClusterConfigurations.get(configType);
-      String user = configs.get(property);
-      if (user != null && !user.isEmpty()) {
-        ensureProperty("core-site", String.format(proxyUserHosts, user), "*");
-        ensureProperty("core-site", String.format(proxyUserGroups, user), "users");
+      if (configs != null) {
+        String user = configs.get(property);
+        if (user != null && !user.isEmpty()) {
+          ensureProperty("core-site", String.format(proxyUserHosts, user), "*");
+          ensureProperty("core-site", String.format(proxyUserGroups, user), "users");
+        }
+      } else {
+        LOG.debug("setMissingConfigurations: no user configuration found for type = " + configType + ".  This may be caused by an error in the blueprint configuration.");
       }
+
     }
   }
 
+
+  /**
+   * Determines if any components in the specified service are
+   *   included in the current blueprint's host group definitions.
+   *
+   * @param serviceName the Hadoop service name to query on
+   * @param blueprintHostGroups the map of Host Groups in the current blueprint
+   * @return true if the named service is included in the blueprint
+   *         false if the named service it not included in the blueprint
+   */
+  protected boolean isServiceIncluded(String serviceName, Map<String, HostGroupImpl> blueprintHostGroups) {
+    for (String hostGroupName : blueprintHostGroups.keySet()) {
+      HostGroupImpl hostGroup = blueprintHostGroups.get(hostGroupName);
+      if (hostGroup.getServices().contains(serviceName)) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
   /**
    * Ensure that the specified property exists.
    * If not, set a default value.
@@ -993,7 +1051,7 @@ public class ClusterResourceProvider extends BaseBlueprintProcessor {
       HostGroupEntity entity = group.getEntity();
       Map<String, Map<String, Config>> groupConfigs = new HashMap<String, Map<String, Config>>();
       
-      handleGlobalsBackwardsCompability(stack, group.getConfigurationProperties());
+      handleGlobalsBackwardsCompability(stack, group.getConfigurationProperties(), clusterName);
       for (Map.Entry<String, Map<String, String>> entry: group.getConfigurationProperties().entrySet()) {
         String type = entry.getKey();
         String service = stack.getServiceForConfigType(type);

+ 4 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigGroupResourceProvider.java

@@ -74,6 +74,8 @@ public class ConfigGroupResourceProvider extends
     .getPropertyId("ConfigGroup", "tag");
   protected static final String CONFIGGROUP_DESC_PROPERTY_ID = PropertyHelper
     .getPropertyId("ConfigGroup", "description");
+  protected static final String CONFIGGROUP_SCV_NOTE_ID = PropertyHelper
+      .getPropertyId("ConfigGroup", "service_config_version_note");
   protected static final String CONFIGGROUP_HOSTNAME_PROPERTY_ID =
     PropertyHelper.getPropertyId(null, "host_name");
   public static final String CONFIGGROUP_HOSTS_PROPERTY_ID = PropertyHelper
@@ -595,6 +597,8 @@ public class ConfigGroupResourceProvider extends
       null,
       null);
 
+    request.setServiceConfigVersionNote((String) properties.get(CONFIGGROUP_SCV_NOTE_ID));
+
     Map<String, Config> configurations = new HashMap<String, Config>();
     Set<String> hosts = new HashSet<String>();
 

+ 27 - 27
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java

@@ -330,9 +330,9 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
     if (null != o)
       hostRequest.setMaintenanceState(o.toString());
     
-    ConfigurationRequest cr = getConfigurationRequest("Hosts", properties);
+    List<ConfigurationRequest> cr = getConfigurationRequests("Hosts", properties);
     
-    hostRequest.setDesiredConfig(cr);
+    hostRequest.setDesiredConfigs(cr);
 
     return hostRequest;
   }
@@ -588,40 +588,40 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
         }
       }
 
-      if (null != request.getClusterName() && null != request.getDesiredConfig()) {
+      if (null != request.getClusterName() && null != request.getDesiredConfigs()) {
         Cluster c = clusters.getCluster(request.getClusterName());
 
         if (clusters.getHostsForCluster(request.getClusterName()).containsKey(h.getHostName())) {
 
-          ConfigurationRequest cr = request.getDesiredConfig();
+          for (ConfigurationRequest cr : request.getDesiredConfigs()) {
 
-          if (null != cr.getProperties() && cr.getProperties().size() > 0) {
-            LOG.info(MessageFormat.format("Applying configuration with tag ''{0}'' to host ''{1}'' in cluster ''{2}''",
-                cr.getVersionTag(),
-                request.getHostname(),
-                request.getClusterName()));
+            if (null != cr.getProperties() && cr.getProperties().size() > 0) {
+              LOG.info(MessageFormat.format("Applying configuration with tag ''{0}'' to host ''{1}'' in cluster ''{2}''",
+                  cr.getVersionTag(),
+                  request.getHostname(),
+                  request.getClusterName()));
 
-            cr.setClusterName(c.getClusterName());
-            controller.createConfiguration(cr);
-          }
+              cr.setClusterName(c.getClusterName());
+              controller.createConfiguration(cr);
+            }
 
-          Config baseConfig = c.getConfig(cr.getType(), cr.getVersionTag());
-          if (null != baseConfig) {
-            String authName = controller.getAuthName();
-            DesiredConfig oldConfig = h.getDesiredConfigs(c.getClusterId()).get(cr.getType());
-
-            if (h.addDesiredConfig(c.getClusterId(), cr.isSelected(), authName,  baseConfig)) {
-              Logger logger = LoggerFactory.getLogger("configchange");
-              logger.info("cluster '" + c.getClusterName() + "', "
-                  + "host '" + h.getHostName() + "' "
-                  + "changed by: '" + authName + "'; "
-                  + "type='" + baseConfig.getType() + "' "
-                  + "version='" + baseConfig.getVersion() + "'"
-                  + "tag='" + baseConfig.getTag() + "'"
-                  + (null == oldConfig ? "" : ", from='" + oldConfig.getTag() + "'"));
+            Config baseConfig = c.getConfig(cr.getType(), cr.getVersionTag());
+            if (null != baseConfig) {
+              String authName = controller.getAuthName();
+              DesiredConfig oldConfig = h.getDesiredConfigs(c.getClusterId()).get(cr.getType());
+
+              if (h.addDesiredConfig(c.getClusterId(), cr.isSelected(), authName,  baseConfig)) {
+                Logger logger = LoggerFactory.getLogger("configchange");
+                logger.info("cluster '" + c.getClusterName() + "', "
+                    + "host '" + h.getHostName() + "' "
+                    + "changed by: '" + authName + "'; "
+                    + "type='" + baseConfig.getType() + "' "
+                    + "version='" + baseConfig.getVersion() + "'"
+                    + "tag='" + baseConfig.getTag() + "'"
+                    + (null == oldConfig ? "" : ", from='" + oldConfig.getTag() + "'"));
+              }
             }
           }
-
         }
       }
       //todo: if attempt was made to update a property other than those

+ 2 - 2
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RecommendationResourceProvider.java

@@ -50,7 +50,7 @@ import org.apache.ambari.server.controller.utilities.PropertyHelper;
 public class RecommendationResourceProvider extends StackAdvisorResourceProvider {
 
   protected static final String RECOMMENDATION_ID_PROPERTY_ID = PropertyHelper.getPropertyId(
-      "Recommendations", "id");
+      "Recommendation", "id");
 
   protected static final String HOSTS_PROPERTY_ID = "hosts";
   protected static final String SERVICES_PROPERTY_ID = "services";
@@ -101,7 +101,7 @@ public class RecommendationResourceProvider extends StackAdvisorResourceProvider
       public Resource invoke() throws AmbariException {
 
         Resource resource = new ResourceImpl(Resource.Type.Recommendation);
-        setResourceProperty(resource, RECOMMENDATION_ID_PROPERTY_ID, "1", getPropertyIds());
+        setResourceProperty(resource, RECOMMENDATION_ID_PROPERTY_ID, response.getId(), getPropertyIds());
         setResourceProperty(resource, STACK_NAME_PROPERTY_ID, response.getVersion().getStackName(),
             getPropertyIds());
         setResourceProperty(resource, STACK_VERSION_PROPERTY_ID, response.getVersion()

+ 7 - 5
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceConfigVersionResourceProvider.java

@@ -26,21 +26,21 @@ import org.apache.ambari.server.controller.ServiceConfigVersionRequest;
 import org.apache.ambari.server.controller.ServiceConfigVersionResponse;
 import org.apache.ambari.server.controller.spi.*;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
-import org.apache.ambari.server.state.Config;
 
 import java.util.*;
 
 public class ServiceConfigVersionResourceProvider extends
     AbstractControllerResourceProvider {
   public static final String SERVICE_CONFIG_VERSION_CLUSTER_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(null, "cluster_name");
-  public static final String SERVICE_CONFIG_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId(null, "serviceconfigversion");
+  public static final String SERVICE_CONFIG_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId(null, "service_config_version");
   public static final String SERVICE_CONFIG_VERSION_SERVICE_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(null, "service_name");
   public static final String SERVICE_CONFIG_VERSION_CREATE_TIME_PROPERTY_ID = PropertyHelper.getPropertyId(null, "createtime");
   public static final String SERVICE_CONFIG_VERSION_USER_PROPERTY_ID = PropertyHelper.getPropertyId(null, "user");
   public static final String SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID = PropertyHelper.getPropertyId(null, "service_config_version_note");
   public static final String SERVICE_CONFIG_VERSION_GROUP_ID_PROPERTY_ID = PropertyHelper.getPropertyId(null, "group_id");
   public static final String SERVICE_CONFIG_VERSION_GROUP_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(null, "group_name");
-  public static final String SERVICE_CONFIG_VERSION_HOSTNAMES_PROPERTY_ID = PropertyHelper.getPropertyId(null, "hosts");
+  public static final String SERVICE_CONFIG_VERSION_IS_CURRENT_PROPERTY_ID = PropertyHelper.getPropertyId(null, "is_current");
+  public static final String SERVICE_CONFIG_VERSION_HOSTS_PROPERTY_ID = PropertyHelper.getPropertyId(null, "hosts");
   public static final String SERVICE_CONFIG_VERSION_CONFIGURATIONS_PROPERTY_ID = PropertyHelper.getPropertyId(null, "configurations");
 
   /**
@@ -106,7 +106,8 @@ public class ServiceConfigVersionResourceProvider extends
       resource.setProperty(SERVICE_CONFIG_VERSION_NOTE_PROPERTY_ID, response.getNote());
       resource.setProperty(SERVICE_CONFIG_VERSION_GROUP_ID_PROPERTY_ID, response.getGroupId());
       resource.setProperty(SERVICE_CONFIG_VERSION_GROUP_NAME_PROPERTY_ID, response.getGroupName());
-      resource.setProperty(SERVICE_CONFIG_VERSION_HOSTNAMES_PROPERTY_ID, response.getHosts());
+      resource.setProperty(SERVICE_CONFIG_VERSION_HOSTS_PROPERTY_ID, response.getHosts());
+      resource.setProperty(SERVICE_CONFIG_VERSION_IS_CURRENT_PROPERTY_ID, response.getIsCurrent());
 
       resources.add(resource);
     }
@@ -134,12 +135,13 @@ public class ServiceConfigVersionResourceProvider extends
 
     for (String propertyId : propertyIds) {
 
-      if (!propertyId.equals("cluster_name") && !propertyId.equals("serviceconfigversion") &&
+      if (!propertyId.equals("cluster_name") && !propertyId.equals("service_config_version") &&
           !propertyId.equals("service_name") && !propertyId.equals("createtime") &&
           !propertyId.equals("appliedtime") && !propertyId.equals("user") &&
           !propertyId.equals("service_config_version_note") &&
           !propertyId.equals("group_id") &&
           !propertyId.equals("group_name") &&
+          !propertyId.equals("is_current") &&
           !propertyId.equals("hosts")) {
 
         unsupportedProperties.add(propertyId);

+ 9 - 13
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackServiceComponentResourceProvider.java

@@ -18,27 +18,17 @@
 
 package org.apache.ambari.server.controller.internal;
 
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.StackServiceComponentRequest;
 import org.apache.ambari.server.controller.StackServiceComponentResponse;
-import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
-import org.apache.ambari.server.controller.spi.NoSuchResourceException;
-import org.apache.ambari.server.controller.spi.Predicate;
-import org.apache.ambari.server.controller.spi.Request;
-import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.*;
 import org.apache.ambari.server.controller.spi.Resource.Type;
-import org.apache.ambari.server.controller.spi.SystemException;
-import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.state.AutoDeployInfo;
 
+import java.util.*;
+
 public class StackServiceComponentResourceProvider extends
     ReadOnlyResourceProvider {
 
@@ -54,6 +44,9 @@ public class StackServiceComponentResourceProvider extends
   private static final String COMPONENT_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(
       "StackServiceComponents", "component_name");
 
+  private static final String COMPONENT_DISPLAY_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(
+          "StackServiceComponents", "display_name");
+
   private static final String COMPONENT_CATEGORY_PROPERTY_ID = PropertyHelper.getPropertyId(
       "StackServiceComponents", "component_category");
 
@@ -127,6 +120,9 @@ public class StackServiceComponentResourceProvider extends
       setResourceProperty(resource, COMPONENT_NAME_PROPERTY_ID,
           response.getComponentName(), requestedIds);
 
+      setResourceProperty(resource, COMPONENT_DISPLAY_NAME_PROPERTY_ID,
+              response.getComponentDisplayName(), requestedIds);
+
       setResourceProperty(resource, COMPONENT_CATEGORY_PROPERTY_ID,
           response.getComponentCategory(), requestedIds);
 

+ 9 - 13
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackServiceResourceProvider.java

@@ -19,26 +19,16 @@
 
 package org.apache.ambari.server.controller.internal;
 
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.StackServiceRequest;
 import org.apache.ambari.server.controller.StackServiceResponse;
-import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
-import org.apache.ambari.server.controller.spi.NoSuchResourceException;
-import org.apache.ambari.server.controller.spi.Predicate;
-import org.apache.ambari.server.controller.spi.Request;
-import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.*;
 import org.apache.ambari.server.controller.spi.Resource.Type;
-import org.apache.ambari.server.controller.spi.SystemException;
-import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 
+import java.util.*;
+
 public class StackServiceResourceProvider extends ReadOnlyResourceProvider {
 
   protected static final String SERVICE_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(
@@ -50,6 +40,9 @@ public class StackServiceResourceProvider extends ReadOnlyResourceProvider {
   public static final String STACK_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId(
       "StackServices", "stack_version");
 
+  private static final String SERVICE_DISPLAY_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(
+      "StackServices", "display_name");
+
   private static final String USER_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(
       "StackServices", "user_name");
 
@@ -119,6 +112,9 @@ public class StackServiceResourceProvider extends ReadOnlyResourceProvider {
       setResourceProperty(resource, SERVICE_NAME_PROPERTY_ID,
           response.getServiceName(), requestedIds);
 
+      setResourceProperty(resource, SERVICE_DISPLAY_NAME_PROPERTY_ID,
+              response.getServiceDisplayName(), requestedIds);
+
       setResourceProperty(resource, USER_NAME_PROPERTY_ID,
           response.getUserName(), requestedIds);
 

+ 2 - 2
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ValidationResourceProvider.java

@@ -49,7 +49,7 @@ import org.apache.ambari.server.controller.utilities.PropertyHelper;
 public class ValidationResourceProvider extends StackAdvisorResourceProvider {
 
   protected static final String VALIDATION_ID_PROPERTY_ID = PropertyHelper.getPropertyId(
-      "Validations", "id");
+      "Validation", "id");
   protected static final String VALIDATE_PROPERTY_ID = "validate";
 
   protected static final String ITEMS_PROPERTY_ID = "items";
@@ -93,7 +93,7 @@ public class ValidationResourceProvider extends StackAdvisorResourceProvider {
       public Resource invoke() throws AmbariException {
 
         Resource resource = new ResourceImpl(Resource.Type.Validation);
-        setResourceProperty(resource, VALIDATION_ID_PROPERTY_ID, "1", getPropertyIds());
+        setResourceProperty(resource, VALIDATION_ID_PROPERTY_ID, response.getId(), getPropertyIds());
         setResourceProperty(resource, STACK_NAME_PROPERTY_ID, response.getVersion().getStackName(), getPropertyIds());
         setResourceProperty(resource, STACK_VERSION_PROPERTY_ID, response.getVersion().getStackVersion(), getPropertyIds());
 

+ 8 - 1
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java

@@ -19,6 +19,7 @@
 package org.apache.ambari.server.controller.internal;
 
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.DuplicateResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
 import org.apache.ambari.server.controller.spi.Predicate;
@@ -332,7 +333,13 @@ public class ViewInstanceResourceProvider extends AbstractResourceProvider {
       @Override
       public Void invoke() throws AmbariException {
         try {
-          ViewRegistry.getInstance().installViewInstance(toEntity(properties));
+          ViewRegistry       viewRegistry   = ViewRegistry.getInstance();
+          ViewInstanceEntity instanceEntity = toEntity(properties);
+
+          if (viewRegistry.instanceExists(instanceEntity)) {
+            throw new DuplicateResourceException("The instance " + instanceEntity.getName() + " already exists.");
+          }
+          viewRegistry.installViewInstance(instanceEntity);
         } catch (org.apache.ambari.view.SystemException e) {
           throw new AmbariException("Caught exception trying to create view instance.", e);
         }

+ 3 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewVersionResourceProvider.java

@@ -47,6 +47,7 @@ public class ViewVersionResourceProvider extends AbstractResourceProvider {
   public static final String VIEW_NAME_PROPERTY_ID      = "ViewVersionInfo/view_name";
   public static final String VIEW_VERSION_PROPERTY_ID   = "ViewVersionInfo/version";
   public static final String LABEL_PROPERTY_ID          = "ViewVersionInfo/label";
+  public static final String DESCRIPTION_PROPERTY_ID    = "ViewVersionInfo/description";
   public static final String VERSION_PROPERTY_ID        = "ViewVersionInfo/version";
   public static final String PARAMETERS_PROPERTY_ID     = "ViewVersionInfo/parameters";
   public static final String ARCHIVE_PROPERTY_ID        = "ViewVersionInfo/archive";
@@ -69,6 +70,7 @@ public class ViewVersionResourceProvider extends AbstractResourceProvider {
     propertyIds.add(VIEW_NAME_PROPERTY_ID);
     propertyIds.add(VIEW_VERSION_PROPERTY_ID);
     propertyIds.add(LABEL_PROPERTY_ID);
+    propertyIds.add(DESCRIPTION_PROPERTY_ID);
     propertyIds.add(VERSION_PROPERTY_ID);
     propertyIds.add(PARAMETERS_PROPERTY_ID);
     propertyIds.add(ARCHIVE_PROPERTY_ID);
@@ -121,6 +123,7 @@ public class ViewVersionResourceProvider extends AbstractResourceProvider {
             setResourceProperty(resource, VIEW_NAME_PROPERTY_ID, viewDefinition.getCommonName(), requestedIds);
             setResourceProperty(resource, VIEW_VERSION_PROPERTY_ID, viewDefinition.getVersion(), requestedIds);
             setResourceProperty(resource, LABEL_PROPERTY_ID, viewDefinition.getLabel(), requestedIds);
+            setResourceProperty(resource, DESCRIPTION_PROPERTY_ID, viewDefinition.getDescription(), requestedIds);
             setResourceProperty(resource, VERSION_PROPERTY_ID, viewDefinition.getVersion(), requestedIds);
             setResourceProperty(resource, PARAMETERS_PROPERTY_ID,
                 viewDefinition.getConfiguration().getParameters(), requestedIds);

+ 40 - 1
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceConfigDAO.java

@@ -26,7 +26,15 @@ import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.ServiceConfigEntity;
 
 import javax.persistence.EntityManager;
+import javax.persistence.Tuple;
 import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+import javax.persistence.criteria.Subquery;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -66,6 +74,37 @@ public class ServiceConfigDAO {
     return maxVersions;
   }
 
+  @RequiresSession
+  public List<ServiceConfigEntity> getLastServiceConfigVersionsForGroups(Collection<Long> configGroupIds) {
+    if (configGroupIds == null || configGroupIds.isEmpty()) {
+      return Collections.emptyList();
+    }
+    CriteriaBuilder cb = entityManagerProvider.get().getCriteriaBuilder();
+    CriteriaQuery<Tuple> cq = cb.createTupleQuery();
+    Root<ServiceConfigEntity> groupVersion = cq.from(ServiceConfigEntity.class);
+
+
+    cq.multiselect(groupVersion.get("groupId").alias("groupId"), cb.max(groupVersion.<Long>get("version")).alias("lastVersion"));
+    cq.where(groupVersion.get("groupId").in(configGroupIds));
+    cq.groupBy(groupVersion.get("groupId"));
+    List<Tuple> tuples = daoUtils.selectList(entityManagerProvider.get().createQuery(cq));
+    List<ServiceConfigEntity> result = new ArrayList<ServiceConfigEntity>();
+    //subquery look to be very poor, no bulk select then, cache should help here as result size is naturally limited
+    for (Tuple tuple : tuples) {
+      CriteriaQuery<ServiceConfigEntity> sce = cb.createQuery(ServiceConfigEntity.class);
+      Root<ServiceConfigEntity> sceRoot = sce.from(ServiceConfigEntity.class);
+
+      sce.where(cb.and(cb.equal(sceRoot.get("groupId"), tuple.get("groupId")),
+        cb.equal(sceRoot.get("version"), tuple.get("lastVersion"))));
+      sce.select(sceRoot);
+      result.add(daoUtils.selectSingle(entityManagerProvider.get().createQuery(sce)));
+    }
+
+    return result;
+  }
+
+
+
   @RequiresSession
   public List<Long> getServiceConfigVersionsByConfig(Long clusterId, String configType, Long configVersion) {
     TypedQuery<Long> query = entityManagerProvider.get().createQuery("SELECT scv.version " +
@@ -80,7 +119,7 @@ public class ServiceConfigDAO {
       createQuery("SELECT scv FROM ServiceConfigEntity scv " +
         "WHERE scv.clusterId = ?1 AND scv.createTimestamp = (" +
         "SELECT MAX(scv2.createTimestamp) FROM ServiceConfigEntity scv2 " +
-        "WHERE scv2.serviceName = scv.serviceName AND scv2.clusterId = ?1)",
+        "WHERE scv2.serviceName = scv.serviceName AND scv2.clusterId = ?1 AND scv2.groupId IS NULL)",
         ServiceConfigEntity.class);
 
     return daoUtils.selectList(query, clusterId);

+ 53 - 21
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java

@@ -65,6 +65,9 @@ public class AlertGroupEntity {
   @Column(name = "is_default", nullable = false)
   private Integer isDefault = Integer.valueOf(0);
 
+  @Column(name = "service_name", nullable = true, length = 255)
+  private String serviceName;
+
   /**
    * Bi-directional many-to-many association to {@link AlertDefinitionEntity}
    */
@@ -81,7 +84,7 @@ public class AlertGroupEntity {
 
   /**
    * Gets the unique ID of this grouping of alerts.
-   * 
+   *
    * @return the ID (never {@code null}).
    */
   public Long getGroupId() {
@@ -90,7 +93,7 @@ public class AlertGroupEntity {
 
   /**
    * Sets the unique ID of this grouping of alerts.
-   * 
+   *
    * @param groupId
    *          the ID (not {@code null}).
    */
@@ -100,7 +103,7 @@ public class AlertGroupEntity {
 
   /**
    * Gets the ID of the cluster that this alert group is a part of.
-   * 
+   *
    * @return the ID (never {@code null}).
    */
   public Long getClusterId() {
@@ -109,7 +112,7 @@ public class AlertGroupEntity {
 
   /**
    * Sets the ID of the cluster that this alert group is a part of.
-   * 
+   *
    * @param clusterId
    *          the ID of the cluster (not {@code null}).
    */
@@ -120,7 +123,7 @@ public class AlertGroupEntity {
   /**
    * Gets the name of the grouping of alerts. Group names are unique in a given
    * cluster.
-   * 
+   *
    * @return the group name (never {@code null}).
    */
   public String getGroupName() {
@@ -130,7 +133,7 @@ public class AlertGroupEntity {
   /**
    * Sets the name of this grouping of alerts. Group names are unique in a given
    * cluster.
-   * 
+   *
    * @param groupName
    *          the name of the group (not {@code null}).
    */
@@ -143,7 +146,7 @@ public class AlertGroupEntity {
    * groups cannot have their alert definition groupings changed. New alert
    * definitions are automtaically added to the default group that belongs to
    * the service of that definition.
-   * 
+   *
    * @return {@code true} if this is a default group, {@code false} otherwise.
    */
   public boolean isDefault() {
@@ -152,7 +155,7 @@ public class AlertGroupEntity {
 
   /**
    * Sets whether this is a default group and is immutable.
-   * 
+   *
    * @param isDefault
    *          {@code true} to make this group immutable.
    */
@@ -161,8 +164,31 @@ public class AlertGroupEntity {
   }
 
   /**
-   * Gets all of the alert definitions that are a part of this grouping.
+   * Gets the name of the service. This is only applicable when
+   * {@link #isDefault()} is {@code true}.
+   *
+   * @return the service that this is the default group for, or {@code null} if
+   *         this is not a default group.
+   */
+  public String getServiceName() {
+    return serviceName;
+  }
+
+  /**
+   * Set the service name. This is only applicable when {@link #isDefault()} is
+   * {@code true}.
    * 
+   * @param serviceName
+   *          the service that this is the default group for, or {@code null} if
+   *          this is not a default group.
+   */
+  public void setServiceName(String serviceName) {
+    this.serviceName = serviceName;
+  }
+
+  /**
+   * Gets all of the alert definitions that are a part of this grouping.
+   *
    * @return the alert definitions or {@code null} if none.
    */
   public Set<AlertDefinitionEntity> getAlertDefinitions() {
@@ -171,7 +197,7 @@ public class AlertGroupEntity {
 
   /**
    * Set all of the alert definitions that are part of this alert group.
-   * 
+   *
    * @param alertDefinitions
    *          the definitions, or {@code null} for none.
    */
@@ -182,25 +208,27 @@ public class AlertGroupEntity {
   /**
    * Gets an immutable set of the targets that will receive notifications for
    * alert definitions in this group.
-   * 
+   *
    * @return the targets, or {@code null} if there are none.
    */
   public Set<AlertTargetEntity> getAlertTargets() {
-    if( null == alertTargets )
+    if( null == alertTargets ) {
       return Collections.emptySet();
-      
+    }
+
     return Collections.unmodifiableSet(alertTargets);
   }
 
   /**
    * Adds the specified target to the targets that this group will dispatch to.
-   * 
+   *
    * @param alertTarget
    *          the target to add (not {@code null}).
    */
   public void addAlertTarget(AlertTargetEntity alertTarget) {
-    if (null == alertTargets)
+    if (null == alertTargets) {
       alertTargets = new HashSet<AlertTargetEntity>();
+    }
 
     alertTargets.add(alertTarget);
     alertTarget.addAlertGroup(this);
@@ -209,13 +237,14 @@ public class AlertGroupEntity {
   /**
    * Removes the specified target from the targets that this group will dispatch
    * to.
-   * 
+   *
    * @param alertTarget
    *          the target to remove (not {@code null}).
    */
   public void removeAlertTarget(AlertTargetEntity alertTarget) {
-    if (null != alertTargets)
+    if (null != alertTargets) {
       alertTargets.remove(alertTarget);
+    }
 
     alertTarget.removeAlertGroup(this);
   }
@@ -223,7 +252,7 @@ public class AlertGroupEntity {
   /**
    * Sets all of the targets that will receive notifications for alert
    * definitions in this group.
-   * 
+   *
    * @param alertTargets
    *          the targets, or {@code null} if there are none.
    */
@@ -248,16 +277,19 @@ public class AlertGroupEntity {
    */
   @Override
   public boolean equals(Object object) {
-    if (this == object)
+    if (this == object) {
       return true;
+    }
 
-    if (object == null || getClass() != object.getClass())
+    if (object == null || getClass() != object.getClass()) {
       return false;
+    }
 
     AlertGroupEntity that = (AlertGroupEntity) object;
 
-    if (groupId != null ? !groupId.equals(that.groupId) : that.groupId != null)
+    if (groupId != null ? !groupId.equals(that.groupId) : that.groupId != null) {
       return false;
+    }
 
     return true;
   }

+ 28 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StageEntity.java

@@ -51,6 +51,14 @@ public class StageEntity {
   @Column(name = "cluster_host_info")
   @Basic
   private byte[] clusterHostInfo;
+ 
+  @Column(name = "command_params")
+  @Basic
+  private byte[] commandParamsStage;
+
+  @Column(name = "host_params")
+  @Basic
+  private byte[] hostParamsStage;
 
   @ManyToOne
   @JoinColumn(name = "request_id", referencedColumnName = "request_id", nullable = false)
@@ -106,6 +114,22 @@ public class StageEntity {
   public void setClusterHostInfo(String clusterHostInfo) {
     this.clusterHostInfo = clusterHostInfo.getBytes();
   }
+ 
+  public String getCommandParamsStage() {
+    return commandParamsStage == null ? new String() : new String(commandParamsStage);
+  }
+
+  public void setCommandParamsStage(String commandParamsStage) {
+    this.commandParamsStage = commandParamsStage.getBytes();
+  }
+
+  public String getHostParamsStage() {
+    return hostParamsStage == null ? new String() : new String(hostParamsStage);
+  }
+
+  public void setHostParamsStage(String hostParamsStage) {
+    this.hostParamsStage = hostParamsStage.getBytes();
+  }
 
   public void setRequestContext(String requestContext) {
     if (requestContext != null) {
@@ -125,6 +149,8 @@ public class StageEntity {
     if (requestId != null ? !requestId.equals(that.requestId) : that.requestId != null) return false;
     if (stageId != null ? !stageId.equals(that.stageId) : that.stageId != null) return false;
     if (clusterHostInfo != null ? !clusterHostInfo.equals(that.clusterHostInfo) : that.clusterHostInfo != null) return false;
+    if (commandParamsStage != null ? !commandParamsStage.equals(that.commandParamsStage) : that.commandParamsStage != null) return false;
+    if (hostParamsStage != null ? !hostParamsStage.equals(that.hostParamsStage) : that.hostParamsStage != null) return false;
     return !(requestContext != null ? !requestContext.equals(that.requestContext) : that.requestContext != null);
 
   }
@@ -136,6 +162,8 @@ public class StageEntity {
     result = 31 * result + (stageId != null ? stageId.hashCode() : 0);
     result = 31 * result + (logInfo != null ? logInfo.hashCode() : 0);
     result = 31 * result + (clusterHostInfo != null ? clusterHostInfo.hashCode() : 0);
+    result = 31 * result + (commandParamsStage != null ? commandParamsStage.hashCode() : 0);
+    result = 31 * result + (hostParamsStage != null ? hostParamsStage.hashCode() : 0);
     result = 31 * result + (requestContext != null ? requestContext.hashCode() : 0);
     return result;
   }

+ 31 - 8
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java

@@ -39,6 +39,7 @@ import javax.persistence.NamedQuery;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
 import javax.persistence.Transient;
+
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -68,6 +69,13 @@ public class ViewEntity implements ViewDefinition {
   @Basic
   private String label;
 
+  /**
+   * The view description.
+   */
+  @Column
+  @Basic
+  private String description;
+
   /**
    * The icon path.
    */
@@ -226,13 +234,14 @@ public class ViewEntity implements ViewDefinition {
 
     String version = configuration.getVersion();
 
-    this.name    = getViewName(configuration.getName(), version);
-    this.label   = configuration.getLabel();
-    this.version = version;
+    this.name        = getViewName(configuration.getName(), version);
+    this.label       = configuration.getLabel();
+    this.description = configuration.getDescription();
+    this.version     = version;
 
-    this.mask    = configuration.getMasker();
-    this.icon    = configuration.getIcon();
-    this.icon64  = configuration.getIcon64();
+    this.mask        = configuration.getMasker();
+    this.icon        = configuration.getIcon();
+    this.icon64      = configuration.getIcon64();
 
     this.externalResourceType =
         new Resource.Type(getQualifiedResourceTypeName(ResourceConfig.EXTERNAL_RESOURCE_PLURAL_NAME));
@@ -251,6 +260,11 @@ public class ViewEntity implements ViewDefinition {
     return label;
   }
 
+  @Override
+  public String getDescription() {
+    return description;
+  }
+
   @Override
   public String getVersion() {
     return version;
@@ -294,16 +308,25 @@ public class ViewEntity implements ViewDefinition {
   /**
    * Set the view label (display name).
    *
-   * @param label  the view label
+   * @param label the view label
    */
   public void setLabel(String label) {
     this.label = label;
   }
 
+  /**
+   * Set the view description.
+   *
+   * @param description the view description
+   */
+  public void setDescription(String description) {
+    this.description = description;
+  }
+
   /**
    * Set the view version.
    *
-   * @param version  the version
+   * @param version the version
    */
   public void setVersion(String version) {
     this.version = version;

+ 2 - 1
ambari-server/src/main/java/org/apache/ambari/server/stageplanner/RoleGraph.java

@@ -139,7 +139,8 @@ public class RoleGraph {
     Stage newStage = new Stage(origStage.getRequestId(),
         origStage.getLogDir(), origStage.getClusterName(),
         origStage.getClusterId(),
-        origStage.getRequestContext(), origStage.getClusterHostInfo());
+        origStage.getRequestContext(), origStage.getClusterHostInfo(),
+        origStage.getCommandParamsStage(), origStage.getHostParamsStage());
     newStage.setSuccessFactors(origStage.getSuccessFactors());
     for (RoleGraphNode rgn : stageGraphNodes) {
       for (String host : rgn.getHosts()) {

+ 8 - 7
ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java

@@ -21,6 +21,7 @@ package org.apache.ambari.server.state;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.locks.ReadWriteLock;
 
 import com.google.common.collect.ListMultimap;
@@ -157,22 +158,22 @@ public interface Cluster {
    * Adds and sets a DESIRED configuration to be applied to a cluster.  There
    * can be only one selected config per type.
    * @param user the user making the change for audit purposes
-   * @param config  the {@link org.apache.ambari.server.state.Config} object to set as desired
+   * @param configs  the set of {@link org.apache.ambari.server.state.Config} objects to set as desired
    * @return <code>true</code> if the config was added, or <code>false</code>
    * if the config is already set as the current
    */
-  public ServiceConfigVersionResponse addDesiredConfig(String user, Config config);
+  public ServiceConfigVersionResponse addDesiredConfig(String user, Set<Config> configs);
 
   /**
    * Adds and sets a DESIRED configuration to be applied to a cluster.  There
    * can be only one selected config per type.
    * @param user the user making the change for audit purposes
-   * @param config  the {@link org.apache.ambari.server.state.Config} object to set as desired
+   * @param configs  the set of {@link org.apache.ambari.server.state.Config} objects to set as desired
    * @param serviceConfigVersionNote note to attach to service config version if created
    * @return <code>true</code> if the config was added, or <code>false</code>
    * if the config is already set as the current
    */
-  ServiceConfigVersionResponse addDesiredConfig(String user, Config config, String serviceConfigVersionNote);
+  ServiceConfigVersionResponse addDesiredConfig(String user, Set<Config> configs, String serviceConfigVersionNote);
 
   ServiceConfigVersionResponse createServiceConfigVersion(String serviceName, String user, String note,
                                                           ConfigGroup configGroup);
@@ -185,16 +186,16 @@ public interface Cluster {
    * @param version service config version
    * @param user the user making the change for audit purposes
    * @param note
-   * @return true if service config version applied
+   * @return service config version created
    * @throws AmbariException
    */
-  boolean setServiceConfigVersion(String serviceName, Long version, String user, String note) throws AmbariException;
+  ServiceConfigVersionResponse setServiceConfigVersion(String serviceName, Long version, String user, String note) throws AmbariException;
 
   /**
    * Get currently active service config versions for stack services
    * @return
    */
-  Map<String, ServiceConfigVersionResponse> getActiveServiceConfigVersions();
+  Map<String, Collection<ServiceConfigVersionResponse>> getActiveServiceConfigVersions();
 
   /**
    * Get service config version history

+ 11 - 3
ambari-server/src/main/java/org/apache/ambari/server/state/ComponentInfo.java

@@ -18,18 +18,18 @@
 
 package org.apache.ambari.server.state;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlElements;
+import java.util.ArrayList;
+import java.util.List;
 
 @XmlAccessorType(XmlAccessType.FIELD)
 public class ComponentInfo {
   private String name;
+  private String displayName;
   private String category;
   private boolean deleted;
   private String cardinality;
@@ -95,6 +95,14 @@ public class ComponentInfo {
     this.name = name;
   }
 
+  public String getDisplayName() {
+    return displayName;
+  }
+
+  public void setDisplayName(String displayName) {
+    this.displayName = displayName;
+  }
+
   public String getCategory() {
     return category;
   }

+ 8 - 7
ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java

@@ -19,6 +19,7 @@ package org.apache.ambari.server.state;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -413,14 +414,14 @@ public class ConfigHelper {
    * @param stackId
    * @param propertyName
    */
-  public Set<String> findConfigTypesByPropertyName(StackId stackId, String propertyName) throws AmbariException {
+  public Set<String> findConfigTypesByPropertyName(StackId stackId, String propertyName, String clusterName) throws AmbariException {
     StackInfo stack = ambariMetaInfo.getStackInfo(stackId.getStackName(),
         stackId.getStackVersion());
     
     Set<String> result = new HashSet<String>();
-    
-    for(ServiceInfo serviceInfo:stack.getServices()) {
-      Set<PropertyInfo> stackProperties = ambariMetaInfo.getProperties(stack.getName(), stack.getVersion(), serviceInfo.getName());
+
+    for(Service service : clusters.getCluster(clusterName).getServices().values()) {
+      Set<PropertyInfo> stackProperties = ambariMetaInfo.getProperties(stack.getName(), stack.getVersion(), service.getName());
       
       for (PropertyInfo stackProperty : stackProperties) {
         if(stackProperty.getName().equals(propertyName)) {
@@ -477,7 +478,7 @@ public class ConfigHelper {
     Config baseConfig = cluster.getConfig(cr.getType(), cr.getVersionTag());
     
     if (baseConfig != null) {
-      cluster.addDesiredConfig(authName, baseConfig);
+      cluster.addDesiredConfig(authName, Collections.singleton(baseConfig));
     }
   }
   
@@ -487,7 +488,7 @@ public class ConfigHelper {
    *
    * @param configurations  map of configurations keyed by type
    */
-  public void moveDeprecatedGlobals(StackId stackId, Map<String, Map<String, String>> configurations) {
+  public void moveDeprecatedGlobals(StackId stackId, Map<String, Map<String, String>> configurations, String clusterName) {
     Map<String, String> globalConfigurations = new HashMap<String, String>();
     
     if(configurations.get(Configuration.GLOBAL_CONFIG_TAG) == null ||
@@ -507,7 +508,7 @@ public class ConfigHelper {
       
       Set<String> newConfigTypes = null;
       try{
-        newConfigTypes = this.findConfigTypesByPropertyName(stackId, propertyName);
+        newConfigTypes = this.findConfigTypesByPropertyName(stackId, propertyName, clusterName);
       } catch(AmbariException e) {
         LOG.error("Exception while getting configurations from the stacks", e);
         return;

+ 9 - 0
ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java

@@ -52,6 +52,7 @@ public class ServiceInfo {
   private String schemaVersion;
 
   private String name;
+  private String displayName;
   private String version;
   private String comment;
   private List<PropertyInfo> properties;
@@ -163,6 +164,14 @@ public class ServiceInfo {
     this.name = name;
   }
 
+  public String getDisplayName() {
+    return displayName;
+  }
+
+  public void setDisplayName(String displayName) {
+    this.displayName = displayName;
+  }
+
   public String getVersion() {
     return version;
   }

+ 90 - 29
ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java

@@ -1365,12 +1365,12 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
-  public ServiceConfigVersionResponse addDesiredConfig(String user, Config config) {
-    return addDesiredConfig(user, config, null);
+  public ServiceConfigVersionResponse addDesiredConfig(String user, Set<Config> configs) {
+    return addDesiredConfig(user, configs, null);
   }
 
   @Override
-  public ServiceConfigVersionResponse addDesiredConfig(String user, Config config, String serviceConfigVersionNote) {
+  public ServiceConfigVersionResponse addDesiredConfig(String user, Set<Config> configs, String serviceConfigVersionNote) {
     if (null == user) {
       throw new NullPointerException("User must be specified.");
     }
@@ -1379,15 +1379,28 @@ public class ClusterImpl implements Cluster {
     try {
       readWriteLock.writeLock().lock();
       try {
-        Config currentDesired = getDesiredConfigByType(config.getType());
-
-        // do not set if it is already the current
-        if (null != currentDesired && currentDesired.getTag().equals(config.getTag())) {
+        if (configs == null) {
           return null;
         }
 
+        Iterator<Config> configIterator = configs.iterator();
+
+        while (configIterator.hasNext()) {
+          Config config = configIterator.next();
+          if (config == null) {
+            configIterator.remove();
+            continue;
+          }
+          Config currentDesired = getDesiredConfigByType(config.getType());
+
+          // do not set if it is already the current
+          if (null != currentDesired && currentDesired.getTag().equals(config.getTag())) {
+            configIterator.remove();
+          }
+        }
+
         ServiceConfigVersionResponse serviceConfigVersionResponse =
-            applyConfig(config.getType(), config.getTag(), user, serviceConfigVersionNote);
+            applyConfigs(configs, user, serviceConfigVersionNote);
 
         configHelper.invalidateStaleConfigsCache();
         return serviceConfigVersionResponse;
@@ -1525,7 +1538,7 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
-  public boolean setServiceConfigVersion(String serviceName, Long version, String user, String note) throws AmbariException {
+  public ServiceConfigVersionResponse setServiceConfigVersion(String serviceName, Long version, String user, String note) throws AmbariException {
     if (null == user) {
       throw new NullPointerException("User must be specified.");
     }
@@ -1534,9 +1547,9 @@ public class ClusterImpl implements Cluster {
     try {
       readWriteLock.writeLock().lock();
       try {
-        applyServiceConfigVersion(serviceName, version, user, note);
+        ServiceConfigVersionResponse serviceConfigVersionResponse = applyServiceConfigVersion(serviceName, version, user, note);
         configHelper.invalidateStaleConfigsCache();
-        return true;
+        return serviceConfigVersionResponse;
       } finally {
         readWriteLock.writeLock().unlock();
       }
@@ -1546,18 +1559,21 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
-  public Map<String, ServiceConfigVersionResponse> getActiveServiceConfigVersions() {
+  public Map<String, Collection<ServiceConfigVersionResponse>> getActiveServiceConfigVersions() {
     clusterGlobalLock.readLock().lock();
     try {
       readWriteLock.readLock().lock();
       try {
-        Map<String, ServiceConfigVersionResponse> result = new HashMap<String, ServiceConfigVersionResponse>();
+        Map<String, Collection<ServiceConfigVersionResponse>> map = new HashMap<String, Collection<ServiceConfigVersionResponse>>();
 
         Set<ServiceConfigVersionResponse> responses = getActiveServiceConfigVersionSet();
         for (ServiceConfigVersionResponse response : responses) {
-          result.put(response.getServiceName(), response);
+          if (map.get(response.getServiceName()) == null) {
+            map.put(response.getServiceName(), new ArrayList<ServiceConfigVersionResponse>());
+          }
+          map.get(response.getServiceName()).add(response);
         }
-        return result;
+        return map;
       } finally {
         readWriteLock.readLock().unlock();
       }
@@ -1574,6 +1590,8 @@ public class ClusterImpl implements Cluster {
       readWriteLock.readLock().lock();
       try {
         List<ServiceConfigVersionResponse> serviceConfigVersionResponses = new ArrayList<ServiceConfigVersionResponse>();
+        Set<Long> activeIds = getActiveServiceConfigVersionIds();
+
         for (ServiceConfigEntity serviceConfigEntity : serviceConfigDAO.getServiceConfigs(getClusterId())) {
           ServiceConfigVersionResponse serviceConfigVersionResponse = new ServiceConfigVersionResponse();
 
@@ -1585,6 +1603,7 @@ public class ClusterImpl implements Cluster {
           serviceConfigVersionResponse.setNote(serviceConfigEntity.getNote());
           serviceConfigVersionResponse.setHosts(serviceConfigEntity.getHostNames());
           serviceConfigVersionResponse.setConfigurations(new ArrayList<ConfigurationResponse>());
+          serviceConfigVersionResponse.setIsCurrent(activeIds.contains(serviceConfigEntity.getServiceConfigId()));
 
           List<ClusterConfigEntity> clusterConfigEntities = serviceConfigEntity.getClusterConfigEntities();
           for (ClusterConfigEntity clusterConfigEntity : clusterConfigEntities) {
@@ -1617,16 +1636,40 @@ public class ClusterImpl implements Cluster {
     }
   }
 
-  @RequiresSession
-  Set<ServiceConfigVersionResponse> getActiveServiceConfigVersionSet() {
+  private Set<ServiceConfigVersionResponse> getActiveServiceConfigVersionSet() {
     Set<ServiceConfigVersionResponse> responses = new HashSet<ServiceConfigVersionResponse>();
-    List<ServiceConfigEntity> lastServiceConfigs = serviceConfigDAO.getLastServiceConfigs(getClusterId());
-    for (ServiceConfigEntity lastServiceConfig : lastServiceConfigs) {
-      responses.add(convertToServiceConfigVersionResponse(lastServiceConfig));
+    List<ServiceConfigEntity> activeServiceConfigVersions = getActiveServiceConfigVersionEntities();
+
+    for (ServiceConfigEntity lastServiceConfig : activeServiceConfigVersions) {
+      ServiceConfigVersionResponse response = convertToServiceConfigVersionResponse(lastServiceConfig);
+      response.setIsCurrent(true); //mark these as current, as they are
+      responses.add(response);
     }
     return responses;
   }
 
+  private Set<Long> getActiveServiceConfigVersionIds() {
+    Set<Long> idSet = new HashSet<Long>();
+    for (ServiceConfigEntity entity : getActiveServiceConfigVersionEntities()) {
+      idSet.add(entity.getServiceConfigId());
+    }
+    return idSet;
+  }
+
+  private List<ServiceConfigEntity> getActiveServiceConfigVersionEntities() {
+
+    List<ServiceConfigEntity> activeServiceConfigVersions = new ArrayList<ServiceConfigEntity>();
+    //for services
+    activeServiceConfigVersions.addAll(serviceConfigDAO.getLastServiceConfigs(getClusterId()));
+    //for config groups
+    if (clusterConfigGroups != null) {
+      activeServiceConfigVersions.addAll(
+        serviceConfigDAO.getLastServiceConfigVersionsForGroups(clusterConfigGroups.keySet()));
+    }
+
+    return activeServiceConfigVersions;
+  }
+
   @RequiresSession
   ServiceConfigVersionResponse getActiveServiceConfigVersion(String serviceName) {
     ServiceConfigEntity lastServiceConfig = serviceConfigDAO.getLastServiceConfig(getClusterId(), serviceName);
@@ -1647,11 +1690,20 @@ public class ClusterImpl implements Cluster {
     serviceConfigVersionResponse.setCreateTime(serviceConfigEntity.getCreateTimestamp());
     serviceConfigVersionResponse.setUserName(serviceConfigEntity.getUser());
     serviceConfigVersionResponse.setNote(serviceConfigEntity.getNote());
+    if (clusterConfigGroups != null) {
+      ConfigGroup configGroup = clusterConfigGroups.get(serviceConfigEntity.getGroupId());
+      if (configGroup != null) {
+        serviceConfigVersionResponse.setGroupId(configGroup.getId());
+        serviceConfigVersionResponse.setGroupName(configGroup.getName());
+      }
+    }
+
+
     return serviceConfigVersionResponse;
   }
 
   @Transactional
-  void applyServiceConfigVersion(String serviceName, Long serviceConfigVersion, String user,
+  ServiceConfigVersionResponse applyServiceConfigVersion(String serviceName, Long serviceConfigVersion, String user,
                                  String serviceConfigVersionNote) throws AmbariException {
     ServiceConfigEntity serviceConfigEntity = serviceConfigDAO.findByServiceAndVersion(serviceName, serviceConfigVersion);
     if (serviceConfigEntity == null) {
@@ -1711,6 +1763,8 @@ public class ClusterImpl implements Cluster {
     serviceConfigEntityClone.setVersion(configVersionHelper.getNextVersion(serviceName));
 
     serviceConfigDAO.create(serviceConfigEntityClone);
+
+    return convertToServiceConfigVersionResponse(serviceConfigEntityClone);
   }
 
   @Transactional
@@ -1739,16 +1793,23 @@ public class ClusterImpl implements Cluster {
   }
 
   @Transactional
-  ServiceConfigVersionResponse applyConfig(String type, String tag, String user, String serviceConfigVersionNote) {
-
-    selectConfig(type, tag, user);
+  ServiceConfigVersionResponse applyConfigs(Set<Config> configs, String user, String serviceConfigVersionNote) {
 
     String serviceName = null;
-    //find service name for config type
-    for (Entry<String, String> entry : serviceConfigTypes.entries()) {
-      if (StringUtils.equals(entry.getValue(), type)) {
-        serviceName = entry.getKey();
-        break;
+    for (Config config: configs) {
+
+      selectConfig(config.getType(), config.getTag(), user);
+      //find service name for config type
+      for (Entry<String, String> entry : serviceConfigTypes.entries()) {
+        if (StringUtils.equals(entry.getValue(), config.getType())) {
+          if (serviceName != null && !serviceName.equals(entry.getKey())) {
+            LOG.error("Updating configs for multiple services by a " +
+              "single API request isn't supported, config version not created");
+            return null;
+          }
+          serviceName = entry.getKey();
+          break;
+        }
       }
     }
 

+ 2 - 1
ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java

@@ -38,6 +38,7 @@ import org.slf4j.LoggerFactory;
 
 import javax.persistence.EntityManager;
 import java.sql.SQLException;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Map;
@@ -227,7 +228,7 @@ public abstract class AbstractUpgradeCatalog implements UpgradeCatalog {
               if (baseConfig != null) {
                 String authName = "ambari-upgrade";
 
-                if (cluster.addDesiredConfig(authName, baseConfig) != null) {
+                if (cluster.addDesiredConfig(authName, Collections.singleton(baseConfig)) != null) {
                   String oldConfigString = (oldConfig != null) ? " from='" + oldConfig.getTag() + "'" : "";
                   LOG.info("cluster '" + cluster.getClusterName() + "' "
                     + "changed by: '" + authName + "'; "

+ 15 - 4
ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java

@@ -74,7 +74,6 @@ import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Config;
 import org.apache.ambari.server.state.ConfigHelper;
 import org.apache.ambari.server.state.alert.Scope;
-import org.apache.ambari.server.view.configuration.InstanceConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -250,9 +249,18 @@ public class UpgradeCatalog170 extends AbstractUpgradeCatalog {
 
     dbAccessor.addColumn("host_role_command", new DBColumnInfo("output_log",
         String.class, 255, null, true));
+
+    dbAccessor.addColumn("stage", new DBColumnInfo("command_params",
+      byte[].class, null, null, true));
+    dbAccessor.addColumn("stage", new DBColumnInfo("host_params",
+      byte[].class, null, null, true));
+
     dbAccessor.addColumn("host_role_command", new DBColumnInfo("error_log",
         String.class, 255, null, true));
 
+    dbAccessor.addColumn("viewmain", new DBColumnInfo("description",
+        String.class, 255, null, true));
+
     addAlertingFrameworkDDL();
 
     //service config versions changes
@@ -435,7 +443,7 @@ public class UpgradeCatalog170 extends AbstractUpgradeCatalog {
   private void renameSequenceValueColumnName() throws AmbariException, SQLException {
     final String dbType = getDbType();
     if (Configuration.MYSQL_DB_NAME.equals(dbType)) {
-      dbAccessor.executeQuery("ALTER TABLE ambari_sequences RENAME COLUMN \"value\" to sequence_value DECIMAL(38) NOT NULL");
+      dbAccessor.executeQuery("ALTER TABLE ambari_sequences RENAME COLUMN value to sequence_value DECIMAL(38) NOT NULL");
     } else if (Configuration.DERBY_DB_NAME.equals(dbType)) {
       dbAccessor.executeQuery("RENAME COLUMN ambari_sequences.\"value\" to sequence_value");
     } else if (Configuration.ORACLE_DB_NAME.equals(dbType)) {
@@ -664,6 +672,7 @@ public class UpgradeCatalog170 extends AbstractUpgradeCatalog {
     columns.add(new DBColumnInfo("cluster_id", Long.class, null, null, false));
     columns.add(new DBColumnInfo("group_name", String.class, 255, null, false));
     columns.add(new DBColumnInfo("is_default", Short.class, 1, 1, false));
+    columns.add(new DBColumnInfo("service_name", String.class, 255, null, true));
     dbAccessor.createTable(ALERT_TABLE_GROUP, columns, "group_id");
 
     dbAccessor.executeQuery(
@@ -804,7 +813,8 @@ public class UpgradeCatalog170 extends AbstractUpgradeCatalog {
 
     if (clusterMap != null && !clusterMap.isEmpty()) {
       for (final Cluster cluster : clusterMap.values()) {
-        Set<String> configTypes = configHelper.findConfigTypesByPropertyName(cluster.getCurrentStackVersion(), CONTENT_FIELD_NAME);
+        Set<String> configTypes = configHelper.findConfigTypesByPropertyName(cluster.getCurrentStackVersion(),
+                CONTENT_FIELD_NAME, cluster.getClusterName());
 
         for(String configType:configTypes) {
           if(!configType.endsWith(ENV_CONFIGS_POSTFIX)) {
@@ -845,7 +855,8 @@ public class UpgradeCatalog170 extends AbstractUpgradeCatalog {
           String propertyName = property.getKey();
           String propertyValue = property.getValue();
 
-          Set<String> newConfigTypes = configHelper.findConfigTypesByPropertyName(cluster.getCurrentStackVersion(), propertyName);
+          Set<String> newConfigTypes = configHelper.findConfigTypesByPropertyName(cluster.getCurrentStackVersion(),
+                  propertyName, cluster.getClusterName());
           // if it's custom user service global.xml can be still there.
           newConfigTypes.remove(Configuration.GLOBAL_CONFIG_TAG);
 

+ 9 - 4
ambari-server/src/main/java/org/apache/ambari/server/utils/StageUtils.java

@@ -42,6 +42,7 @@ import org.apache.ambari.server.Role;
 import org.apache.ambari.server.RoleCommand;
 import org.apache.ambari.server.actionmanager.Stage;
 import org.apache.ambari.server.agent.ExecutionCommand;
+import org.apache.ambari.server.controller.ActionExecutionContext;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Host;
 import org.apache.ambari.server.state.HostComponentAdminState;
@@ -147,20 +148,20 @@ public class StageUtils {
     return requestStageIds;
   }
 
-  public static Stage getATestStage(long requestId, long stageId, String clusterHostInfo) {
+  public static Stage getATestStage(long requestId, long stageId, String clusterHostInfo, String commandParamsStage, String hostParamsStage) {
     String hostname;
     try {
       hostname = InetAddress.getLocalHost().getHostName();
     } catch (UnknownHostException e) {
       hostname = "host-dummy";
     }
-    return getATestStage(requestId, stageId, hostname, clusterHostInfo);
+    return getATestStage(requestId, stageId, hostname, clusterHostInfo, commandParamsStage, hostParamsStage);
   }
 
   //For testing only
-  public static Stage getATestStage(long requestId, long stageId, String hostname, String clusterHostInfo) {
+  public static Stage getATestStage(long requestId, long stageId, String hostname, String clusterHostInfo, String commandParamsStage, String hostParamsStage) {
 
-    Stage s = new Stage(requestId, "/tmp", "cluster1", 1L, "context", clusterHostInfo);
+    Stage s = new Stage(requestId, "/tmp", "cluster1", 1L, "context", clusterHostInfo, commandParamsStage, hostParamsStage);
     s.setStageId(stageId);
     long now = System.currentTimeMillis();
     s.addHostRoleExecutionCommand(hostname, Role.NAMENODE, RoleCommand.INSTALL,
@@ -211,6 +212,10 @@ public class StageUtils {
     InputStream is = new ByteArrayInputStream(json.getBytes(Charset.forName("UTF8")));
     return mapper.readValue(is, clazz);
   }
+ 
+  public static Map<String, String> getCommandParamsStage(ActionExecutionContext actionExecContext) throws AmbariException {
+    return actionExecContext.getParameters() != null ? actionExecContext.getParameters() : new TreeMap<String, String>();
+  }
 
   public static Map<String, Set<String>> getClusterHostInfo(
       Map<String, Host> allHosts, Cluster cluster) throws AmbariException {

+ 15 - 0
ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java

@@ -465,6 +465,21 @@ public class ViewRegistry {
     }
   }
 
+  /**
+   * Determine whether or not the given view instance exists.
+   *
+   * @param instanceEntity  the view instance entity
+   *
+   * @return true if the the given view instance exists; false otherwise
+   */
+  public boolean instanceExists(ViewInstanceEntity instanceEntity) {
+
+    ViewEntity viewEntity = getDefinition(instanceEntity.getViewName());
+
+    return viewEntity != null &&
+        (getInstanceDefinition(viewEntity.getCommonName(), viewEntity.getVersion(), instanceEntity.getName()) != null);
+  }
+
   /**
    * Install the given view instance with its associated view.
    *

+ 14 - 0
ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java

@@ -47,6 +47,11 @@ public class ViewConfig {
    */
   private String label;
 
+  /**
+   * The view description.
+   */
+  private String description;
+
   /**
    * The view version.
    */
@@ -132,6 +137,15 @@ public class ViewConfig {
     return label;
   }
 
+  /**
+   * Get the view description.
+   *
+   * @return the view description
+   */
+  public String getDescription() {
+    return description;
+  }
+
   /**
    * Get the view version.
    *

+ 3 - 2
ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql

@@ -45,7 +45,7 @@ CREATE TABLE members (member_id INTEGER, group_id INTEGER NOT NULL, user_id INTE
 CREATE TABLE execution_command (task_id BIGINT NOT NULL, command LONGBLOB, PRIMARY KEY (task_id));
 CREATE TABLE host_role_command (task_id BIGINT NOT NULL, attempt_count SMALLINT NOT NULL, event LONGTEXT NOT NULL, exitcode INTEGER NOT NULL, host_name VARCHAR(255) NOT NULL, last_attempt_time BIGINT NOT NULL, request_id BIGINT NOT NULL, role VARCHAR(255), role_command VARCHAR(255), stage_id BIGINT NOT NULL, start_time BIGINT NOT NULL, end_time BIGINT, status VARCHAR(255), std_error LONGBLOB, std_out LONGBLOB, output_log VARCHAR(255) NULL, error_log VARCHAR(255) NULL, structured_out LONGBLOB, command_detail VARCHAR(255), custom_command_name VARCHAR(255), PRIMARY KEY (task_id));
 CREATE TABLE role_success_criteria (role VARCHAR(255) NOT NULL, request_id BIGINT NOT NULL, stage_id BIGINT NOT NULL, success_factor DOUBLE NOT NULL, PRIMARY KEY (role, request_id, stage_id));
-CREATE TABLE stage (stage_id BIGINT NOT NULL, request_id BIGINT NOT NULL, cluster_id BIGINT, log_info VARCHAR(255) NOT NULL, request_context VARCHAR(255), cluster_host_info LONGBLOB, PRIMARY KEY (stage_id, request_id));
+CREATE TABLE stage (stage_id BIGINT NOT NULL, request_id BIGINT NOT NULL, cluster_id BIGINT, log_info VARCHAR(255) NOT NULL, request_context VARCHAR(255), cluster_host_info LONGBLOB, command_params LONGBLOB, host_params LONGBLOB, PRIMARY KEY (stage_id, request_id));
 CREATE TABLE request (request_id BIGINT NOT NULL, cluster_id BIGINT, request_schedule_id BIGINT, command_name VARCHAR(255), create_time BIGINT NOT NULL, end_time BIGINT NOT NULL, inputs LONGBLOB, request_context VARCHAR(255), request_type VARCHAR(255), start_time BIGINT NOT NULL, status VARCHAR(255), PRIMARY KEY (request_id));
 CREATE TABLE requestresourcefilter (filter_id BIGINT NOT NULL, request_id BIGINT NOT NULL, service_name VARCHAR(255), component_name VARCHAR(255), hosts LONGBLOB, PRIMARY KEY (filter_id));
 CREATE TABLE requestoperationlevel (operation_level_id BIGINT NOT NULL, request_id BIGINT NOT NULL, level_name VARCHAR(255), cluster_name VARCHAR(255), service_name VARCHAR(255), host_component_name VARCHAR(255), host_name VARCHAR(255), PRIMARY KEY (operation_level_id));
@@ -65,7 +65,7 @@ CREATE TABLE hostgroup (blueprint_name VARCHAR(255) NOT NULL, name VARCHAR(255)
 CREATE TABLE hostgroup_component (blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, name));
 CREATE TABLE blueprint_configuration (blueprint_name VARCHAR(255) NOT NULL, type_name VARCHAR(255) NOT NULL, config_data VARCHAR(32000) NOT NULL, config_attributes VARCHAR(32000), PRIMARY KEY(blueprint_name, type_name));
 CREATE TABLE hostgroup_configuration (blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, type_name VARCHAR(255) NOT NULL, config_data TEXT NOT NULL, config_attributes TEXT, PRIMARY KEY(blueprint_name, hostgroup_name, type_name));
-CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), version VARCHAR(255), resource_type_id INTEGER NOT NULL, icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), mask VARCHAR(255), PRIMARY KEY(view_name));
+CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), description VARCHAR(255), version VARCHAR(255), resource_type_id INTEGER NOT NULL, icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), mask VARCHAR(255), PRIMARY KEY(view_name));
 CREATE TABLE viewinstancedata (view_instance_id BIGINT, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, user_name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(VIEW_INSTANCE_ID, NAME, USER_NAME));
 CREATE TABLE viewinstance (view_instance_id BIGINT, resource_id BIGINT NOT NULL, view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, label VARCHAR(255), description VARCHAR(255), visible CHAR(1), icon VARCHAR(255), icon64 VARCHAR(255), xml_driven CHAR(1), PRIMARY KEY(view_instance_id));
 CREATE TABLE viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
@@ -200,6 +200,7 @@ CREATE TABLE alert_group (
   cluster_id BIGINT NOT NULL,
   group_name VARCHAR(255) NOT NULL,
   is_default SMALLINT NOT NULL DEFAULT 0,
+  service_name VARCHAR(255),
   PRIMARY KEY (group_id),
   CONSTRAINT uni_alert_group_name UNIQUE(cluster_id,group_name)
 );

+ 3 - 2
ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql

@@ -36,7 +36,7 @@ CREATE TABLE members (member_id NUMBER(10), group_id NUMBER(10) NOT NULL, user_i
 CREATE TABLE execution_command (task_id NUMBER(19) NOT NULL, command BLOB NULL, PRIMARY KEY (task_id));
 CREATE TABLE host_role_command (task_id NUMBER(19) NOT NULL, attempt_count NUMBER(5) NOT NULL, event CLOB NULL, exitcode NUMBER(10) NOT NULL, host_name VARCHAR2(255) NOT NULL, last_attempt_time NUMBER(19) NOT NULL, request_id NUMBER(19) NOT NULL, role VARCHAR2(255) NULL, role_command VARCHAR2(255) NULL, stage_id NUMBER(19) NOT NULL, start_time NUMBER(19) NOT NULL, end_time NUMBER(19), status VARCHAR2(255) NULL, std_error BLOB NULL, std_out BLOB NULL, output_log VARCHAR2(255) NULL, error_log VARCHAR2(255) NULL, structured_out BLOB NULL,  command_detail VARCHAR2(255) NULL, custom_command_name VARCHAR2(255) NULL, PRIMARY KEY (task_id));
 CREATE TABLE role_success_criteria (role VARCHAR2(255) NOT NULL, request_id NUMBER(19) NOT NULL, stage_id NUMBER(19) NOT NULL, success_factor NUMBER(19,4) NOT NULL, PRIMARY KEY (role, request_id, stage_id));
-CREATE TABLE stage (stage_id NUMBER(19) NOT NULL, request_id NUMBER(19) NOT NULL, cluster_id NUMBER(19) NULL, log_info VARCHAR2(255) NULL, request_context VARCHAR2(255) NULL, cluster_host_info BLOB NOT NULL, PRIMARY KEY (stage_id, request_id));
+CREATE TABLE stage (stage_id NUMBER(19) NOT NULL, request_id NUMBER(19) NOT NULL, cluster_id NUMBER(19) NULL, log_info VARCHAR2(255) NULL, request_context VARCHAR2(255) NULL, cluster_host_info BLOB NOT NULL, command_params BLOB, host_params BLOB, PRIMARY KEY (stage_id, request_id));
 CREATE TABLE request (request_id NUMBER(19) NOT NULL, cluster_id NUMBER(19), request_schedule_id NUMBER(19), command_name VARCHAR(255), create_time NUMBER(19) NOT NULL, end_time NUMBER(19) NOT NULL, inputs BLOB, request_context VARCHAR(255), request_type VARCHAR(255), start_time NUMBER(19) NOT NULL, status VARCHAR(255), PRIMARY KEY (request_id));
 CREATE TABLE requestresourcefilter (filter_id NUMBER(19) NOT NULL, request_id NUMBER(19) NOT NULL, service_name VARCHAR2(255), component_name VARCHAR2(255), hosts BLOB, PRIMARY KEY (filter_id));
 CREATE TABLE requestoperationlevel (operation_level_id NUMBER(19) NOT NULL, request_id NUMBER(19) NOT NULL, level_name VARCHAR2(255), cluster_name VARCHAR2(255), service_name VARCHAR2(255), host_component_name VARCHAR2(255), host_name VARCHAR2(255), PRIMARY KEY (operation_level_id));
@@ -56,7 +56,7 @@ CREATE TABLE hostgroup (blueprint_name VARCHAR2(255) NOT NULL, name VARCHAR2(255
 CREATE TABLE hostgroup_component (blueprint_name VARCHAR2(255) NOT NULL, hostgroup_name VARCHAR2(255) NOT NULL, name VARCHAR2(255) NOT NULL, PRIMARY KEY(blueprint_name, hostgroup_name, name));
 CREATE TABLE blueprint_configuration (blueprint_name VARCHAR2(255) NOT NULL, type_name VARCHAR2(255) NOT NULL, config_data CLOB NOT NULL, config_attributes CLOB, PRIMARY KEY(blueprint_name, type_name));
 CREATE TABLE hostgroup_configuration (blueprint_name VARCHAR2(255) NOT NULL, hostgroup_name VARCHAR2(255) NOT NULL, type_name VARCHAR2(255) NOT NULL, config_data CLOB NOT NULL, config_attributes CLOB, PRIMARY KEY(blueprint_name, hostgroup_name, type_name));
-CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), version VARCHAR(255), resource_type_id NUMBER(10) NOT NULL, icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), mask VARCHAR(255), PRIMARY KEY(view_name));
+CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), description VARCHAR(255), version VARCHAR(255), resource_type_id NUMBER(10) NOT NULL, icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), mask VARCHAR(255), PRIMARY KEY(view_name));
 CREATE TABLE viewinstancedata (view_instance_id NUMBER(19), view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, user_name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_instance_id, name, user_name));
 CREATE TABLE viewinstance (view_instance_id NUMBER(19), resource_id NUMBER(19) NOT NULL, view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, label VARCHAR(255), description VARCHAR(255), visible CHAR(1), icon VARCHAR(255), icon64 VARCHAR(255), xml_driven CHAR(1), PRIMARY KEY(view_instance_id));
 CREATE TABLE viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
@@ -191,6 +191,7 @@ CREATE TABLE alert_group (
   cluster_id NUMBER(19) NOT NULL,
   group_name VARCHAR2(255) NOT NULL,
   is_default NUMBER(1) DEFAULT 0 NOT NULL,
+  service_name VARCHAR2(255),
   PRIMARY KEY (group_id),
   CONSTRAINT uni_alert_group_name UNIQUE(cluster_id,group_name)
 );

+ 3 - 2
ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql

@@ -57,7 +57,7 @@ CREATE TABLE host_role_command (task_id BIGINT NOT NULL, attempt_count SMALLINT
 
 CREATE TABLE role_success_criteria (role VARCHAR(255) NOT NULL, request_id BIGINT NOT NULL, stage_id BIGINT NOT NULL, success_factor FLOAT NOT NULL, PRIMARY KEY (role, request_id, stage_id));
 
-CREATE TABLE stage (stage_id BIGINT NOT NULL, request_id BIGINT NOT NULL, cluster_id BIGINT NOT NULL, log_info VARCHAR(255) NOT NULL, request_context VARCHAR(255), cluster_host_info BYTEA NOT NULL, PRIMARY KEY (stage_id, request_id));
+CREATE TABLE stage (stage_id BIGINT NOT NULL, request_id BIGINT NOT NULL, cluster_id BIGINT NOT NULL, log_info VARCHAR(255) NOT NULL, request_context VARCHAR(255), cluster_host_info BYTEA NOT NULL, command_params BYTEA, host_params BYTEA, PRIMARY KEY (stage_id, request_id));
 
 CREATE TABLE request (request_id BIGINT NOT NULL, cluster_id BIGINT, command_name VARCHAR(255), create_time BIGINT NOT NULL, end_time BIGINT NOT NULL, inputs BYTEA, request_context VARCHAR(255), request_type VARCHAR(255), request_schedule_id BIGINT, start_time BIGINT NOT NULL, status VARCHAR(255), PRIMARY KEY (request_id));
 
@@ -91,7 +91,7 @@ CREATE TABLE hostgroup_component (blueprint_name VARCHAR(255) NOT NULL, hostgrou
 CREATE TABLE blueprint_configuration (blueprint_name varchar(255) NOT NULL, type_name varchar(255) NOT NULL, config_data varchar(32000) NOT NULL , config_attributes varchar(32000), PRIMARY KEY(blueprint_name, type_name));
 CREATE TABLE hostgroup_configuration (blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, type_name VARCHAR(255) NOT NULL, config_data TEXT NOT NULL, config_attributes varchar(32000), PRIMARY KEY(blueprint_name, hostgroup_name, type_name));
 
-CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), version VARCHAR(255), resource_type_id INTEGER NOT NULL, icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), mask VARCHAR(255), PRIMARY KEY(view_name));
+CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), description VARCHAR(255), version VARCHAR(255), resource_type_id INTEGER NOT NULL, icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), mask VARCHAR(255), PRIMARY KEY(view_name));
 CREATE TABLE viewinstancedata (view_instance_id BIGINT, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, user_name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_instance_id, name, user_name));
 CREATE TABLE viewinstance (view_instance_id BIGINT, resource_id BIGINT NOT NULL, view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, label VARCHAR(255), description VARCHAR(255), visible CHAR(1), icon VARCHAR(255), icon64 VARCHAR(255), xml_driven CHAR(1), PRIMARY KEY(view_instance_id));
 CREATE TABLE viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
@@ -223,6 +223,7 @@ CREATE TABLE alert_group (
   cluster_id BIGINT NOT NULL,
   group_name VARCHAR(255) NOT NULL,
   is_default SMALLINT NOT NULL DEFAULT 0,
+  service_name VARCHAR(255),
   PRIMARY KEY (group_id),
   CONSTRAINT uni_alert_group_name UNIQUE(cluster_id,group_name)
 );

+ 3 - 2
ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql

@@ -88,7 +88,7 @@ GRANT ALL PRIVILEGES ON TABLE ambari.host_role_command TO :username;
 CREATE TABLE ambari.role_success_criteria (role VARCHAR(255) NOT NULL, request_id BIGINT NOT NULL, stage_id BIGINT NOT NULL, success_factor FLOAT NOT NULL, PRIMARY KEY (role, request_id, stage_id));
 GRANT ALL PRIVILEGES ON TABLE ambari.role_success_criteria TO :username;
 
-CREATE TABLE ambari.stage (stage_id BIGINT NOT NULL, request_id BIGINT NOT NULL, cluster_id BIGINT NOT NULL, log_info VARCHAR(255) NOT NULL, request_context VARCHAR(255), cluster_host_info BYTEA NOT NULL, PRIMARY KEY (stage_id, request_id));
+CREATE TABLE ambari.stage (stage_id BIGINT NOT NULL, request_id BIGINT NOT NULL, cluster_id BIGINT NOT NULL, log_info VARCHAR(255) NOT NULL, request_context VARCHAR(255), cluster_host_info BYTEA NOT NULL, command_params BYTEA, host_params BYTEA, PRIMARY KEY (stage_id, request_id));
 GRANT ALL PRIVILEGES ON TABLE ambari.stage TO :username;
 
 CREATE TABLE ambari.request (request_id BIGINT NOT NULL, cluster_id BIGINT, command_name VARCHAR(255), create_time BIGINT NOT NULL, end_time BIGINT NOT NULL, inputs BYTEA, request_context VARCHAR(255), request_type VARCHAR(255), request_schedule_id BIGINT, start_time BIGINT NOT NULL, status VARCHAR(255), PRIMARY KEY (request_id));
@@ -141,7 +141,7 @@ GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup_component TO :username;
 GRANT ALL PRIVILEGES ON TABLE ambari.blueprint_configuration TO :username;
 GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup_configuration TO :username;
 
-CREATE TABLE ambari.viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), version VARCHAR(255), resource_type_id INTEGER NOT NULL, icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), mask VARCHAR(255), PRIMARY KEY(view_name));
+CREATE TABLE ambari.viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), description VARCHAR(255), version VARCHAR(255), resource_type_id INTEGER NOT NULL, icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), mask VARCHAR(255), PRIMARY KEY(view_name));
 CREATE TABLE ambari.viewinstancedata (view_instance_id BIGINT, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, user_name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_instance_id, name, user_name));
 CREATE TABLE ambari.viewinstance (view_instance_id BIGINT, resource_id BIGINT NOT NULL, view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, label VARCHAR(255), description VARCHAR(255), visible CHAR(1), icon VARCHAR(255), icon64 VARCHAR(255), xml_driven CHAR(1), PRIMARY KEY(view_instance_id));
 CREATE TABLE ambari.viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name));
@@ -287,6 +287,7 @@ CREATE TABLE ambari.alert_group (
   cluster_id BIGINT NOT NULL,
   group_name VARCHAR(255) NOT NULL,
   is_default SMALLINT NOT NULL DEFAULT 0,
+  service_name VARCHAR(255),
   PRIMARY KEY (group_id),
   CONSTRAINT uni_alert_group_name UNIQUE(cluster_id,group_name)
 );

+ 4 - 3
ambari-server/src/main/resources/custom_actions/check_host.py

@@ -46,6 +46,7 @@ JDBC_DRIVER_SYMLINK_POSTGRESQL = "postgres-jdbc-driver.jar"
 class CheckHost(Script):
   def actionexecute(self, env):
     config = Script.get_config()
+    tmp_dir = Script.get_tmp_dir()
 
     #print "CONFIG: " + str(config)
 
@@ -64,7 +65,7 @@ class CheckHost(Script):
 
     if CHECK_DB_CONNECTION in check_execute_list:
       try :
-        db_connection_check_structured_output = self.execute_db_connection_check(config)
+        db_connection_check_structured_output = self.execute_db_connection_check(config, tmp_dir)
         structured_output[CHECK_DB_CONNECTION] = db_connection_check_structured_output
       except Exception, exception:
         print "There was an unknown error while checking database connectivity: " + str(exception)
@@ -97,7 +98,7 @@ class CheckHost(Script):
     return java_home_check_structured_output
 
 
-  def execute_db_connection_check(self, config):
+  def execute_db_connection_check(self, config, tmp_dir):
     print "DB connection check started."
   
     # initialize needed data
@@ -135,7 +136,7 @@ class CheckHost(Script):
       return db_connection_check_structured_output
 
     environment = { "no_proxy": format("{ambari_server_hostname}") }
-    artifact_dir = "/tmp/HDP-artifacts/"
+    artifact_dir = format("{tmp_dir}/AMBARI-artifacts/")
     java_dir = os.path.dirname(java64_home)
 
     # download and install java if it doesn't exists

+ 5 - 2
ambari-server/src/main/resources/properties.json

@@ -6,7 +6,7 @@
         "Clusters/version",
         "Clusters/state",
         "Clusters/desired_configs",
-        "Clusters/desired_serviceconfigversions",
+        "Clusters/desired_service_config_versions",
         "Clusters/total_hosts",
         "Clusters/health_report",
         "_"
@@ -91,7 +91,8 @@
         "ServiceConfigVersion/group_id",
         "ServiceConfigVersion/group_name",
         "ServiceConfigVersion/hosts",
-        "ServiceConfigVersion/serviceconfigversion",
+        "ServiceConfigVersion/service_config_version",
+        "ServiceConfigVersion/is_current",
         "ServiceConfigVersion/createtime",
         "ServiceConfigVersion/user",
         "ServiceConfigVersion/service_config_version_note"
@@ -226,6 +227,7 @@
         "StackServices/stack_name",
         "StackServices/stack_version",
         "StackServices/service_name",
+        "StackServices/display_name",
         "StackServices/user_name",
         "StackServices/comments",
         "StackServices/service_version",
@@ -251,6 +253,7 @@
         "StackServiceComponents/stack_version",
         "StackServiceComponents/service_name",
         "StackServiceComponents/component_name",
+        "StackServiceComponents/display_name",
         "StackServiceComponents/component_category",
         "StackServiceComponents/is_client",
         "StackServiceComponents/is_master",

+ 2 - 3
ambari-server/src/main/resources/scripts/stack_advisor.py

@@ -82,9 +82,8 @@ def main(argv=None):
   stackName = services["Versions"]["stack_name"]
   stackVersion = services["Versions"]["stack_version"]
   parentVersions = []
-  if "parent_stack_version" in services["Versions"] and \
-      services["Versions"]["parent_stack_version"] is not None:
-    parentVersions = [ services["Versions"]["parent_stack_version"] ]
+  if "stack_hierarchy" in services["Versions"]:
+    parentVersions = services["Versions"]["stack_hierarchy"]["stack_versions"]
 
   stackAdvisor = instantiateStackAdvisor(stackName, stackVersion, parentVersions)
 

+ 2 - 1
ambari-server/src/main/resources/stacks/HDP/1.3.2/hooks/before-ANY/scripts/params.py

@@ -20,11 +20,12 @@ limitations under the License.
 from resource_management import *
 
 config = Script.get_config()
+tmp_dir = Script.get_tmp_dir()
 
 _authentication = config['configurations']['core-site']['hadoop.security.authentication']
 security_enabled = ( not is_empty(_authentication) and _authentication == 'kerberos')
 
-artifact_dir = "/tmp/HDP-artifacts/"
+artifact_dir = format("{tmp_dir}/AMBARI-artifacts/")
 jce_policy_zip = default("/hostLevelParams/jce_name", None) # None when jdk is already installed by user
 jce_location = config['hostLevelParams']['jdk_location']
 jdk_name = default("/hostLevelParams/jdk_name", None)

+ 1 - 1
ambari-server/src/main/resources/stacks/HDP/1.3.2/hooks/before-INSTALL/scripts/params.py

@@ -25,7 +25,7 @@ config = Script.get_config()
 tmp_dir = Script.get_tmp_dir()
 
 #java params
-artifact_dir = "/tmp/HDP-artifacts/"
+artifact_dir = format("{tmp_dir}/AMBARI-artifacts/")
 jdk_name = default("/hostLevelParams/jdk_name", None) # None when jdk is already installed by user
 jce_policy_zip = default("/hostLevelParams/jce_name", None) # None when jdk is already installed by user
 jce_location = config['hostLevelParams']['jdk_location']

+ 3 - 0
ambari-server/src/main/resources/stacks/HDP/1.3.2/services/GANGLIA/metainfo.xml

@@ -20,11 +20,13 @@
   <services>
     <service>
       <name>GANGLIA</name>
+      <displayName>Ganglia</displayName>
       <comment>Ganglia Metrics Collection system (&lt;a href=&quot;http://oss.oetiker.ch/rrdtool/&quot; target=&quot;_blank&quot;&gt;RRDTool&lt;/a&gt; will be installed too)</comment>
       <version>3.5.0</version>
       <components>
         <component>
           <name>GANGLIA_SERVER</name>
+          <displayName>Ganglia Server</displayName>
           <category>MASTER</category>
           <cardinality>1</cardinality>
           <commandScript>
@@ -36,6 +38,7 @@
 
         <component>
           <name>GANGLIA_MONITOR</name>
+          <displayName>Ganglia Monitor</displayName>
           <category>SLAVE</category>
           <cardinality>ALL</cardinality>
           <auto-deploy>

+ 4 - 0
ambari-server/src/main/resources/stacks/HDP/1.3.2/services/HBASE/metainfo.xml

@@ -20,6 +20,7 @@
   <services>
     <service>
       <name>HBASE</name>
+      <displayName>HBase</displayName>
       <comment>Non-relational distributed database and centralized service for configuration management &amp;
         synchronization
       </comment>
@@ -27,6 +28,7 @@
       <components>
         <component>
           <name>HBASE_MASTER</name>
+          <displayName>HBase Master</displayName>
           <category>MASTER</category>
           <cardinality>1+</cardinality>
           <dependencies>
@@ -65,6 +67,7 @@
 
         <component>
           <name>HBASE_REGIONSERVER</name>
+          <displayName>RegionServer</displayName>
           <category>SLAVE</category>
           <cardinality>1+</cardinality>
           <commandScript>
@@ -85,6 +88,7 @@
 
         <component>
           <name>HBASE_CLIENT</name>
+          <displayName>HBase Client</displayName>
           <category>CLIENT</category>
           <cardinality>1+</cardinality>
           <commandScript>

+ 5 - 0
ambari-server/src/main/resources/stacks/HDP/1.3.2/services/HDFS/metainfo.xml

@@ -20,12 +20,14 @@
   <services>
     <service>
       <name>HDFS</name>
+      <displayName>HDFS</displayName>
       <comment>Apache Hadoop Distributed File System</comment>
       <version>1.2.0.1.3.3.0</version>
 
       <components>
         <component>
           <name>NAMENODE</name>
+          <displayName>NameNode</displayName>
           <category>MASTER</category>
           <cardinality>1-2</cardinality>
           <commandScript>
@@ -47,6 +49,7 @@
 
         <component>
           <name>DATANODE</name>
+          <displayName>DataNode</displayName>
           <category>SLAVE</category>
           <cardinality>1+</cardinality>
           <commandScript>
@@ -58,6 +61,7 @@
 
         <component>
           <name>SECONDARY_NAMENODE</name>
+          <displayName>SNameNode</displayName>
           <category>MASTER</category>
           <cardinality>1</cardinality>
           <commandScript>
@@ -69,6 +73,7 @@
 
         <component>
           <name>HDFS_CLIENT</name>
+          <displayName>HDFS Client</displayName>
           <category>CLIENT</category>
           <cardinality>1+</cardinality>
           <commandScript>

+ 10 - 1
ambari-server/src/main/resources/stacks/HDP/1.3.2/services/HIVE/metainfo.xml

@@ -20,12 +20,14 @@
   <services>
     <service>
       <name>HIVE</name>
+      <displayName>Hive</displayName>
       <comment>Data warehouse system for ad-hoc queries &amp; analysis of large datasets and table &amp; storage management service</comment>
       <version>0.11.0.1.3.3.0</version>
       <components>
 
         <component>
           <name>HIVE_METASTORE</name>
+          <displayName>Hive Metastore</displayName>
           <category>MASTER</category>
           <cardinality>1</cardinality>
           <auto-deploy>
@@ -41,6 +43,7 @@
 
         <component>
           <name>HIVE_SERVER</name>
+          <displayName>HiveServer2</displayName>
           <category>MASTER</category>
           <cardinality>1</cardinality>
           <dependencies>
@@ -68,6 +71,7 @@
 
         <component>
           <name>MYSQL_SERVER</name>
+          <displayName>MySQL Server</displayName>
           <category>MASTER</category>
           <cardinality>0-1</cardinality>
           <commandScript>
@@ -78,6 +82,7 @@
 
         <component>
           <name>HIVE_CLIENT</name>
+          <displayName>Hive Client</displayName>
           <category>CLIENT</category>
           <cardinality>1+</cardinality>
           <commandScript>
@@ -163,11 +168,15 @@
 
     <service>
       <name>HCATALOG</name>
-      <comment>This is comment for HCATALOG service</comment>
+      <displayName>HCatalog</displayName>
+      <comment>A table and storage management layer for Hadoop that enables users with different data processing tools
+        to more easily read and write data on the grid.
+      </comment>
       <version>0.11.0.1.3.3.0</version>
       <components>
         <component>
           <name>HCAT</name>
+          <displayName>HCat</displayName>
           <category>CLIENT</category>
           <commandScript>
             <script>scripts/hcat_client.py</script>

+ 1 - 1
ambari-server/src/main/resources/stacks/HDP/1.3.2/services/HIVE/package/scripts/params.py

@@ -91,7 +91,7 @@ driver_curl_target = format("{java_share_dir}/{jdbc_jar_name}")
 
 hdfs_user =  config['configurations']['hadoop-env']['hdfs_user']
 user_group = config['configurations']['hadoop-env']['user_group']
-artifact_dir = "/tmp/HDP-artifacts/"
+artifact_dir = format("{tmp_dir}/AMBARI-artifacts/")
 
 target = format("{hive_lib}/{jdbc_jar_name}")
 

+ 5 - 0
ambari-server/src/main/resources/stacks/HDP/1.3.2/services/MAPREDUCE/metainfo.xml

@@ -21,11 +21,13 @@
   <services>
     <service>
       <name>MAPREDUCE</name>
+      <displayName>MapReduce</displayName>
       <comment>Apache Hadoop Distributed Processing Framework</comment>
       <version>1.2.0.1.3.3.0</version>
       <components>
         <component>
           <name>JOBTRACKER</name>
+          <displayName>JobTracker</displayName>
           <category>MASTER</category>
           <cardinality>1</cardinality>
           <commandScript>
@@ -47,6 +49,7 @@
 
         <component>
           <name>TASKTRACKER</name>
+          <displayName>TaskTracker</displayName>
           <category>SLAVE</category>
           <cardinality>1+</cardinality>
           <commandScript>
@@ -58,6 +61,7 @@
 
         <component>
           <name>MAPREDUCE_CLIENT</name>
+          <displayName>MapReduce Client</displayName>
           <category>CLIENT</category>
           <cardinality>1+</cardinality>
           <commandScript>
@@ -91,6 +95,7 @@
               
         <component>
           <name>HISTORYSERVER</name>
+          <displayName>History Server</displayName>
           <category>MASTER</category>
           <cardinality>1</cardinality>
           <auto-deploy>

+ 2 - 0
ambari-server/src/main/resources/stacks/HDP/1.3.2/services/NAGIOS/metainfo.xml

@@ -20,11 +20,13 @@
   <services>
     <service>
       <name>NAGIOS</name>
+      <displayName>Nagios</displayName>
       <comment>Nagios Monitoring and Alerting system</comment>
       <version>3.5.0</version>
       <components>
         <component>
           <name>NAGIOS_SERVER</name>
+          <displayName>Nagios Server</displayName>
           <category>MASTER</category>
           <cardinality>1</cardinality>
           <dependencies>

+ 3 - 0
ambari-server/src/main/resources/stacks/HDP/1.3.2/services/OOZIE/metainfo.xml

@@ -20,12 +20,14 @@
   <services>
     <service>
       <name>OOZIE</name>
+      <displayName>Oozie</displayName>
       <comment>System for workflow coordination and execution of Apache Hadoop jobs.  This also includes the installation of the optional Oozie Web Console which relies on and will install the &lt;a target="_blank" href="http://www.sencha.com/legal/open-source-faq/"&gt;ExtJS&lt;/a&gt; Library.
       </comment>
       <version>3.3.2.1.3.3.0</version>
       <components>
         <component>
           <name>OOZIE_SERVER</name>
+          <displayName>Oozie Server</displayName>
           <category>MASTER</category>
           <cardinality>1</cardinality>
           <dependencies>
@@ -53,6 +55,7 @@
 
         <component>
           <name>OOZIE_CLIENT</name>
+          <displayName>Oozie Client</displayName>
           <category>CLIENT</category>
           <cardinality>1+</cardinality>
           <dependencies>

+ 2 - 0
ambari-server/src/main/resources/stacks/HDP/1.3.2/services/PIG/metainfo.xml

@@ -20,11 +20,13 @@
   <services>
     <service>
       <name>PIG</name>
+      <displayName>Pig</displayName>
       <comment>Scripting platform for analyzing large datasets</comment>
       <version>0.11.1.1.3.3.0</version>
       <components>
         <component>
           <name>PIG</name>
+          <displayName>Pig</displayName>
           <category>CLIENT</category>
           <cardinality>1+</cardinality>
           <commandScript>

+ 2 - 0
ambari-server/src/main/resources/stacks/HDP/1.3.2/services/SQOOP/metainfo.xml

@@ -20,6 +20,7 @@
   <services>
     <service>
       <name>SQOOP</name>
+      <displayName>Sqoop</displayName>
       <comment>Tool for transferring bulk data between Apache Hadoop and
         structured data stores such as relational databases
       </comment>
@@ -28,6 +29,7 @@
       <components>
         <component>
           <name>SQOOP</name>
+          <displayName>Pig</displayName>
           <category>CLIENT</category>
           <cardinality>1+</cardinality>
           <dependencies>

+ 3 - 1
ambari-server/src/main/resources/stacks/HDP/1.3.2/services/WEBHCAT/metainfo.xml

@@ -20,11 +20,13 @@
   <services>
     <service>
       <name>WEBHCAT</name>
-      <comment>This is comment for WEBHCAT service</comment>
+      <displayName>WebHCat</displayName>
+      <comment>Provides a REST-like web API for HCatalog and related Hadoop components.</comment>
       <version>0.11.0.1.3.3.0</version>
       <components>
         <component>
           <name>WEBHCAT_SERVER</name>
+          <displayName>WebHCat Server</displayName>
           <category>MASTER</category>
           <cardinality>1</cardinality>
           <dependencies>

+ 3 - 0
ambari-server/src/main/resources/stacks/HDP/1.3.2/services/ZOOKEEPER/metainfo.xml

@@ -20,12 +20,14 @@
   <services>
     <service>
       <name>ZOOKEEPER</name>
+      <displayName>ZooKeeper</displayName>
       <comment>Centralized service which provides highly reliable distributed coordination</comment>
       <version>3.4.5.1.3.3.0</version>
       <components>
 
         <component>
           <name>ZOOKEEPER_SERVER</name>
+          <displayName>ZooKeeper Server</displayName>
           <category>MASTER</category>
           <cardinality>1+</cardinality>
           <commandScript>
@@ -37,6 +39,7 @@
 
         <component>
           <name>ZOOKEEPER_CLIENT</name>
+          <displayName>ZooKeeper Client</displayName>
           <category>CLIENT</category>
           <cardinality>1+</cardinality>
           <commandScript>

+ 519 - 0
ambari-server/src/main/resources/stacks/HDP/1.3.2/services/stack_advisor.py

@@ -0,0 +1,519 @@
+#!/usr/bin/env ambari-python-wrap
+"""
+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.
+"""
+
+import re
+import socket
+import sys
+
+from stack_advisor import StackAdvisor
+
+class HDP132StackAdvisor(StackAdvisor):
+
+  def recommendComponentLayout(self, services, hosts):
+    """
+    Returns Services object with hostnames array populated for components
+    If hostnames are populated for some components (partial blueprint) - these components will not be processed
+    """
+    stackName = services["Versions"]["stack_name"]
+    stackVersion = services["Versions"]["stack_version"]
+    hostsList = [host["Hosts"]["host_name"] for host in hosts["items"]]
+    servicesList = [service["StackServices"]["service_name"] for service in services["services"]]
+
+    recommendations = {
+      "Versions": {"stack_name": stackName, "stack_version": stackVersion},
+      "hosts": hostsList,
+      "services": servicesList,
+      "recommendations": {
+        "blueprint": {
+          "host_groups": [ ]
+        },
+        "blueprint_cluster_binding": {
+          "host_groups": [ ]
+        }
+      }
+    }
+
+    hostsComponentsMap = {}
+
+    #extend 'hostsComponentsMap' with MASTER components
+    for service in services["services"]:
+      masterComponents = [component for component in service["components"] if isMaster(component)]
+      for component in masterComponents:
+        componentName = component["StackServiceComponents"]["component_name"]
+        hostsForComponent = []
+
+        if isAlreadyPopulated(component):
+          hostsForComponent = component["StackServiceComponents"]["hostnames"]
+        else:
+          availableHosts = hostsList
+          if len(hostsList) > 1 and self.isNotPreferableOnAmbariServerHost(component):
+            availableHosts = [hostName for hostName in hostsList if not isLocalHost(hostName)]
+
+          if isMasterWithMultipleInstances(component):
+            hostsCount = defaultNoOfMasterHosts(component)
+            if hostsCount > 1: # get first 'hostsCount' available hosts
+              if len(availableHosts) < hostsCount:
+                hostsCount = len(availableHosts)
+              hostsForComponent = availableHosts[:hostsCount]
+            else:
+              hostsForComponent = [self.getHostForComponent(component, availableHosts)]
+          else:
+            hostsForComponent = [self.getHostForComponent(component, availableHosts)]
+
+        #extend 'hostsComponentsMap' with 'hostsForComponent'
+        for hostName in hostsForComponent:
+          if hostName not in hostsComponentsMap:
+            hostsComponentsMap[hostName] = []
+          hostsComponentsMap[hostName].append( { "name":componentName } )
+
+    #extend 'hostsComponentsMap' with Slave and Client Components
+    componentsListList = [service["components"] for service in services["services"]]
+    componentsList = [item for sublist in componentsListList for item in sublist]
+    usedHostsListList = [component["StackServiceComponents"]["hostnames"] for component in componentsList if not self.isNotValuable(component)]
+    utilizedHosts = [item for sublist in usedHostsListList for item in sublist]
+    freeHosts = [hostName for hostName in hostsList if hostName not in utilizedHosts]
+
+    for service in services["services"]:
+      slaveClientComponents = [component for component in service["components"] if isSlave(component) or isClient(component)]
+      for component in slaveClientComponents:
+        componentName = component["StackServiceComponents"]["component_name"]
+        hostsForComponent = []
+
+        if isAlreadyPopulated(component):
+          hostsForComponent = component["StackServiceComponents"]["hostnames"]
+        elif component["StackServiceComponents"]["cardinality"] == "ALL":
+          hostsForComponent = hostsList
+        else:
+          if len(freeHosts) == 0:
+            hostsForComponent = hostsList[-1:]
+          else: # len(freeHosts) >= 1
+            hostsForComponent = freeHosts
+            if isClient(component):
+              hostsForComponent = freeHosts[0:1]
+
+        #extend 'hostsComponentsMap' with 'hostsForComponent'
+        for hostName in hostsForComponent:
+          if hostName not in hostsComponentsMap:
+            hostsComponentsMap[hostName] = []
+          hostsComponentsMap[hostName].append( { "name": componentName } )
+
+    #prepare 'host-group's from 'hostsComponentsMap'
+    host_groups = recommendations["recommendations"]["blueprint"]["host_groups"]
+    bindings = recommendations["recommendations"]["blueprint_cluster_binding"]["host_groups"]
+    index = 0
+    for key in hostsComponentsMap.keys():
+      index += 1
+      host_group_name = "host-group-{0}".format(index)
+      host_groups.append( { "name": host_group_name, "components": hostsComponentsMap[key] } )
+      bindings.append( { "name": host_group_name, "hosts": [{ "fqdn": socket.getfqdn(key) }] } )
+
+    return recommendations
+  pass
+
+  def getHostForComponent(self, component, hostsList):
+    componentName = component["StackServiceComponents"]["component_name"]
+    scheme = self.defineSelectionScheme(componentName)
+
+    if len(hostsList) == 1:
+      return hostsList[0]
+    else:
+      for key in scheme.keys():
+        if isinstance(key, ( int, long )):
+          if len(hostsList) < key:
+            return hostsList[scheme[key]]
+      return hostsList[scheme['else']]
+
+  def defineSelectionScheme(self, componentName):
+    scheme = self.selectionScheme(componentName)
+    if scheme is None:
+      scheme = {"else": 0}
+    return scheme
+
+  def selectionScheme(self, componentName):
+    return {
+      'NAMENODE': {"else": 0},
+      'SECONDARY_NAMENODE': {"else": 1},
+      'HBASE_MASTER': {6: 0, 31: 2, "else": 3},
+
+      'HISTORYSERVER': {31: 1, "else": 2},
+      'RESOURCEMANAGER': {31: 1, "else": 2},
+
+      'OOZIE_SERVER': {6: 1, 31: 2, "else": 3},
+
+      'HIVE_SERVER': {6: 1, 31: 2, "else": 4},
+      'HIVE_METASTORE': {6: 1, 31: 2, "else": 4},
+      'WEBHCAT_SERVER': {6: 1, 31: 2, "else": 4},
+      }.get(componentName, None)
+
+  def isNotPreferableOnAmbariServerHost(self, component):
+    componentName = component["StackServiceComponents"]["component_name"]
+    service = ['GANGLIA_SERVER', 'NAGIOS_SERVER']
+    return componentName in service
+
+  def validateComponentLayout(self, services, hosts):
+    """Returns array of Validation objects about issues with hostnames components assigned to"""
+    stackName = services["Versions"]["stack_name"]
+    stackVersion = services["Versions"]["stack_version"]
+
+    validations = {
+      "Versions": {"stack_name": stackName, "stack_version": stackVersion},
+      "items": [ ]
+    }
+    items = validations["items"]
+
+    # Validating NAMENODE and SECONDARY_NAMENODE are on different hosts if possible
+    hostsList = [host["Hosts"]["host_name"] for host in hosts["items"]]
+    hostsCount = len(hostsList)
+    servicesList = [service["StackServices"]["service_name"] for service in services["services"]]
+
+    componentsListList = [service["components"] for service in services["services"]]
+    componentsList = [item for sublist in componentsListList for item in sublist]
+    nameNodeHosts = [component["StackServiceComponents"]["hostnames"] for component in componentsList if component["StackServiceComponents"]["component_name"] == "NAMENODE"]
+    secondaryNameNodeHosts = [component["StackServiceComponents"]["hostnames"] for component in componentsList if component["StackServiceComponents"]["component_name"] == "SECONDARY_NAMENODE"]
+
+    if hostsCount > 1 and len(nameNodeHosts) > 0 and len(secondaryNameNodeHosts) > 0:
+      nameNodeHosts = nameNodeHosts[0]
+      secondaryNameNodeHosts = secondaryNameNodeHosts[0]
+      commonHosts = list(set(nameNodeHosts).intersection(secondaryNameNodeHosts))
+      for host in commonHosts:
+        items.append( { "type": 'host-component', "level": 'WARN', "message": 'NameNode and Secondary NameNode cannot be hosted on same machine', "component-name": 'NAMENODE', "host": str(host) } )
+        items.append( { "type": 'host-component', "level": 'WARN', "message": 'NameNode and Secondary NameNode cannot be hosted on same machine', "component-name": 'SECONDARY_NAMENODE', "host": str(host) } )
+
+    # Validating cardinality
+    for component in componentsList:
+      if component["StackServiceComponents"]["cardinality"] is not None:
+         componentName = component["StackServiceComponents"]["component_name"]
+         componentHostsCount = 0
+         if component["StackServiceComponents"]["hostnames"] is not None:
+           componentHostsCount = len(component["StackServiceComponents"]["hostnames"])
+         cardinality = str(component["StackServiceComponents"]["cardinality"])
+         # cardinality types: null, 1+, 1-2, 1, ALL
+         hostsMax = -sys.maxint - 1
+         hostsMin = sys.maxint
+         hostsMin = 0
+         hostsMax = 0
+         if "+" in cardinality:
+           hostsMin = int(cardinality[:-1])
+           hostsMax = sys.maxint
+         elif "-" in cardinality:
+           nums = cardinality.split("-")
+           hostsMin = int(nums[0])
+           hostsMax = int(nums[1])
+         elif "ALL" == cardinality:
+           hostsMin = hostsCount
+           hostsMax = hostsCount
+         else:
+           hostsMin = int(cardinality)
+           hostsMax = int(cardinality)
+
+         if componentHostsCount > hostsMax or componentHostsCount < hostsMin:
+           items.append( { "type": 'host-component', "level": 'ERROR', "message": 'Cardinality violation, cardinality={0}, hosts count={1}'.format(cardinality, str(componentHostsCount)), "component-name": str(componentName) } )
+
+    # Validating host-usage
+    usedHostsListList = [component["StackServiceComponents"]["hostnames"] for component in componentsList if not self.isNotValuable(component)]
+    usedHostsList = [item for sublist in usedHostsListList for item in sublist]
+    nonUsedHostsList = [item for item in hostsList if item not in usedHostsList]
+    for host in nonUsedHostsList:
+      items.append( { "type": 'host-component', "level": 'ERROR', "message": 'Host is not used', "host": str(host) } )
+
+    return validations
+  pass
+
+  def isNotValuable(self, component):
+    componentName = component["StackServiceComponents"]["component_name"]
+    service = ['JOURNALNODE', 'ZKFC', 'GANGLIA_MONITOR']
+    return componentName in service
+
+  def recommendConfigurations(self, services, hosts):
+    stackName = services["Versions"]["stack_name"]
+    stackVersion = services["Versions"]["stack_version"]
+    hostsList = [host["Hosts"]["host_name"] for host in hosts["items"]]
+    servicesList = [service["StackServices"]["service_name"] for service in services["services"]]
+    components = [component["StackServiceComponents"]["component_name"]
+                  for service in services["services"]
+                  for component in service["components"]]
+
+    clusterData = self.getClusterData(servicesList, hosts, components)
+
+    recommendations = {
+      "Versions": {"stack_name": stackName, "stack_version": stackVersion},
+      "hosts": hostsList,
+      "services": servicesList,
+      "recommendations": {
+        "blueprint": {
+          "configurations": {},
+          "host_groups": []
+        },
+        "blueprint_cluster_binding": {
+          "host_groups": []
+        }
+      }
+    }
+
+    configurations = recommendations["recommendations"]["blueprint"]["configurations"]
+
+    for service in servicesList:
+      calculation = self.recommendServiceConfigurations(service)
+      if calculation is not None:
+        calculation(configurations, clusterData)
+
+    return recommendations
+
+  def recommendServiceConfigurations(self, service):
+    return {
+    }.get(service, None)
+
+  def putProperty(self, config, configType):
+    config[configType] = {"properties": {}}
+    def appendProperty(key, value):
+      config[configType]["properties"][key] = str(value)
+    return appendProperty
+
+  def getClusterData(self, servicesList, hosts, components):
+
+    hBaseInstalled = False
+    if 'HBASE' in servicesList:
+      hBaseInstalled = True
+
+    cluster = {
+      "cpu": 0,
+      "disk": 0,
+      "ram": 0,
+      "hBaseInstalled": hBaseInstalled,
+      "components": components
+    }
+
+    if len(hosts["items"]) > 0:
+      host = hosts["items"][0]["Hosts"]
+      cluster["cpu"] = host["cpu_count"]
+      cluster["disk"] = len(host["disk_info"])
+      cluster["ram"] = int(host["total_mem"] / (1024 * 1024))
+
+    ramRecommendations = [
+      {"os":1, "hbase":1},
+      {"os":2, "hbase":1},
+      {"os":2, "hbase":2},
+      {"os":4, "hbase":4},
+      {"os":6, "hbase":8},
+      {"os":8, "hbase":8},
+      {"os":8, "hbase":8},
+      {"os":12, "hbase":16},
+      {"os":24, "hbase":24},
+      {"os":32, "hbase":32},
+      {"os":64, "hbase":64}
+    ]
+    index = {
+      cluster["ram"] <= 4: 0,
+      4 < cluster["ram"] <= 8: 1,
+      8 < cluster["ram"] <= 16: 2,
+      16 < cluster["ram"] <= 24: 3,
+      24 < cluster["ram"] <= 48: 4,
+      48 < cluster["ram"] <= 64: 5,
+      64 < cluster["ram"] <= 72: 6,
+      72 < cluster["ram"] <= 96: 7,
+      96 < cluster["ram"] <= 128: 8,
+      128 < cluster["ram"] <= 256: 9,
+      256 < cluster["ram"]: 10
+    }[1]
+    cluster["reservedRam"] = ramRecommendations[index]["os"]
+    cluster["hbaseRam"] = ramRecommendations[index]["hbase"]
+
+    cluster["minContainerSize"] = {
+      cluster["ram"] <= 4: 256,
+      4 < cluster["ram"] <= 8: 512,
+      8 < cluster["ram"] <= 24: 1024,
+      24 < cluster["ram"]: 2048
+    }[1]
+
+    '''containers = max(3, min (2*cores,min (1.8*DISKS,(Total available RAM) / MIN_CONTAINER_SIZE))))'''
+    cluster["containers"] = max(3,
+                                min(2 * cluster["cpu"],
+                                    int(min(1.8 * cluster["disk"],
+                                            cluster["ram"] / cluster["minContainerSize"]))))
+
+    '''ramPerContainers = max(2GB, RAM - reservedRam - hBaseRam) / containers'''
+    cluster["ramPerContainer"] = max(2048,
+                                     cluster["ram"] - cluster["reservedRam"] - cluster["hbaseRam"])
+    cluster["ramPerContainer"] /= cluster["containers"]
+    '''If greater than 1GB, value will be in multiples of 512.'''
+    if cluster["ramPerContainer"] > 1024:
+      cluster["ramPerContainer"] = ceil(cluster["ramPerContainer"] / 512) * 512
+
+    cluster["mapMemory"] = int(cluster["ramPerContainer"])
+    cluster["reduceMemory"] = cluster["ramPerContainer"]
+    cluster["amMemory"] = max(cluster["mapMemory"], cluster["reduceMemory"])
+
+    return cluster
+
+
+  def validateConfigurations(self, services, hosts):
+    """Returns array of Validation objects about issues with configuration values provided in services"""
+    stackName = services["Versions"]["stack_name"]
+    stackVersion = services["Versions"]["stack_version"]
+
+    validations = {
+      "Versions": {"stack_name": stackName, "stack_version": stackVersion},
+      "items": [ ]
+    }
+    items = validations["items"]
+
+    recommendations = self.recommendConfigurations(services, hosts)
+    recommendedDefaults = recommendations["recommendations"]["blueprint"]["configurations"]
+
+    configurations = services["configurations"]
+    for service in services["services"]:
+      serviceName = service["StackServices"]["service_name"]
+      validator = self.validateServiceConfigurations(serviceName)
+      if validator is not None:
+        siteName = validator[0]
+        method = validator[1]
+        if siteName in recommendedDefaults:
+          siteProperties = getSiteProperties(configurations, siteName)
+          if siteProperties is not None:
+            resultItems = method(siteProperties, recommendedDefaults[siteName]["properties"])
+            items.extend(resultItems)
+    return validations
+    pass
+
+  def validateServiceConfigurations(self, serviceName):
+    return {
+    }.get(serviceName, None)
+
+  def toConfigurationValidationErrors(self, items, siteName):
+    result = []
+    for item in items:
+      if item["message"] is not None:
+        error = { "type": 'configuration', "level": 'ERROR', "message": item["message"], "config-type": siteName, "config-name": item["config-name"] }
+        result.append(error)
+    return result
+
+  def validatorLessThenDefaultValue(self, properties, recommendedDefaults, propertyName):
+    if not propertyName in properties:
+      return "Value should be set"
+    value = to_number(properties[propertyName])
+    if value is None:
+      return "Value should be integer"
+    defaultValue = to_number(recommendedDefaults[propertyName])
+    if defaultValue is None:
+      return None
+    if value < defaultValue:
+      return "Value is less than the recommended default of {0}".format(defaultValue)
+    return None
+
+  def validateXmxValue(self, properties, recommendedDefaults, propertyName):
+    if not propertyName in properties:
+      return "Value should be set"
+    value = properties[propertyName]
+    defaultValue = recommendedDefaults[propertyName]
+    if defaultValue is None:
+      return "Config's default value can't be null or undefined"
+    if not checkXmxValueFormat(value):
+      return 'Invalid value format'
+    valueInt = formatXmxSizeToBytes(getXmxSize(value))
+    defaultValueXmx = getXmxSize(defaultValue)
+    defaultValueInt = formatXmxSizeToBytes(defaultValueXmx)
+    if valueInt < defaultValueInt:
+      return "Value is less than the recommended default of -Xmx" + defaultValueXmx
+    return None
+
+
+# Validation helper methods
+def getSiteProperties(configurations, siteName):
+  siteConfig = configurations.get(siteName)
+  if siteConfig is None:
+    return None
+  return siteConfig.get("properties")
+
+def to_number(s):
+  try:
+    return int(re.sub("\D", "", s))
+  except ValueError:
+    return None
+
+def checkXmxValueFormat(value):
+  p = re.compile('-Xmx(\d+)(b|k|m|g|p|t|B|K|M|G|P|T)?')
+  matches = p.findall(value)
+  return len(matches) == 1
+
+def getXmxSize(value):
+  p = re.compile("-Xmx(\d+)(.?)")
+  result = p.findall(value)[0]
+  if len(result) > 1:
+    # result[1] - is a space or size formatter (b|k|m|g etc)
+    return result[0] + result[1].lower()
+  return result[0]
+
+def formatXmxSizeToBytes(value):
+  value = value.lower()
+  if len(value) == 0:
+    return 0
+  modifier = value[-1]
+
+  if modifier == ' ' or modifier in "0123456789":
+    modifier = 'b'
+  m = {
+    modifier == 'b': 1,
+    modifier == 'k': 1024,
+    modifier == 'm': 1024 * 1024,
+    modifier == 'g': 1024 * 1024 * 1024,
+    modifier == 't': 1024 * 1024 * 1024 * 1024,
+    modifier == 'p': 1024 * 1024 * 1024 * 1024 * 1024
+    }[1]
+  return to_number(value) * m
+
+
+# Recommendation helper methods
+def isAlreadyPopulated(component):
+  if component["StackServiceComponents"]["hostnames"] is not None:
+    return len(component["StackServiceComponents"]["hostnames"]) > 0
+  return False
+
+def isClient(component):
+  return component["StackServiceComponents"]["component_category"] == 'CLIENT'
+
+def isSlave(component):
+  componentName = component["StackServiceComponents"]["component_name"]
+  isSlave = component["StackServiceComponents"]["component_category"] == 'SLAVE'
+  return isSlave
+
+def isMaster(component):
+  componentName = component["StackServiceComponents"]["component_name"]
+  isMaster = component["StackServiceComponents"]["is_master"]
+  return isMaster
+
+def isLocalHost(hostName):
+  return socket.getfqdn(hostName) == socket.getfqdn()
+
+def isMasterWithMultipleInstances(component):
+  componentName = component["StackServiceComponents"]["component_name"]
+  masters = ['ZOOKEEPER_SERVER', 'HBASE_MASTER']
+  return componentName in masters
+
+def defaultNoOfMasterHosts(component):
+  componentName = component["StackServiceComponents"]["component_name"]
+  return cardinality(componentName)[min]
+
+
+# Helper dictionaries
+def cardinality(componentName):
+  return {
+    'ZOOKEEPER_SERVER': {min: 3},
+    'HBASE_MASTER': {min: 1},
+    }.get(componentName, {min:1, max:1})
+

+ 25 - 0
ambari-server/src/main/resources/stacks/HDP/1.3.3/services/stack_advisor.py

@@ -0,0 +1,25 @@
+#!/usr/bin/env ambari-python-wrap
+"""
+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.
+"""
+
+import socket
+
+from stack_advisor import StackAdvisor
+
+class HDP133StackAdvisor(HDP132StackAdvisor):
+  pass

+ 25 - 0
ambari-server/src/main/resources/stacks/HDP/1.3/services/stack_advisor.py

@@ -0,0 +1,25 @@
+#!/usr/bin/env ambari-python-wrap
+"""
+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.
+"""
+
+import socket
+
+from stack_advisor import StackAdvisor
+
+class HDP13StackAdvisor(HDP133StackAdvisor):
+  pass

+ 2 - 1
ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-ANY/scripts/params.py

@@ -20,11 +20,12 @@ limitations under the License.
 from resource_management import *
 
 config = Script.get_config()
+tmp_dir = Script.get_tmp_dir()
 
 _authentication = config['configurations']['core-site']['hadoop.security.authentication']
 security_enabled = ( not is_empty(_authentication) and _authentication == 'kerberos')
 
-artifact_dir = "/tmp/HDP-artifacts/"
+artifact_dir = format("{tmp_dir}/AMBARI-artifacts/")
 jce_policy_zip = default("/hostLevelParams/jce_name", None) # None when jdk is already installed by user
 jce_location = config['hostLevelParams']['jdk_location']
 jdk_name = default("/hostLevelParams/jdk_name", None)

+ 1 - 1
ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-INSTALL/scripts/params.py

@@ -100,7 +100,7 @@ security_enabled = ( not is_empty(_authentication) and _authentication == 'kerbe
 
 #java params
 java_home = config['hostLevelParams']['java_home']
-artifact_dir = "/tmp/HDP-artifacts/"
+artifact_dir = format("{tmp_dir}/AMBARI-artifacts/")
 jdk_name = default("/hostLevelParams/jdk_name", None) # None when jdk is already installed by user
 jce_policy_zip = default("/hostLevelParams/jce_name", None) # None when jdk is already installed by user
 jce_location = config['hostLevelParams']['jdk_location']

+ 2 - 0
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/FLUME/metainfo.xml

@@ -20,11 +20,13 @@
   <services>
     <service>
       <name>FLUME</name>
+      <displayName>Flume</displayName>
       <comment>Data management and processing platform</comment>
       <version>1.4.0.2.0</version>
       <components>
         <component>
           <name>FLUME_HANDLER</name>
+          <displayName>Flume</displayName>
           <category>SLAVE</category>
           <cardinality>1+</cardinality>
           <commandScript>

+ 3 - 0
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/GANGLIA/metainfo.xml

@@ -20,11 +20,13 @@
   <services>
     <service>
       <name>GANGLIA</name>
+      <displayName>Ganglia</displayName>
       <comment>Ganglia Metrics Collection system (&lt;a href=&quot;http://oss.oetiker.ch/rrdtool/&quot; target=&quot;_blank&quot;&gt;RRDTool&lt;/a&gt; will be installed too)</comment>
       <version>3.5.0</version>
       <components>
         <component>
           <name>GANGLIA_SERVER</name>
+          <displayName>Ganglia Server</displayName>
           <category>MASTER</category>
           <cardinality>1</cardinality>
           <commandScript>
@@ -36,6 +38,7 @@
 
         <component>
           <name>GANGLIA_MONITOR</name>
+          <displayName>Ganglia Monitor</displayName>
           <category>SLAVE</category>
           <cardinality>ALL</cardinality>
           <auto-deploy>

+ 4 - 0
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HBASE/metainfo.xml

@@ -20,6 +20,7 @@
   <services>
     <service>
       <name>HBASE</name>
+      <displayName>HBase</displayName>
       <comment>Non-relational distributed database and centralized service for configuration management &amp;
         synchronization
       </comment>
@@ -27,6 +28,7 @@
       <components>
         <component>
           <name>HBASE_MASTER</name>
+          <displayName>HBase Master</displayName>
           <category>MASTER</category>
           <cardinality>1+</cardinality>
           <dependencies>
@@ -65,6 +67,7 @@
 
         <component>
           <name>HBASE_REGIONSERVER</name>
+          <displayName>RegionServer</displayName>
           <category>SLAVE</category>
           <cardinality>1+</cardinality>
           <commandScript>
@@ -75,6 +78,7 @@
 
         <component>
           <name>HBASE_CLIENT</name>
+          <displayName>HBase Client</displayName>
           <category>CLIENT</category>
           <cardinality>1+</cardinality>
           <commandScript>

+ 7 - 0
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HDFS/metainfo.xml

@@ -20,12 +20,14 @@
   <services>
     <service>
       <name>HDFS</name>
+      <displayName>HDFS</displayName>
       <comment>Apache Hadoop Distributed File System</comment>
       <version>2.1.0.2.0</version>
 
       <components>
         <component>
           <name>NAMENODE</name>
+          <displayName>NameNode</displayName>
           <category>MASTER</category>
           <cardinality>1-2</cardinality>
           <commandScript>
@@ -55,6 +57,7 @@
 
         <component>
           <name>DATANODE</name>
+          <displayName>DataNode</displayName>
           <category>SLAVE</category>
           <cardinality>1+</cardinality>
           <commandScript>
@@ -66,6 +69,7 @@
 
         <component>
           <name>SECONDARY_NAMENODE</name>
+          <displayName>SNameNode</displayName>
           <!-- TODO:  cardinality is conditional on HA usage -->
           <cardinality>1</cardinality>
           <category>MASTER</category>
@@ -78,6 +82,7 @@
 
         <component>
           <name>HDFS_CLIENT</name>
+          <displayName>HDFS Client</displayName>
           <category>CLIENT</category>
           <cardinality>1+</cardinality>
           <commandScript>
@@ -111,6 +116,7 @@
 
         <component>
           <name>JOURNALNODE</name>
+          <displayName>JournalNode</displayName>
           <category>SLAVE</category>
           <cardinality>0+</cardinality>
           <commandScript>
@@ -122,6 +128,7 @@
 
         <component>
           <name>ZKFC</name>
+          <displayName>ZKFailoverController</displayName>
           <category>SLAVE</category>
           <!-- TODO: cardinality is conditional on HA topology -->
           <cardinality>0+</cardinality>

+ 10 - 1
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HIVE/metainfo.xml

@@ -20,12 +20,14 @@
   <services>
     <service>
       <name>HIVE</name>
+      <displayName>Hive</displayName>
       <comment>Data warehouse system for ad-hoc queries &amp; analysis of large datasets and table &amp; storage management service</comment>
       <version>0.12.0.2.0</version>
       <components>
 
         <component>
           <name>HIVE_METASTORE</name>
+          <displayName>Hive Metastore</displayName>
           <category>MASTER</category>
           <cardinality>1</cardinality>
           <auto-deploy>
@@ -41,6 +43,7 @@
 
         <component>
           <name>HIVE_SERVER</name>
+          <displayName>HiveServer2</displayName>
           <category>MASTER</category>
           <cardinality>1</cardinality>
           <dependencies>
@@ -75,6 +78,7 @@
 
         <component>
           <name>MYSQL_SERVER</name>
+          <displayName>MySQL Server</displayName>
           <category>MASTER</category>
           <cardinality>0-1</cardinality>
           <commandScript>
@@ -85,6 +89,7 @@
 
         <component>
           <name>HIVE_CLIENT</name>
+          <displayName>Hive Client</displayName>
           <category>CLIENT</category>
           <cardinality>1+</cardinality>
           <commandScript>
@@ -176,11 +181,15 @@
 
     <service>
       <name>HCATALOG</name>
-      <comment>This is comment for HCATALOG service</comment>
+      <displayName>HCatalog</displayName>
+      <comment>A table and storage management layer for Hadoop that enables users with different data processing tools
+        to more easily read and write data on the grid.
+      </comment>
       <version>0.12.0.2.0.6.0</version>
       <components>
         <component>
           <name>HCAT</name>
+          <displayName>HCat</displayName>
           <category>CLIENT</category>
           <commandScript>
             <script>scripts/hcat_client.py</script>

+ 1 - 1
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HIVE/package/scripts/params.py

@@ -95,7 +95,7 @@ driver_curl_target = format("{java_share_dir}/{jdbc_jar_name}")
 
 hdfs_user =  config['configurations']['hadoop-env']['hdfs_user']
 user_group = config['configurations']['hadoop-env']['user_group']
-artifact_dir = "/tmp/HDP-artifacts/"
+artifact_dir = format("{tmp_dir}/AMBARI-artifacts/")
 
 target = format("{hive_lib}/{jdbc_jar_name}")
 

+ 2 - 0
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/NAGIOS/metainfo.xml

@@ -20,11 +20,13 @@
   <services>
     <service>
       <name>NAGIOS</name>
+      <displayName>Nagios</displayName>
       <comment>Nagios Monitoring and Alerting system</comment>
       <version>3.5.0</version>
       <components>
         <component>
            <name>NAGIOS_SERVER</name>
+          <displayName>Nagios Server</displayName>
            <category>MASTER</category>
            <cardinality>1</cardinality>
           <dependencies>

+ 3 - 0
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/OOZIE/metainfo.xml

@@ -20,12 +20,14 @@
   <services>
     <service>
       <name>OOZIE</name>
+      <displayName>Oozie</displayName>
       <comment>System for workflow coordination and execution of Apache Hadoop jobs.  This also includes the installation of the optional Oozie Web Console which relies on and will install the &lt;a target="_blank" href="http://www.sencha.com/legal/open-source-faq/"&gt;ExtJS&lt;/a&gt; Library.
       </comment>
       <version>4.0.0.2.0</version>
       <components>
         <component>
           <name>OOZIE_SERVER</name>
+          <displayName>Oozie Server</displayName>
           <category>MASTER</category>
           <cardinality>1</cardinality>
           <dependencies>
@@ -60,6 +62,7 @@
 
         <component>
           <name>OOZIE_CLIENT</name>
+          <displayName>Oozie Client</displayName>
           <category>CLIENT</category>
           <cardinality>1+</cardinality>
           <dependencies>

+ 2 - 0
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/PIG/metainfo.xml

@@ -20,11 +20,13 @@
   <services>
     <service>
       <name>PIG</name>
+      <displayName>Pig</displayName>
       <comment>Scripting platform for analyzing large datasets</comment>
       <version>0.12.0.2.0</version>
       <components>
         <component>
           <name>PIG</name>
+          <displayName>Pig</displayName>
           <category>CLIENT</category>
           <cardinality>0+</cardinality>
           <commandScript>

+ 2 - 0
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/SQOOP/metainfo.xml

@@ -20,6 +20,7 @@
   <services>
     <service>
       <name>SQOOP</name>
+      <displayName>Sqoop</displayName>
       <comment>Tool for transferring bulk data between Apache Hadoop and
         structured data stores such as relational databases
       </comment>
@@ -28,6 +29,7 @@
       <components>
         <component>
           <name>SQOOP</name>
+          <displayName>Sqoop</displayName>
           <category>CLIENT</category>
           <cardinality>1+</cardinality>
           <dependencies>

+ 3 - 1
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/WEBHCAT/metainfo.xml

@@ -20,11 +20,13 @@
   <services>
     <service>
       <name>WEBHCAT</name>
-      <comment>This is comment for WEBHCAT service</comment>
+      <displayName>WebHCat</displayName>
+      <comment>Provides a REST-like web API for HCatalog and related Hadoop components.</comment>
       <version>0.12.0.2.0</version>
       <components>
         <component>
           <name>WEBHCAT_SERVER</name>
+          <displayName>WebHCat Server</displayName>
           <category>MASTER</category>
           <cardinality>1</cardinality>
           <dependencies>

+ 7 - 0
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/YARN/metainfo.xml

@@ -21,12 +21,14 @@
   <services>
     <service>
       <name>YARN</name>
+      <displayName>YARN</displayName>
       <comment>Apache Hadoop NextGen MapReduce (YARN)</comment>
       <version>2.1.0.2.0</version>
       <components>
 
         <component>
           <name>RESOURCEMANAGER</name>
+          <displayName>ResourceManager</displayName>
           <category>MASTER</category>
           <cardinality>1-2</cardinality>
           <commandScript>
@@ -59,6 +61,7 @@
 
         <component>
           <name>NODEMANAGER</name>
+          <displayName>NodeManager</displayName>
           <category>SLAVE</category>
           <cardinality>1+</cardinality>
           <commandScript>
@@ -70,6 +73,7 @@
 
         <component>
           <name>YARN_CLIENT</name>
+          <displayName>Yarn Client</displayName>
           <category>CLIENT</category>
           <cardinality>1+</cardinality>
           <commandScript>
@@ -143,11 +147,13 @@
 
     <service>
       <name>MAPREDUCE2</name>
+      <displayName>MapReduce2</displayName>
       <comment>Apache Hadoop NextGen MapReduce (YARN)</comment>
       <version>2.1.0.2.0.6.0</version>
       <components>
         <component>
           <name>HISTORYSERVER</name>
+          <displayName>History Server</displayName>
           <category>MASTER</category>
           <cardinality>1</cardinality>
           <auto-deploy>
@@ -172,6 +178,7 @@
 
         <component>
           <name>MAPREDUCE2_CLIENT</name>
+          <displayName>MapReduce2 Client</displayName>
           <category>CLIENT</category>
           <cardinality>0+</cardinality>
           <commandScript>

+ 2 - 0
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/ZOOKEEPER/metainfo.xml

@@ -20,12 +20,14 @@
   <services>
     <service>
       <name>ZOOKEEPER</name>
+      <displayName>ZooKeeper</displayName>
       <comment>Centralized service which provides highly reliable distributed coordination</comment>
       <version>3.4.5.2.0</version>
       <components>
 
         <component>
           <name>ZOOKEEPER_SERVER</name>
+          <displayName>ZooKeeper Server</displayName>
           <category>MASTER</category>
           <cardinality>1+</cardinality>
           <commandScript>

+ 63 - 0
ambari-server/src/main/resources/stacks/HDP/2.1.GlusterFS/services/FALCON/configuration/falcon-env.xml

@@ -0,0 +1,63 @@
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<!--
+/**
+ * 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.
+ */
+-->
+<configuration supports_final="false">
+  <property>
+    <name>falcon_user</name>
+    <value>falcon</value>
+    <description>Falcon user.</description>
+  </property>
+  <property>
+    <name>falcon_port</name>
+    <value>15000</value>
+    <description>Port the Falcon Server listens on.</description>
+  </property>
+  <property>
+    <name>falcon_log_dir</name>
+    <value>/var/log/falcon</value>
+    <description>Falcon log directory.</description>
+  </property>
+  <property>
+    <name>falcon_pid_dir</name>
+    <value>/var/run/falcon</value>
+    <description>Falcon pid-file directory.</description>
+  </property>
+  <property>
+    <name>falcon_local_dir</name>
+    <value>/hadoop/falcon</value>
+    <description>Directory where Falcon data, such as activemq data, is stored.</description>
+  </property>
+  <!--embeddedmq properties-->
+  <property>
+    <name>falcon.embeddedmq.data</name>
+    <value>/hadoop/falcon/embeddedmq/data</value>
+    <description>Directory in which embeddedmq data is stored.</description>
+  </property>
+  <property>
+    <name>falcon.embeddedmq</name>
+    <value>true</value>
+    <description>Whether embeddedmq is enabled or not.</description>
+  </property>
+  <property>
+    <name>falcon.emeddedmq.port</name>
+    <value>61616</value>
+    <description>Port that embeddedmq will listen on.</description>
+  </property>
+</configuration>

Some files were not shown because too many files changed in this diff