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:57 UTC

[31/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/main/java/org/apache/ambari/server/api/util/ApiVersion.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/util/ApiVersion.java b/ambari-server/src/main/java/org/apache/ambari/server/api/util/ApiVersion.java
new file mode 100644
index 0000000..5e85e56
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/util/ApiVersion.java
@@ -0,0 +1,31 @@
+/**
+ * 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.util;
+
+import java.util.EnumSet;
+
+public enum ApiVersion {
+  v1,
+  v2;
+
+  public static EnumSet<ApiVersion> all = EnumSet.allOf(ApiVersion.class);
+  public static EnumSet<ApiVersion> v1Only = EnumSet.of(v1);
+  public static EnumSet<ApiVersion> v2Only = EnumSet.of(v2);
+  public static EnumSet<ApiVersion> v2Plus = EnumSet.complementOf(v1Only);
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
index f5e8f39..cecbf50 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
@@ -189,6 +189,9 @@ public class Configuration {
   public static final String LDAP_GROUP_NAMING_ATTR_KEY = "authentication.ldap.groupNamingAttr";
   public static final String LDAP_GROUP_MEMEBERSHIP_ATTR_KEY = "authentication.ldap.groupMembershipAttr";
   public static final String LDAP_ADMIN_GROUP_MAPPING_RULES_KEY = "authorization.ldap.adminGroupMappingRules";
+  public static final String YARN_DASH_API_ENDPOINT = "yarn.dash.api.endpoint";
+  public static final String YARN_DASH_API_ENDPOINT_DEFAULT = "http://cn008.l42scl.hortonworks.com:9191/services/v1/applications";
+
   /**
    * When authentication through LDAP is enabled then Ambari Server uses this filter to lookup
    * the user in LDAP based on the provided ambari user name.
@@ -3030,4 +3033,8 @@ public class Configuration {
   public boolean isLdapAlternateUserSearchEnabled() {
     return Boolean.parseBoolean(properties.getProperty(LDAP_ALT_USER_SEARCH_ENABLED_KEY, LDAP_ALT_USER_SEARCH_ENABLED_DEFAULT));
   }
+
+  public String getDashApiEndpoint() {
+    return properties.getProperty(YARN_DASH_API_ENDPOINT, YARN_DASH_API_ENDPOINT_DEFAULT);
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
index b60592d..6c166dc 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
@@ -1234,7 +1234,7 @@ public class AmbariCustomCommandExecutionHelper {
 
       StackInfo stack = ambariMetaInfo.getStack(stackId.getStackName(), stackId.getStackVersion());
       if (stack != null) {
-        ServiceInfo serviceInfo = stack.getService(serviceName);
+        ServiceInfo serviceInfo = ambariMetaInfo.getService(stackId.getStackName(), stackId.getStackVersion(), serviceName);
 
         if (serviceInfo != null) {
           // if there is a chance that this action was triggered by a change in rack info then we want to

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
index d6b9d0e..4917d4f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
@@ -30,6 +30,7 @@ import org.apache.ambari.server.agent.ExecutionCommand;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.controller.internal.RequestStageContainer;
 import org.apache.ambari.server.controller.metrics.timeline.cache.TimelineMetricCacheProvider;
+import org.apache.ambari.server.controller.servicegroup.cache.ServiceGroupCacheProvider;
 import org.apache.ambari.server.metadata.RoleCommandOrder;
 import org.apache.ambari.server.scheduler.ExecutionScheduleManager;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
@@ -48,6 +49,8 @@ import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentFactory;
 import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.ServiceFactory;
+import org.apache.ambari.server.state.ServiceGroup;
+import org.apache.ambari.server.state.ServiceGroupFactory;
 import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.state.ServiceOsSpecific;
 import org.apache.ambari.server.state.State;
@@ -506,6 +509,13 @@ public interface AmbariManagementController {
   ServiceFactory getServiceFactory();
 
   /**
+   * Get the service groups factory for this management controller.
+   *
+   * @return the service factory
+   */
+  ServiceGroupFactory getServiceGroupFactory();
+
+  /**
    * Get the service component factory for this management controller.
    *
    * @return the service component factory
@@ -600,6 +610,24 @@ public interface AmbariManagementController {
                              Collection<ServiceComponentHost> ignoredHosts,
                              boolean runSmokeTest, boolean reconfigureClients) throws AmbariException;
 
+
+  /**
+   * Add stages for a service group to the request.
+   *
+   * @param requestStages       Stages currently associated with request
+   * @param cluster             cluster being acted on
+   * @param requestProperties   the request properties
+   * @param requestParameters   the request parameters; may be null
+   * @param changedServiceGroups     the service groups being changed
+   *
+   * @return request stages
+   *
+   * @throws AmbariException if stages can't be created
+   */
+  RequestStageContainer addServiceGroupStages(RequestStageContainer requestStages, Cluster cluster, Map<String, String> requestProperties,
+                                  Map<String, String> requestParameters,
+                                  Map<State, List<ServiceGroup>> changedServiceGroups) throws AmbariException;
+
   /**
    * Getter for the url of JDK, stored at server resources folder
    */
@@ -708,6 +736,8 @@ public interface AmbariManagementController {
    */
   RoleCommandOrder getRoleCommandOrder(Cluster cluster);
 
+  String getDashApiEndpoint();
+
   /**
    * Performs a test if LDAP server is reachable.
    *
@@ -796,6 +826,8 @@ public interface AmbariManagementController {
 
   TimelineMetricCacheProvider getTimelineMetricCacheProvider();
 
+  public ServiceGroupCacheProvider getServiceGroupCacheProvider();
+
   /**
    * Returns KerberosHelper instance
    * @return

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index dd3d098..ed10c3c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -44,8 +44,11 @@ import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
+import java.io.InputStream;
 import java.lang.reflect.Type;
 import java.net.InetAddress;
+import java.net.URL;
+import java.net.HttpURLConnection;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -65,18 +68,8 @@ import java.util.TreeMap;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Lock;
 
-import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.ClusterNotFoundException;
-import org.apache.ambari.server.DuplicateResourceException;
-import org.apache.ambari.server.HostNotFoundException;
-import org.apache.ambari.server.ObjectNotFoundException;
-import org.apache.ambari.server.ParentObjectNotFoundException;
-import org.apache.ambari.server.Role;
-import org.apache.ambari.server.RoleCommand;
-import org.apache.ambari.server.ServiceComponentHostNotFoundException;
-import org.apache.ambari.server.ServiceComponentNotFoundException;
-import org.apache.ambari.server.ServiceNotFoundException;
-import org.apache.ambari.server.StackAccessException;
+import jline.internal.Log;
+import org.apache.ambari.server.*;
 import org.apache.ambari.server.actionmanager.ActionManager;
 import org.apache.ambari.server.actionmanager.HostRoleCommand;
 import org.apache.ambari.server.actionmanager.RequestFactory;
@@ -87,13 +80,12 @@ import org.apache.ambari.server.agent.ExecutionCommand.KeyNames;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.configuration.Configuration.DatabaseType;
-import org.apache.ambari.server.controller.internal.RequestOperationLevel;
-import org.apache.ambari.server.controller.internal.RequestResourceFilter;
-import org.apache.ambari.server.controller.internal.RequestStageContainer;
-import org.apache.ambari.server.controller.internal.URLStreamProvider;
-import org.apache.ambari.server.controller.internal.WidgetLayoutResourceProvider;
-import org.apache.ambari.server.controller.internal.WidgetResourceProvider;
+import org.apache.ambari.server.controller.internal.*;
 import org.apache.ambari.server.controller.metrics.timeline.cache.TimelineMetricCacheProvider;
+import org.apache.ambari.server.controller.servicegroup.cache.ServiceGroupCache;
+import org.apache.ambari.server.controller.servicegroup.cache.ServiceGroupCacheKey;
+import org.apache.ambari.server.controller.servicegroup.cache.ServiceGroupCacheProvider;
+import org.apache.ambari.server.controller.servicegroup.cache.ServiceGroupCacheValue;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.customactions.ActionDefinition;
 import org.apache.ambari.server.metadata.ActionMetadata;
@@ -127,6 +119,7 @@ import org.apache.ambari.server.security.ldap.LdapBatchDto;
 import org.apache.ambari.server.security.ldap.LdapSyncDto;
 import org.apache.ambari.server.serveraction.kerberos.KerberosInvalidConfigurationException;
 import org.apache.ambari.server.serveraction.kerberos.KerberosOperationException;
+import org.apache.ambari.server.serveraction.servicegroup.YarnServiceGroupServerAction;
 import org.apache.ambari.server.stageplanner.RoleGraph;
 import org.apache.ambari.server.stageplanner.RoleGraphFactory;
 import org.apache.ambari.server.state.Cluster;
@@ -154,6 +147,8 @@ import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.ServiceComponentHostEvent;
 import org.apache.ambari.server.state.ServiceComponentHostFactory;
 import org.apache.ambari.server.state.ServiceFactory;
+import org.apache.ambari.server.state.ServiceGroup;
+import org.apache.ambari.server.state.ServiceGroupFactory;
 import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.state.ServiceOsSpecific;
 import org.apache.ambari.server.state.StackId;
@@ -165,12 +160,11 @@ import org.apache.ambari.server.state.scheduler.RequestExecutionFactory;
 import org.apache.ambari.server.state.stack.RepositoryXml;
 import org.apache.ambari.server.state.stack.WidgetLayout;
 import org.apache.ambari.server.state.stack.WidgetLayoutInfo;
-import org.apache.ambari.server.state.svccomphost.ServiceComponentHostInstallEvent;
-import org.apache.ambari.server.state.svccomphost.ServiceComponentHostStartEvent;
-import org.apache.ambari.server.state.svccomphost.ServiceComponentHostStopEvent;
-import org.apache.ambari.server.state.svccomphost.ServiceComponentHostUpgradeEvent;
+import org.apache.ambari.server.state.svccomphost.*;
+import org.apache.ambari.server.state.UpgradeState;
 import org.apache.ambari.server.utils.SecretReference;
 import org.apache.ambari.server.utils.StageUtils;
+import org.apache.ambari.server.utils.MapUtils;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.StringUtils;
@@ -190,6 +184,8 @@ import com.google.inject.Injector;
 import com.google.inject.Singleton;
 import com.google.inject.persist.Transactional;
 
+import javax.annotation.OverridingMethodsMustInvokeSuper;
+
 @Singleton
 public class AmbariManagementControllerImpl implements AmbariManagementController {
 
@@ -218,6 +214,8 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
   @Inject
   private ServiceFactory serviceFactory;
   @Inject
+  private ServiceGroupFactory serviceGroupFactory;
+  @Inject
   private ServiceComponentFactory serviceComponentFactory;
   @Inject
   private ServiceComponentHostFactory serviceComponentHostFactory;
@@ -266,6 +264,8 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
 
   private MaintenanceStateHelper maintenanceStateHelper;
 
+  private static Map<String, String> componentNameMappings = MapUtils.fillMap("/var/lib/ambari-server/resources/componentsMap.dat");
+
   /**
    * The KerberosHelper to help setup for enabling for disabling Kerberos
    */
@@ -281,6 +281,9 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
   final private static int REPO_URL_CONNECT_TIMEOUT = 3000;
   final private static int REPO_URL_READ_TIMEOUT = 2000;
 
+  final private static int DASH_URL_CONNECT_TIMEOUT = 3000;
+  final private static int DASH_URL_READ_TIMEOUT = 2000;
+
   final private String jdkResourceUrl;
   final private String javaHome;
   final private String jdkName;
@@ -1121,7 +1124,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
           throw new ServiceComponentHostNotFoundException(
               cluster.getClusterName(), null, request.getComponentName(), request.getHostname());
         }
-        request.setServiceName(serviceName);
+//        request.setServiceName(serviceName);
       }
     }
 
