Browse Source

AMBARI-2699. API to expose Ambari Server resource. (odiachenko)

Oleksandr Diachenko 12 năm trước cách đây
mục cha
commit
8f5b66286b
31 tập tin đã thay đổi với 2110 bổ sung4 xóa
  1. 12 0
      ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
  2. 53 0
      ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootServiceComponentResourceDefinition.java
  3. 76 0
      ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootServiceHostComponentResourceDefinition.java
  4. 56 0
      ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootServiceResourceDefinition.java
  5. 164 0
      ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceService.java
  6. 5 1
      ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
  7. 63 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/AbstractRootServiceResponseFactory.java
  8. 34 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
  9. 77 1
      ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
  10. 1 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
  11. 39 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceComponentRequest.java
  12. 74 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceComponentResponse.java
  13. 37 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceHostComponentRequest.java
  14. 105 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceHostComponentResponse.java
  15. 37 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceRequest.java
  16. 55 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceResponse.java
  17. 188 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceResponseFactory.java
  18. 6 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
  19. 110 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentResourceProvider.java
  20. 121 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceHostComponentResourceProvider.java
  21. 96 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceResourceProvider.java
  22. 4 1
      ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
  23. 13 0
      ambari-server/src/main/resources/key_properties.json
  24. 15 0
      ambari-server/src/main/resources/properties.json
  25. 145 0
      ambari-server/src/test/java/org/apache/ambari/server/api/services/RootServiceServiceTest.java
  26. 1 1
      ambari-server/src/test/java/org/apache/ambari/server/api/services/ServiceServiceTest.java
  27. 48 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
  28. 156 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/RootServiceResponseFactoryTest.java
  29. 105 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RootServiceComponentResourceProviderTest.java
  30. 112 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RootServiceHostComponentResourceProviderTest.java
  31. 102 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RootServiceResourceProviderTest.java

+ 12 - 0
ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java

@@ -130,6 +130,18 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
       case TaskAttempt:
         resourceDefinition = new TaskAttemptResourceDefinition();
         break;
+        
+      case RootService:
+        resourceDefinition = new RootServiceResourceDefinition();
+        break;
+        
+      case RootServiceComponent:
+        resourceDefinition = new RootServiceComponentResourceDefinition();
+        break;
+        
+      case RootServiceHostComponent:
+        resourceDefinition = new RootServiceHostComponentResourceDefinition();
+        break;
 
       default:
         throw new IllegalArgumentException("Unsupported resource type: " + type);

+ 53 - 0
ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootServiceComponentResourceDefinition.java

@@ -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.
+ */
+
+package org.apache.ambari.server.api.resources;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.Resource.Type;
+
+public class RootServiceComponentResourceDefinition extends
+    BaseResourceDefinition {
+
+  public RootServiceComponentResourceDefinition(Type resourceType) {
+    super(resourceType);
+  }
+
+  public RootServiceComponentResourceDefinition() {
+    super(Resource.Type.RootServiceComponent);
+  }
+
+  @Override
+  public String getPluralName() {
+    return "components";
+  }
+
+  @Override
+  public String getSingularName() {
+    return "component";
+  }
+  
+  @Override
+  public Set<SubResourceDefinition> getSubResourceDefinitions() {
+    return Collections.singleton(new SubResourceDefinition(
+        Resource.Type.RootServiceHostComponent, Collections.singleton(Resource.Type.Host), true));
+  }
+}

+ 76 - 0
ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootServiceHostComponentResourceDefinition.java

