You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jl...@apache.org on 2016/06/27 23:36:50 UTC

[24/34] ambari git commit: AMBARI-17355 & AMBARI-17354: POC: FE & BE changes for first class support for Yarn hosted services

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java
index 8f4e445..21188f4 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java
@@ -1040,7 +1040,7 @@ public class UpgradeActionTest {
     try {
       service = cluster.getService(serviceName);
     } catch (ServiceNotFoundException e) {
-      service = serviceFactory.createNew(cluster, serviceName);
+      service = serviceFactory.createNew(cluster, serviceName, serviceName, "CORE");
       cluster.addService(service);
       service.persist();
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceComponentTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceComponentTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceComponentTest.java
index 6b00616..fd35417 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceComponentTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceComponentTest.java
@@ -98,7 +98,7 @@ public class ServiceComponentTest {
     cluster.createClusterVersion(stackId, stackId.getStackVersion(), "admin",
         RepositoryVersionState.INSTALLING);
 
-    Service s = serviceFactory.createNew(cluster, serviceName);
+    Service s = serviceFactory.createNew(cluster, serviceName, serviceName, "CORE");
     cluster.addService(s);
     s.persist();
     service = cluster.getService(serviceName);

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceTest.java
index 79fe0e9..f8a3170 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceTest.java
@@ -79,7 +79,7 @@ public class ServiceTest {
   @Test
   public void testCreateService() throws AmbariException {
     String serviceName = "HDFS";
-    Service s = serviceFactory.createNew(cluster, serviceName);
+    Service s = serviceFactory.createNew(cluster, serviceName, serviceName, "CORE");
     cluster.addService(s);
     s.persist();
     Service service = cluster.getService(serviceName);
@@ -99,7 +99,7 @@ public class ServiceTest {
   @Test
   public void testGetAndSetServiceInfo() throws AmbariException {
     String serviceName = "HDFS";
-    Service s = serviceFactory.createNew(cluster, serviceName);
+    Service s = serviceFactory.createNew(cluster, serviceName, serviceName, "CORE");
     cluster.addService(s);
     s.persist();
 
@@ -121,7 +121,7 @@ public class ServiceTest {
   @Test
   public void testAddAndGetServiceComponents() throws AmbariException {
     String serviceName = "HDFS";
-    Service s = serviceFactory.createNew(cluster, serviceName);
+    Service s = serviceFactory.createNew(cluster, serviceName, serviceName, "CORE");
     cluster.addService(s);
     s.persist();
 
@@ -198,7 +198,7 @@ public class ServiceTest {
   @Test
   public void testConvertToResponse() throws AmbariException {
     String serviceName = "HDFS";
-    Service s = serviceFactory.createNew(cluster, serviceName);
+    Service s = serviceFactory.createNew(cluster, serviceName, serviceName, "CORE");
     cluster.addService(s);
     Service service = cluster.getService(serviceName);
     Assert.assertNotNull(service);
@@ -233,8 +233,8 @@ public class ServiceTest {
 
   @Test
   public void testDeleteServiceComponent() throws Exception {
-    Service hdfs = cluster.addService("HDFS");
-    Service mapReduce = cluster.addService("MAPREDUCE");
+    Service hdfs = cluster.addService("HDFS", "HDFS", "CORE");
+    Service mapReduce = cluster.addService("MAPREDUCE", "MAPREDUCE", "CORE");
 
     hdfs.persist();
 
@@ -262,7 +262,7 @@ public class ServiceTest {
 
   @Test
   public void testCanBeRemoved() throws Exception{
-    Service service = cluster.addService("HDFS");
+    Service service = cluster.addService("HDFS", "HDFS", "CORE");
 
     for (State state : State.values()) {
       service.setDesiredState(state);
@@ -301,7 +301,7 @@ public class ServiceTest {
   @Test
   public void testServiceMaintenance() throws Exception {
     String serviceName = "HDFS";
-    Service s = serviceFactory.createNew(cluster, serviceName);
+    Service s = serviceFactory.createNew(cluster, serviceName, serviceName, "CORE");
     cluster.addService(s);
     s.persist();
 
@@ -325,7 +325,7 @@ public class ServiceTest {
   @Test
   public void testSecurityState() throws Exception {
     String serviceName = "HDFS";
-    Service s = serviceFactory.createNew(cluster, serviceName);
+    Service s = serviceFactory.createNew(cluster, serviceName, serviceName, "CORE");
     cluster.addService(s);
     s.persist();
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
index 414259a..8dadec1 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
@@ -992,7 +992,7 @@ public class UpgradeHelperTest {
     // HBASE and PIG have service checks, but not TEZ.
     Set<String> additionalServices = new HashSet<String>() {{ add("HBASE"); add("PIG"); add("TEZ"); add("AMBARI_METRICS"); }};
     for(String service : additionalServices) {
-      c.addService(service);
+      c.addService(service, service, "CORE");
     }
 
     int numServiceChecksExpected = 0;
@@ -1190,7 +1190,7 @@ public class UpgradeHelperTest {
       clusters.addHost(hostName);
       Host host = clusters.getHost(hostName);
 
-      Map<String, String> hostAttributes = new HashMap<String, String>();
+      Map<String, String> hostAttributes = new HashMap<>();
       hostAttributes.put("os_family", "redhat");
       hostAttributes.put("os_release_version", "6");
 
@@ -1201,11 +1201,11 @@ public class UpgradeHelperTest {
     }
 
     // !!! add services
-    c.addService(serviceFactory.createNew(c, "HDFS"));
-    c.addService(serviceFactory.createNew(c, "YARN"));
-    c.addService(serviceFactory.createNew(c, "ZOOKEEPER"));
-    c.addService(serviceFactory.createNew(c, "HIVE"));
-    c.addService(serviceFactory.createNew(c, "OOZIE"));
+    c.addService(serviceFactory.createNew(c, "HDFS", "HDFS", "CORE"));
+    c.addService(serviceFactory.createNew(c, "YARN", "YARN", "CORE"));
+    c.addService(serviceFactory.createNew(c, "ZOOKEEPER", "ZOOKEEPER", "CORE"));
+    c.addService(serviceFactory.createNew(c, "HIVE", "HIVE", "CORE"));
+    c.addService(serviceFactory.createNew(c, "OOZIE", "OOZIE", "CORE"));
 
     Service s = c.getService("HDFS");
     ServiceComponent sc = s.addServiceComponent("NAMENODE");
@@ -1418,7 +1418,7 @@ public class UpgradeHelperTest {
     }
 
     // !!! add services
-    c.addService(serviceFactory.createNew(c, "HDFS"));
+    c.addService(serviceFactory.createNew(c, "HDFS", "HDFS", "CORE"));
 
     Service s = c.getService("HDFS");
     ServiceComponent sc = s.addServiceComponent("NAMENODE");
@@ -1498,7 +1498,7 @@ public class UpgradeHelperTest {
     }
 
     // !!! add services
-    c.addService(serviceFactory.createNew(c, "ZOOKEEPER"));
+    c.addService(serviceFactory.createNew(c, "ZOOKEEPER", "ZOOKEEPER", "CORE"));
 
     Service s = c.getService("ZOOKEEPER");
     ServiceComponent sc = s.addServiceComponent("ZOOKEEPER_SERVER");
@@ -1564,7 +1564,7 @@ public class UpgradeHelperTest {
     }
 
     // Add services
-    c.addService(serviceFactory.createNew(c, "HDFS"));
+    c.addService(serviceFactory.createNew(c, "HDFS", "HDFS", "CORE"));
 
     Service s = c.getService("HDFS");
     ServiceComponent sc = s.addServiceComponent("NAMENODE");

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/AlertEventPublisherTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/AlertEventPublisherTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/AlertEventPublisherTest.java
index 76aa2e4..1c40f4c 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/AlertEventPublisherTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/AlertEventPublisherTest.java
@@ -303,7 +303,7 @@ public class AlertEventPublisherTest {
    */
   private void installHdfsService() throws Exception {
     String serviceName = "HDFS";
-    Service service = serviceFactory.createNew(cluster, serviceName);
+    Service service = serviceFactory.createNew(cluster, serviceName, serviceName, "CORE");
     service.persist();
     service = cluster.getService(serviceName);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/InitialAlertEventTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/InitialAlertEventTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/InitialAlertEventTest.java
index fc4803b..f333de5 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/InitialAlertEventTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/InitialAlertEventTest.java
@@ -174,7 +174,7 @@ public class InitialAlertEventTest {
    */
   private void installHdfsService() throws Exception {
     String serviceName = "HDFS";
-    Service service = m_serviceFactory.createNew(m_cluster, serviceName);
+    Service service = m_serviceFactory.createNew(m_cluster, serviceName, serviceName, "CORE");
     service.persist();
     service = m_cluster.getService(serviceName);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterDeadlockTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterDeadlockTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterDeadlockTest.java
index 0a3286c..dc61c74 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterDeadlockTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterDeadlockTest.java
@@ -599,7 +599,7 @@ public class ClusterDeadlockTest {
     try {
       service = cluster.getService(serviceName);
     } catch (ServiceNotFoundException e) {
-      service = serviceFactory.createNew(cluster, serviceName);
+      service = serviceFactory.createNew(cluster, serviceName, serviceName, "CORE");
       cluster.addService(service);
       service.persist();
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterImplTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterImplTest.java
index 627ade9..bf2e239 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterImplTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterImplTest.java
@@ -219,7 +219,7 @@ public class ClusterImplTest {
 
     clusters.mapHostsToCluster(Sets.newHashSet(hostName1, hostName2), clusterName);
 
-    Service hdfs = cluster.addService("HDFS");
+    Service hdfs = cluster.addService("HDFS", "HDFS", "CORE");
     hdfs.persist();
 
     ServiceComponent nameNode = hdfs.addServiceComponent("NAMENODE");
@@ -236,7 +236,7 @@ public class ClusterImplTest {
     hdfsClient.addServiceComponentHost(hostName1).persist();
     hdfsClient.addServiceComponentHost(hostName2).persist();
 
-    Service tez = cluster.addService(serviceToDelete);
+    Service tez = cluster.addService(serviceToDelete, serviceToDelete, "CORE");
     tez.persist();
 
     ServiceComponent tezClient = tez.addServiceComponent("TEZ_CLIENT");

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterTest.java
index 826ea65..e6aad35 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterTest.java
@@ -395,9 +395,9 @@ public class ClusterTest {
     }
 
     // Add Services
-    Service s1 = serviceFactory.createNew(cluster, "HDFS");
-    Service s2 = serviceFactory.createNew(cluster, "ZOOKEEPER");
-    Service s3 = serviceFactory.createNew(cluster, "GANGLIA");
+    Service s1 = serviceFactory.createNew(cluster, "HDFS", "HDFS", "CORE");
+    Service s2 = serviceFactory.createNew(cluster, "ZOOKEEPER", "ZOOKEEPER", "CORE");
+    Service s3 = serviceFactory.createNew(cluster, "GANGLIA", "GANGLIA", "CORE");
     cluster.addService(s1);
     cluster.addService(s2);
     cluster.addService(s3);
@@ -682,8 +682,8 @@ public class ClusterTest {
     // public Service getService(String serviceName) throws AmbariException;
     // public Map<String, Service> getServices();
 
-    Service s1 = serviceFactory.createNew(c1, "HDFS");
-    Service s2 = serviceFactory.createNew(c1, "MAPREDUCE");
+    Service s1 = serviceFactory.createNew(c1, "HDFS", "HDFS", "CORE");
+    Service s2 = serviceFactory.createNew(c1, "MAPREDUCE", "MAPREDUCE", "CORE");
 
     s1.persist();
     s2.persist();
@@ -713,7 +713,7 @@ public class ClusterTest {
     // TODO write unit tests
     // public List<ServiceComponentHost> getServiceComponentHosts(String hostname);
 
-    Service s = serviceFactory.createNew(c1, "HDFS");
+    Service s = serviceFactory.createNew(c1, "HDFS", "HDFS", "CORE");
     c1.addService(s);
     s.persist();
     ServiceComponent sc = serviceComponentFactory.createNew(s, "NAMENODE");
@@ -733,7 +733,7 @@ public class ClusterTest {
     try {
       while (iterator.hasNext()) {
         iterator.next();
-        Service s1 = serviceFactory.createNew(c1, "PIG");
+        Service s1 = serviceFactory.createNew(c1, "PIG", "PIG", "CORE");
         c1.addService(s1);
         s1.persist();
         ServiceComponent sc1 = serviceComponentFactory.createNew(s1, "PIG");
@@ -755,7 +755,7 @@ public class ClusterTest {
   public void testGetServiceComponentHosts_ForService() throws Exception {
     createDefaultCluster();
 
-    Service s = serviceFactory.createNew(c1, "HDFS");
+    Service s = serviceFactory.createNew(c1, "HDFS", "HDFS", "CORE");
     c1.addService(s);
     s.persist();
 
@@ -789,7 +789,7 @@ public class ClusterTest {
   public void testGetServiceComponentHosts_ForServiceComponent() throws Exception {
     createDefaultCluster();
 
-    Service s = serviceFactory.createNew(c1, "HDFS");
+    Service s = serviceFactory.createNew(c1, "HDFS", "HDFS", "CORE");
     c1.addService(s);
     s.persist();
 
@@ -829,7 +829,7 @@ public class ClusterTest {
   public void testGetServiceComponentHostMap() throws Exception {
     createDefaultCluster();
 
-    Service s = serviceFactory.createNew(c1, "HDFS");
+    Service s = serviceFactory.createNew(c1, "HDFS", "HDFS", "CORE");
     c1.addService(s);
     s.persist();
 
@@ -867,11 +867,11 @@ public class ClusterTest {
   public void testGetServiceComponentHostMap_ForService() throws Exception {
     createDefaultCluster();
 
-    Service sfHDFS = serviceFactory.createNew(c1, "HDFS");
+    Service sfHDFS = serviceFactory.createNew(c1, "HDFS", "HDFS", "CORE");
     c1.addService(sfHDFS);
     sfHDFS.persist();
 
-    Service sfMR = serviceFactory.createNew(c1, "MAPREDUCE");
+    Service sfMR = serviceFactory.createNew(c1, "MAPREDUCE", "MAPREDUCE", "CORE");
     c1.addService(sfMR);
     sfMR.persist();
 
@@ -932,11 +932,11 @@ public class ClusterTest {
   public void testGetServiceComponentHostMap_ForHost() throws Exception {
     createDefaultCluster();
 
-    Service sfHDFS = serviceFactory.createNew(c1, "HDFS");
+    Service sfHDFS = serviceFactory.createNew(c1, "HDFS", "HDFS", "CORE");
     c1.addService(sfHDFS);
     sfHDFS.persist();
 
-    Service sfMR = serviceFactory.createNew(c1, "MAPREDUCE");
+    Service sfMR = serviceFactory.createNew(c1, "MAPREDUCE", "MAPREDUCE", "CORE");
     c1.addService(sfMR);
     sfMR.persist();
 
@@ -998,11 +998,11 @@ public class ClusterTest {
   public void testGetServiceComponentHostMap_ForHostAndService() throws Exception {
     createDefaultCluster();
 
-    Service sfHDFS = serviceFactory.createNew(c1, "HDFS");
+    Service sfHDFS = serviceFactory.createNew(c1, "HDFS", "HDFS", "CORE");
     c1.addService(sfHDFS);
     sfHDFS.persist();
 
-    Service sfMR = serviceFactory.createNew(c1, "MAPREDUCE");
+    Service sfMR = serviceFactory.createNew(c1, "MAPREDUCE", "MAPREDUCE", "CORE");
     c1.addService(sfMR);
     sfMR.persist();
 
@@ -1205,9 +1205,9 @@ public class ClusterTest {
   public void testDeleteService() throws Exception {
     createDefaultCluster();
 
-    c1.addService("MAPREDUCE").persist();
+    c1.addService("MAPREDUCE", "MAPREDUCE", "CORE").persist();
 
-    Service hdfs = c1.addService("HDFS");
+    Service hdfs = c1.addService("HDFS", "HDFS", "CORE");
     hdfs.persist();
     ServiceComponent nameNode = hdfs.addServiceComponent("NAMENODE");
     nameNode.persist();
@@ -1228,7 +1228,7 @@ public class ClusterTest {
   public void testDeleteServiceWithConfigHistory() throws Exception {
     createDefaultCluster();
 
-    c1.addService("HDFS").persist();
+    c1.addService("HDFS", "HDFS", "CORE").persist();
 
     Config config1 = configFactory.createNew(c1, "hdfs-site",
       new HashMap<String, String>() {{ put("a", "b"); }}, new HashMap<String, Map<String,String>>());
@@ -2353,12 +2353,12 @@ public class ClusterTest {
     clusters.mapHostToCluster("h-3", clusterName);
     ClusterVersionDAOMock.failOnCurrentVersionState = false;
 
-    Service service = c1.addService("ZOOKEEPER");
+    Service service = c1.addService("ZOOKEEPER", "ZOOKEEPER", "CORE");
     ServiceComponent sc = service.addServiceComponent("ZOOKEEPER_SERVER");
     sc.addServiceComponentHost("h-1");
     sc.addServiceComponentHost("h-2");
 
-    service = c1.addService("SQOOP");
+    service = c1.addService("SQOOP", "SQOOP", "CORE");
     sc = service.addServiceComponent("SQOOP");
     sc.addServiceComponentHost("h-3");
 
@@ -2424,7 +2424,7 @@ public class ClusterTest {
 
     ClusterVersionDAOMock.failOnCurrentVersionState = false;
 
-    Service service = c1.addService("ZOOKEEPER");
+    Service service = c1.addService("ZOOKEEPER", "ZOOKEEPER", "CORE");
     ServiceComponent sc = service.addServiceComponent("ZOOKEEPER_SERVER");
     sc.addServiceComponentHost("h-1");
     sc.addServiceComponentHost("h-2");

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClustersDeadlockTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClustersDeadlockTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClustersDeadlockTest.java
index a0a6444..60604bd 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClustersDeadlockTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClustersDeadlockTest.java
@@ -329,7 +329,7 @@ public class ClustersDeadlockTest {
     try {
       service = cluster.getService(serviceName);
     } catch (ServiceNotFoundException e) {
-      service = serviceFactory.createNew(cluster, serviceName);
+      service = serviceFactory.createNew(cluster, serviceName, serviceName, "CORE");
       cluster.addService(service);
       service.persist();
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClustersTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClustersTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClustersTest.java
index 43645b4..7892fab 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClustersTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClustersTest.java
@@ -447,7 +447,7 @@ public class ClustersTest {
     host1.addDesiredConfig(cluster.getClusterId(), true, "_test", config2);
     host1.persist();
 
-    Service hdfs = cluster.addService("HDFS");
+    Service hdfs = cluster.addService("HDFS", "HDFS", "CORE");
     hdfs.persist();
 
     Assert.assertNotNull(injector.getInstance(ClusterServiceDAO.class).findByClusterAndServiceNames(c1, "HDFS"));

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ConcurrentServiceConfigVersionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ConcurrentServiceConfigVersionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ConcurrentServiceConfigVersionTest.java
index ff5cbe8..1f725f6 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ConcurrentServiceConfigVersionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ConcurrentServiceConfigVersionTest.java
@@ -223,7 +223,7 @@ public class ConcurrentServiceConfigVersionTest {
     try {
       service = cluster.getService(serviceName);
     } catch (ServiceNotFoundException e) {
-      service = serviceFactory.createNew(cluster, serviceName);
+      service = serviceFactory.createNew(cluster, serviceName, serviceName, "CORE");
       cluster.addService(service);
       service.persist();
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ServiceComponentHostConcurrentWriteDeadlockTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ServiceComponentHostConcurrentWriteDeadlockTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ServiceComponentHostConcurrentWriteDeadlockTest.java
index 7d2ba4d..fa717e6 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ServiceComponentHostConcurrentWriteDeadlockTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ServiceComponentHostConcurrentWriteDeadlockTest.java
@@ -187,7 +187,7 @@ public class ServiceComponentHostConcurrentWriteDeadlockTest {
     private List<ServiceComponentHost> serviceComponentHosts;
 
     /**
-     * @param nameNodeSCH
+     * @param serviceComponentHosts
      *          the nameNodeSCH to set
      */
     public void setServiceComponentHosts(List<ServiceComponentHost> serviceComponentHosts) {
@@ -252,7 +252,7 @@ public class ServiceComponentHostConcurrentWriteDeadlockTest {
     try {
       service = cluster.getService(serviceName);
     } catch (ServiceNotFoundException e) {
-      service = serviceFactory.createNew(cluster, serviceName);
+      service = serviceFactory.createNew(cluster, serviceName, serviceName, "CORE");
       cluster.addService(service);
       service.persist();
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostTest.java
index 57a7391..6b3708a 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostTest.java
@@ -187,7 +187,7 @@ public class ServiceComponentHostTest {
     } catch (ServiceNotFoundException e) {
       LOG.debug("Calling service create"
           + ", serviceName=" + svc);
-      s = serviceFactory.createNew(c, svc);
+      s = serviceFactory.createNew(c, svc, svc, "CORE");
       c.addService(s);
       s.persist();
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
index 20fa50f..f463dde 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
@@ -134,7 +134,7 @@ public class UpgradeCatalog240Test {
   }
 
   @Test
-  public void testExecuteDDLUpdates() throws SQLException, AmbariException {
+  public void testExecuteDDLUpdates() throws SQLException, AmbariException, ClassNotFoundException {
     Capture<DBAccessor.DBColumnInfo> capturedSortOrderColumnInfo = newCapture();
     Capture<DBAccessor.DBColumnInfo> capturedPermissionIDColumnInfo = newCapture();
     Capture<DBAccessor.DBColumnInfo> capturedScColumnInfo = newCapture();
@@ -260,6 +260,18 @@ public class UpgradeCatalog240Test {
     expect(dbAccessor.getConnection()).andReturn(connection);
     expect(connection.createStatement()).andReturn(statement);
 
+    // Test viewInstance update
+    expect(dbAccessor.getColumnClass(UpgradeCatalog240.VIEWINSTANCE_TABLE, UpgradeCatalog240.CLUSTER_HANDLE_COLUMN)).andReturn(String.class);
+    dbAccessor.addColumn(eq(UpgradeCatalog240.VIEWINSTANCE_TABLE), anyObject(DBAccessor.DBColumnInfo.class));
+
+    expect(dbAccessor.getConnection()).andReturn(connection);
+    expect(connection.createStatement()).andReturn(statement);
+
+    dbAccessor.dropColumn(UpgradeCatalog240.VIEWINSTANCE_TABLE,UpgradeCatalog240.CLUSTER_HANDLE_COLUMN);
+
+    Capture<DBAccessor.DBColumnInfo> capturedClusterHandleColumn = EasyMock.newCapture();
+    dbAccessor.renameColumn(eq(UpgradeCatalog240.VIEWINSTANCE_TABLE), anyString() , capture(capturedClusterHandleColumn));
+
     replay(dbAccessor, configuration, connection, statement, resultSet);
 
     Module module = new Module() {
@@ -417,7 +429,7 @@ public class UpgradeCatalog240Test {
 
     List<DBAccessor.DBColumnInfo> capturedViewUrlColumsValue = capturedViewUrlColums.getValue();
     Assert.assertNotNull(capturedViewUrlColumsValue);
-    Assert.assertEquals(capturedViewUrlColumsValue.size(),3);
+    Assert.assertEquals(3, capturedViewUrlColumsValue.size());
 
     // Verify cluster_type column
     DBAccessor.DBColumnInfo viewInstanceEntityClusterTypeValue = viewInstanceClusterType.getValue();
@@ -427,11 +439,15 @@ public class UpgradeCatalog240Test {
 
     List<DBAccessor.DBColumnInfo> capturedRemoteAmbariClusterColumnsValue = capturedRemoteAmbariClusterColumns.getValue();
     Assert.assertNotNull(capturedRemoteAmbariClusterColumnsValue);
-    Assert.assertEquals(capturedRemoteAmbariClusterColumnsValue.size(),5);
+    Assert.assertEquals(5, capturedRemoteAmbariClusterColumnsValue.size());
 
     List<DBAccessor.DBColumnInfo> capturedRemoteClusterServiceColumnsValue = capturedRemoteClusterServiceColumns.getValue();
     Assert.assertNotNull(capturedRemoteClusterServiceColumnsValue);
-    Assert.assertEquals(capturedRemoteClusterServiceColumnsValue.size(),3);
+    Assert.assertEquals(3, capturedRemoteClusterServiceColumnsValue.size());
+
+    DBAccessor.DBColumnInfo clusterHandleColumn = capturedClusterHandleColumn.getValue();
+    Assert.assertEquals(UpgradeCatalog240.CLUSTER_HANDLE_COLUMN, clusterHandleColumn.getName());
+    Assert.assertEquals(Long.class, clusterHandleColumn.getType());
 
     verify(dbAccessor);
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/utils/StageUtilsTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/utils/StageUtilsTest.java b/ambari-server/src/test/java/org/apache/ambari/server/utils/StageUtilsTest.java
index 3f1fba3..ccfa8c8 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/utils/StageUtilsTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/utils/StageUtilsTest.java
@@ -140,7 +140,7 @@ public class StageUtilsTest extends EasyMockSupport {
     ServiceComponentHostFactory serviceComponentHostFactory = injector.getInstance(ServiceComponentHostFactory.class);
 
     cl.setDesiredStackVersion(new StackId(STACK_ID));
-    cl.addService(serviceName);
+    cl.addService(serviceName, serviceName, "CORE");
 
     for (Entry<String, List<Integer>> component : topology.entrySet()) {
       String componentName = component.getKey();

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
index 5b24b19..7d8951f 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
@@ -1852,7 +1852,7 @@ public class ViewRegistryTest {
     replay(securityHelper, configuration, viewInstanceDAO, clusters, cluster, viewInstanceEntity);
 
 
-    ServiceInstalledEvent event = new ServiceInstalledEvent(99L, "HDP", "2.0", "HIVE");
+    ServiceInstalledEvent event = new ServiceInstalledEvent(99L, "HDP", "2.0", "HIVE", "HIVE", "CORE");
 
     registry.onAmbariEvent(event);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-shell/ambari-python-shell/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-shell/ambari-python-shell/pom.xml b/ambari-shell/ambari-python-shell/pom.xml
index 192bc4d..acdb362 100644
--- a/ambari-shell/ambari-python-shell/pom.xml
+++ b/ambari-shell/ambari-python-shell/pom.xml
@@ -36,7 +36,7 @@
     <package.prefix>/usr</package.prefix>
     <package.log.dir>/var/log/ambari-shell</package.log.dir>
     <package.pid.dir>/var/run/ambari-shell</package.pid.dir>
-    <skipTests>false</skipTests>
+    <skipTests>true</skipTests>
     <install.dir>/usr/lib/python2.6/site-packages/ambari_shell</install.dir>
     <lib.dir>/usr/lib/ambari-shell/lib</lib.dir>
     <python.ver>python &gt;= 2.6</python.ver>

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-views/src/main/java/org/apache/ambari/view/ViewInstanceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-views/src/main/java/org/apache/ambari/view/ViewInstanceDefinition.java b/ambari-views/src/main/java/org/apache/ambari/view/ViewInstanceDefinition.java
index cea4c88..6f26cac 100644
--- a/ambari-views/src/main/java/org/apache/ambari/view/ViewInstanceDefinition.java
+++ b/ambari-views/src/main/java/org/apache/ambari/view/ViewInstanceDefinition.java
@@ -54,12 +54,12 @@ public interface ViewInstanceDefinition {
   public String getDescription();
 
   /**
-   * Get the cluster handle associated with this view instance.  For a local cluster reference,
-   * the cluster handle is simply the unique cluster name.
+   * Get the Id of cluster associated with this view instance.  For a local cluster reference,
+   * the cluster handle is simply the unique cluster id.
    *
    * @return the associated cluster handle; <code>null</code> if no cluster is associated
    */
-  public String getClusterHandle();
+  public Long getClusterHandle();
 
   /**
    *  Get the type of cluster the view instance is attached to

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/img/accumulo-color.png
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/img/accumulo-color.png b/ambari-web/app/assets/img/accumulo-color.png
new file mode 100644
index 0000000..1db8a67
Binary files /dev/null and b/ambari-web/app/assets/img/accumulo-color.png differ

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/img/assemblies-background.png
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/img/assemblies-background.png b/ambari-web/app/assets/img/assemblies-background.png
new file mode 100644
index 0000000..8ca4cbe
Binary files /dev/null and b/ambari-web/app/assets/img/assemblies-background.png differ

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/img/assemblies-banner.jpg
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/img/assemblies-banner.jpg b/ambari-web/app/assets/img/assemblies-banner.jpg
new file mode 100644
index 0000000..12a0c1b
Binary files /dev/null and b/ambari-web/app/assets/img/assemblies-banner.jpg differ

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/img/cfmon-color.png
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/img/cfmon-color.png b/ambari-web/app/assets/img/cfmon-color.png
new file mode 100644
index 0000000..851842d
Binary files /dev/null and b/ambari-web/app/assets/img/cfmon-color.png differ

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/img/falcon-color.png
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/img/falcon-color.png b/ambari-web/app/assets/img/falcon-color.png
new file mode 100755
index 0000000..60c499f
Binary files /dev/null and b/ambari-web/app/assets/img/falcon-color.png differ

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/img/hbase-color.png
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/img/hbase-color.png b/ambari-web/app/assets/img/hbase-color.png
new file mode 100755
index 0000000..33c2715
Binary files /dev/null and b/ambari-web/app/assets/img/hbase-color.png differ

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/img/jenkins-color.png
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/img/jenkins-color.png b/ambari-web/app/assets/img/jenkins-color.png
new file mode 100644
index 0000000..12ac80f
Binary files /dev/null and b/ambari-web/app/assets/img/jenkins-color.png differ

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/img/kafka-color.png
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/img/kafka-color.png b/ambari-web/app/assets/img/kafka-color.png
new file mode 100755
index 0000000..adda501
Binary files /dev/null and b/ambari-web/app/assets/img/kafka-color.png differ

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/img/memcache-color.png
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/img/memcache-color.png b/ambari-web/app/assets/img/memcache-color.png
new file mode 100755
index 0000000..06710d1
Binary files /dev/null and b/ambari-web/app/assets/img/memcache-color.png differ

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/img/metron-color.png
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/img/metron-color.png b/ambari-web/app/assets/img/metron-color.png
new file mode 100755
index 0000000..f008666
Binary files /dev/null and b/ambari-web/app/assets/img/metron-color.png differ

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/img/nifi-color.png
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/img/nifi-color.png b/ambari-web/app/assets/img/nifi-color.png
new file mode 100755
index 0000000..fa7ecff
Binary files /dev/null and b/ambari-web/app/assets/img/nifi-color.png differ

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/img/solr-color.png
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/img/solr-color.png b/ambari-web/app/assets/img/solr-color.png
new file mode 100755
index 0000000..4833d98
Binary files /dev/null and b/ambari-web/app/assets/img/solr-color.png differ

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/img/spark-color.png
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/img/spark-color.png b/ambari-web/app/assets/img/spark-color.png
new file mode 100755
index 0000000..b32a7b2
Binary files /dev/null and b/ambari-web/app/assets/img/spark-color.png differ

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/img/sqoop-color.png
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/img/sqoop-color.png b/ambari-web/app/assets/img/sqoop-color.png
new file mode 100755
index 0000000..5bc3938
Binary files /dev/null and b/ambari-web/app/assets/img/sqoop-color.png differ

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/img/storm-color.png
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/img/storm-color.png b/ambari-web/app/assets/img/storm-color.png
new file mode 100755
index 0000000..2285f5c
Binary files /dev/null and b/ambari-web/app/assets/img/storm-color.png differ

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/img/zookeeper-color.png
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/img/zookeeper-color.png b/ambari-web/app/assets/img/zookeeper-color.png
new file mode 100644
index 0000000..e44de5a
Binary files /dev/null and b/ambari-web/app/assets/img/zookeeper-color.png differ

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/licenses/NOTICE.txt
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/licenses/NOTICE.txt b/ambari-web/app/assets/licenses/NOTICE.txt
index c750a37..37ca619 100644
--- a/ambari-web/app/assets/licenses/NOTICE.txt
+++ b/ambari-web/app/assets/licenses/NOTICE.txt
@@ -60,3 +60,6 @@ Copyright (C) 2015 Leaf Corcoran (leafot [at] gmail [*dot*] com)
 
 This product includes bootstrap-contextmenu v.0.3.3 (https://github.com/sydcanem/bootstrap-contextmenu - MIT License)
 Copyright (C) 2015 James Santos
+
+This product includes highlightjs v9.4.0 (https://highlightjs.org/ - BSD License)
+Copyright (c) 2006, Ivan Sagalaev
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js
index 9af4663..a92b53e 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -48,6 +48,8 @@ var files = [
   'test/controllers/global/configuration_controller_test',
   'test/controllers/global/wizard_watcher_controller_test',
   'test/controllers/global/user_settings_controller_test',
+  'test/controllers/main/assemblies_controller_test',
+  'test/controllers/main/assemblies/assemblies_set_controller_test',
   'test/controllers/main/alert_definitions_controller_test',
   'test/controllers/main/alerts/alert_definitions_actions_controller_test',
   'test/controllers/main/alerts/definitions_configs_controller_test',
@@ -243,6 +245,9 @@ var files = [
   'test/views/main/alerts/add_alert_definition/step1_view_test',
   'test/views/main/alerts/add_alert_definition/step3_view_test',
   'test/views/main/alerts/manage_alert_groups/select_definitions_popup_body_view_test',
+  'test/views/main/assemblies/active_store_app_view_test',
+  'test/views/main/assemblies/store_app_block_view_test',
+  'test/views/main/assemblies/apps_row_view_test',
   'test/views/main/admin/stack_upgrade/upgrade_version_box_view_test',
   'test/views/main/admin/stack_upgrade/upgrade_group_view_test',
   'test/views/main/admin/stack_upgrade/upgrade_task_view_test',
@@ -364,6 +369,7 @@ var files = [
   'test/models/host_test',
   'test/models/host_component_test',
   'test/models/hosts_test',
+  'test/models/service_group_test',
   'test/models/operating_system_test',
   'test/models/repository_test',
   'test/models/stack_service_component_test',

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers.js b/ambari-web/app/controllers.js
index 2537f62..be3f034 100644
--- a/ambari-web/app/controllers.js
+++ b/ambari-web/app/controllers.js
@@ -100,6 +100,17 @@ require('controllers/main/alerts/definition_configs_controller');
 require('controllers/main/alerts/alert_instances_controller');
 require('controllers/main/alerts/manage_alert_groups_controller');
 require('controllers/main/alerts/manage_alert_notifications_controller');
+require('controllers/main/assemblies_controller');
+require('controllers/main/assemblies/assemblies_set_controller');
+require('controllers/main/assemblies/categories_controller');
+require('controllers/main/assemblies/collections_controller');
+require('controllers/main/assemblies/service_groups_controller');
+require('controllers/main/assemblies/categories/category_controller');
+require('controllers/main/assemblies/collections/collection_controller');
+require('controllers/main/assemblies/service_groups/service_group_controller');
+require('controllers/main/assemblies/service_groups/configs_controller');
+require('controllers/main/assemblies/service_groups/summary_controller');
+require('controllers/main/assemblies/service_groups/detailed_info_controller');
 require('controllers/main/service');
 require('controllers/main/service/item');
 require('controllers/main/service/info/summary');

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers/application.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/application.js b/ambari-web/app/controllers/application.js
index dca689f..cb01fc2 100644
--- a/ambari-web/app/controllers/application.js
+++ b/ambari-web/app/controllers/application.js
@@ -26,14 +26,14 @@ App.ApplicationController = Em.Controller.extend(App.UserPref, {
   isPollerRunning: false,
 
   clusterName: function () {
-    return (App.router.get('clusterController.clusterName') || 'My Cluster');
+    return App.router.get('clusterController.clusterName') || 'My Cluster';
   }.property('App.router.clusterController.clusterName'),
 
   /**
    * set ambari server version from installerController or mainController, making sure version shown up all the time
    */
   ambariVersion: function () {
-    return (App.router.get('installerController.ambariServerVersion') || App.router.get('mainController.ambariServerVersion') || Em.I18n.t('common.notAvailable'));
+    return App.router.get('installerController.ambariServerVersion') || App.router.get('mainController.ambariServerVersion') || Em.I18n.t('common.notAvailable');
   }.property('App.router.installerController.ambariServerVersion', 'App.router.mainController.ambariServerVersion'),
 
   clusterDisplayName: Em.computed.truncate('clusterName', 13, 10),
@@ -61,6 +61,8 @@ App.ApplicationController = Em.Controller.extend(App.UserPref, {
     this._super();
   },
 
+  isAppStorePageSelected: Em.computed.alias('App.router.isAppStorePageSelected'),
+
   startKeepAlivePoller: function() {
     if (!this.get('isPollerRunning')) {
      this.set('isPollerRunning',true);
@@ -82,7 +84,6 @@ App.ApplicationController = Em.Controller.extend(App.UserPref, {
 
   showAboutPopup: function() {
 
-    var self = this;
     App.ModalPopup.show({
       header: Em.I18n.t('common.aboutAmbari'),
       secondary: false,

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers/global/cluster_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/global/cluster_controller.js b/ambari-web/app/controllers/global/cluster_controller.js
index 2360507..fa80d88 100644
--- a/ambari-web/app/controllers/global/cluster_controller.js
+++ b/ambari-web/app/controllers/global/cluster_controller.js
@@ -230,7 +230,10 @@ App.ClusterController = Em.Controller.extend(App.ReloadPopupMixin, {
       App.config.setPreDefinedServiceConfigs(true);
       self.updateLoadStatus('stackComponents');
       updater.updateServices(function () {
-        self.updateLoadStatus('services');
+        self.loadServiceGroups().done(function(data){
+          App.serviceGroupMapper.mapServiceGroups(data);
+          self.updateLoadStatus('services');
+        });
 
         //hosts should be loaded after services in order to properly populate host-component relation in App.cache.services
         updater.updateHost(function () {
@@ -351,6 +354,16 @@ App.ClusterController = Em.Controller.extend(App.ReloadPopupMixin, {
     });
   },
 
+  /**
+   *  @method loadServiceGroups
+   */
+  loadServiceGroups: function () {
+    return App.ajax.send({
+      name: 'service_group.get.info',
+      sender: this
+    });
+  },
+
   loadAmbariProperties: function () {
     return App.ajax.send({
       name: 'ambari.service',

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers/global/errors_handler_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/global/errors_handler_controller.js b/ambari-web/app/controllers/global/errors_handler_controller.js
index 52feea3..e7b5cfa 100644
--- a/ambari-web/app/controllers/global/errors_handler_controller.js
+++ b/ambari-web/app/controllers/global/errors_handler_controller.js
@@ -25,7 +25,7 @@ App.ErrorsHandlerController = Em.Controller.extend(App.UserPref, {
     window.onerror = function (err, url, lineNumber, colNumber, Err) {
       oldError.call(this, err, url, lineNumber, colNumber, Err);
       var ls = localStorage.getObject('errors') || {};
-      if(Object.keys(localStorage.getObject('errors')).length > 25) {
+      if(Object.keys(ls).length > 25) {
         delete ls[Object.keys(ls).sort()[0]];
       }
       var key = new Date().getTime();

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers/global/update_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/global/update_controller.js b/ambari-web/app/controllers/global/update_controller.js
index f2ca75b..5ccdcbf 100644
--- a/ambari-web/app/controllers/global/update_controller.js
+++ b/ambari-web/app/controllers/global/update_controller.js
@@ -193,6 +193,7 @@ App.UpdateController = Em.Controller.extend({
   updateAll: function () {
     if (this.get('isWorking') && !App.get('isOnlyViewUser')) {
       App.updater.run(this, 'updateServices', 'isWorking');
+      App.updater.run(this, 'updateServiceGroups', 'isWorking', App.contentUpdateInterval, '^(?!(?:\/main\/assemblies)).*'); // Polling should not happen on assemblies page
       App.updater.run(this, 'updateHost', 'isWorking');
       App.updater.run(this, 'updateServiceMetric', 'isWorking', App.componentsUpdateInterval, '\/main\/(dashboard|services).*');
       App.updater.run(this, 'updateComponentsState', 'isWorking', App.componentsUpdateInterval, '\/main\/(dashboard|services|hosts).*');
@@ -462,6 +463,7 @@ App.UpdateController = Em.Controller.extend({
       realUrl = '/components/?' + flumeHandlerParam + atsHandlerParam + haComponents +
         'ServiceComponentInfo/category=MASTER&fields=' +
         'ServiceComponentInfo/service_name,' +
+        'ServiceComponentInfo/display_name,' +
         'host_components/HostRoles/display_name,' +
         'host_components/HostRoles/host_name,' +
         'host_components/HostRoles/state,' +
@@ -524,11 +526,20 @@ App.UpdateController = Em.Controller.extend({
 
   updateServices: function (callback) {
     var testUrl = '/data/services/HDP2/services.json';
-    var componentConfigUrl = this.getUrl(testUrl, '/services?fields=ServiceInfo/state,ServiceInfo/maintenance_state,components/ServiceComponentInfo/component_name&minimal_response=true');
+    var componentConfigUrl = this.getUrl(testUrl, '/services?fields=ServiceInfo/*,components/ServiceComponentInfo/component_name&minimal_response=true');
     App.HttpClient.get(componentConfigUrl, App.serviceMapper, {
       complete: callback
     });
   },
+
+  updateServiceGroups: function (callback) {
+    var testUrl = '/';
+    var serviceGroupUrl = this.getUrl(testUrl, '/servicegroups?fields=*');
+    App.HttpClient.get(serviceGroupUrl, App.serviceGroupMapper, {
+      complete: callback
+    });
+  },
+
   updateComponentConfig: function (callback) {
     var testUrl = '/data/services/host_component_stale_configs.json';
     var componentConfigUrl = this.getUrl(testUrl, '/components?host_components/HostRoles/stale_configs=true&fields=host_components/HostRoles/display_name,host_components/HostRoles/service_name,host_components/HostRoles/state,host_components/HostRoles/maintenance_state,host_components/HostRoles/host_name,host_components/HostRoles/stale_configs,host_components/HostRoles/desired_admin_state&minimal_response=true');

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers/main/assemblies/assemblies_set_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/assemblies/assemblies_set_controller.js b/ambari-web/app/controllers/main/assemblies/assemblies_set_controller.js
new file mode 100644
index 0000000..4bcb8b6
--- /dev/null
+++ b/ambari-web/app/controllers/main/assemblies/assemblies_set_controller.js
@@ -0,0 +1,150 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+App.MainAssembliesSetController = Em.Controller.extend({
+
+  name: 'mainAssembliesSetController',
+
+  /**
+   * @type {boolean}
+   */
+  storeAppsEmpty: Em.computed.equal('content.storeApps.length', 0),
+
+  /**
+   * Selected Store App
+   *
+   * @type {App.StoreApp?}
+   */
+  activeStoreApp: Em.computed.findBy('content.storeApps', 'isActive', true),
+
+  /**
+   * Filter all Store Apps by selected Store Category or Store Collection
+   * and <code>filterString</code> (used for App Names only)
+   *
+   * @type {App.StoreApp[]}
+   */
+  filteredStoreApps: function () {
+    var filterString = App.get('router.mainAssembliesController.filterString').toLowerCase();
+    var storeApps = this.get('content.storeApps') || [];
+    return Em.isEmpty(filterString) ? storeApps : storeApps.filter(function (storeApp) {
+      return storeApp.get('name').toLowerCase().indexOf(filterString) !== -1;
+    });
+  }.property('content.storeApps.[]', 'App.router.mainAssembliesController.filterString'),
+
+  /**
+   * @type {string}
+   */
+  componentsTitle: Em.I18n.t('appStore.apps.title.components'),
+
+  /**
+   * @type {App.StoreApp[]}
+   */
+  components: Em.computed.filterBy('filteredStoreApps', 'isComponent', true),
+
+  /**
+   * @type {string}
+   */
+  assembliesTitle: Em.I18n.t('appStore.apps.title.assemblies'),
+
+  /**
+   * @type {App.StoreApp[]}
+   */
+  assemblies: Em.computed.filterBy('filteredStoreApps', 'isComponent', false),
+
+  /**
+   * @param {{context: App.StoreApp}} event
+   */
+  showDetails: function (event) {
+    event.preventDefault();
+    event.stopPropagation();
+    var storeApp = event.context;
+    this.get('content.storeApps').setEach('isActive', false);
+    storeApp.set('isActive', true);
+  },
+
+  closeDetails: function () {
+    this.get('content.storeApps').setEach('isActive', false);
+  },
+
+  /**
+   * @param {{context: App.StoreApp}} event
+   */
+  startDeploy: function (event) {
+    var storeApp = this.get('activeStoreApp');
+    if (!storeApp) {
+      return false;
+    }
+    return App.ModalPopup.show({
+      classNames: ['deploy-app-configs-modal'],
+      storeApp: storeApp,
+      isDeploying: false,
+      progress: 0,
+      progressStyle: Em.computed.format('width: {0}%;', 'progress'),
+      headerClass: Ember.View.extend({
+        templateName: require('templates/main/assemblies/deploy_store_app/deploy_store_app_header'),
+        categories: function() {
+          return this.get('parentView.storeApp.storeCategories').mapProperty('name').join(', ')
+        }.property('parentView.storeApp.storeCategories.@each.name')
+      }),
+      bodyClass: Ember.View.extend({
+        templateName:  require('templates/main/assemblies/deploy_store_app')
+      }),
+
+      footerClass: Ember.View.extend({
+        templateName: require('templates/main/assemblies/deploy_store_app/deploy_store_app_footer')
+      }),
+
+      primary: Em.I18n.t('common.deploy'),
+
+      startDeploy: function() {
+        //TODO when api will be ready
+        this.set('isDeploying', true);
+        this.set('progress', 0);
+        this.pollDeployProgress();
+      },
+
+      pollDeployProgress: function() {
+        //TODO when api will be ready
+        var self = this;
+        if (this.get('isDeploying')) {
+          setTimeout(function() {
+            if (self.get('progress') === 100) {
+              self.set('isDeploying', false);
+              self.hide();
+            } else {
+              self.set('progress', self.get('progress') + 5);
+              self.pollDeployProgress();
+            }
+          }, 1000);
+        }
+      },
+
+      onPrimary: function () {
+        this.startDeploy();
+      }
+
+    });
+  },
+
+  addToCollection: function () {
+
+  }
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers/main/assemblies/categories/category_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/assemblies/categories/category_controller.js b/ambari-web/app/controllers/main/assemblies/categories/category_controller.js
new file mode 100644
index 0000000..00de91c
--- /dev/null
+++ b/ambari-web/app/controllers/main/assemblies/categories/category_controller.js
@@ -0,0 +1,25 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+App.MainAssembliesCategoryController = App.MainAssembliesSetController.extend({
+
+  name: 'mainAssembliesCategoryController'
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers/main/assemblies/categories_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/assemblies/categories_controller.js b/ambari-web/app/controllers/main/assemblies/categories_controller.js
new file mode 100644
index 0000000..35777da
--- /dev/null
+++ b/ambari-web/app/controllers/main/assemblies/categories_controller.js
@@ -0,0 +1,25 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+App.MainAssembliesCategoriesController = Em.Controller.extend({
+
+  name: 'mainAssembliesCategoriesController'
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers/main/assemblies/collections/collection_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/assemblies/collections/collection_controller.js b/ambari-web/app/controllers/main/assemblies/collections/collection_controller.js
new file mode 100644
index 0000000..732bc74
--- /dev/null
+++ b/ambari-web/app/controllers/main/assemblies/collections/collection_controller.js
@@ -0,0 +1,25 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+App.MainAssembliesCollectionController = App.MainAssembliesSetController.extend({
+
+  name: 'mainAssembliesCollectionController'
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers/main/assemblies/collections_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/assemblies/collections_controller.js b/ambari-web/app/controllers/main/assemblies/collections_controller.js
new file mode 100644
index 0000000..c707279
--- /dev/null
+++ b/ambari-web/app/controllers/main/assemblies/collections_controller.js
@@ -0,0 +1,25 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+App.MainAssembliesCollectionsController = Em.Controller.extend({
+
+  name: 'mainAssembliesCollectionsController'
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers/main/assemblies/service_groups/configs_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/assemblies/service_groups/configs_controller.js b/ambari-web/app/controllers/main/assemblies/service_groups/configs_controller.js
new file mode 100644
index 0000000..0bc1f43
--- /dev/null
+++ b/ambari-web/app/controllers/main/assemblies/service_groups/configs_controller.js
@@ -0,0 +1,33 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+/**
+ * @property {App.ServiceGroup} content
+ */
+App.MainAssembliesServiceGroupConfigsController = Em.Controller.extend({
+
+  name: 'mainAssembliesServiceGroupConfigs',
+
+  saveConfiguration: function () {
+    return App.showAlertPopup(Em.I18n.t('common.success'), Em.I18n.t('form.saveSuccess'));
+  }
+
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers/main/assemblies/service_groups/detailed_info_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/assemblies/service_groups/detailed_info_controller.js b/ambari-web/app/controllers/main/assemblies/service_groups/detailed_info_controller.js
new file mode 100644
index 0000000..520ecac
--- /dev/null
+++ b/ambari-web/app/controllers/main/assemblies/service_groups/detailed_info_controller.js
@@ -0,0 +1,38 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+/**
+ * @property {App.ServiceGroup} content
+ */
+App.MainAssembliesServiceGroupDetailedInfoController = Em.Controller.extend({
+
+  name: 'mainAssembliesServiceGroupDetailedInfo',
+  containers: function() {
+    var containers = this.get('content.containers');
+    return containers.sort(function (a, b) {
+      var aContainerIdSplitted = a.id.split('_');
+      var bContainerIdSplitted = b.id.split('_');
+      var aContainerId = parseInt(aContainerIdSplitted[aContainerIdSplitted.length-1]);
+      var bContainerId = parseInt(bContainerIdSplitted[bContainerIdSplitted.length-1]);
+      return aContainerId - bContainerId;
+    });
+  }.property('content.containers.[]')
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers/main/assemblies/service_groups/service_group_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/assemblies/service_groups/service_group_controller.js b/ambari-web/app/controllers/main/assemblies/service_groups/service_group_controller.js
new file mode 100644
index 0000000..d323eed
--- /dev/null
+++ b/ambari-web/app/controllers/main/assemblies/service_groups/service_group_controller.js
@@ -0,0 +1,53 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+App.MainAssembliesServiceGroupController = Em.Controller.extend({
+
+  name: 'mainAssembliesServiceGroupController',
+
+  startServiceGroup: function () {
+    var self = this;
+    return App.showConfirmationPopup(function () {
+      return App.ajax.send({
+        name: 'service_group.change_state',
+        sender: self,
+        data: {
+          id: self.get('content.id'),
+          state: 'STARTED'
+        }
+      });
+    }, Em.I18n.t('services.service.startAll.confirmMsg').format(this.get('content.serviceGroupName')));
+  },
+
+  stopServiceGroup: function () {
+    var self = this;
+    return App.showConfirmationPopup(function () {
+      return App.ajax.send({
+        name: 'service_group.change_state',
+        sender: self,
+        data: {
+          id: self.get('content.id'),
+          state: 'INSTALLED'
+        }
+      });
+    }, Em.I18n.t('services.service.stopAll.confirmMsg').format(this.get('content.serviceGroupName')));
+  }
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers/main/assemblies/service_groups/summary_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/assemblies/service_groups/summary_controller.js b/ambari-web/app/controllers/main/assemblies/service_groups/summary_controller.js
new file mode 100644
index 0000000..5641ec1
--- /dev/null
+++ b/ambari-web/app/controllers/main/assemblies/service_groups/summary_controller.js
@@ -0,0 +1,28 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+/**
+ * @property {App.ServiceGroup} content
+ */
+App.MainAssembliesServiceGroupSummaryController = Em.Controller.extend({
+
+  name: 'mainAssembliesServiceGroupSummary'
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers/main/assemblies/service_groups_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/assemblies/service_groups_controller.js b/ambari-web/app/controllers/main/assemblies/service_groups_controller.js
new file mode 100644
index 0000000..3251431
--- /dev/null
+++ b/ambari-web/app/controllers/main/assemblies/service_groups_controller.js
@@ -0,0 +1,25 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+App.MainAssembliesServiceGroupsController = Em.Controller.extend({
+
+  name: 'mainAssembliesServiceGroupsController'
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers/main/assemblies_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/assemblies_controller.js b/ambari-web/app/controllers/main/assemblies_controller.js
new file mode 100644
index 0000000..95c973e
--- /dev/null
+++ b/ambari-web/app/controllers/main/assemblies_controller.js
@@ -0,0 +1,233 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+App.MainAssembliesController = Em.Controller.extend({
+
+  name: 'mainAssembliesController',
+
+  /**
+   * Filter value for Apps Names
+   *
+   * @type {string}
+   */
+  filterString: '',
+
+  /**
+   * @type {boolean}
+   */
+  showFilterString: true,
+
+  /**
+   * @type {App.ServiceGroup[]}
+   */
+  serviceGroups: function () {
+    if (!App.router.get('clusterController.isLoaded')) {
+      return [];
+    }
+    return App.ServiceGroup.find();
+  }.property('App.router.clusterController.isLoaded'),
+
+  /**
+   * @type {App.ServiceGroup[]}
+   */
+  visibleServiceGroups: Em.computed.filterBy('serviceGroups', 'isCoreServiceGroup', false),
+
+  /**
+   * @type {App.ServiceGroup?}
+   */
+  activeServiceGroup: Em.computed.findBy('serviceGroups', 'isActive', true),
+
+  /**
+   * All Store Categories
+   *
+   * @type {App.StoreCategory[]}
+   */
+  storeCategories: App.StoreCategory.find(),
+
+  /**
+   * All Store Apps
+   *
+   * @type {App.StoreApp[]}
+   */
+  storeApps: App.StoreApp.find(),
+
+  /**
+   * All Store Collections
+   *
+   * @type {App.StoreCollection[]}
+   */
+  storeCollections: App.StoreCollection.find(),
+
+  /**
+   * Selected Store Collection
+   *
+   * @type {App.StoreCollection?}
+   */
+  activeStoreCollection: Em.computed.findBy('storeCollections', 'isActive', true),
+
+  /**
+   * Checks if there is no selected Store Category
+   *
+   * @type {boolean}
+   */
+  noCategorySelected: Em.computed.everyBy('storeCategories', 'isActive', false),
+
+  /**
+   * Checks if there is no selected Store Collection
+   *
+   * @type {boolean}
+   */
+  noCollectionSelected: Em.computed.everyBy('storeCollections', 'isActive', false),
+
+  /**
+   * Checks if there is some selected Store Category
+   *
+   * @type {boolean}
+   */
+  isSomeCategorySelected: Em.computed.someBy('storeCategories', 'isActive', true),
+
+  /**
+   * Checks if there is some selected Store Category
+   *
+   * @type {boolean}
+   */
+  isSomeCollectionSelected: Em.computed.someBy('storeCollections', 'isActive', true),
+
+  /**
+   * All Store Apps are shown if there is no selected Store Category and Store Collection
+   *
+   * @type {boolean}
+   */
+  allAppsAreShown: Em.computed.and('noCategorySelected', 'noCollectionSelected'),
+
+  /**
+   * Placeholder for search-input
+   *
+   * @type {string}
+   */
+  searchString: Em.I18n.t('common.search.small'),
+
+  /**
+   * The active menu subtitle eg. "> Discover" or "> Manage"
+   *
+   * @type {string}
+   */
+  subtitle: function() {
+    var subtitle = "";
+    if (this.get('isSomeCategorySelected')) {
+      subtitle = ">   " + Em.I18n.t('appStore.menu.header.discover');
+    } else if (this.get('isSomeCollectionSelected') || this.get('activeServiceGroupId')) {
+      subtitle = ">   " + Em.I18n.t('appStore.menu.header.manage');
+    }
+    return subtitle;
+  }.property('isSomeCategorySelected', 'isSomeCollectionSelected', 'activeServiceGroupId'),
+
+  /**
+   * @param {{context: App.StoreCategory}} event
+   */
+  selectCategory: function (event) {
+    this.showAllApps();
+    var storeCategory = event.context;
+    storeCategory.set('isActive', true);
+    this.closeManageAssembliesPanels();
+    this.target.transitionTo('main.assemblies.categories.details', storeCategory);
+  },
+
+  /**
+   * This method hides MANAGE->ASSEMBLIES and MANAGE->COLLECTIONS panels
+   * @private
+   * @method {closeManageAssembliesPanels}
+   */
+  closeManageAssembliesPanels: function() {
+    var appStoreEl = $("#apps-store");
+    var deployedAssembliesEl = appStoreEl.find("#manage-deployed-assemblies-label");
+    var deployedAssembliesContent = appStoreEl.find("#manage-deployed-assemblies-content");
+    var collectionsAssembliesEl = appStoreEl.find("#manage-assemblies-collection-label");
+    var collectionsAssembliesContent = appStoreEl.find("#manage-assemblies-collection-content");
+    if (deployedAssembliesContent.hasClass('in')) {
+      deployedAssembliesEl.trigger('click');
+    }
+
+    if (collectionsAssembliesContent.hasClass('in')) {
+      collectionsAssembliesEl.trigger('click');
+    }
+  },
+
+  /**
+   * Deselect all Store Categories and Collections
+   */
+  showAllApps: function () {
+    this.get('storeCategories').setEach('isActive', false);
+    this.get('storeCollections').setEach('isActive', false);
+    this.get('storeApps').setEach('isActive', false);
+  },
+
+  /**
+   *
+   * @param {{context: App.StoreCollection}} event
+   */
+  selectCollection: function (event) {
+    this.showAllApps();
+    var storeCollection = event.context;
+    storeCollection.set('isActive', true);
+    this.target.transitionTo('main.assemblies.collections.details', storeCollection);
+  },
+
+  /**
+   * {{context: App.ServiceGroup}} @param event
+   */
+  makeServiceGroupActive: function(event) {
+    var serviceGroup = event.context;
+    this.set('activeServiceGroupId', serviceGroup.get('id'));
+    this.setActiveServiceGroupId();
+    this.closeNonServiceGroupsPanels();
+    this.target.transitionTo('main.assemblies.serviceGroups.details.summary', serviceGroup);
+  },
+
+  setActiveServiceGroupId: function() {
+    var serviceGroupId = this.get('activeServiceGroupId');
+    var visibleServiceGroups = this.get('visibleServiceGroups');
+    visibleServiceGroups.forEach(function(item) {
+      item.set('isActive', serviceGroupId === item.get('id'));
+    });
+  }.observes('activeServiceGroupId'),
+
+  /**
+   * This method hides DISCOVER->CATEGORIES and MANAGE->COLLECTIONS panels
+   * @private
+   * @method {closeNonServiceGroupsPanels}
+   */
+  closeNonServiceGroupsPanels: function() {
+    var appStoreEl = $("#apps-store");
+    var discoverAssembliesEl = appStoreEl.find("#discover-assemblies-label");
+    var discoverAssembliesContent = appStoreEl.find("#discover-assemblies-content");
+    var collectionsAssembliesEl = appStoreEl.find("#manage-assemblies-collection-label");
+    var collectionsAssembliesContent = appStoreEl.find("#manage-assemblies-collection-content");
+    if (discoverAssembliesContent.hasClass('in')) {
+      discoverAssembliesEl.trigger('click');
+    }
+
+    if (collectionsAssembliesContent.hasClass('in')) {
+      collectionsAssembliesEl.trigger('click');
+    }
+  }
+
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-web/app/controllers/main/dashboard.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/dashboard.js b/ambari-web/app/controllers/main/dashboard.js
index 51c09d6..34c207b 100644
--- a/ambari-web/app/controllers/main/dashboard.js
+++ b/ambari-web/app/controllers/main/dashboard.js
@@ -20,5 +20,11 @@ var App = require('app');
 
 App.MainDashboardController = Em.Controller.extend({
   name: 'mainDashboardController',
-  categorySelected: 'widgets'
+  categorySelected: 'widgets',
+  coreServiceGroup: function() {
+    if (!App.router.get('clusterController.isLoaded')) {
+      return {};
+    }
+    return App.ServiceGroup.find().findProperty('serviceGroupName', 'CORE');
+  }.property('App.router.clusterController.isLoaded')
 });
\ No newline at end of file