@@ -1132,7 +1135,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       services.addAll(cluster.getServices().values());
     }
 
-    Set<ServiceComponentHostResponse> response =
+    Set<ServiceComponentHostResponse> responses =
         new HashSet<ServiceComponentHostResponse>();
 
     boolean checkDesiredState = false;
@@ -1169,7 +1172,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     for (Service s : services) {
       // filter on component name if provided
       Set<ServiceComponent> components = new HashSet<ServiceComponent>();
-      if (request.getComponentName() != null) {
+      if (request.getComponentName() != null && request.getServiceName() != null) {
         components.add(s.getServiceComponent(request.getComponentName()));
       } else {
         components.addAll(s.getServiceComponents().values());
@@ -1187,105 +1190,170 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
         Map<String, ServiceComponentHost> serviceComponentHostMap =
           sc.getServiceComponentHosts();
 
-        if (request.getHostname() != null) {
-          try {
-            if (serviceComponentHostMap == null
-                || !serviceComponentHostMap.containsKey(request.getHostname())) {
-              throw new ServiceComponentHostNotFoundException(cluster.getClusterName(),
-                s.getName(), sc.getName(), request.getHostname());
-            }
+        ServiceGroup sg = null;
+        try {
+          sg = cluster.getServiceGroup(s.getServiceGroupName());
+        } catch (ServiceGroupNotFoundException e) {
+          sg = null;
+        }
 
-            ServiceComponentHost sch = serviceComponentHostMap.get(request.getHostname());
+        if(sg == null || sg.getServiceGroupType().equalsIgnoreCase("AMBARI")) {
+          if (request.getHostname() != null) {
+            try {
+              if (serviceComponentHostMap == null
+                  || !serviceComponentHostMap.containsKey(request.getHostname())) {
+                throw new ServiceComponentHostNotFoundException(cluster.getClusterName(),
+                    s.getName(), sc.getName(), request.getHostname());
+              }
 
-            if (null == sch) {
-              // It's possible that the host was deleted during the time that the request was generated.
-              continue;
-            }
+              ServiceComponentHost sch = serviceComponentHostMap.get(request.getHostname());
 
-            if (checkDesiredState && (desiredStateToCheck != sch.getDesiredState())) {
-              continue;
-            }
+              if (null == sch) {
+                // It's possible that the host was deleted during the time that the request was generated.
+                continue;
+              }
 
-            if (checkState && stateToCheck != sch.getState()) {
-              continue;
-            }
+              if (checkDesiredState && (desiredStateToCheck != sch.getDesiredState())) {
+                continue;
+              }
 
-            if (request.getAdminState() != null) {
-              String stringToMatch =
-                  sch.getComponentAdminState() == null ? "" : sch.getComponentAdminState().name();
-              if (!request.getAdminState().equals(stringToMatch)) {
+              if (checkState && stateToCheck != sch.getState()) {
                 continue;
               }
-            }
 
-            ServiceComponentHostResponse r = sch.convertToResponse();
-            if (null == r || (filterBasedConfigStaleness && r.isStaleConfig() != staleConfig)) {
-              continue;
-            }
+              if (request.getAdminState() != null) {
+                String stringToMatch =
+                    sch.getComponentAdminState() == null ? "" : sch.getComponentAdminState().name();
+                if (!request.getAdminState().equals(stringToMatch)) {
+                  continue;
+                }
+              }
 
-            Host host = hosts.get(sch.getHostName());
-            if (host == null) {
-              throw new HostNotFoundException(cluster.getClusterName(), sch.getHostName());
-            }
+              ServiceComponentHostResponse r = sch.convertToResponse();
+              if (null == r || (filterBasedConfigStaleness && r.isStaleConfig() != staleConfig)) {
+                continue;
+              }
 
-            r.setMaintenanceState(maintenanceStateHelper.getEffectiveState(sch, host).name());
-            response.add(r);
-          } catch (ServiceComponentHostNotFoundException e) {
-            if (request.getServiceName() == null || request.getComponentName() == null) {
-              // Ignore the exception if either the service name or component name are not specified.
-              // This is an artifact of how we get host_components and can happen in the case where
-              // we get all host_components for a host, for example.
-              LOG.debug("Ignoring not specified host_component ", e);
-
-            } else {
-              // Otherwise rethrow the exception and let the caller decide if it's an error condition.
-              // Logging the exception as debug since this does not necessarily indicate an error
-              // condition.
-              LOG.debug("ServiceComponentHost not found ", e);
-              throw new ServiceComponentHostNotFoundException(cluster.getClusterName(),
-                  request.getServiceName(), request.getComponentName(), request.getHostname());
-            }
-          }
-        } else {
-          for (ServiceComponentHost sch : serviceComponentHostMap.values()) {
-            if (null == sch) {
-              // It's possible that the host was deleted during the time that the request was generated.
-              continue;
-            }
+              Host host = hosts.get(sch.getHostName());
+              if (host == null) {
+                throw new HostNotFoundException(cluster.getClusterName(), sch.getHostName());
+              }
 
-            if (checkDesiredState && (desiredStateToCheck != sch.getDesiredState())) {
-              continue;
-            }
+              r.setMaintenanceState(maintenanceStateHelper.getEffectiveState(sch, host).name());
+              responses.add(r);
+            } catch (ServiceComponentHostNotFoundException e) {
+              if (request.getServiceName() == null || request.getComponentName() == null) {
+                // Ignore the exception if either the service name or component name are not specified.
+                // This is an artifact of how we get host_components and can happen in the case where
+                // we get all host_components for a host, for example.
+                LOG.debug("Ignoring not specified host_component ", e);
 
-            if (checkState && stateToCheck != sch.getState()) {
-              continue;
+              } else {
+                // Otherwise rethrow the exception and let the caller decide if it's an error condition.
+                // Logging the exception as debug since this does not necessarily indicate an error
+                // condition.
+                LOG.debug("ServiceComponentHost not found ", e);
+                throw new ServiceComponentHostNotFoundException(cluster.getClusterName(),
+                    request.getServiceName(), request.getComponentName(), request.getHostname());
+              }
             }
+          } else {
+            for (ServiceComponentHost sch : serviceComponentHostMap.values()) {
+              if (null == sch) {
+                // It's possible that the host was deleted during the time that the request was generated.
+                continue;
+              }
 
-            if (request.getAdminState() != null) {
-              String stringToMatch =
-                  sch.getComponentAdminState() == null ? "" : sch.getComponentAdminState().name();
-              if (!request.getAdminState().equals(stringToMatch)) {
+              if (checkDesiredState && (desiredStateToCheck != sch.getDesiredState())) {
                 continue;
               }
-            }
 
-            ServiceComponentHostResponse r = sch.convertToResponse();
-            if (null == r || (filterBasedConfigStaleness && r.isStaleConfig() != staleConfig)) {
-              continue;
-            }
+              if (checkState && stateToCheck != sch.getState()) {
+                continue;
+              }
+
+              if (request.getAdminState() != null) {
+                String stringToMatch =
+                    sch.getComponentAdminState() == null ? "" : sch.getComponentAdminState().name();
+                if (!request.getAdminState().equals(stringToMatch)) {
+                  continue;
+                }
+              }
+
+              ServiceComponentHostResponse r = sch.convertToResponse();
+              if (null == r || (filterBasedConfigStaleness && r.isStaleConfig() != staleConfig)) {
+                continue;
+              }
+
+              Host host = hosts.get(sch.getHostName());
+              if (host == null) {
+                throw new HostNotFoundException(cluster.getClusterName(), sch.getHostName());
+              }
 
-            Host host = hosts.get(sch.getHostName());
-            if (host == null) {
-              throw new HostNotFoundException(cluster.getClusterName(), sch.getHostName());
+              r.setMaintenanceState(maintenanceStateHelper.getEffectiveState(sch, host).name());
+              responses.add(r);
             }
+          }
+        } else {
+          ServiceGroupCache cache = getServiceGroupCacheProvider().getServiceGroupCache();
+          int desiredCount = sc.getDesiredCount();
+          String clusterName = sc.getClusterName();
+          String serviceName = sc.getServiceName();
+          String componentName = sc.getName();
+          String mappedComponentName = componentNameMappings.containsKey(componentName)?
+              componentNameMappings.get(componentName) : componentName;
+          String displayName = componentName;
+          HostComponentAdminState adminState = HostComponentAdminState.INSERVICE;
+          String stackVersion = "";
+          String desiredStackVersion = "";
+          String desiredState = sc.isClientComponent()? State.INSTALLED.toString(): State.STARTED.toString();
+          int totalCount = 0;
+
+          ServiceGroupCacheKey cacheKey = new ServiceGroupCacheKey(sg.getName());
+          Map<String, Object> responseMap = null;
+          try {
+            responseMap = cache.getResponseFromCache(cacheKey);
+          } catch (Exception e) {
+            Log.info("Hit exception when retrieving service group from cache. Exception: " + e.getMessage());
+          }
 
-            r.setMaintenanceState(maintenanceStateHelper.getEffectiveState(sch, host).name());
-            response.add(r);
+          if(responseMap != null && responseMap.containsKey("containers")) {
+            for(Map<String, String> cMap : (ArrayList<Map<String, String>>) responseMap.get("containers")) {
+              String dashContainerName = cMap.get("id");
+              String dashComponentName = cMap.get("component_name");
+              String dashState = cMap.get("state");
+              String dashHostName = cMap.get("hostname");
+              String dashBareHostName = cMap.get("bare_host");
+
+              if (dashComponentName.contains(mappedComponentName)) {
+                String liveState = State.INSTALLED.toString();
+                if(dashState.equalsIgnoreCase("READY")) {
+                  liveState = sc.isClientComponent()? State.INSTALLED.toString() : State.STARTED.toString();
+                }
+                ServiceComponentHostResponse r = new ServiceComponentHostResponse(clusterName, serviceName, componentName,
+                    displayName, dashHostName, liveState, stackVersion, desiredState, desiredStackVersion, adminState,
+                    dashBareHostName, dashContainerName);
+                r.setUpgradeState(UpgradeState.NONE);
+                r.setMaintenanceState(MaintenanceState.OFF.name());
+                responses.add(r);
+                totalCount++;
+              }
+            }
+          }
+          if(totalCount < desiredCount) {
+            while(totalCount < desiredCount) {
+              ServiceComponentHostResponse r = new ServiceComponentHostResponse(clusterName, serviceName, componentName,
+                  displayName, "", State.INIT.toString(), stackVersion, desiredState, desiredStackVersion, adminState);
+              r.setUpgradeState(UpgradeState.NONE);
+              r.setMaintenanceState(MaintenanceState.OFF.name());
+              responses.add(r);
+              totalCount++;
+            }
           }
         }
       }
     }
-    return response;
+    return responses;
   }
 
   @Override
@@ -2380,6 +2448,61 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     }
   }
 
+
+  private RequestStageContainer doStageCreationForServiceGroups(RequestStageContainer requestStages, Cluster cluster,
+      Map<State, List<ServiceGroup>> changedServiceGroups, Map<String, String> requestParameters,
+      Map<String, String> requestProperties)
+      throws AmbariException {
+
+    if (changedServiceGroups == null || changedServiceGroups.isEmpty()) {
+      LOG.debug("Created 0 stages");
+      return requestStages;
+    }
+
+    String clusterHostInfoJson = StageUtils.getGson().toJson(
+        StageUtils.getClusterHostInfo(cluster));
+    String hostParamsJson = StageUtils.getGson().toJson(
+        customCommandExecutionHelper.createDefaultHostParams(cluster));
+
+    Stage stage = createNewStage(requestStages.getLastStageId(), cluster,
+        requestStages.getId(), requestProperties.get(REQUEST_CONTEXT_PROPERTY),
+        clusterHostInfoJson, "{}", hostParamsJson);
+
+    String ambariServerHostname = StageUtils.getHostName();
+    ServiceComponentHostServerActionEvent event = new ServiceComponentHostServerActionEvent(
+        "AMBARI_SERVER",
+        ambariServerHostname, // TODO: Choose a random hostname from the cluster. All tasks for the AMBARI_SERVER service will be executed on this Ambari server
+        System.currentTimeMillis());
+
+    for(State newState : changedServiceGroups.keySet()) {
+      for(ServiceGroup sg : changedServiceGroups.get(newState)) {
+        Map<String, String> commandParameters = new HashMap<>();
+        commandParameters.put(YarnServiceGroupServerAction.COMMAND_PARAM_SERVICE_GROUP, sg.getName());
+        commandParameters.put(YarnServiceGroupServerAction.COMMAND_PARAM_DESIRED_STATE, newState.toString());
+        commandParameters.put(YarnServiceGroupServerAction.COMMAND_PARAM_DASH_API_ENDPOINT, getDashApiEndpoint());
+        String commandDetail = "";
+        if (newState == State.INSTALLED) {
+          if(sg.getDesiredState() == State.INIT) {
+            commandDetail = "Installing " + sg.getName();
+          } else if(sg.getDesiredState() == State.STARTED) {
+            commandDetail = "Stopping " + sg.getName();
+          }
+        } else if (newState == State.STARTED) {
+          commandDetail = "Starting " + sg.getName();
+        }
+        stage.addServerActionCommand(YarnServiceGroupServerAction.class.getName(), null, Role.AMBARI_SERVER_ACTION,
+            RoleCommand.EXECUTE, cluster.getClusterName(), event, commandParameters, commandDetail,
+            findConfigurationTagsWithOverrides(cluster, null), configs.getDefaultServerTaskTimeout(),
+            false, false);
+      }
+    }
+    RoleCommandOrder rco = getRoleCommandOrder(cluster);
+    RoleGraph rg = roleGraphFactory.createNew(rco);
+    rg.build(stage);
+    requestStages.addStages(rg.getStages());
+    return requestStages;
+  }
+
   private RequestStageContainer doStageCreation(RequestStageContainer requestStages,
       Cluster cluster,
       Map<State, List<Service>> changedServices,
@@ -2855,6 +2978,20 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     return response;  }
 
   @Transactional
+  void updateServiceGroupStates(
+      Cluster cluster,
+      Map<State, List<ServiceGroup>> changedServiceGroups) {
+    if (changedServiceGroups != null) {
+      for (Entry<State, List<ServiceGroup>> entry : changedServiceGroups.entrySet()) {
+        State newState = entry.getKey();
+        for (ServiceGroup sg : entry.getValue()) {
+          sg.setDesiredState(newState);
+        }
+      }
+    }
+  }
+
+  @Transactional
   void updateServiceStates(
       Cluster cluster,
       Map<State, List<Service>> changedServices,
@@ -2945,6 +3082,27 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     return requestStages;
   }
 
+  @Override
+  public RequestStageContainer addServiceGroupStages(RequestStageContainer requestStages, Cluster cluster,
+     Map<String, String> requestProperties, Map<String, String> requestParameters,
+     Map<State, List<ServiceGroup>> changedServiceGroups) throws AmbariException {
+
+    if (requestStages == null) {
+      requestStages = new RequestStageContainer(actionManager.getNextRequestId(), null, requestFactory, actionManager);
+    }
+
+    requestStages = doStageCreationForServiceGroups(requestStages, cluster, changedServiceGroups,
+        requestParameters, requestProperties);
+    Lock clusterWriteLock = cluster.getClusterGlobalLock().writeLock();
+    clusterWriteLock.lock();
+    try {
+      updateServiceGroupStates(cluster, changedServiceGroups);
+    } finally {
+      clusterWriteLock.unlock();
+    }
+    return requestStages;
+  }
+
   //todo: for now made this public since is is still used by createHostComponents
   //todo: delete after all host component logic is in HostComponentResourceProvider
   public void validateServiceComponentHostRequest(ServiceComponentHostRequest request) {
@@ -4397,6 +4555,11 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
   }
 
   @Override
+  public ServiceGroupFactory getServiceGroupFactory() {
+    return serviceGroupFactory;
+  }
+
+  @Override
   public ServiceComponentFactory getServiceComponentFactory() {
     return serviceComponentFactory;
   }
@@ -4480,6 +4643,11 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
   }
 
   @Override
+  public String getDashApiEndpoint() {
+    return configs.getDashApiEndpoint();
+  }
+
+  @Override
   public boolean checkLdapConfigured() {
     return ldapDataPopulator.isLdapEnabled();
   }
@@ -4548,7 +4716,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       StackInfo stackInfo = ambariMetaInfo.getStack(stackId.getStackName(), stackId.getStackVersion());
       if (service != null) {
         // Service widgets
-        ServiceInfo serviceInfo = stackInfo.getService(service.getName());
+        ServiceInfo serviceInfo = stackInfo.getService(service.getStackServiceName());
         File widgetDescriptorFile = serviceInfo.getWidgetsDescriptorFile();
         if (widgetDescriptorFile != null && widgetDescriptorFile.exists()) {
           try {
@@ -4714,6 +4882,12 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
   }
 
   @Override
+  public ServiceGroupCacheProvider getServiceGroupCacheProvider() {
+    return injector.getInstance(ServiceGroupCacheProvider.class);
+  }
+
+
+  @Override
   public KerberosHelper getKerberosHelper() {
     return kerberosHelper;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index db66961..e028593 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -371,12 +371,16 @@ public class AmbariServer {
       // requests.
       root.addFilter(new FilterHolder(injector.getInstance(AmbariViewsSecurityHeaderFilter.class)), "/api/v1/views/*",
           DISPATCHER_TYPES);
+      root.addFilter(new FilterHolder(injector.getInstance(AmbariViewsSecurityHeaderFilter.class)), "/api/v2/views/*",
+          DISPATCHER_TYPES);
 
       // since views share the REST API threadpool, a misbehaving view could
       // consume all of the available threads and effectively cause a loss of
       // service for Ambari
       root.addFilter(new FilterHolder(injector.getInstance(ViewThrottleFilter.class)),
           "/api/v1/views/*", DISPATCHER_TYPES);
+      root.addFilter(new FilterHolder(injector.getInstance(ViewThrottleFilter.class)),
+          "/api/v2/views/*", DISPATCHER_TYPES);
 
       // session-per-request strategy for api
       root.addFilter(new FilterHolder(injector.getInstance(AmbariPersistFilter.class)), "/api/*", DISPATCHER_TYPES);
@@ -387,6 +391,7 @@ public class AmbariServer {
 
       root.addFilter(new FilterHolder(springSecurityFilter), "/api/*", DISPATCHER_TYPES);
       root.addFilter(new FilterHolder(new UserNameOverrideFilter()), "/api/v1/users/*", DISPATCHER_TYPES);
+      root.addFilter(new FilterHolder(new UserNameOverrideFilter()), "/api/v2/users/*", DISPATCHER_TYPES);
 
       // session-per-request strategy for agents
       agentroot.addFilter(new FilterHolder(injector.getInstance(AmbariPersistFilter.class)), "/agent/*", DISPATCHER_TYPES);
@@ -485,7 +490,7 @@ public class AmbariServer {
           "org.apache.ambari.server.api");
 
       sh.setInitParameter("com.sun.jersey.api.json.POJOMappingFeature", "true");
-      root.addServlet(sh, "/api/v1/*");
+      root.addServlet(sh, "/api/*");
       sh.setInitOrder(2);
 
       SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index 617553b..879c4c0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -69,9 +69,12 @@ import org.apache.ambari.server.controller.internal.KerberosDescriptorResourcePr
 import org.apache.ambari.server.controller.internal.MemberResourceProvider;
 import org.apache.ambari.server.controller.internal.RepositoryVersionResourceProvider;
 import org.apache.ambari.server.controller.internal.ServiceResourceProvider;
+import org.apache.ambari.server.controller.internal.ServiceGroupResourceProvider;
 import org.apache.ambari.server.controller.internal.UpgradeResourceProvider;
 import org.apache.ambari.server.controller.metrics.timeline.cache.TimelineMetricCacheEntryFactory;
 import org.apache.ambari.server.controller.metrics.timeline.cache.TimelineMetricCacheProvider;
+import org.apache.ambari.server.controller.servicegroup.cache.ServiceGroupCacheEntryFactory;
+import org.apache.ambari.server.controller.servicegroup.cache.ServiceGroupCacheProvider;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
 import org.apache.ambari.server.controller.utilities.KerberosChecker;
 import org.apache.ambari.server.notifications.DispatchFactory;
@@ -100,13 +103,16 @@ import org.apache.ambari.server.state.ConfigFactory;
 import org.apache.ambari.server.state.ConfigImpl;
 import org.apache.ambari.server.state.Host;
 import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.ServiceGroup;
 import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentFactory;
 import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.ServiceComponentHostFactory;
 import org.apache.ambari.server.state.ServiceComponentImpl;
 import org.apache.ambari.server.state.ServiceFactory;
+import org.apache.ambari.server.state.ServiceGroupFactory;
 import org.apache.ambari.server.state.ServiceImpl;
+import org.apache.ambari.server.state.ServiceGroupImpl;
 import org.apache.ambari.server.state.cluster.ClusterFactory;
 import org.apache.ambari.server.state.cluster.ClusterImpl;
 import org.apache.ambari.server.state.cluster.ClustersImpl;
@@ -361,6 +367,8 @@ public class ControllerModule extends AbstractModule {
     bind(ViewInstanceHandlerList.class).to(AmbariHandlerList.class);
     bind(TimelineMetricCacheProvider.class);
     bind(TimelineMetricCacheEntryFactory.class);
+    bind(ServiceGroupCacheProvider.class);
+    bind(ServiceGroupCacheEntryFactory.class);
     bind(SecurityConfigurationFactory.class).in(Scopes.SINGLETON);
 
     bind(PersistedState.class).to(PersistedStateImpl.class);
@@ -424,11 +432,14 @@ public class ControllerModule extends AbstractModule {
         Host.class, HostImpl.class).build(HostFactory.class));
     install(new FactoryModuleBuilder().implement(
         Service.class, ServiceImpl.class).build(ServiceFactory.class));
+    install(new FactoryModuleBuilder().implement(
+        ServiceGroup.class, ServiceGroupImpl.class).build(ServiceGroupFactory.class));
 
     install(new FactoryModuleBuilder()
         .implement(ResourceProvider.class, Names.named("host"), HostResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("hostComponent"), HostComponentResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("service"), ServiceResourceProvider.class)
+        .implement(ResourceProvider.class, Names.named("servicegroup"), ServiceGroupResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("component"), ComponentResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("member"), MemberResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("repositoryVersion"), RepositoryVersionResourceProvider.class)

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
index 3ec38c2..3f3f8ad 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
@@ -46,6 +46,11 @@ public interface ResourceProviderFactory {
       Map<Type, String> keyPropertyIds,
       AmbariManagementController managementController);
 
+  @Named("servicegroup")
+  ResourceProvider getServiceGroupResourceProvider(Set<String> propertyIds,
+      Map<Type, String> keyPropertyIds,
+      AmbariManagementController managementController);
+
   @Named("component")
   ResourceProvider getComponentResourceProvider(Set<String> propertyIds,
       Map<Type, String> keyPropertyIds,

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostResponse.java
index 85b2b46..7d7ef34 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostResponse.java
@@ -31,6 +31,8 @@ public class ServiceComponentHostResponse {
   private String componentName;
   private String displayName;
   private String hostname;
+  private String baseHostName;
+  private String containerName;
   // type -> desired config
   private Map<String, HostConfig> actualConfigs;
   private String liveState;
@@ -48,6 +50,17 @@ public class ServiceComponentHostResponse {
                                       String liveState, String stackVersion,
                                       String desiredState, String desiredStackVersion,
                                       HostComponentAdminState adminState) {
+
+    this(clusterName, serviceName, componentName, displayName, hostname,
+        liveState, stackVersion, desiredState, desiredStackVersion, adminState, null, null);
+  }
+
+  public ServiceComponentHostResponse(String clusterName, String serviceName,
+                                      String componentName, String displayName, String hostname,
+                                      String liveState, String stackVersion,
+                                      String desiredState, String desiredStackVersion,
+                                      HostComponentAdminState adminState,
+                                      String bareHostName, String containerName) {
     this.clusterName = clusterName;
     this.serviceName = serviceName;
     this.componentName = componentName;
@@ -60,11 +73,13 @@ public class ServiceComponentHostResponse {
     if (adminState != null) {
       this.adminState = adminState.name();
     }
+    this.baseHostName = bareHostName;
+    this.containerName = containerName;
   }
 
-  /**
-   * @return the serviceName
-   */
+    /**
+     * @return the serviceName
+     */
   public String getServiceName() {
     return serviceName;
   }
@@ -98,6 +113,35 @@ public class ServiceComponentHostResponse {
   }
 
   /**
+   * @return the bare-metal hostname
+   */
+  public String getBareHostName() {
+    return baseHostName;
+  }
+
+  /**
+   * @param baseHostName the bare-metal hostname to set
+   */
+  public void setBareHostName(String baseHostName) {
+    this.baseHostName = baseHostName;
+  }
+
+  /**
+   * @return the container name
+   */
+  public String getContainerName() {
+    return containerName;
+  }
+
+  /**
+   * @param containerName the container name to set
+   */
+  public void setContainerName(String containerName) {
+    this.containerName = containerName;
+  }
+
+
+  /**
    * @return the hostname
    */
   public String getHostname() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentRequest.java
index ba0b84f..b1a6c5d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentRequest.java
@@ -29,29 +29,37 @@ public class ServiceComponentRequest {
 
   private String desiredState; // CREATE/UPDATE
 
+  private String desiredCount; // CREATE/UPDATE
+
   private String componentCategory;
 
   private String recoveryEnabled; // CREATE/UPDATE
 
   public ServiceComponentRequest(String clusterName, String serviceName,
                                  String componentName, String desiredState) {
-    this(clusterName, serviceName, componentName, desiredState, null, null);
+    this(clusterName, serviceName, componentName, desiredState, null, null, null);
+  }
+
+  public ServiceComponentRequest(String clusterName, String serviceName,
+                                 String componentName, String desiredState, String desiredCount) {
+    this(clusterName, serviceName, componentName, desiredState, desiredCount, null, null);
   }
 
   public ServiceComponentRequest(String clusterName, String serviceName,
-                                 String componentName, String desiredState,
+                                 String componentName, String desiredState, String desiredCount,
                                  String recoveryEnabled) {
-    this(clusterName, serviceName, componentName, desiredState, recoveryEnabled, null);
+    this(clusterName, serviceName, componentName, desiredState, desiredCount, recoveryEnabled, null);
   }
 
   public ServiceComponentRequest(String clusterName,
                                  String serviceName, String componentName,
-                                 String desiredState, String recoveryEnabled,
+                                 String desiredState, String desiredCount, String recoveryEnabled,
                                  String componentCategory) {
     this.clusterName = clusterName;
     this.serviceName = serviceName;
     this.componentName = componentName;
     this.desiredState = desiredState;
+    this.desiredCount = desiredCount;
     this.recoveryEnabled = recoveryEnabled;
     this.componentCategory = componentCategory;
   }
@@ -99,6 +107,20 @@ public class ServiceComponentRequest {
   }
 
   /**
+   * @return the desiredCount
+   */
+  public String getDesiredCount() {
+    return desiredCount;
+  }
+
+  /**
+   * @param desiredCount the desiredCount to set
+   */
+  public void setDesiredCount(String desiredCount) {
+    this.desiredCount = desiredCount;
+  }
+
+  /**
    * @return the clusterName
    */
   public String getClusterName() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentResponse.java
index cb84b89..fae09f4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentResponse.java
@@ -43,6 +43,8 @@ public class ServiceComponentResponse {
 
   private int installedCount;
 
+  private int desiredCount;
+
   private boolean recoveryEnabled;
 
   public ServiceComponentResponse(Long clusterId, String clusterName,
@@ -53,6 +55,7 @@ public class ServiceComponentResponse {
                                   int totalCount,
                                   int startedCount,
                                   int installedCount,
+                                  int desiredCount,
                                   boolean recoveryEnabled,
                                   String displayName) {
     super();
@@ -66,6 +69,7 @@ public class ServiceComponentResponse {
     this.totalCount = totalCount;
     this.startedCount = startedCount;
     this.installedCount = installedCount;
+    this.desiredCount = desiredCount;
     this.recoveryEnabled = recoveryEnabled;
   }
 
@@ -161,6 +165,23 @@ public class ServiceComponentResponse {
   }
 
   /**
+   * Get the number of desired SCH's
+   * @return number of desired SCH's
+   */
+  public int getDesiredCount() {
+    return desiredCount;
+  }
+
+  /**
+   * Set the number of desired SCH's
+   * @param desiredCount
+   */
+  public void setDesiredCount(int desiredCount) {
+    this.desiredCount = desiredCount;
+  }
+
+
+  /**
    * Get the component category.
    *
    * @return the category

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupRequest.java
new file mode 100644
index 0000000..af00bb6
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupRequest.java
@@ -0,0 +1,152 @@
+/**
+ * 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.controller;
+
+
+
+public class ServiceGroupRequest {
+
+  private String clusterName; // REF
+  private String serviceGroupName; // GET/CREATE/UPDATE/DELETE
+  private String serviceGroupDisplayName; // GET/CREATE/UPDATE/DELETE
+  private String serviceGroupType; // GET/CREATE/UPDATE/DELETE
+  private String assemblyFile; // GET/CREATE/UPDATE/DELETE
+  private String desiredState;
+  private String currentState;
+
+  public ServiceGroupRequest(String clusterName, String serviceGroupName, String serviceGroupDisplayName,
+      String serviceGroupType, String assemblyFile, String desiredState, String currentState) {
+    this.clusterName = clusterName;
+    this.serviceGroupName = serviceGroupName;
+    this.serviceGroupDisplayName = serviceGroupDisplayName;
+    this.serviceGroupType = serviceGroupType;
+    this.assemblyFile = assemblyFile;
+    this.desiredState = desiredState;
+    this.currentState = currentState;
+  }
+
+  /**
+   * @return the clusterName
+   */
+  public String getClusterName() {
+    return clusterName;
+  }
+
+  /**
+   * @param clusterName the clusterName to set
+   */
+  public void setClusterName(String clusterName) {
+    this.clusterName = clusterName;
+  }
+
+  /**
+   * @return the serviceGroupName
+   */
+  public String getServiceGroupName() {
+    return serviceGroupName;
+  }
+
+  /**
+   * @param serviceGroupName the service group name to set
+   */
+  public void setServiceGroupName(String serviceGroupName) {
+    this.serviceGroupName = serviceGroupName;
+  }
+
+  /**
+   * @return the serviceGroupDisplayName
+   */
+  public String getServiceGroupDisplayName() {
+    return serviceGroupDisplayName;
+  }
+
+  /**
+   * @param serviceGroupDisplayName the service group display name to set
+   */
+  public void setServiceGroupDisplayName(String serviceGroupDisplayName) {
+    this.serviceGroupDisplayName = serviceGroupDisplayName;
+  }
+
+  /**
+   * @return the desired state of the service group
+   */
+  public String getDesiredState() {
+    return desiredState;
+  }
+
+  /**
+   * @param desiredState the desired state of service group
+   */
+  public void setDesiredState(String desiredState) {
+    this.desiredState = desiredState;
+  }
+
+  /**
+   * @return the current state of the service group
+   */
+  public String getCurrentState() {
+    return currentState;
+  }
+
+  /**
+   * @param currentState the current state of service group
+   */
+  public void setCurrentState(String currentState) {
+    this.currentState = currentState;
+  }
+
+  /**
+   * @return the serviceGroupType
+   */
+  public String getServiceGroupType() {
+    return serviceGroupType;
+  }
+
+  /**
+   * @param serviceGroupType the service group type to set
+   */
+  public void setServiceGroupType(String serviceGroupType) {
+    this.serviceGroupType = serviceGroupType;
+  }
+
+  /**
+   * @return the assembly file
+   */
+  public String getAssemblyFile() {
+    return assemblyFile;
+  }
+
+  /**
+   * @param assemblyFile the assembly file to set
+   */
+  public void setAssemblyFile(String assemblyFile) {
+    this.assemblyFile = assemblyFile;
+  }
+
+
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("clusterName=" + clusterName
+        + ", serviceGroupName=" + serviceGroupName
+        + ", serviceGroupDisplayName=" + serviceGroupDisplayName
+        + ", serviceGroupType=" + serviceGroupType
+        + ", desiredState=" + desiredState
+        + ", assemblyFile=" + assemblyFile);
+    return sb.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupResponse.java
new file mode 100644
index 0000000..5451160
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupResponse.java
@@ -0,0 +1,239 @@
+/**
+ * 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.controller;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+
+public class ServiceGroupResponse {
+
+  private Long clusterId;
+  private String clusterName;
+  private String serviceGroupName;
+  private String serviceGroupDisplayName;
+  private String serviceGroupType;
+  private String assemblyFile;
+  private String desiredState;
+  private String currentState;
+  private String applicationId;
+  private String lifetime = null;
+  private Map<String, String> quicklinks;
+  private Integer numContainers;
+  private Integer expectedContainers;
+  private ArrayList<Map<String, Object>> containers;
+
+  public ServiceGroupResponse(Long clusterId, String clusterName, String serviceGroupName, String serviceGroupDisplayName,
+                              String serviceGroupType, String assemblyFile, String desiredState, String currentState) {
+    this.clusterId = clusterId;
+    this.clusterName = clusterName;
+    this.serviceGroupName = serviceGroupName;
+    this.serviceGroupDisplayName = serviceGroupDisplayName;
+    this.serviceGroupType = serviceGroupType;
+    this.assemblyFile = assemblyFile;
+    this.desiredState = desiredState;
+    this.currentState = currentState;
+  }
+
+  /**
+   * @return the clusterId
+   */
+  public Long getClusterId() {
+    return clusterId;
+  }
+
+  /**
+   * @param clusterId the clusterId to set
+   */
+  public void setClusterId(Long clusterId) {
+    this.clusterId = clusterId;
+  }
+
+  /**
+   * @return the clusterName
+   */
+  public String getClusterName() {
+    return clusterName;
+  }
+
+  /**
+   * @param clusterName the clusterName to set
+   */
+  public void setClusterName(String clusterName) {
+    this.clusterName = clusterName;
+  }
+
+  /**
+   * @return the service group name
+   */
+  public String getServiceGroupName() {
+    return serviceGroupName;
+  }
+
+  /**
+   * @param  serviceGroupName the service group name
+   */
+  public void setServiceGroupName(String serviceGroupName) {
+    this.serviceGroupName = serviceGroupName;
+  }
+
+  /**
+   * @return the service group display name
+   */
+  public String getServiceGroupDisplayName() {
+    return serviceGroupDisplayName;
+  }
+
+  /**
+   * @param  serviceGroupDisplayName the service group display name
+   */
+  public void setServiceGroupDisplayName(String serviceGroupDisplayName) {
+    this.serviceGroupDisplayName = serviceGroupDisplayName;
+  }
+
+  /**
+   * @return the desired state of the service group
+   */
+  public String getDesiredState() {
+    return desiredState;
+  }
+
+  /**
+   * @param  desiredState the desired state of the service group
+   */
+  public void setDesiredState(String desiredState) {
+    this.desiredState = desiredState;
+  }
+
+  /**
+   * @return the current state of the service group
+   */
+  public String getCurrentState() {
+    return currentState;
+  }
+
+  /**
+   * @param  currentState the current state of the service group
+   */
+  public void setCurrentState(String currentState) {
+    this.currentState = currentState;
+  }
+
+
+  /**
+   * @return the service group type
+   */
+  public String getServiceGroupType() {
+    return serviceGroupType;
+  }
+
+  /**
+   * @param  serviceGroupType the service group type
+   */
+  public void setServiceGroupType(String serviceGroupType) {
+    this.serviceGroupType = serviceGroupType;
+  }
+
+  /**
+   * @return the assembly file
+   */
+  public String getAssemblyFile() {
+    return assemblyFile;
+  }
+
+  /**
+   * @param  assemblyFile the assembly file
+   */
+  public void setAssemblyFile(String assemblyFile) {
+    this.assemblyFile = assemblyFile;
+  }
+
+  public String getApplicationId() {
+    return applicationId;
+  }
+
+  public void setApplicationId(String applicationId) {
+    this.applicationId = applicationId;
+  }
+
+  public Map<String, String> getQuickLinks() {
+    return quicklinks;
+  }
+
+  public void setQuickLinks(Map<String, String> quicklinks) {
+    this.quicklinks = quicklinks;
+  }
+
+  public ArrayList<Map<String, Object>> getContainers() {
+    return containers;
+  }
+
+  public void setContainers(ArrayList<Map<String, Object>> containers) {
+    this.containers = containers;
+  }
+
+
+  public Integer getNumContainers() {
+    return numContainers;
+  }
+
+  public void setNumContainers(Integer numContainers) {
+    this.numContainers = numContainers;
+  }
+
+  public Integer getExpectedContainers() {
+    return expectedContainers;
+  }
+
+  public void setExpectedContainers(Integer expectedContainers) {
+    this.expectedContainers = expectedContainers;
+  }
+
+  public String getLifetime() {
+    return lifetime;
+  }
+
+  public void setLifetime(String lifetime) {
+    this.lifetime = lifetime;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ServiceGroupResponse that = (ServiceGroupResponse) o;
+
+    if (clusterId != null ?
+        !clusterId.equals(that.clusterId) : that.clusterId != null) {
+      return false;
+    }
+    if (clusterName != null ?
+        !clusterName.equals(that.clusterName) : that.clusterName != null) {
+      return false;
+    }
+    if (serviceGroupName != null ?
+        !serviceGroupName.equals(that.serviceGroupName) : that.serviceGroupName != null) {
+      return false;
+    }
+
+    return true;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
index eb874b5..4f9b1e8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
@@ -23,13 +23,17 @@ public class ServiceRequest {
 
   private String clusterName; // REF
   private String serviceName; // GET/CREATE/UPDATE/DELETE
+  private String stackServiceName; // GET/CREATE/UPDATE/DELETE
+  private String serviceGroupName; // GET/CREATE/UPDATE/DELETE
   private String desiredState; // CREATE/UPDATE
   private String maintenanceState; // UPDATE
 
-  public ServiceRequest(String clusterName, String serviceName,
-                        String desiredState) {
+  public ServiceRequest(String clusterName, String serviceName, String stackServiceName,
+    String serviceGroupName, String desiredState) {
     this.clusterName = clusterName;
     this.serviceName = serviceName;
+    this.stackServiceName = stackServiceName;
+    this.serviceGroupName = serviceGroupName;
     this.desiredState = desiredState;
   }
 
@@ -48,6 +52,34 @@ public class ServiceRequest {
   }
 
   /**
+   * @return the serviceName
+   */
+  public String getStackServiceName() {
+    return stackServiceName;
+  }
+
+  /**
+   * @param stackServiceName the actual serviceName to set
+   */
+  public void setStackServiceName(String stackServiceName) {
+    this.stackServiceName = stackServiceName;
+  }
+
+  /**
+   * @return the serviceGroupName
+   */
+  public String getServiceGroupName() {
+    return serviceGroupName;
+  }
+
+  /**
+   * @param serviceGroupName the service group name to set
+   */
+  public void setServiceGroupName(String serviceGroupName) {
+    this.serviceGroupName = serviceGroupName;
+  }
+
+  /**
    * @return the desiredState
    */
   public String getDesiredState() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceResponse.java
index c4881b8..3fd4af6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceResponse.java
@@ -24,16 +24,20 @@ public class ServiceResponse {
   private Long clusterId;
   private String clusterName;
   private String serviceName;
+  private String stackServiceName;
+  private String serviceGroupName;
   private String desiredStackVersion;
   private String desiredState;
   private String maintenanceState;
 
   public ServiceResponse(Long clusterId, String clusterName,
-                         String serviceName,
+                         String serviceName, String stackServiceName, String serviceGroupName,
                          String desiredStackVersion, String desiredState) {
     this.clusterId = clusterId;
     this.clusterName = clusterName;
     this.serviceName = serviceName;
+    this.serviceGroupName = serviceGroupName;
+    this.stackServiceName = stackServiceName;
     this.setDesiredStackVersion(desiredStackVersion);
     this.setDesiredState(desiredState);
   }
@@ -55,6 +59,34 @@ public class ServiceResponse {
   }
 
   /**
+   * @return the real serviceName
+   */
+  public String getStackServiceName() {
+    return stackServiceName;
+  }
+
+  /**
+   * @param stackServiceName the real serviceName to set
+   */
+  public void setStackServiceName(String stackServiceName) {
+    this.stackServiceName = stackServiceName;
+  }
+
+  /**
+   * @return the service group name
+   */
+  public String getServiceGroupName() {
+    return serviceGroupName;
+  }
+
+  /**
+   * @param  serviceGroupName the service group name
+   */
+  public void setServiceGroupName(String serviceGroupName) {
+    this.serviceGroupName = serviceGroupName;
+  }
+
+  /**
    * @return the clusterId
    */
   public Long getClusterId() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
index 3721113..80b8baa 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
@@ -131,6 +131,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori
         return new ClusterResourceProvider(managementController);
       case Service:
         return resourceProviderFactory.getServiceResourceProvider(propertyIds, keyPropertyIds, managementController);
+      case ServiceGroup:
+        return resourceProviderFactory.getServiceGroupResourceProvider(propertyIds, keyPropertyIds, managementController);
       case Component:
         return resourceProviderFactory.getComponentResourceProvider(propertyIds, keyPropertyIds, managementController);
       case Host:

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
index dd2b31b..cdcca30 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
@@ -27,18 +27,17 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.ClusterNotFoundException;
-import org.apache.ambari.server.DuplicateResourceException;
-import org.apache.ambari.server.ObjectNotFoundException;
-import org.apache.ambari.server.ParentObjectNotFoundException;
-import org.apache.ambari.server.ServiceNotFoundException;
+import jline.internal.Log;
+import org.apache.ambari.server.*;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.MaintenanceStateHelper;
 import org.apache.ambari.server.controller.RequestStatusResponse;
 import org.apache.ambari.server.controller.ServiceComponentRequest;
 import org.apache.ambari.server.controller.ServiceComponentResponse;
+import org.apache.ambari.server.controller.servicegroup.cache.ServiceGroupCache;
+import org.apache.ambari.server.controller.servicegroup.cache.ServiceGroupCacheKey;
+import org.apache.ambari.server.controller.servicegroup.cache.ServiceGroupCacheProvider;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
 import org.apache.ambari.server.controller.spi.Predicate;
@@ -52,19 +51,12 @@ import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.security.authorization.AuthorizationHelper;
 import org.apache.ambari.server.security.authorization.ResourceType;
 import org.apache.ambari.server.security.authorization.RoleAuthorization;
-import org.apache.ambari.server.state.Cluster;
-import org.apache.ambari.server.state.Clusters;
-import org.apache.ambari.server.state.ComponentInfo;
-import org.apache.ambari.server.state.Service;
-import org.apache.ambari.server.state.ServiceComponent;
-import org.apache.ambari.server.state.ServiceComponentFactory;
-import org.apache.ambari.server.state.ServiceComponentHost;
-import org.apache.ambari.server.state.StackId;
-import org.apache.ambari.server.state.State;
+import org.apache.ambari.server.state.*;
 
 import com.google.inject.assistedinject.Assisted;
 import com.google.inject.assistedinject.AssistedInject;
 import com.google.inject.persist.Transactional;
+import org.apache.ambari.server.utils.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.Validate;
 
@@ -81,6 +73,7 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
   protected static final String COMPONENT_COMPONENT_NAME_PROPERTY_ID  = "ServiceComponentInfo/component_name";
   protected static final String COMPONENT_DISPLAY_NAME_PROPERTY_ID    = "ServiceComponentInfo/display_name";
   protected static final String COMPONENT_STATE_PROPERTY_ID           = "ServiceComponentInfo/state";
+  protected static final String COMPONENT_DESIRED_COUNT_PROPERTY_ID    = "ServiceComponentInfo/desired_count";
   protected static final String COMPONENT_CATEGORY_PROPERTY_ID        = "ServiceComponentInfo/category";
   protected static final String COMPONENT_TOTAL_COUNT_PROPERTY_ID     = "ServiceComponentInfo/total_count";
   protected static final String COMPONENT_STARTED_COUNT_PROPERTY_ID   = "ServiceComponentInfo/started_count";
@@ -100,6 +93,11 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
 
   private MaintenanceStateHelper maintenanceStateHelper;
 
+  private static Map<String, String> componentNameMappings = MapUtils.fillMap("/var/lib/ambari-server/resources/componentsMap.dat");
+
+  private ServiceGroupCacheProvider cacheProvider;
+  private ServiceGroupCache cache;
+
   // ----- Constructors ----------------------------------------------------
 
   /**
@@ -122,6 +120,9 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
     setRequiredGetAuthorizations(RoleAuthorization.AUTHORIZATIONS_VIEW_SERVICE);
     setRequiredGetAuthorizations(RoleAuthorization.AUTHORIZATIONS_VIEW_SERVICE);
     setRequiredUpdateAuthorizations(RoleAuthorization.AUTHORIZATIONS_UPDATE_CLUSTER);
+
+    this.cacheProvider = managementController.getServiceGroupCacheProvider();
+    this.cache = cacheProvider.getServiceGroupCache();
   }
 
 
@@ -180,6 +181,7 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
       setResourceProperty(resource, COMPONENT_CATEGORY_PROPERTY_ID, response.getCategory(), requestedIds);
       setResourceProperty(resource, COMPONENT_TOTAL_COUNT_PROPERTY_ID, response.getTotalCount(), requestedIds);
       setResourceProperty(resource, COMPONENT_STARTED_COUNT_PROPERTY_ID, response.getStartedCount(), requestedIds);
+      setResourceProperty(resource, COMPONENT_DESIRED_COUNT_PROPERTY_ID, response.getDesiredCount(), requestedIds);
       setResourceProperty(resource, COMPONENT_INSTALLED_COUNT_PROPERTY_ID, response.getInstalledCount(), requestedIds);
       setResourceProperty(resource, COMPONENT_RECOVERY_ENABLED_ID, String.valueOf(response.isRecoveryEnabled()), requestedIds);
 
@@ -255,6 +257,7 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
         (String) properties.get(COMPONENT_SERVICE_NAME_PROPERTY_ID),
         (String) properties.get(COMPONENT_COMPONENT_NAME_PROPERTY_ID),
         (String) properties.get(COMPONENT_STATE_PROPERTY_ID),
+        (String) properties.get(COMPONENT_DESIRED_COUNT_PROPERTY_ID),
         (String) properties.get(COMPONENT_RECOVERY_ENABLED_ID),
         (String) properties.get(COMPONENT_CATEGORY_PROPERTY_ID));
   }
@@ -351,6 +354,11 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
       } else {
         sc.setDesiredState(s.getDesiredState());
       }
+      int desiredCount = 0;
+      if(StringUtils.isNotEmpty(request.getDesiredCount())) {
+        desiredCount = Integer.parseInt(request.getDesiredCount());
+      }
+      sc.setDesiredCount(desiredCount);
 
       /**
        * If request does not have recovery_enabled field,
@@ -395,8 +403,9 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
   // Get the components for the given request.
   private Set<ServiceComponentResponse> getComponents(ServiceComponentRequest request) throws AmbariException {
 
-    final AmbariMetaInfo ambariMetaInfo = getManagementController().getAmbariMetaInfo();
-    final Clusters clusters = getManagementController().getClusters();
+    AmbariManagementController controller = getManagementController();
+    final AmbariMetaInfo ambariMetaInfo = controller.getAmbariMetaInfo();
+    final Clusters clusters = controller.getClusters();
     final Cluster cluster = getCluster(request, clusters);
 
     Set<ServiceComponentResponse> response = new HashSet<>();
@@ -410,6 +419,49 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
       final Service s = getServiceFromCluster(request, cluster);
       ServiceComponent sc = s.getServiceComponent(request.getComponentName());
       ServiceComponentResponse serviceComponentResponse = sc.convertToResponse();
+      ServiceGroup sg = null;
+      try {
+        sg = cluster.getServiceGroup(sc.getServiceGroupName());
+      } catch (ServiceGroupNotFoundException e) {
+        sg = null;
+      }
+      if(sg != null && !sg.getServiceGroupType().equalsIgnoreCase("AMBARI")) {
+        ServiceGroupCacheKey cacheKey = new ServiceGroupCacheKey(sg.getName());
+        Map<String, Object> responseMap = null;
+        try {
+          responseMap = cache.getResponseFromCache(cacheKey);
+        } catch (Exception e) {
+          Log.info("Hit exception when retrieving service group from cache. Exception: " + e.getMessage());
+        }
+        if (responseMap != null && responseMap.containsKey("containers")) {
+          String mappedComponentName = componentNameMappings.containsKey(request.getComponentName()) ?
+              componentNameMappings.get(request.getComponentName()) : request.getComponentName();
+          int installedCount = 0;
+          int startedCount = 0;
+
+          for (Map<String, String> cMap : (ArrayList<Map<String, String>>) responseMap.get("containers")) {
+            String dashContainerName = cMap.get("id");
+            String dashComponentName = cMap.get("component_name");
+            String dashState = cMap.get("state");
+            String dashHostName = cMap.get("hostname");
+            String dashBareHostName = cMap.get("bare_host");
+            if (dashComponentName.contains(mappedComponentName)) {
+              if (dashState.equalsIgnoreCase("READY")) {
+                if (sc.isClientComponent()) {
+                  installedCount++;
+                } else {
+                  startedCount++;
+                }
+              } else {
+                installedCount++;
+              }
+            }
+          }
+          serviceComponentResponse.setInstalledCount(installedCount);
+          serviceComponentResponse.setStartedCount(startedCount);
+        }
+      }
+
 
       try {
         ComponentInfo componentInfo = ambariMetaInfo.getComponent(stackId.getStackName(),
@@ -443,6 +495,48 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
         }
 
         ServiceComponentResponse serviceComponentResponse = sc.convertToResponse();
+        ServiceGroup sg = null;
+        try {
+          sg = cluster.getServiceGroup(sc.getServiceGroupName());
+        } catch (ServiceGroupNotFoundException e) {
+          sg = null;
+        }
+        if(sg != null && !sg.getServiceGroupType().equalsIgnoreCase("AMBARI")) {
+          ServiceGroupCacheKey cacheKey = new ServiceGroupCacheKey(sg.getName());
+          Map<String, Object> responseMap = null;
+          try {
+            responseMap = cache.getResponseFromCache(cacheKey);
+          } catch (Exception e) {
+            Log.info("Hit exception when retrieving service group from cache. Exception: " + e.getMessage());
+          }
+          if (responseMap != null && responseMap.containsKey("containers")) {
+            String mappedComponentName = componentNameMappings.containsKey(sc.getName()) ?
+                componentNameMappings.get(sc.getName()) : sc.getName();
+            int installedCount = 0;
+            int startedCount = 0;
+
+            for (Map<String, String> cMap : (ArrayList<Map<String, String>>) responseMap.get("containers")) {
+              String dashContainerName = cMap.get("id");
+              String dashComponentName = cMap.get("component_name");
+              String dashState = cMap.get("state");
+              String dashHostName = cMap.get("hostname");
+              String dashBareHostName = cMap.get("bare_host");
+              if (dashComponentName.contains(mappedComponentName)) {
+                if (dashState.equalsIgnoreCase("READY")) {
+                  if (sc.isClientComponent()) {
+                    installedCount++;
+                  } else {
+                    startedCount++;
+                  }
+                } else {
+                  installedCount++;
+                }
+              }
+            }
+            serviceComponentResponse.setInstalledCount(installedCount);
+            serviceComponentResponse.setStartedCount(startedCount);
+          }
+        }
         try {
           ComponentInfo componentInfo = ambariMetaInfo.getComponent(stackId.getStackName(),
               stackId.getStackVersion(), s.getName(), sc.getName());

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DashHttpPropertyRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DashHttpPropertyRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DashHttpPropertyRequest.java
new file mode 100644
index 0000000..76537f6
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DashHttpPropertyRequest.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.controller.internal;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.state.Cluster;
+
+import java.util.Collections;
+import java.util.Map;
+
+public class DashHttpPropertyRequest extends JsonHttpPropertyRequest {
+
+  private static String DashApplicationsUrl = "http://cn008.l42scl.hortonworks.com:9191/services/v1/applications";
+
+  /**
+   * Create a property request.
+   *
+   * @param propertyMappings the property name mapping
+   */
+  public DashHttpPropertyRequest(Map<String, String> propertyMappings) {
+    super(propertyMappings);
+  }
+
+  @Override
+  public String getUrl(Cluster cluster, String hostName) throws SystemException {
+    return DashApplicationsUrl;
+  }
+
+  public String getUrl(Cluster cluster, String hostName, String yarnAppName) throws SystemException {
+    return DashApplicationsUrl + "/" + yarnAppName;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b88db3cc/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
index 9d8389a..3258b29 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
@@ -89,6 +89,10 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
       = PropertyHelper.getPropertyId("HostRoles", "display_name");
   public static final String HOST_COMPONENT_HOST_NAME_PROPERTY_ID
       = PropertyHelper.getPropertyId("HostRoles", "host_name");
+  public static final String HOST_COMPONENT_BARE_HOST_NAME_PROPERTY_ID
+      = PropertyHelper.getPropertyId("HostRoles", "bare_host_name");
+  public static final String HOST_COMPONENT_CONTAINER_NAME_PROPERTY_ID
+      = PropertyHelper.getPropertyId("HostRoles", "container_name");
   public static final String HOST_COMPONENT_STATE_PROPERTY_ID
       = PropertyHelper.getPropertyId("HostRoles", "state");
   public static final String HOST_COMPONENT_DESIRED_STATE_PROPERTY_ID
@@ -227,6 +231,10 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
               response.getDisplayName(), requestedIds);
       setResourceProperty(resource, HOST_COMPONENT_HOST_NAME_PROPERTY_ID,
               response.getHostname(), requestedIds);
+      setResourceProperty(resource, HOST_COMPONENT_BARE_HOST_NAME_PROPERTY_ID,
+          response.getBareHostName(), requestedIds);
+      setResourceProperty(resource, HOST_COMPONENT_CONTAINER_NAME_PROPERTY_ID,
+          response.getContainerName(), requestedIds);
       setResourceProperty(resource, HOST_COMPONENT_STATE_PROPERTY_ID,
               response.getLiveState(), requestedIds);
       setResourceProperty(resource, HOST_COMPONENT_DESIRED_STATE_PROPERTY_ID,