@@ -0,0 +1,76 @@
+/**
+ * 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.resources;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.ambari.server.api.services.Request;
+import org.apache.ambari.server.api.util.TreeNode;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.Schema;
+import org.apache.ambari.server.controller.spi.Resource.Type;
+import org.apache.ambari.server.controller.utilities.ClusterControllerHelper;
+
+public class RootServiceHostComponentResourceDefinition extends
+    BaseResourceDefinition {
+
+  public RootServiceHostComponentResourceDefinition(Type resourceType) {
+    super(resourceType);
+  }
+
+  public RootServiceHostComponentResourceDefinition() {
+    super(Resource.Type.RootServiceHostComponent);
+  }
+
+  @Override
+  public String getPluralName() {
+    return "hostComponents";
+  }
+
+  @Override
+  public String getSingularName() {
+    return "hostComponent";
+  }
+  
+  @Override
+  public List<PostProcessor> getPostProcessors() {
+    List<PostProcessor> listProcessors = new ArrayList<PostProcessor>();
+    listProcessors.add(new RootServiceHostComponentHrefProcessor());
+
+    return listProcessors;
+  }
+  
+  private class RootServiceHostComponentHrefProcessor extends BaseHrefPostProcessor {
+    @Override
+    public void process(Request request, TreeNode<Resource> resultNode, String href) {
+      Resource r = resultNode.getObject();
+      Schema schema = ClusterControllerHelper.getClusterController().getSchema(r.getType());
+      Object host = r.getPropertyValue(schema.getKeyPropertyId(Resource.Type.Host));
+      Object hostComponent = r.getPropertyValue(schema.getKeyPropertyId(r.getType()));
+
+      int idx = href.indexOf("services/") + "services/".length();
+      idx = href.indexOf("/", idx) + 1;
+
+      href = href.substring(0, idx) + "hosts/" + host + "/hostComponents/" + hostComponent;
+
+      resultNode.setProperty("href", href);
+    }
+  }
+}

+ 56 - 0
ambari-server/src/main/java/org/apache/ambari/server/api/resources/RootServiceResourceDefinition.java

@@ -0,0 +1,56 @@
+/**
+ * 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.resources;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.Resource.Type;
+
+public class RootServiceResourceDefinition extends BaseResourceDefinition {
+
+  public RootServiceResourceDefinition(Type resourceType) {
+    super(resourceType);
+  }
+
+  public RootServiceResourceDefinition() {
+    super(Resource.Type.RootService);
+  }
+
+  @Override
+  public String getPluralName() {
+    return "rootServices";
+  }
+
+  @Override
+  public String getSingularName() {
+    return "rootService";
+  }
+  
+  @Override
+  public Set<SubResourceDefinition> getSubResourceDefinitions() {
+    
+    Set<SubResourceDefinition> setChildren = new HashSet<SubResourceDefinition>();
+    setChildren.add(new SubResourceDefinition(Resource.Type.RootServiceComponent));
+
+    return setChildren;
+  }
+
+}

+ 164 - 0
ambari-server/src/main/java/org/apache/ambari/server/api/services/RootServiceService.java

@@ -0,0 +1,164 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.services;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.spi.Resource;
+
+@Path("/services/")
+public class RootServiceService extends BaseService {
+  
+  @GET
+  @Produces("text/plain")
+  public Response getServices(@Context HttpHeaders headers, @Context UriInfo ui) {
+
+    return handleRequest(headers, null, ui, Request.Type.GET,
+      createServiceResource(null));
+  }
+  
+  @GET
+  @Path("{serviceName}")
+  @Produces("text/plain")
+  public Response getService(@Context HttpHeaders headers, @Context UriInfo ui,
+      @PathParam("serviceName") String serviceName) {
+
+    return handleRequest(headers, null, ui, Request.Type.GET,
+      createServiceResource(serviceName));
+  }
+
+  @GET
+  @Path("{serviceName}/components/{componentName}/hostComponents")
+  @Produces("text/plain")
+  public Response getRootHostComponents(@Context HttpHeaders headers, @Context UriInfo ui,
+      @PathParam("serviceName") String serviceName,
+      @PathParam("componentName") String componentName) {
+
+    return handleRequest(headers, null, ui, Request.Type.GET,
+      createHostComponentResource(serviceName, null, componentName));
+  }
+  
+  
+  @GET
+  @Path("{serviceName}/hosts/")
+  @Produces("text/plain")
+  public Response getRootHosts(@Context HttpHeaders headers, @Context UriInfo ui) {
+
+    return handleRequest(headers, null, ui, Request.Type.GET,
+      createHostResource(null));
+  }
+  
+  @GET
+  @Path("{serviceName}/hosts/{hostName}")
+  @Produces("text/plain")
+  public Response getRootHost(@Context HttpHeaders headers, @Context UriInfo ui,
+      @PathParam("hostName") String hostName) {
+
+    return handleRequest(headers, null, ui, Request.Type.GET,
+      createHostResource(hostName));
+  }
+  
+  
+  protected ResourceInstance createHostResource(String hostName) {
+    return createResource(Resource.Type.Host, Collections.<Resource.Type, String>singletonMap(Resource.Type.Host, hostName));
+  }
+
+  
+  @GET
+  @Path("{serviceName}/hosts/{hostName}/hostComponents/")
+  @Produces("text/plain")
+  public Response getRootHostComponent(@Context HttpHeaders headers, @Context UriInfo ui,
+      @PathParam("serviceName") String serviceName,
+      @PathParam("hostName") String hostName) {
+
+    return handleRequest(headers, null, ui, Request.Type.GET,
+      createHostComponentResource(serviceName, hostName, null));
+  }
+  
+  @GET
+  @Path("{serviceName}/hosts/{hostName}/hostComponents/{hostComponent}")
+  @Produces("text/plain")
+  public Response getRootHostComponent(@Context HttpHeaders headers, @Context UriInfo ui,
+      @PathParam("serviceName") String serviceName,
+      @PathParam("hostName") String hostName,
+      @PathParam("hostComponent") String hostComponent) {
+
+    return handleRequest(headers, null, ui, Request.Type.GET,
+      createHostComponentResource(serviceName, hostName, hostComponent));
+  }
+  
+  
+  protected ResourceInstance createHostComponentResource(String serviceName, String hostName, String componentName) {
+    
+    Map<Resource.Type,String> mapIds = new HashMap<Resource.Type, String>();
+    mapIds.put(Resource.Type.RootService, serviceName);
+    mapIds.put(Resource.Type.Host, hostName);
+    mapIds.put(Resource.Type.RootServiceComponent, componentName);
+
+    return createResource(Resource.Type.RootServiceHostComponent, mapIds);
+  }
+
+  @GET
+  @Path("{serviceName}/components/")
+  @Produces("text/plain")
+  public Response getServiceComponents(@Context HttpHeaders headers, @Context UriInfo ui,
+      @PathParam("serviceName") String serviceName) {
+
+    return handleRequest(headers, null, ui, Request.Type.GET,
+      createServiceComponentResource(serviceName, null));
+  }
+  
+  @GET
+  @Path("{serviceName}/components/{componentName}")
+  @Produces("text/plain")
+  public Response getServiceComponent(@Context HttpHeaders headers, @Context UriInfo ui,
+      @PathParam("serviceName") String serviceName,
+      @PathParam("componentName") String componentName) {
+
+    return handleRequest(headers, null, ui, Request.Type.GET,
+        createServiceComponentResource(serviceName, componentName));
+  }
+  
+  protected ResourceInstance createServiceResource(String serviceName) {
+    return createResource(Resource.Type.RootService,
+        Collections.singletonMap(Resource.Type.RootService, serviceName));
+  }
+  
+  protected ResourceInstance createServiceComponentResource(String serviceName,
+      String componentName) {
+    
+    Map<Resource.Type,String> mapIds = new HashMap<Resource.Type, String>();
+    mapIds.put(Resource.Type.RootService, serviceName);
+    mapIds.put(Resource.Type.RootServiceComponent, componentName);
+
+    return createResource(Resource.Type.RootServiceComponent, mapIds);
+  }
+}

+ 5 - 1
ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java

@@ -36,7 +36,6 @@ import java.io.InputStream;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
-import java.util.Set;
 import java.util.Map.Entry;
 
 
@@ -77,6 +76,7 @@ public class Configuration {
   public static final String METADETA_DIR_PATH = "metadata.path";
   public static final String SERVER_VERSION_FILE = "server.version.file";
   public static final String SERVER_VERSION_KEY = "version";
+  public static final String JAVA_HOME_KEY = "java.home";
 
   public static final String CLIENT_SECURITY_KEY = "client.security";
   public static final String CLIENT_API_PORT_KEY = "client.api.port";
@@ -200,6 +200,8 @@ public class Configuration {
   private static final String PASSPHRASE_ENV_DEFAULT = "AMBARI_PASSPHRASE";
   private static final String RESOURCES_DIR_DEFAULT =
       "/var/share/ambari/resources/";
+  
+  public static final String JAVA_HOME_DEFAULT = "/usr/jdk64/jdk1.6.0_31";
 
   private static final String  ANONYMOUS_AUDIT_NAME_KEY = "anonymous.audit.name";
       
@@ -305,6 +307,8 @@ public class Configuration {
       CLIENT_API_SSL_KEY_NAME_KEY, CLIENT_API_SSL_KEY_NAME_DEFAULT));
     configsMap.put(CLIENT_API_SSL_CRT_NAME_KEY, properties.getProperty(
       CLIENT_API_SSL_CRT_NAME_KEY, CLIENT_API_SSL_CRT_NAME_DEFAULT));
+    configsMap.put(JAVA_HOME_KEY, properties.getProperty(
+        JAVA_HOME_KEY, JAVA_HOME_DEFAULT));
 
     File passFile = new File(configsMap.get(SRVR_KSTR_DIR_KEY) + File.separator
         + configsMap.get(SRVR_CRT_PASS_FILE_KEY));

+ 63 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/AbstractRootServiceResponseFactory.java

@@ -0,0 +1,63 @@
+/**
+ * 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.Set;
+
+import org.apache.ambari.server.AmbariException;
+
+public abstract class AbstractRootServiceResponseFactory {
+
+  /**
+   * Get all root services.
+   * 
+   * @param request the root services 
+   * 
+   * @return a set of root services 
+   * 
+   * @throws  AmbariException if the resources cannot be read
+   */
+  public abstract Set<RootServiceResponse> getRootServices(RootServiceRequest request) throws AmbariException;
+  
+  /**
+   * Get all components of root services.
+   * 
+   * @param request the host components of root services
+   * 
+   * @return a set of components of root services
+   * 
+   * @throws  AmbariException if the resources cannot be read
+   */
+  public abstract Set<RootServiceComponentResponse> getRootServiceComponents(RootServiceComponentRequest request) throws AmbariException;
+  
+  /**
+   * Get all components of root services related to hosts.
+   * 
+   * @param request the host components of root services related to hosts
+   * @param hosts the list of hosts
+   * 
+   * 
+   * @return a set of components of root services related to hosts
+   * 
+   * @throws  AmbariException if the resources cannot be read
+   */
+  public abstract Set<RootServiceHostComponentResponse> getRootServiceHostComponent(RootServiceHostComponentRequest request,
+      Set<HostResponse> hosts) throws AmbariException;
+}

+ 34 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java

@@ -511,4 +511,38 @@ public interface AmbariManagementController {
    * @throws  AmbariException if the resources cannot be read
    */
   public Set<OperatingSystemResponse> getStackOperatingSystems(Set<OperatingSystemRequest> requests) throws AmbariException;
+
+  /**
+   * Get all top-level services of Ambari, not related to certain cluster.
+   * 
+   * @param requests the top-level services 
+   * 
+   * @return a set of top-level services 
+   * 
+   * @throws  AmbariException if the resources cannot be read
+   */
+  
+  public Set<RootServiceResponse> getRootServices(Set<RootServiceRequest> requests) throws AmbariException;
+  /**
+   * Get all components of top-level services of Ambari, not related to certain cluster.
+   * 
+   * @param requests the components of top-level services 
+   * 
+   * @return a set of components 
+   * 
+   * @throws  AmbariException if the resources cannot be read
+   */
+  public Set<RootServiceComponentResponse> getRootServiceComponents(Set<RootServiceComponentRequest> requests) throws AmbariException;
+
+  /**
+   * Get all hosts components of top-level services of Ambari, not related to certain cluster.
+   * 
+   * @param requests the host components of top-level services 
+   * 
+   * @return a set of host components 
+   * 
+   * @throws  AmbariException if the resources cannot be read
+   */
+  public Set<RootServiceHostComponentResponse> getRootServiceHostComponents(Set<RootServiceHostComponentRequest> requests) throws AmbariException;
 }
+  

+ 77 - 1
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java

@@ -145,6 +145,8 @@ public class AmbariManagementControllerImpl implements
   private HostsMap hostsMap;
   @Inject
   private Configuration configs;
+  @Inject
+  private AbstractRootServiceResponseFactory rootServiceResponseFactory;
 
   final private String masterHostname;
   final private Integer masterPort;
@@ -4624,5 +4626,79 @@ public class AmbariManagementControllerImpl implements
   private String getAuthName() {
     return AuthorizationHelper.getAuthenticatedName(configs.getAnonymousAuditName());
   }
-  
+
+  @Override
+  public Set<RootServiceResponse> getRootServices(
+      Set<RootServiceRequest> requests) throws AmbariException {
+    Set<RootServiceResponse> response = new HashSet<RootServiceResponse>();
+    for (RootServiceRequest request : requests) {
+      try {
+        response.addAll(getRootServices(request));
+      } catch (AmbariException e) {
+        if (requests.size() == 1) {
+          // only throw exception if 1 request.
+          // there will be > 1 request in case of OR predicate
+          throw e;
+        }
+      }
+    }
+    return response;
+  }
+
+  private Set<RootServiceResponse> getRootServices (RootServiceRequest request)
+      throws AmbariException{
+    Set<RootServiceResponse> response = this.rootServiceResponseFactory.getRootServices(request);
+    return response;
+  }
+
+  @Override
+  public Set<RootServiceComponentResponse> getRootServiceComponents(
+      Set<RootServiceComponentRequest> requests) throws AmbariException {
+    Set<RootServiceComponentResponse> response = new HashSet<RootServiceComponentResponse>();
+    for (RootServiceComponentRequest request : requests) {
+      try {
+        response.addAll(getRootServiceComponents(request));
+      } catch (AmbariException e) {
+        if (requests.size() == 1) {
+          // only throw exception if 1 request.
+          // there will be > 1 request in case of OR predicate
+          throw e;
+        }
+      }
+    }
+    return response;
+  }
+
+  private Set<RootServiceComponentResponse> getRootServiceComponents(
+      RootServiceComponentRequest request) throws AmbariException{
+    Set<RootServiceComponentResponse> response = this.rootServiceResponseFactory.getRootServiceComponents(request);
+    return response;
+  }
+
+  @Override
+  public Set<RootServiceHostComponentResponse> getRootServiceHostComponents(
+      Set<RootServiceHostComponentRequest> requests) throws AmbariException {
+    Set<RootServiceHostComponentResponse> response = new HashSet<RootServiceHostComponentResponse>();
+    for (RootServiceHostComponentRequest request : requests) {
+      try {
+        response.addAll(getRootServiceHostComponents(request));
+      } catch (AmbariException e) {
+        if (requests.size() == 1) {
+          // only throw exception if 1 request.
+          // there will be > 1 request in case of OR predicate
+          throw e;
+        }
+      }
+    }
+    return response;
+  }
+
+  private Set<RootServiceHostComponentResponse> getRootServiceHostComponents(RootServiceHostComponentRequest request) throws AmbariException{
+
+    //Get all hosts of all clusters
+    Set<HostResponse> hosts = getHosts(new HostRequest(request.getHostName(), null, null));
+    
+    Set<RootServiceHostComponentResponse> response = this.rootServiceResponseFactory.getRootServiceHostComponent(request, hosts);
+    return response;
+  }
 }

+ 1 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java

@@ -81,6 +81,7 @@ public class ControllerModule extends AbstractModule {
     bindConstant().annotatedWith(Names.named("actionTimeout")).to(600000L);
     bind(AmbariManagementController.class)
         .to(AmbariManagementControllerImpl.class);
+    bind(AbstractRootServiceResponseFactory.class).to(RootServiceResponseFactory.class);
     bind(HBaseMasterPortScanner.class).in(Singleton.class);
     bind(ServerActionManager.class).to(ServerActionManagerImpl.class);
   }

+ 39 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceComponentRequest.java

@@ -0,0 +1,39 @@
+/**
+ * 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 RootServiceComponentRequest extends RootServiceRequest{
+
+  private String componentName;
+
+  public RootServiceComponentRequest(String serviceName, String componentName) {
+    super(serviceName);
+    this.componentName = componentName;
+  }
+
+  public String getComponentName() {
+    return componentName;
+  }
+
+  public void setComponentName(String componentName) {
+    this.componentName = componentName;
+  }
+
+}

+ 74 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceComponentResponse.java

@@ -0,0 +1,74 @@
+/**
+ * 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.Map;
+
+public class RootServiceComponentResponse {
+
+  private String componentName;
+  private Map<String, String> properties;
+
+  public RootServiceComponentResponse(String componentName, Map<String, String> properties) {
+    this.componentName = componentName;
+    this.setProperties(properties);
+  }
+
+  public String getComponentName() {
+    return componentName;
+  }
+
+  public Map<String, String> getProperties() {
+    return properties;
+  }
+
+  public void setProperties(Map<String, String> properties) {
+    this.properties = properties;
+  }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    RootServiceComponentResponse that = (RootServiceComponentResponse) o;
+
+    if (componentName != null ?
+        !componentName.equals(that.componentName) : that.componentName != null) {
+      return false;
+    }
+    
+    if (properties != null ?
+        !properties.equals(that.properties) : that.properties != null) {
+      return false;
+    }
+    
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = 1;
+    result = 31 + (componentName != null ? componentName.hashCode() : 0);
+    return result;
+  }
+
+
+}

+ 37 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceHostComponentRequest.java

@@ -0,0 +1,37 @@
+/**
+ * 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 RootServiceHostComponentRequest extends RootServiceComponentRequest{
+
+  private String hostName;
+
+  public RootServiceHostComponentRequest(String serviceName, String hostName, String componentName) {
+    super(serviceName, componentName);
+    this.hostName = hostName;
+  }
+  
+  public String getHostName() {
+    return hostName;
+  }
+
+  public void setHostName(String hostName) {
+    this.hostName = hostName;
+  }
+}

+ 105 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceHostComponentResponse.java

@@ -0,0 +1,105 @@
+/**
+ * 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.Map;
+
+public class RootServiceHostComponentResponse {
+
+  private String hostName;
+  private String componentName;
+  private String componentState;
+  private Map<String, String> properties;
+
+  public RootServiceHostComponentResponse(String hostName, String componentName, String componentState,
+      Map<String, String> properties) {
+    this.hostName = hostName;
+    this.componentName = componentName;
+    this.componentState = componentState;
+    this.properties = properties;
+  }
+
+  public String getHostName() {
+    return hostName;
+  }
+
+  public String getComponentName() {
+    return componentName;
+  }
+
+  public void setComponentName(String componentName) {
+    this.componentName = componentName;
+  }
+
+  public Map<String, String> getProperties() {
+    return properties;
+  }
+
+  public void setProperties(Map<String, String> properties) {
+    this.properties = properties;
+  }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    RootServiceHostComponentResponse that = (RootServiceHostComponentResponse) o;
+
+    if (hostName != null ?
+        !hostName.equals(that.hostName) : that.hostName != null) {
+      return false;
+    }
+    
+    if (componentName != null ?
+        !componentName.equals(that.componentName) : that.componentName != null) {
+      return false;
+    }
+    
+    if (componentState != null ?
+        !componentState.equals(that.componentState) : that.componentState != null) {
+      return false;
+    }
+    
+    if (properties != null ?
+        !properties.equals(that.properties) : that.properties != null) {
+      return false;
+    }
+    
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = 1;
+    result = 31 + (hostName != null ? hostName.hashCode() : 0);
+    result = result + (componentName != null ? componentName.hashCode() : 0);
+    result = result + (componentState != null ? componentState.hashCode() : 0);
+    return result;
+  }
+
+  public String getComponentState() {
+    return componentState;
+  }
+
+  public void setComponentState(String componentState) {
+    this.componentState = componentState;
+  }
+
+}

+ 37 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceRequest.java

@@ -0,0 +1,37 @@
+/**
+ * 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 RootServiceRequest {
+  
+  private String serviceName;
+
+  public RootServiceRequest(String serviceName) {
+    this.serviceName = serviceName;
+  }
+
+  public String getServiceName() {
+    return serviceName;
+  }
+
+  public void setServiceName(String serviceName) {
+    this.serviceName = serviceName;
+  }
+
+}

+ 55 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceResponse.java

@@ -0,0 +1,55 @@
+/**
+ * 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 RootServiceResponse {
+
+  private String serviceName;
+
+  public RootServiceResponse(String serviceName) {
+    this.serviceName = serviceName;
+  }
+
+  public String getServiceName() {
+    return serviceName;
+  }
+  
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    RootServiceResponse that = (RootServiceResponse) o;
+
+    if (serviceName != null ?
+        !serviceName.equals(that.serviceName) : that.serviceName != null) {
+      return false;
+    }
+    
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = 1;
+    result = 31 + (serviceName != null ? serviceName.hashCode() : 0);
+    return result;
+  }
+
+}

+ 188 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceResponseFactory.java

@@ -0,0 +1,188 @@
+/**
+ * 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.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ObjectNotFoundException;
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.utils.StageUtils;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.Predicate;
+import org.apache.commons.lang.ArrayUtils;
+
+import com.google.inject.Inject;
+
+public class RootServiceResponseFactory extends
+    AbstractRootServiceResponseFactory {
+
+  private static final String RUNNING_STATE = "RUNNING";
+  @Inject
+  private Configuration configs;
+  
+  @Override
+  public Set<RootServiceResponse> getRootServices(RootServiceRequest request) throws ObjectNotFoundException {
+    
+    Set<RootServiceResponse> response;
+    
+    String serviceName = null;
+    
+    if (request != null)
+      serviceName = request.getServiceName();
+
+    if (serviceName != null) {
+      Services service;
+      try {
+        service = Services.valueOf(serviceName);
+      }
+      catch (IllegalArgumentException ex) {
+        throw new ObjectNotFoundException("Root service name: " + serviceName);
+      }
+      
+      response = Collections.singleton(new RootServiceResponse(service.toString()));
+    } else {
+      response = new HashSet<RootServiceResponse>();
+      
+      for (Services service: Services.values())    
+        response.add(new RootServiceResponse(service.toString()));
+    }    
+    return response;
+  }
+  
+  @Override
+  public Set<RootServiceComponentResponse> getRootServiceComponents(
+      RootServiceComponentRequest request) throws ObjectNotFoundException {
+    Set<RootServiceComponentResponse> response = new HashSet<RootServiceComponentResponse>();
+    
+    String serviceName = request.getServiceName();
+    String componentName = request.getComponentName();
+    Services service;
+
+    try {
+      service = Services.valueOf(serviceName);
+    }
+    catch (IllegalArgumentException ex) {
+      throw new ObjectNotFoundException("Root service name: " + serviceName);
+    }
+    catch (NullPointerException np) {
+      throw new ObjectNotFoundException("Root service name: null");
+    }
+    
+    if (componentName != null) {
+      Components component;
+      try {
+        component = Components.valueOf(componentName);
+        if (!ArrayUtils.contains(service.getComponents(), component))
+          throw new ObjectNotFoundException("No component name: " + componentName + "in service: " + serviceName);
+      }
+      catch (IllegalArgumentException ex) {
+        throw new ObjectNotFoundException("Component name: " + componentName);
+      }
+      response = Collections.singleton(new RootServiceComponentResponse(component.toString(),
+                                       getComponentProperties(componentName)));
+    } else {
+    
+      for (Components component: service.getComponents())    
+        response.add(new RootServiceComponentResponse(component.toString(),
+                     getComponentProperties(component.name())));
+      }
+    return response;
+  }
+
+  private Map<String, String> getComponentProperties(String componentName){
+    
+    Map<String, String> response;
+    Components component = null;
+
+    if (componentName != null) {
+      component = Components.valueOf(componentName);
+      
+      switch (component) {
+      case AMBARI_SERVER:
+        response = configs.getConfigsMap();
+        break;
+
+      default:
+        response = Collections.emptyMap();
+      }
+    }
+    else
+      response = Collections.emptyMap();
+
+    return response;
+  }
+
+  
+  public enum Services {
+    AMBARI(Components.values());
+    private Components[] components;
+
+    Services(Components[] components) {
+      this.components = components;
+    }
+
+    public Components[] getComponents() {
+      return components;
+    }
+  }
+  
+  public enum Components {
+    AMBARI_SERVER, AMBARI_AGENT
+  }
+
+  @Override
+  public Set<RootServiceHostComponentResponse> getRootServiceHostComponent(RootServiceHostComponentRequest request, Set<HostResponse> hosts) throws AmbariException {
+    Set<RootServiceHostComponentResponse> response = new HashSet<RootServiceHostComponentResponse>();
+
+    Set<RootServiceComponentResponse> rootServiceComponents = 
+        getRootServiceComponents(new RootServiceComponentRequest(request.getServiceName(), request.getComponentName()));
+
+    //Cartesian product with hosts and components
+    for (RootServiceComponentResponse component : rootServiceComponents) {
+      
+      Set<HostResponse> filteredHosts = new HashSet<HostResponse>(hosts);      
+      
+      //Make some filtering of hosts if need
+      if (component.getComponentName().equals(Components.AMBARI_SERVER.name()))
+        CollectionUtils.filter(filteredHosts, new Predicate() {
+          @Override
+          public boolean evaluate(Object arg0) {
+            HostResponse hostResponse = (HostResponse) arg0;
+            return hostResponse.getHostname().equals(StageUtils.getHostName());
+          }
+        });
+      
+      for (HostResponse host : filteredHosts) {
+        
+        if (component.getComponentName().equals(Components.AMBARI_SERVER.name()))
+          response.add(new RootServiceHostComponentResponse(host.getHostname(), component.getComponentName(),
+            RUNNING_STATE, component.getProperties()));
+        else
+          response.add(new RootServiceHostComponentResponse(host.getHostname(), component.getComponentName(),
+            host.getHostState(), component.getProperties()));
+      }
+    }
+    
+    return response;
+  }
+}

+ 6 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java

@@ -119,6 +119,12 @@ public abstract class AbstractControllerResourceProvider extends AbstractResourc
         return new OperatingSystemResourceProvider(propertyIds, keyPropertyIds, managementController);
       case Repository:
         return new RepositoryResourceProvider(propertyIds, keyPropertyIds, managementController);
+      case RootService:
+        return new RootServiceResourceProvider(propertyIds, keyPropertyIds, managementController);
+      case RootServiceComponent:
+        return new RootServiceComponentResourceProvider(propertyIds, keyPropertyIds, managementController);
+      case RootServiceHostComponent:
+        return new RootServiceHostComponentResourceProvider(propertyIds, keyPropertyIds, managementController);
       default:
         throw new IllegalArgumentException("Unknown type " + type);
     }

+ 110 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceComponentResourceProvider.java

@@ -0,0 +1,110 @@
+/**
+ * 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.internal;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.RootServiceComponentRequest;
+import org.apache.ambari.server.controller.RootServiceComponentResponse;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.controller.spi.Resource.Type;
+import org.apache.ambari.server.controller.utilities.PredicateHelper;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+
+public class RootServiceComponentResourceProvider extends
+    ReadOnlyResourceProvider {
+  
+  public static final String SERVICE_NAME_PROPERTY_ID = PropertyHelper
+      .getPropertyId("RootServiceComponents", "service_name");
+  
+  public static final String COMPONENT_NAME_PROPERTY_ID = PropertyHelper
+      .getPropertyId("RootServiceComponents", "component_name");
+  
+  public static final String PROPERTIES_PROPERTY_ID = PropertyHelper
+      .getPropertyId("RootServiceComponents", "properties");
+  
+  private Set<String> pkPropertyIds = new HashSet<String>(
+      Arrays.asList(new String[] { SERVICE_NAME_PROPERTY_ID, COMPONENT_NAME_PROPERTY_ID }));
+
+  protected RootServiceComponentResourceProvider(Set<String> propertyIds,
+      Map<Type, String> keyPropertyIds,
+      AmbariManagementController managementController) {
+    super(propertyIds, keyPropertyIds, managementController);
+  }
+  
+  @Override
+  public Set<Resource> getResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+
+    final RootServiceComponentRequest rootServiceComponentRequest = getRequest(PredicateHelper
+        .getProperties(predicate));
+    Set<String> requestedIds = getRequestPropertyIds(request, predicate);
+
+    Set<RootServiceComponentResponse> responses = getResources(new Command<Set<RootServiceComponentResponse>>() {
+      @Override
+      public Set<RootServiceComponentResponse> invoke() throws AmbariException {
+        return getManagementController().getRootServiceComponents(
+            Collections.singleton(rootServiceComponentRequest));
+      }
+    });
+
+    Set<Resource> resources = new HashSet<Resource>();
+
+    for (RootServiceComponentResponse response : responses) {
+      Resource resource = new ResourceImpl(Resource.Type.RootServiceComponent);
+
+      setResourceProperty(resource, SERVICE_NAME_PROPERTY_ID,
+          rootServiceComponentRequest.getServiceName(), requestedIds);
+      
+      setResourceProperty(resource, COMPONENT_NAME_PROPERTY_ID,
+          response.getComponentName(), requestedIds);
+      
+      setResourceProperty(resource, PROPERTIES_PROPERTY_ID,
+          response.getProperties(), requestedIds);
+
+      resources.add(resource);
+    }
+
+    return resources;
+  }
+
+  private RootServiceComponentRequest getRequest(Map<String, Object> properties) {
+    return new RootServiceComponentRequest((String) properties.get(SERVICE_NAME_PROPERTY_ID),
+                                           (String) properties.get(COMPONENT_NAME_PROPERTY_ID));
+  }
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return pkPropertyIds;
+  }
+
+}

+ 121 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceHostComponentResourceProvider.java

@@ -0,0 +1,121 @@
+/**
+ * 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.internal;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.RootServiceHostComponentRequest;
+import org.apache.ambari.server.controller.RootServiceHostComponentResponse;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.controller.spi.Resource.Type;
+import org.apache.ambari.server.controller.utilities.PredicateHelper;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+
+public class RootServiceHostComponentResourceProvider extends
+    ReadOnlyResourceProvider {
+  
+  public static final String SERVICE_NAME_PROPERTY_ID = PropertyHelper
+      .getPropertyId("RootServiceHostComponents", "service_name");
+  public static final String HOST_NAME_PROPERTY_ID = PropertyHelper
+      .getPropertyId("RootServiceHostComponents", "host_name");
+  public static final String COMPONENT_NAME_PROPERTY_ID = PropertyHelper
+      .getPropertyId("RootServiceHostComponents", "component_name");
+  public static final String COMPONENT_STATE_PROPERTY_ID = PropertyHelper
+      .getPropertyId("RootServiceHostComponents", "component_state");
+  public static final String PROPERTIES_PROPERTY_ID = PropertyHelper
+      .getPropertyId("RootServiceHostComponents", "properties");
+  
+  
+  private Set<String> pkPropertyIds = new HashSet<String>(
+      Arrays.asList(new String[] { SERVICE_NAME_PROPERTY_ID, HOST_NAME_PROPERTY_ID, COMPONENT_NAME_PROPERTY_ID }));
+
+
+  public RootServiceHostComponentResourceProvider(Set<String> propertyIds,
+      Map<Type, String> keyPropertyIds,
+      AmbariManagementController managementController) {
+    super(propertyIds, keyPropertyIds, managementController);
+  }
+
+  
+  @Override
+  public Set<Resource> getResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+
+    final RootServiceHostComponentRequest rootServiceComponentRequest = getRequest(PredicateHelper.getProperties(predicate));
+    Set<String> requestedIds = getRequestPropertyIds(request, predicate);
+
+    Set<RootServiceHostComponentResponse> responses = getResources(new Command<Set<RootServiceHostComponentResponse>>() {
+      @Override
+      public Set<RootServiceHostComponentResponse> invoke() throws AmbariException {
+        return getManagementController().getRootServiceHostComponents(
+            Collections.singleton(rootServiceComponentRequest));
+      }
+    });
+
+    Set<Resource> resources = new HashSet<Resource>();
+
+    for (RootServiceHostComponentResponse response : responses) {
+      Resource resource = new ResourceImpl(Resource.Type.RootServiceHostComponent);
+
+      setResourceProperty(resource, SERVICE_NAME_PROPERTY_ID,
+          rootServiceComponentRequest.getServiceName(), requestedIds);
+      
+      setResourceProperty(resource, HOST_NAME_PROPERTY_ID,
+          response.getHostName(), requestedIds);
+      
+      setResourceProperty(resource, COMPONENT_NAME_PROPERTY_ID,
+          response.getComponentName(), requestedIds);
+      
+      setResourceProperty(resource, COMPONENT_STATE_PROPERTY_ID,
+          response.getComponentState(), requestedIds);
+      
+      setResourceProperty(resource, PROPERTIES_PROPERTY_ID,
+          response.getProperties(), requestedIds);
+
+      resources.add(resource);
+    }
+
+    return resources;
+  }
+  
+  private RootServiceHostComponentRequest getRequest(Map<String, Object> properties) {
+    return new RootServiceHostComponentRequest((String) properties.get(SERVICE_NAME_PROPERTY_ID),
+                                               (String) properties.get(HOST_NAME_PROPERTY_ID),
+                                               (String) properties.get(COMPONENT_NAME_PROPERTY_ID));
+  }
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return pkPropertyIds;
+  }
+
+}

+ 96 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RootServiceResourceProvider.java

@@ -0,0 +1,96 @@
+/**
+ * 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.internal;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.RootServiceRequest;
+import org.apache.ambari.server.controller.RootServiceResponse;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.controller.spi.Resource.Type;
+import org.apache.ambari.server.controller.utilities.PredicateHelper;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+
+public class RootServiceResourceProvider extends ReadOnlyResourceProvider {
+  
+  public static final String SERVICE_NAME_PROPERTY_ID = PropertyHelper
+      .getPropertyId("RootService", "service_name");
+
+  private Set<String> pkPropertyIds = new HashSet<String>(
+      Arrays.asList(new String[] { SERVICE_NAME_PROPERTY_ID }));
+
+  protected RootServiceResourceProvider(Set<String> propertyIds,
+      Map<Type, String> keyPropertyIds,
+      AmbariManagementController managementController) {
+    super(propertyIds, keyPropertyIds, managementController);
+  }
+  
+  @Override
+  public Set<Resource> getResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+
+    final RootServiceRequest ambariServiceRequest = getRequest(PredicateHelper
+        .getProperties(predicate));
+    Set<String> requestedIds = getRequestPropertyIds(request, predicate);
+
+    Set<RootServiceResponse> responses = getResources(new Command<Set<RootServiceResponse>>() {
+      @Override
+      public Set<RootServiceResponse> invoke() throws AmbariException {
+        return getManagementController().getRootServices(
+            Collections.singleton(ambariServiceRequest));
+      }
+    });
+
+    Set<Resource> resources = new HashSet<Resource>();
+
+    for (RootServiceResponse response : responses) {
+      Resource resource = new ResourceImpl(Resource.Type.RootService);
+
+      setResourceProperty(resource, SERVICE_NAME_PROPERTY_ID,
+          response.getServiceName(), requestedIds);
+
+      resources.add(resource);
+    }
+
+    return resources;
+  }
+
+  private RootServiceRequest getRequest(Map<String, Object> properties) {
+    return new RootServiceRequest((String) properties.get(SERVICE_NAME_PROPERTY_ID));
+  }
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return pkPropertyIds ;
+  }
+
+}

+ 4 - 1
ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java

@@ -92,6 +92,9 @@ public interface Resource {
     DRInstance,
     Workflow,
     Job,
-    TaskAttempt
+    TaskAttempt,
+    RootService,
+    RootServiceComponent,
+    RootServiceHostComponent
   }
 }

+ 13 - 0
ambari-server/src/main/resources/key_properties.json

@@ -87,5 +87,18 @@
   "DRInstance":{
     "DRFeed":"Instance/feedName",
     "DRInstance":"Instance/id"
+  },
+  "RootService":{
+    "RootService":"RootService/service_name"
+  },
+  "RootServiceComponent":{
+    "RootService":"RootServiceComponents/service_name",
+    "RootServiceComponent":"RootServiceComponents/component_name"
+  },
+  "RootServiceHostComponent":{
+    "RootService":"RootServiceHostComponents/service_name",
+    "Host":"RootServiceHostComponents/host_name",
+    "RootServiceComponent":"RootServiceHostComponents/component_name",
+    "RootServiceHostComponent":"RootServiceHostComponents/component_name"
   }
 }

+ 15 - 0
ambari-server/src/main/resources/properties.json

@@ -238,5 +238,20 @@
         "TaskAttempt/output_bytes",
         "TaskAttempt/status",
         "TaskAttempt/locality"
+     ],
+     "RootService":[
+        "RootService/service_name"
+     ],
+    "RootServiceComponent":[
+        "RootServiceComponents/service_name",
+        "RootServiceComponents/component_name",
+        "RootServiceComponents/properties"
+     ],
+    "RootServiceHostComponent":[
+        "RootServiceHostComponents/service_name",
+        "RootServiceHostComponents/component_name",
+        "RootServiceHostComponents/host_name",
+        "RootServiceHostComponents/component_state",
+        "RootServiceHostComponents/properties"
      ]
 }

+ 145 - 0
ambari-server/src/test/java/org/apache/ambari/server/api/services/RootServiceServiceTest.java

@@ -0,0 +1,145 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.services;
+
+import static org.junit.Assert.assertEquals;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.api.services.parsers.RequestBodyParser;
+import org.apache.ambari.server.api.services.serializers.ResultSerializer;
+
+/**
+* Unit tests for RootServiceService.
+*/
+public class RootServiceServiceTest extends BaseServiceTest {
+
+  @Override
+  public List<ServiceTestInvocation> getTestInvocations() throws Exception {
+    List<ServiceTestInvocation> listInvocations = new ArrayList<ServiceTestInvocation>();
+    
+    //getServices
+    RootServiceService service = new TestRootServiceService(null, null, null);
+    Method m = service.getClass().getMethod("getServices", HttpHeaders.class, UriInfo.class);
+    Object[] args = new Object[] {getHttpHeaders(), getUriInfo()};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, service, m, args, null));
+    
+    //getService
+    service = new TestRootServiceService("AMBARI", null, null);
+    m = service.getClass().getMethod("getService", HttpHeaders.class, UriInfo.class, String.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo(), "AMBARI"};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, service, m, args, null));
+    
+    //getServiceComponents
+    service = new TestRootServiceService("AMBARI", null, null);
+    m = service.getClass().getMethod("getServiceComponents", HttpHeaders.class, UriInfo.class, String.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo(), "AMBARI"};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, service, m, args, null));
+    
+    //getServiceComponent
+    service = new TestRootServiceService("AMBARI", "AMBARI_SERVER", null);
+    m = service.getClass().getMethod("getServiceComponent", HttpHeaders.class, UriInfo.class, String.class, String.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo(), "AMBARI", "AMBARI_SERVER"};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, service, m, args, null));
+    
+    //getRootHostComponents
+    service = new TestRootServiceService("AMBARI", "AMBARI_SERVER", null);
+    m = service.getClass().getMethod("getRootHostComponents", HttpHeaders.class, UriInfo.class, String.class, String.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo(), "AMBARI", "AMBARI_SERVER"};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, service, m, args, null));
+    
+    //getRootHosts
+    service = new TestRootServiceService("AMBARI", "AMBARI_SERVER", null);
+    m = service.getClass().getMethod("getRootHosts", HttpHeaders.class, UriInfo.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo()};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, service, m, args, null));
+    
+    //getRootHost
+    service = new TestRootServiceService("AMBARI", "AMBARI_SERVER", "host1");
+    m = service.getClass().getMethod("getRootHost", HttpHeaders.class, UriInfo.class, String.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo(), "host1"};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, service, m, args, null));
+    
+    
+    return listInvocations;
+  }
+  
+  private class TestRootServiceService extends RootServiceService {
+
+    private String m_serviceName;
+    private String m_componentName;
+    private String m_hostName;
+
+    private TestRootServiceService(String serviceName, String componentName, String hostName) {
+      m_serviceName = serviceName;
+      m_componentName = componentName;
+      m_hostName = hostName;
+    }
+
+    @Override
+    protected ResourceInstance createServiceResource(String serviceName) {
+      assertEquals(m_serviceName, serviceName);
+      return getTestResource();
+    }
+    
+    @Override
+    protected ResourceInstance createServiceComponentResource(String serviceName, String componentName) {
+      assertEquals(m_serviceName, serviceName);
+      assertEquals(m_componentName, componentName);
+      return getTestResource();
+    }
+
+    @Override
+    protected ResourceInstance createHostComponentResource(String serviceName, String hostName, String componentName) {
+      assertEquals(m_serviceName, serviceName);
+      assertEquals(m_hostName, hostName);
+      assertEquals(m_componentName, componentName);
+      return getTestResource();
+    }
+    
+    @Override
+    protected ResourceInstance createHostResource(String hostName) {
+      assertEquals(m_hostName, hostName);
+      return getTestResource();
+    }
+    
+    
+    @Override
+    RequestFactory getRequestFactory() {
+      return getTestRequestFactory();
+    }
+
+    @Override
+    protected RequestBodyParser getBodyParser() {
+      return getTestBodyParser();
+    }
+
+    @Override
+    protected ResultSerializer getResultSerializer() {
+      return getTestResultSerializer();
+    }
+  }
+
+}

+ 1 - 1
ambari-server/src/test/java/org/apache/ambari/server/api/services/ServiceServiceTest.java

@@ -45,7 +45,7 @@ public class ServiceServiceTest extends BaseServiceTest {
     Object[] args = new Object[] {getHttpHeaders(), getUriInfo(), "serviceName"};
     listInvocations.add(new ServiceTestInvocation(Request.Type.GET, service, m, args, null));
 
-    //getService
+    //getServices
     service = new TestServiceService("clusterName", null);
     m = service.getClass().getMethod("getServices", HttpHeaders.class, UriInfo.class);
     args = new Object[] {getHttpHeaders(), getUriInfo()};

+ 48 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java

@@ -122,6 +122,8 @@ public class AmbariManagementControllerTest {
   
   private static final String REQUEST_CONTEXT_PROPERTY = "context";
 
+  private static final int CONFIG_MAP_CNT = 21;
+
   private AmbariManagementController controller;
   private Clusters clusters;
   private ActionDBAccessor actionDB;
@@ -6989,4 +6991,50 @@ public class AmbariManagementControllerTest {
 
   }
   
+  @Test
+  public void testGetRootServices() throws Exception {
+
+    RootServiceRequest request = new RootServiceRequest(null);
+    Set<RootServiceResponse> responses = controller.getRootServices(Collections.singleton(request));
+    Assert.assertEquals(RootServiceResponseFactory.Services.values().length, responses.size());
+
+    RootServiceRequest requestWithParams = new RootServiceRequest(RootServiceResponseFactory.Services.AMBARI.toString());
+    Set<RootServiceResponse> responsesWithParams = controller.getRootServices(Collections.singleton(requestWithParams));
+    Assert.assertEquals(1, responsesWithParams.size());
+    for (RootServiceResponse responseWithParams: responsesWithParams) {
+      Assert.assertEquals(responseWithParams.getServiceName(), RootServiceResponseFactory.Services.AMBARI.toString());
+    }
+
+    RootServiceRequest invalidRequest = new RootServiceRequest(NON_EXT_VALUE);
+    try {
+      controller.getRootServices(Collections.singleton(invalidRequest));
+    } catch (ObjectNotFoundException e) {
+      Assert.assertTrue(e instanceof ObjectNotFoundException);
+    }
+  }
+  
+  @Test
+  public void testGetRootServiceComponents() throws Exception {
+
+    RootServiceComponentRequest request = new RootServiceComponentRequest(RootServiceResponseFactory.Services.AMBARI.toString(), null);
+    Set<RootServiceComponentResponse> responses = controller.getRootServiceComponents(Collections.singleton(request));
+    Assert.assertEquals(RootServiceResponseFactory.Services.AMBARI.getComponents().length, responses.size());
+
+    RootServiceComponentRequest requestWithParams = new RootServiceComponentRequest(
+        RootServiceResponseFactory.Services.AMBARI.toString(),
+        RootServiceResponseFactory.Services.AMBARI.getComponents()[0].toString());
+    
+    Set<RootServiceComponentResponse> responsesWithParams = controller.getRootServiceComponents(Collections.singleton(requestWithParams));
+    Assert.assertEquals(1, responsesWithParams.size());
+    for (RootServiceComponentResponse responseWithParams: responsesWithParams) {
+      Assert.assertEquals(responseWithParams.getComponentName(), RootServiceResponseFactory.Services.AMBARI.getComponents()[0].toString());
+    }
+
+    RootServiceComponentRequest invalidRequest = new RootServiceComponentRequest(NON_EXT_VALUE, NON_EXT_VALUE);
+    try {
+      controller.getRootServiceComponents(Collections.singleton(invalidRequest));
+    } catch (ObjectNotFoundException e) {
+      Assert.assertTrue(e instanceof ObjectNotFoundException);
+    }
+  }
 }

+ 156 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/RootServiceResponseFactoryTest.java

@@ -0,0 +1,156 @@
+/**
+ * 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.Collections;
+import java.util.Set;
+import org.apache.ambari.server.ObjectNotFoundException;
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.controller.RootServiceResponseFactory.Components;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.junit.Before;
+import org.junit.Test;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.assertEquals;
+
+public class RootServiceResponseFactoryTest {
+
+  private RootServiceResponseFactory responseFactory;
+  private Injector injector;
+  private Configuration configs;
+
+  @Before
+  public void setUp() {
+    injector = Guice.createInjector(new InMemoryDefaultTestModule());
+    responseFactory = injector.getInstance(RootServiceResponseFactory.class);
+    configs = injector.getInstance(Configuration.class);
+  }
+
+  @Test
+  public void testGetRootServices() throws Exception {
+
+    // Request a null service name
+    RootServiceRequest request = new RootServiceRequest(null);
+    Set<RootServiceResponse> rootServices =
+        responseFactory.getRootServices(request);
+    assertEquals(RootServiceResponseFactory.Services.values().length,
+        rootServices.size());
+
+    // null request
+    request = null;
+    rootServices = responseFactory.getRootServices(request);
+    assertEquals(RootServiceResponseFactory.Services.values().length,
+        rootServices.size());
+
+    // Request nonexistent service
+    try {
+      request = new RootServiceRequest("XXX");
+      ;
+      rootServices = responseFactory.getRootServices(request);
+    } catch (Exception e) {
+      assertTrue(e instanceof ObjectNotFoundException);
+    }
+
+    // Request existent service
+    request =
+        new RootServiceRequest(
+            RootServiceResponseFactory.Services.AMBARI.name());
+    ;
+    rootServices = responseFactory.getRootServices(request);
+    assertEquals(1, rootServices.size());
+    assertTrue(rootServices.contains(new RootServiceResponse(
+        RootServiceResponseFactory.Services.AMBARI.name())));
+  }
+
+  @Test
+  public void testGetRootServiceComponents() throws Exception {
+
+    // Request null service name, null component name
+    RootServiceComponentRequest request =
+        new RootServiceComponentRequest(null, null);
+    Set<RootServiceComponentResponse> rootServiceComponents;
+    try {
+      rootServiceComponents = responseFactory.getRootServiceComponents(request);
+    } catch (Exception e) {
+      assertTrue(e instanceof ObjectNotFoundException);
+    }
+
+    // Request null service name, not-null component name
+    request =
+        new RootServiceComponentRequest(null,
+            RootServiceResponseFactory.Components.AMBARI_SERVER.name());
+
+    try {
+      rootServiceComponents = responseFactory.getRootServiceComponents(request);
+    } catch (Exception e) {
+      assertTrue(e instanceof ObjectNotFoundException);
+    }
+
+    // Request existent service name, null component name
+    request =
+        new RootServiceComponentRequest(
+            RootServiceResponseFactory.Services.AMBARI.name(), null);
+    rootServiceComponents = responseFactory.getRootServiceComponents(request);
+    assertEquals(
+        RootServiceResponseFactory.Services.AMBARI.getComponents().length,
+        rootServiceComponents.size());
+
+    for (int i = 0; i < RootServiceResponseFactory.Services.AMBARI
+        .getComponents().length; i++) {
+      Components component =
+          RootServiceResponseFactory.Services.AMBARI.getComponents()[i];
+
+      if (component.name().equals(
+          RootServiceResponseFactory.Components.AMBARI_SERVER.name()))
+        assertTrue(rootServiceComponents
+            .contains(new RootServiceComponentResponse(component.name(),
+                configs.getConfigsMap())));
+      else
+        assertTrue(rootServiceComponents
+            .contains(new RootServiceComponentResponse(component.name(),
+                Collections.<String, String> emptyMap())));
+    }
+
+    // Request existent service name, existent component name
+    request =
+        new RootServiceComponentRequest(
+            RootServiceResponseFactory.Services.AMBARI.name(),
+            RootServiceResponseFactory.Services.AMBARI.getComponents()[0]
+                .name());
+    rootServiceComponents = responseFactory.getRootServiceComponents(request);
+    assertEquals(1, rootServiceComponents.size());
+    assertTrue(rootServiceComponents.contains(new RootServiceComponentResponse(
+        RootServiceResponseFactory.Services.AMBARI.getComponents()[0].name(),
+        configs.getConfigsMap())));
+    
+    // Request existent service name, and component, not belongs to requested service
+    request =
+        new RootServiceComponentRequest(
+            RootServiceResponseFactory.Services.AMBARI.name(),
+            "XXX");
+    try {
+      rootServiceComponents = responseFactory.getRootServiceComponents(request);
+    } catch (Exception e) {
+      assertTrue(e instanceof ObjectNotFoundException);
+    }
+  }
+}

+ 105 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RootServiceComponentResourceProviderTest.java

@@ -0,0 +1,105 @@
+/**
+ * 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.internal;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.RootServiceComponentRequest;
+import org.apache.ambari.server.controller.RootServiceComponentResponse;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class RootServiceComponentResourceProviderTest {
+  
+  @Test
+  public void testGetResources() throws Exception{
+    Resource.Type type = Resource.Type.RootServiceComponent;
+
+    AmbariManagementController managementController = createMock(AmbariManagementController.class);
+
+    Set<RootServiceComponentResponse> allResponse = new HashSet<RootServiceComponentResponse>();
+    allResponse.add(new RootServiceComponentResponse("component1", Collections.<String,String>emptyMap()));
+    allResponse.add(new RootServiceComponentResponse("component2", Collections.<String,String>emptyMap()));
+    allResponse.add(new RootServiceComponentResponse("component3", Collections.<String,String>emptyMap()));
+
+    Set<RootServiceComponentResponse> nameResponse = new HashSet<RootServiceComponentResponse>();
+    nameResponse.add(new RootServiceComponentResponse("component4", Collections.<String,String>emptyMap()));
+
+
+    // set expectations
+    expect(managementController.getRootServiceComponents(EasyMock.<Set<RootServiceComponentRequest>>anyObject())).andReturn(allResponse).once();
+    expect(managementController.getRootServiceComponents(EasyMock.<Set<RootServiceComponentRequest>>anyObject())).andReturn(nameResponse).once();
+    // replay
+    replay(managementController);
+
+    ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
+        type,
+        PropertyHelper.getPropertyIds(type),
+        PropertyHelper.getKeyPropertyIds(type),
+        managementController);
+
+    Set<String> propertyIds = new HashSet<String>();
+
+    propertyIds.add(RootServiceComponentResourceProvider.SERVICE_NAME_PROPERTY_ID);
+    propertyIds.add(RootServiceComponentResourceProvider.COMPONENT_NAME_PROPERTY_ID);
+    propertyIds.add(RootServiceComponentResourceProvider.PROPERTIES_PROPERTY_ID);
+
+    // create the request
+    Request request = PropertyHelper.getReadRequest(propertyIds);
+
+    // get all ... no predicate
+    Set<Resource> resources = provider.getResources(request, null);
+
+    Assert.assertEquals(allResponse.size(), resources.size());
+    for (Resource resource : resources) {
+      String componentName = (String) resource.getPropertyValue(RootServiceComponentResourceProvider.COMPONENT_NAME_PROPERTY_ID);
+      Assert.assertTrue(allResponse.contains(new RootServiceComponentResponse(componentName, Collections.<String,String>emptyMap())));
+    }
+
+    // get service named service4
+    Predicate predicate =
+        new PredicateBuilder().property(RootServiceComponentResourceProvider.COMPONENT_NAME_PROPERTY_ID).
+        equals("component4").toPredicate();
+    resources = provider.getResources(request, predicate);
+
+    Assert.assertEquals(1, resources.size());
+    Assert.assertEquals("component4", resources.iterator().next().
+        getPropertyValue(RootServiceComponentResourceProvider.COMPONENT_NAME_PROPERTY_ID));
+
+
+    // verify
+    verify(managementController);
+  }
+
+}

+ 112 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RootServiceHostComponentResourceProviderTest.java

@@ -0,0 +1,112 @@
+/**
+ * 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.internal;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.RootServiceHostComponentRequest;
+import org.apache.ambari.server.controller.RootServiceHostComponentResponse;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class RootServiceHostComponentResourceProviderTest {
+  
+  @Test
+  public void testGetResources() throws Exception{
+    Resource.Type type = Resource.Type.RootServiceHostComponent;
+
+    AmbariManagementController managementController = createMock(AmbariManagementController.class);
+
+    Set<RootServiceHostComponentResponse> allResponse = new HashSet<RootServiceHostComponentResponse>();
+    allResponse.add(new RootServiceHostComponentResponse("host1", "component1", "HEALTHY", Collections.<String,String>emptyMap()));
+    allResponse.add(new RootServiceHostComponentResponse("host2", "component2", "HEALTHY", Collections.<String,String>emptyMap()));
+    allResponse.add(new RootServiceHostComponentResponse("host3", "component3", "HEARBEAT_LOST", Collections.<String,String>emptyMap()));
+
+    Set<RootServiceHostComponentResponse> nameResponse = new HashSet<RootServiceHostComponentResponse>();
+    nameResponse.add(new RootServiceHostComponentResponse("host4", "component4", "HEALTHY", Collections.<String,String>emptyMap()));
+
+
+    // set expectations
+    expect(managementController.getRootServiceHostComponents(EasyMock.<Set<RootServiceHostComponentRequest>>anyObject())).andReturn(allResponse).once();
+    expect(managementController.getRootServiceHostComponents(EasyMock.<Set<RootServiceHostComponentRequest>>anyObject())).andReturn(nameResponse).once();
+    // replay
+    replay(managementController);
+
+    ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
+        type,
+        PropertyHelper.getPropertyIds(type),
+        PropertyHelper.getKeyPropertyIds(type),
+        managementController);
+
+    Set<String> propertyIds = new HashSet<String>();
+
+    propertyIds.add(RootServiceHostComponentResourceProvider.SERVICE_NAME_PROPERTY_ID);
+    propertyIds.add(RootServiceHostComponentResourceProvider.HOST_NAME_PROPERTY_ID);
+    propertyIds.add(RootServiceHostComponentResourceProvider.COMPONENT_NAME_PROPERTY_ID);
+    propertyIds.add(RootServiceHostComponentResourceProvider.COMPONENT_STATE_PROPERTY_ID);
+    propertyIds.add(RootServiceHostComponentResourceProvider.PROPERTIES_PROPERTY_ID);
+    
+    
+    // create the request
+    Request request = PropertyHelper.getReadRequest(propertyIds);
+
+    // get all ... no predicate
+    Set<Resource> resources = provider.getResources(request, null);
+
+    Assert.assertEquals(allResponse.size(), resources.size());
+    for (Resource resource : resources) {
+      String hostName = (String) resource.getPropertyValue(RootServiceHostComponentResourceProvider.HOST_NAME_PROPERTY_ID);
+      String componentName = (String) resource.getPropertyValue(RootServiceHostComponentResourceProvider.COMPONENT_NAME_PROPERTY_ID);
+      String componentState = (String) resource.getPropertyValue(RootServiceHostComponentResourceProvider.COMPONENT_STATE_PROPERTY_ID);
+      Assert.assertTrue(allResponse.contains(new RootServiceHostComponentResponse(hostName, componentName, componentState,
+          Collections.<String, String>emptyMap())));
+    }
+
+    // get service named service4
+    Predicate predicate =
+        new PredicateBuilder().property(RootServiceHostComponentResourceProvider.COMPONENT_NAME_PROPERTY_ID).
+        equals("component4").toPredicate();
+    resources = provider.getResources(request, predicate);
+
+    Assert.assertEquals(1, resources.size());
+    Assert.assertEquals("component4", resources.iterator().next().
+        getPropertyValue(RootServiceHostComponentResourceProvider.COMPONENT_NAME_PROPERTY_ID));
+
+
+    // verify
+    verify(managementController);
+  }
+
+}

+ 102 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RootServiceResourceProviderTest.java

@@ -0,0 +1,102 @@
+/**
+ * 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.internal;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.RootServiceRequest;
+import org.apache.ambari.server.controller.RootServiceResponse;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class RootServiceResourceProviderTest {
+  
+  @Test
+  public void testGetResources() throws Exception{
+    Resource.Type type = Resource.Type.RootService;
+
+    AmbariManagementController managementController = createMock(AmbariManagementController.class);
+
+    Set<RootServiceResponse> allResponse = new HashSet<RootServiceResponse>();
+    allResponse.add(new RootServiceResponse("service1"));
+    allResponse.add(new RootServiceResponse("service2"));
+    allResponse.add(new RootServiceResponse("service3"));
+
+    Set<RootServiceResponse> nameResponse = new HashSet<RootServiceResponse>();
+    nameResponse.add(new RootServiceResponse("service4"));
+
+
+    // set expectations
+    expect(managementController.getRootServices(EasyMock.<Set<RootServiceRequest>>anyObject())).andReturn(allResponse).once();
+    expect(managementController.getRootServices(EasyMock.<Set<RootServiceRequest>>anyObject())).andReturn(nameResponse).once();
+    // replay
+    replay(managementController);
+
+    ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
+        type,
+        PropertyHelper.getPropertyIds(type),
+        PropertyHelper.getKeyPropertyIds(type),
+        managementController);
+
+    Set<String> propertyIds = new HashSet<String>();
+
+    propertyIds.add(RootServiceResourceProvider.SERVICE_NAME_PROPERTY_ID);
+
+    // create the request
+    Request request = PropertyHelper.getReadRequest(propertyIds);
+
+    // get all ... no predicate
+    Set<Resource> resources = provider.getResources(request, null);
+
+    Assert.assertEquals(allResponse.size(), resources.size());
+    for (Resource resource : resources) {
+      String serviceName = (String) resource.getPropertyValue(RootServiceResourceProvider.SERVICE_NAME_PROPERTY_ID);
+      Assert.assertTrue(allResponse.contains(new RootServiceResponse(serviceName)));
+    }
+
+    // get service named service4
+    Predicate predicate =
+        new PredicateBuilder().property(RootServiceResourceProvider.SERVICE_NAME_PROPERTY_ID).
+        equals("service4").toPredicate();
+    resources = provider.getResources(request, predicate);
+
+    Assert.assertEquals(1, resources.size());
+    Assert.assertEquals("service4", resources.iterator().next().
+        getPropertyValue(RootServiceResourceProvider.SERVICE_NAME_PROPERTY_ID));
+
+
+    // verify
+    verify(managementController);
+  }
+
+}