You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by nc...@apache.org on 2014/11/20 15:29:25 UTC

[2/2] ambari git commit: AMBARI-8353. Repository Version Management - Create subresource for hosts and clusters (Yurii Shylov via ncole)

AMBARI-8353. Repository Version Management - Create subresource for hosts and clusters (Yurii Shylov via ncole)


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

Branch: refs/heads/trunk
Commit: 2f00656c824390bbebb9a3441d3839c37427f3bc
Parents: d5d9a9d
Author: Nate Cole <nc...@hortonworks.com>
Authored: Thu Nov 20 09:29:01 2014 -0500
Committer: Nate Cole <nc...@hortonworks.com>
Committed: Thu Nov 20 09:29:01 2014 -0500

----------------------------------------------------------------------
 .../resources/ClusterResourceDefinition.java    |   1 +
 ...ComponentStackVersionResourceDefinition.java |  39 ++++
 .../api/resources/HostResourceDefinition.java   |   1 +
 .../resources/ResourceInstanceFactoryImpl.java  |   8 +
 .../server/api/services/ClusterService.java     |  18 ++
 .../services/ClusterStackVersionService.java    | 100 ++++++++++
 .../ambari/server/api/services/HostService.java |  17 ++
 .../api/services/HostStackVersionService.java   |  99 ++++++++++
 .../controller/ResourceProviderFactory.java     |   2 +-
 .../AbstractControllerResourceProvider.java     |   2 +-
 .../ClusterStackVersionResourceProvider.java    | 196 +++++++++++++++++++
 .../internal/DefaultProviderModule.java         |   4 +
 .../HostStackVersionResourceProvider.java       | 175 +++++++++++++++++
 .../internal/StackVersionResourceProvider.java  |   8 +-
 .../ambari/server/controller/spi/Resource.java  |   4 +
 .../server/orm/dao/ClusterVersionDAO.java       |  30 ++-
 .../ambari/server/orm/dao/HostVersionDAO.java   |  30 ++-
 .../orm/entities/ClusterVersionEntity.java      |  15 +-
 .../server/orm/entities/HostVersionEntity.java  |  15 +-
 .../server/state/ClusterVersionState.java       |  81 --------
 .../server/state/RepositoryVersionState.java    |  81 ++++++++
 .../ClusterResourceDefinitionTest.java          |   3 +-
 ...onentStackVersionResourceDefinitionTest.java |  48 +++++
 .../resources/HostResourceDefinitionTest.java   |  63 ++++++
 ...RepositoryVersionResourceDefinitionTest.java |  12 +-
 .../ClusterStackVersionServiceTest.java         |  86 ++++++++
 .../services/HostStackVersionServiceTest.java   |  86 ++++++++
 .../RepositoryVersionResourceProviderTest.java  |  13 +-
 .../server/orm/dao/ClusterVersionDAOTest.java   |  93 +++++----
 .../server/orm/dao/HostVersionDAOTest.java      |  73 ++++---
 30 files changed, 1203 insertions(+), 200 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java
index ef907c0..44a06c5 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java
@@ -69,6 +69,7 @@ public class ClusterResourceDefinition extends BaseResourceDefinition {
     setChildren.add(new SubResourceDefinition(Resource.Type.ClusterPrivilege));
     setChildren.add(new SubResourceDefinition(Resource.Type.AlertDefinition));
     setChildren.add(new SubResourceDefinition(Resource.Type.Alert));
+    setChildren.add(new SubResourceDefinition(Resource.Type.ClusterStackVersion));
 
     return setChildren;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ComponentStackVersionResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ComponentStackVersionResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ComponentStackVersionResourceDefinition.java
new file mode 100644
index 0000000..3d00c82
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ComponentStackVersionResourceDefinition.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.api.resources;
+
+import org.apache.ambari.server.controller.spi.Resource;
+
+/**
+ * Stack Version Resource Definition for hosts and clusters.
+ */
+public class ComponentStackVersionResourceDefinition extends BaseResourceDefinition {
+  public ComponentStackVersionResourceDefinition(Resource.Type type) {
+    super(type);
+  }
+
+  @Override
+  public String getPluralName() {
+    return "stack_versions";
+  }
+
+  @Override
+  public String getSingularName() {
+    return "stack_version";
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostResourceDefinition.java
index 14ed799..380e751 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostResourceDefinition.java
@@ -51,6 +51,7 @@ public class HostResourceDefinition extends BaseResourceDefinition {
     Set<SubResourceDefinition> subs = new HashSet<SubResourceDefinition>();
     subs.add(new SubResourceDefinition(Resource.Type.HostComponent));
     subs.add(new SubResourceDefinition(Resource.Type.Alert));
+    subs.add(new SubResourceDefinition(Resource.Type.HostStackVersion));
     return subs;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
index 9ad37ec..ba3f32f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
@@ -309,6 +309,14 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
         resourceDefinition = new RepositoryVersionResourceDefinition();
         break;
 
+      case HostStackVersion:
+        resourceDefinition = new ComponentStackVersionResourceDefinition(Resource.Type.HostStackVersion);
+        break;
+
+      case ClusterStackVersion:
+        resourceDefinition = new ComponentStackVersionResourceDefinition(Resource.Type.ClusterStackVersion);
+        break;
+
       case Upgrade:
         resourceDefinition = new UpgradeResourceDefinition();
         break;

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
index f75ae11..e950d57 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
@@ -413,6 +413,24 @@ public class ClusterService extends BaseService {
   }
 
   /**
+   * Gets the cluster stack versions service.
+   *
+   * @param request
+   *          the request
+   * @param clusterName
+   *          the cluster name
+   *
+   * @return the cluster stack versions service
+   */
+  @Path("{clusterName}/stack_versions")
+  public ClusterStackVersionService getClusterStackVersionService(@Context javax.ws.rs.core.Request request,
+      @PathParam("clusterName") String clusterName) {
+
+    hasPermission(Request.Type.valueOf(request.getMethod()), clusterName);
+    return new ClusterStackVersionService(clusterName);
+  }
+
+  /**
    * Gets the services for upgrades.
    *
    * @param request the request

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterStackVersionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterStackVersionService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterStackVersionService.java
new file mode 100644
index 0000000..ed94877
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterStackVersionService.java
@@ -0,0 +1,100 @@
+/**
+ * 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.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;
+
+/**
+ * Service responsible for cluster stack version requests.
+ */
+public class ClusterStackVersionService extends BaseService {
+  /**
+   * Name of the cluster.
+   */
+  private String clusterName;
+
+  /**
+   * Constructor.
+   *
+   * @param clusterName name of the cluster
+   */
+  public ClusterStackVersionService(String clusterName) {
+    this.clusterName = clusterName;
+  }
+
+  /**
+   * Gets all cluster stack version.
+   * Handles: GET /clusters/{clustername}/stack_versions requests.
+   *
+   * @param headers http headers
+   * @param ui      uri info
+   *
+   * @return information regarding all cluster stack versions
+   */
+  @GET
+  @Produces("text/plain")
+  public Response getClusterStackVersions(@Context HttpHeaders headers, @Context UriInfo ui) {
+    return handleRequest(headers, null, ui, Request.Type.GET, createResource(clusterName, null));
+  }
+
+  /**
+   * Gets a single cluster stack version.
+   * Handles: GET /clusters/{clustername}/stack_versions/{stackversionid} requests.
+   *
+   * @param headers        http headers
+   * @param ui             uri info
+   * @param stackVersionId cluster stack version id
+   *
+   * @return information regarding the specific cluster stack version
+   */
+  @GET
+  @Path("{stackversionid}")
+  @Produces("text/plain")
+  public Response getClusterStackVersion(@Context HttpHeaders headers, @Context UriInfo ui,
+      @PathParam("stackversionid") String stackVersionId) {
+    return handleRequest(headers, null, ui, Request.Type.GET, createResource(clusterName, stackVersionId));
+  }
+
+  /**
+   * Create a cluster stack version resource instance.
+   *
+   * @param clusterName    cluster name
+   * @param stackVersionId cluster stack version id
+   *
+   * @return a cluster stack version resource instance
+   */
+  private ResourceInstance createResource(String clusterName, String stackVersionId) {
+    final Map<Resource.Type, String> mapIds = new HashMap<Resource.Type, String>();
+    mapIds.put(Resource.Type.Cluster, clusterName);
+    mapIds.put(Resource.Type.ClusterStackVersion, stackVersionId);
+    return createResource(Resource.Type.ClusterStackVersion, mapIds);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java
index c51722c..c4ad169 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java
@@ -236,6 +236,23 @@ public class HostService extends BaseService {
   }
 
   /**
+   * Gets the host stack versions service.
+   *
+   * @param request
+   *          the request
+   * @param hostName
+   *          the host name
+   *
+   * @return the host stack versions service
+   */
+  @Path("{hostName}/stack_versions")
+  public HostStackVersionService getHostStackVersionService(@Context javax.ws.rs.core.Request request,
+      @PathParam("hostName") String hostName) {
+
+    return new HostStackVersionService(hostName);
+  }
+
+  /**
    * Create a service resource instance.
    *
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostStackVersionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostStackVersionService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostStackVersionService.java
new file mode 100644
index 0000000..86a00a8
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostStackVersionService.java
@@ -0,0 +1,99 @@
+/**
+ * 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.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;
+
+/**
+ * Service responsible for stack version requests.
+ */
+public class HostStackVersionService extends BaseService {
+  /**
+   * Name of the host.
+   */
+  private String hostName;
+
+  /**
+   * Constructor.
+   *
+   * @param hostName name of the host
+   */
+  public HostStackVersionService(String hostName) {
+    this.hostName = hostName;
+  }
+
+  /**
+   * Gets all host host version.
+   * Handles: GET /hosts/{hostname}/stack_versions requests.
+   *
+   * @param headers http headers
+   * @param ui      uri info
+   *
+   * @return information regarding all host stack versions
+   */
+  @GET
+  @Produces("text/plain")
+  public Response getHostStackVersions(@Context HttpHeaders headers, @Context UriInfo ui) {
+    return handleRequest(headers, null, ui, Request.Type.GET, createResource(hostName, null));
+  }
+
+  /**
+   * Gets a single host stack version.
+   * Handles: GET /host/{hostname}/host_versions/{stackversionid} requests.
+   *
+   * @param headers        http headers
+   * @param ui             uri info
+   * @param stackversionid host stack version id
+   *
+   * @return information regarding the specific host stack version
+   */
+  @GET
+  @Path("{stackversionid}")
+  @Produces("text/plain")
+  public Response getHostStackVersion(@Context HttpHeaders headers, @Context UriInfo ui,
+      @PathParam("stackversionid") String stackVersionId) {
+    return handleRequest(headers, null, ui, Request.Type.GET, createResource(hostName, stackVersionId));
+  }
+
+  /**
+   * Create a host stack version resource instance.
+   *
+   * @param hostName host name
+   * @param stackVersionId host stack version id
+   * @return a host host version resource instance
+   */
+  private ResourceInstance createResource(String hostName, String stackVersionId) {
+    final Map<Resource.Type, String> mapIds = new HashMap<Resource.Type, String>();
+    mapIds.put(Resource.Type.Host, hostName);
+    mapIds.put(Resource.Type.HostStackVersion, stackVersionId);
+    return createResource(Resource.Type.HostStackVersion, mapIds);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
index 212f944..f7eb2d9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
@@ -54,5 +54,5 @@ public interface ResourceProviderFactory {
       AmbariManagementController managementController);
 
   @Named("repositoryVersion")
-  ResourceProvider getRepositoryVersionProvider();
+  ResourceProvider getRepositoryVersionResourceProvider();
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
index c198dd6..da05edf 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
@@ -152,7 +152,7 @@ public abstract class AbstractControllerResourceProvider extends AbstractResourc
       case ClientConfig:
         return new ClientConfigResourceProvider(propertyIds, keyPropertyIds, managementController);
       case RepositoryVersion:
-        return resourceProviderFactory.getRepositoryVersionProvider();
+        return resourceProviderFactory.getRepositoryVersionResourceProvider();
       default:
         throw new IllegalArgumentException("Unknown type " + type);
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
new file mode 100644
index 0000000..0fc590e
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
@@ -0,0 +1,196 @@
+/**
+ * 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.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.StaticallyInject;
+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.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+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.PropertyHelper;
+import org.apache.ambari.server.orm.dao.ClusterVersionDAO;
+import org.apache.ambari.server.orm.dao.HostVersionDAO;
+import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
+import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
+import org.apache.ambari.server.orm.entities.HostVersionEntity;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
+import org.apache.ambari.server.state.RepositoryVersionState;
+
+import com.google.inject.Inject;
+
+/**
+ * Resource provider for cluster stack versions resources.
+ */
+@StaticallyInject
+public class ClusterStackVersionResourceProvider extends AbstractResourceProvider {
+
+  // ----- Property ID constants ---------------------------------------------
+
+  protected static final String CLUSTER_STACK_VERSION_ID_PROPERTY_ID              = PropertyHelper.getPropertyId("ClusterStackVersions", "id");
+  protected static final String CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID    = PropertyHelper.getPropertyId("ClusterStackVersions", "cluster_name");
+  protected static final String CLUSTER_STACK_VERSION_STACK_PROPERTY_ID           = PropertyHelper.getPropertyId("ClusterStackVersions", "stack");
+  protected static final String CLUSTER_STACK_VERSION_VERSION_PROPERTY_ID         = PropertyHelper.getPropertyId("ClusterStackVersions", "version");
+  protected static final String CLUSTER_STACK_VERSION_STATE_PROPERTY_ID           = PropertyHelper.getPropertyId("ClusterStackVersions", "state");
+  protected static final String CLUSTER_STACK_VERSION_INSTALLED_HOSTS_PROPERTY_ID = PropertyHelper.getPropertyId("ClusterStackVersions", "installed_hosts");
+  protected static final String CLUSTER_STACK_VERSION_CURRENT_HOSTS_PROPERTY_ID   = PropertyHelper.getPropertyId("ClusterStackVersions", "current_hosts");
+  protected static final String CLUSTER_STACK_VERSION_REPOSITORIES_PROPERTY_ID    = PropertyHelper.getPropertyId("ClusterStackVersions", "repositories");
+
+  @SuppressWarnings("serial")
+  private static Set<String> pkPropertyIds = new HashSet<String>() {
+    {
+      add(CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID);
+      add(CLUSTER_STACK_VERSION_ID_PROPERTY_ID);
+    }
+  };
+
+  @SuppressWarnings("serial")
+  private static Set<String> propertyIds = new HashSet<String>() {
+    {
+      add(CLUSTER_STACK_VERSION_ID_PROPERTY_ID);
+      add(CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID);
+      add(CLUSTER_STACK_VERSION_STACK_PROPERTY_ID);
+      add(CLUSTER_STACK_VERSION_VERSION_PROPERTY_ID);
+      add(CLUSTER_STACK_VERSION_STATE_PROPERTY_ID);
+      add(CLUSTER_STACK_VERSION_INSTALLED_HOSTS_PROPERTY_ID);
+      add(CLUSTER_STACK_VERSION_CURRENT_HOSTS_PROPERTY_ID);
+      add(CLUSTER_STACK_VERSION_REPOSITORIES_PROPERTY_ID);
+    }
+  };
+
+  @SuppressWarnings("serial")
+  private static Map<Type, String> keyPropertyIds = new HashMap<Type, String>() {
+    {
+      put(Resource.Type.Cluster, CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID);
+      put(Resource.Type.ClusterStackVersion, CLUSTER_STACK_VERSION_ID_PROPERTY_ID);
+    }
+  };
+
+  @Inject
+  private static ClusterVersionDAO clusterVersionDAO;
+
+  @Inject
+  private static HostVersionDAO hostVersionDAO;
+
+  @Inject
+  private static RepositoryVersionDAO repositoryVersionDAO;
+
+  /**
+   * Constructor.
+   */
+  public ClusterStackVersionResourceProvider() {
+    super(propertyIds, keyPropertyIds);
+  }
+
+  @Override
+  public Set<Resource> getResources(Request request, Predicate predicate) throws
+      SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    final Set<Resource> resources = new HashSet<Resource>();
+    final Set<String> requestedIds = getRequestPropertyIds(request, predicate);
+    final Set<Map<String, Object>> propertyMaps = getPropertyMaps(predicate);
+
+    List<ClusterVersionEntity> requestedEntities = new ArrayList<ClusterVersionEntity>();
+    for (Map<String, Object> propertyMap: propertyMaps) {
+      final String clusterName = propertyMap.get(CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID).toString();
+      final Long id;
+      if (propertyMap.get(CLUSTER_STACK_VERSION_ID_PROPERTY_ID) == null && propertyMaps.size() == 1) {
+        requestedEntities = clusterVersionDAO.findByCluster(clusterName);
+      } else {
+        try {
+          id = Long.parseLong(propertyMap.get(CLUSTER_STACK_VERSION_ID_PROPERTY_ID).toString());
+        } catch (Exception ex) {
+          throw new SystemException("Stack version should have numerical id");
+        }
+        final ClusterVersionEntity entity = clusterVersionDAO.findByPK(id);
+        if (entity == null) {
+          throw new NoSuchResourceException("There is no stack version with id " + id);
+        } else {
+          requestedEntities.add(entity);
+        }
+      }
+    }
+
+    for (ClusterVersionEntity entity: requestedEntities) {
+      final Resource resource = new ResourceImpl(Resource.Type.ClusterStackVersion);
+      final RepositoryVersionEntity repositoryVersionEntity = repositoryVersionDAO.findByStackAndVersion(entity.getStack(), entity.getVersion());
+
+      final Map<RepositoryVersionState, List<String>> hosts = new HashMap<RepositoryVersionState, List<String>>();
+      for (RepositoryVersionState state: RepositoryVersionState.values()) {
+        hosts.put(state, new ArrayList<String>());
+      }
+      for (HostVersionEntity hostVersionEntity: hostVersionDAO.findByClusterStackAndVersion(entity.getClusterEntity().getClusterName(), entity.getStack(), entity.getVersion())) {
+        hosts.get(hostVersionEntity.getState()).add(hostVersionEntity.getHostName());
+      }
+
+      setResourceProperty(resource, CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID, entity.getClusterEntity().getClusterName(), requestedIds);
+
+      setResourceProperty(resource, CLUSTER_STACK_VERSION_CURRENT_HOSTS_PROPERTY_ID, hosts.get(RepositoryVersionState.CURRENT), requestedIds);
+      setResourceProperty(resource, CLUSTER_STACK_VERSION_ID_PROPERTY_ID, entity.getId(), requestedIds);
+      setResourceProperty(resource, CLUSTER_STACK_VERSION_INSTALLED_HOSTS_PROPERTY_ID, hosts.get(RepositoryVersionState.INSTALLED), requestedIds);
+      if (repositoryVersionEntity != null) {
+        setResourceProperty(resource, CLUSTER_STACK_VERSION_REPOSITORIES_PROPERTY_ID, repositoryVersionEntity.getRepositories(), requestedIds);
+      }
+      setResourceProperty(resource, CLUSTER_STACK_VERSION_STACK_PROPERTY_ID, entity.getStack(), requestedIds);
+      setResourceProperty(resource, CLUSTER_STACK_VERSION_STATE_PROPERTY_ID, entity.getState().name(), requestedIds);
+      setResourceProperty(resource, CLUSTER_STACK_VERSION_VERSION_PROPERTY_ID, entity.getVersion(), requestedIds);
+
+      if (predicate == null || predicate.evaluate(resource)) {
+        resources.add(resource);
+      }
+    }
+    return resources;
+  }
+
+  @Override
+  public RequestStatus createResources(Request request) throws SystemException,
+      UnsupportedPropertyException, ResourceAlreadyExistsException,
+      NoSuchParentResourceException {
+    throw new SystemException("Method not supported");
+  }
+
+  @Override
+  public RequestStatus updateResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+    throw new SystemException("Method not supported");
+  }
+
+  @Override
+  public RequestStatus deleteResources(Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+    throw new SystemException("Method not supported");
+  }
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return pkPropertyIds;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
index 8f10143..d0ce1cf 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
@@ -100,6 +100,10 @@ public class DefaultProviderModule extends AbstractProviderModule {
         return new UpgradeResourceProvider(managementController);
       case UpgradeItem:
         return new UpgradeItemResourceProvider(managementController);
+      case ClusterStackVersion:
+        return new ClusterStackVersionResourceProvider();
+      case HostStackVersion:
+        return new HostStackVersionResourceProvider();
 
       default:
         return AbstractControllerResourceProvider.getResourceProvider(type, propertyIds,

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostStackVersionResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostStackVersionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostStackVersionResourceProvider.java
new file mode 100644
index 0000000..67e62d7
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostStackVersionResourceProvider.java
@@ -0,0 +1,175 @@
+/**
+ * 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.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.StaticallyInject;
+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.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+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.PropertyHelper;
+import org.apache.ambari.server.orm.dao.HostVersionDAO;
+import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
+import org.apache.ambari.server.orm.entities.HostVersionEntity;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
+
+import com.google.inject.Inject;
+
+/**
+ * Resource provider for host stack versions resources.
+ */
+@StaticallyInject
+public class HostStackVersionResourceProvider extends AbstractResourceProvider {
+
+  // ----- Property ID constants ---------------------------------------------
+
+  protected static final String HOST_STACK_VERSION_ID_PROPERTY_ID              = PropertyHelper.getPropertyId("HostStackVersions", "id");
+  protected static final String HOST_STACK_VERSION_HOST_NAME_PROPERTY_ID       = PropertyHelper.getPropertyId("HostStackVersions", "host_name");
+  protected static final String HOST_STACK_VERSION_STACK_PROPERTY_ID           = PropertyHelper.getPropertyId("HostStackVersions", "stack");
+  protected static final String HOST_STACK_VERSION_VERSION_PROPERTY_ID         = PropertyHelper.getPropertyId("HostStackVersions", "version");
+  protected static final String HOST_STACK_VERSION_STATE_PROPERTY_ID           = PropertyHelper.getPropertyId("HostStackVersions", "state");
+  protected static final String HOST_STACK_VERSION_REPOSITORIES_PROPERTY_ID    = PropertyHelper.getPropertyId("HostStackVersions", "repositories");
+
+  @SuppressWarnings("serial")
+  private static Set<String> pkPropertyIds = new HashSet<String>() {
+    {
+      add(HOST_STACK_VERSION_HOST_NAME_PROPERTY_ID);
+      add(HOST_STACK_VERSION_ID_PROPERTY_ID);
+    }
+  };
+
+  @SuppressWarnings("serial")
+  private static Set<String> propertyIds = new HashSet<String>() {
+    {
+      add(HOST_STACK_VERSION_ID_PROPERTY_ID);
+      add(HOST_STACK_VERSION_HOST_NAME_PROPERTY_ID);
+      add(HOST_STACK_VERSION_STACK_PROPERTY_ID);
+      add(HOST_STACK_VERSION_VERSION_PROPERTY_ID);
+      add(HOST_STACK_VERSION_STATE_PROPERTY_ID);
+      add(HOST_STACK_VERSION_REPOSITORIES_PROPERTY_ID);
+    }
+  };
+
+  @SuppressWarnings("serial")
+  private static Map<Type, String> keyPropertyIds = new HashMap<Type, String>() {
+    {
+      put(Resource.Type.Host, HOST_STACK_VERSION_HOST_NAME_PROPERTY_ID);
+      put(Resource.Type.HostStackVersion, HOST_STACK_VERSION_ID_PROPERTY_ID);
+    }
+  };
+
+  @Inject
+  private static HostVersionDAO hostVersionDAO;
+
+  @Inject
+  private static RepositoryVersionDAO repositoryVersionDAO;
+
+  /**
+   * Constructor.
+   */
+  public HostStackVersionResourceProvider() {
+    super(propertyIds, keyPropertyIds);
+  }
+
+  @Override
+  public Set<Resource> getResources(Request request, Predicate predicate) throws
+      SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    final Set<Resource> resources = new HashSet<Resource>();
+    final Set<String> requestedIds = getRequestPropertyIds(request, predicate);
+    final Set<Map<String, Object>> propertyMaps = getPropertyMaps(predicate);
+
+    List<HostVersionEntity> requestedEntities = new ArrayList<HostVersionEntity>();
+    for (Map<String, Object> propertyMap: propertyMaps) {
+      final String hostName = propertyMap.get(HOST_STACK_VERSION_HOST_NAME_PROPERTY_ID).toString();
+      final Long id;
+      if (propertyMap.get(HOST_STACK_VERSION_ID_PROPERTY_ID) == null && propertyMaps.size() == 1) {
+        requestedEntities = hostVersionDAO.findByHost(hostName);
+      } else {
+        try {
+          id = Long.parseLong(propertyMap.get(HOST_STACK_VERSION_ID_PROPERTY_ID).toString());
+        } catch (Exception ex) {
+          throw new SystemException("Stack version should have numerical id");
+        }
+        final HostVersionEntity entity = hostVersionDAO.findByPK(id);
+        if (entity == null) {
+          throw new NoSuchResourceException("There is no stack version with id " + id);
+        } else {
+          requestedEntities.add(entity);
+        }
+      }
+    }
+
+    for (HostVersionEntity entity: requestedEntities) {
+      final Resource resource = new ResourceImpl(Resource.Type.HostStackVersion);
+      final RepositoryVersionEntity repositoryVersionEntity = repositoryVersionDAO.findByStackAndVersion(entity.getStack(), entity.getVersion());
+
+      setResourceProperty(resource, HOST_STACK_VERSION_HOST_NAME_PROPERTY_ID, entity.getHostName(), requestedIds);
+      setResourceProperty(resource, HOST_STACK_VERSION_ID_PROPERTY_ID, entity.getId(), requestedIds);
+      setResourceProperty(resource, HOST_STACK_VERSION_STACK_PROPERTY_ID, entity.getStack(), requestedIds);
+      setResourceProperty(resource, HOST_STACK_VERSION_VERSION_PROPERTY_ID, entity.getVersion(), requestedIds);
+      if (repositoryVersionEntity != null) {
+        setResourceProperty(resource, HOST_STACK_VERSION_REPOSITORIES_PROPERTY_ID, repositoryVersionEntity.getRepositories(), requestedIds);
+      }
+      setResourceProperty(resource, HOST_STACK_VERSION_STATE_PROPERTY_ID, entity.getState().name(), requestedIds);
+
+      if (predicate == null || predicate.evaluate(resource)) {
+        resources.add(resource);
+      }
+    }
+    return resources;
+  }
+
+  @Override
+  public RequestStatus createResources(Request request) throws SystemException,
+      UnsupportedPropertyException, ResourceAlreadyExistsException,
+      NoSuchParentResourceException {
+    throw new SystemException("Method not supported");
+  }
+
+  @Override
+  public RequestStatus updateResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+    throw new SystemException("Method not supported");
+  }
+
+  @Override
+  public RequestStatus deleteResources(Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+    throw new SystemException("Method not supported");
+  }
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return pkPropertyIds;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackVersionResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackVersionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackVersionResourceProvider.java
index 1442a0c..11fc04d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackVersionResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackVersionResourceProvider.java
@@ -58,7 +58,7 @@ public class StackVersionResourceProvider extends ReadOnlyResourceProvider {
 
   private static final String STACK_ACTIVE_PROPERTY_ID = PropertyHelper
       .getPropertyId("Versions", "active");
-  
+
   private static final String STACK_CONFIG_TYPES = PropertyHelper
       .getPropertyId("Versions", "config_types");
 
@@ -103,7 +103,7 @@ public class StackVersionResourceProvider extends ReadOnlyResourceProvider {
 
       setResourceProperty(resource, STACK_VERSION_PROPERTY_ID,
           response.getStackVersion(), requestedIds);
-      
+
       setResourceProperty(resource, STACK_MIN_VERSION_PROPERTY_ID,
           response.getMinUpgradeVersion(), requestedIds);
 
@@ -112,7 +112,7 @@ public class StackVersionResourceProvider extends ReadOnlyResourceProvider {
 
       setResourceProperty(resource, STACK_PARENT_PROPERTY_ID,
         response.getParentVersion(), requestedIds);
-      
+
       setResourceProperty(resource, STACK_CONFIG_TYPES,
           response.getConfigTypes(), requestedIds);
 
@@ -127,7 +127,7 @@ public class StackVersionResourceProvider extends ReadOnlyResourceProvider {
         (String) properties.get(STACK_NAME_PROPERTY_ID),
         (String) properties.get(STACK_VERSION_PROPERTY_ID));
   }
-  
+
   @Override
   protected Set<String> getPKPropertyIds() {
     return pkPropertyIds;

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
index dbac906..b71b43c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
@@ -129,6 +129,8 @@ public interface Resource {
     LdapSyncEvent,
     UserPrivilege,
     RepositoryVersion,
+    ClusterStackVersion,
+    HostStackVersion,
     Upgrade,
     UpgradeItem;
 
@@ -220,6 +222,8 @@ public interface Resource {
     public static final Type LdapSyncEvent = InternalType.LdapSyncEvent.getType();
     public static final Type UserPrivilege = InternalType.UserPrivilege.getType();
     public static final Type RepositoryVersion = InternalType.RepositoryVersion.getType();
+    public static final Type ClusterStackVersion = InternalType.ClusterStackVersion.getType();
+    public static final Type HostStackVersion = InternalType.HostStackVersion.getType();
     public static final Type Upgrade = InternalType.Upgrade.getType();
     public static final Type UpgradeItem = InternalType.UpgradeItem.getType();
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterVersionDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterVersionDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterVersionDAO.java
index e2a2e2d..7202373 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterVersionDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterVersionDAO.java
@@ -25,15 +25,15 @@ import javax.persistence.TypedQuery;
 
 import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
-import org.apache.ambari.server.state.ClusterVersionState;
+import org.apache.ambari.server.state.RepositoryVersionState;
 
 import com.google.inject.Singleton;
 
 /**
  * The {@link ClusterVersionDAO} class manages the {@link ClusterVersionEntity} instances associated with a cluster.
- * Each cluster can have multiple stack versions {@link ClusterVersionState#INSTALLED},
- * exactly one stack version that is {@link ClusterVersionState#CURRENT}, and at most one
- * stack version that is {@link ClusterVersionState#UPGRADING}.
+ * Each cluster can have multiple stack versions {@link RepositoryVersionState#INSTALLED},
+ * exactly one stack version that is {@link RepositoryVersionState#CURRENT}, and at most one
+ * stack version that is {@link RepositoryVersionState#UPGRADING}.
  */
 @Singleton
 public class ClusterVersionDAO extends CrudDAO<ClusterVersionEntity, Long>{
@@ -80,18 +80,32 @@ public class ClusterVersionDAO extends CrudDAO<ClusterVersionEntity, Long>{
   }
 
   /**
-   * Retrieve the single cluster version whose state is {@link ClusterVersionState#CURRENT}, of which there should be exactly one at all times
+   * Get the cluster version for the given cluster name.
+   *
+   * @param clusterName Cluster name
+   * @return Return all of the cluster versions associated with the given cluster.
+   */
+  public List<ClusterVersionEntity> findByCluster(String  clusterName) {
+    final TypedQuery<ClusterVersionEntity> query = entityManagerProvider.get()
+        .createNamedQuery("clusterVersionByCluster", ClusterVersionEntity.class);
+    query.setParameter("clusterName", clusterName);
+
+    return daoUtils.selectList(query);
+  }
+
+  /**
+   * Retrieve the single cluster version whose state is {@link RepositoryVersionState#CURRENT}, of which there should be exactly one at all times
    * for the given cluster.
    *
    * @param clusterName Cluster name
-   * @return Returns the single cluster version for this cluster whose state is {@link ClusterVersionState#CURRENT}, or {@code null} otherwise.
+   * @return Returns the single cluster version for this cluster whose state is {@link RepositoryVersionState#CURRENT}, or {@code null} otherwise.
    */
   @RequiresSession
   public ClusterVersionEntity findByClusterAndStateCurrent(String clusterName) {
     final TypedQuery<ClusterVersionEntity> query = entityManagerProvider.get()
         .createNamedQuery("clusterVersionByClusterAndState", ClusterVersionEntity.class);
     query.setParameter("clusterName", clusterName);
-    query.setParameter("state", ClusterVersionState.CURRENT);
+    query.setParameter("state", RepositoryVersionState.CURRENT);
 
     try {
       List results = query.getResultList();
@@ -116,7 +130,7 @@ public class ClusterVersionDAO extends CrudDAO<ClusterVersionEntity, Long>{
    * @return Returns a list of cluster versions for the given cluster and a state.
    */
   @RequiresSession
-  public List<ClusterVersionEntity> findByClusterAndState(String clusterName, ClusterVersionState state) {
+  public List<ClusterVersionEntity> findByClusterAndState(String clusterName, RepositoryVersionState state) {
     final TypedQuery<ClusterVersionEntity> query = entityManagerProvider.get()
         .createNamedQuery("clusterVersionByClusterAndState", ClusterVersionEntity.class);
     query.setParameter("clusterName", clusterName);

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java
index 8d147a1..20648a1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java
@@ -22,19 +22,20 @@ import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
 import com.google.inject.persist.Transactional;
+
 import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.HostVersionEntity;
-import org.apache.ambari.server.state.UpgradeState;
-
+import org.apache.ambari.server.state.RepositoryVersionState;
 import javax.persistence.EntityManager;
 import javax.persistence.TypedQuery;
+
 import java.util.List;
 
 /**
  * The {@link org.apache.ambari.server.orm.dao.HostVersionDAO} class manages the {@link org.apache.ambari.server.orm.entities.HostVersionEntity}
- * instances associated with a host. Each host can have multiple stack versions in {@link org.apache.ambari.server.state.UpgradeState#NONE}
- * which are installed, exactly one stack version that is either {@link org.apache.ambari.server.state.UpgradeState#PENDING} or
- * {@link org.apache.ambari.server.state.UpgradeState#IN_PROGRESS}.
+ * instances associated with a host. Each host can have multiple stack versions in {@link org.apache.ambari.server.state.RepositoryVersionState#INSTALLED}
+ * which are installed, exactly one stack version that is either {@link org.apache.ambari.server.state.RepositoryVersionState#CURRENT} or
+ * {@link org.apache.ambari.server.state.RepositoryVersionState.#UPGRADING}.
  */
 @Singleton
 public class HostVersionDAO {
@@ -90,15 +91,30 @@ public class HostVersionDAO {
   }
 
   /**
+   * Retrieve all of the host versions for the given and host name.
+   *
+   * @param hostName FQDN of host
+   * @return Return all of the host versions that match the criteria.
+   */
+  @RequiresSession
+  public List<HostVersionEntity> findByHost(String hostName) {
+    final TypedQuery<HostVersionEntity> query = entityManagerProvider.get()
+        .createNamedQuery("hostVersionByHostname", HostVersionEntity.class);
+    query.setParameter("hostName", hostName);
+
+    return daoUtils.selectList(query);
+  }
+
+  /**
    * Retrieve all of the host versions for the given cluster name, host name, and state.
    *
    * @param clusterName Cluster name
    * @param hostName FQDN of host
-   * @param state Upgrade state
+   * @param state repository version state
    * @return Return all of the host versions that match the criteria.
    */
   @RequiresSession
-  public List<HostVersionEntity> findByClusterHostAndState(String  clusterName, String hostName, UpgradeState state) {
+  public List<HostVersionEntity> findByClusterHostAndState(String  clusterName, String hostName, RepositoryVersionState state) {
     final TypedQuery<HostVersionEntity> query = entityManagerProvider.get()
         .createNamedQuery("hostVersionByClusterHostnameAndState", HostVersionEntity.class);
     query.setParameter("clusterName", clusterName);

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterVersionEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterVersionEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterVersionEntity.java
index aaf8eed..a7d4d24 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterVersionEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterVersionEntity.java
@@ -18,7 +18,7 @@
 
 package org.apache.ambari.server.orm.entities;
 
-import org.apache.ambari.server.state.ClusterVersionState;
+import org.apache.ambari.server.state.RepositoryVersionState;
 
 import javax.persistence.Basic;
 import javax.persistence.Column;
@@ -52,6 +52,9 @@ import static org.apache.commons.lang.StringUtils.defaultString;
     @NamedQuery(name = "clusterVersionByClusterAndState", query =
         "SELECT clusterVersion FROM ClusterVersionEntity clusterVersion JOIN clusterVersion.clusterEntity cluster " +
         "WHERE cluster.clusterName=:clusterName AND clusterVersion.state=:state"),
+    @NamedQuery(name = "clusterVersionByCluster", query =
+        "SELECT clusterVersion FROM ClusterVersionEntity clusterVersion JOIN clusterVersion.clusterEntity cluster " +
+        "WHERE cluster.clusterName=:clusterName"),
     @NamedQuery(name = "clusterVersionByStackVersion",
         query = "SELECT clusterVersion FROM ClusterVersionEntity clusterVersion WHERE clusterVersion.stack=:stack AND clusterVersion.version=:version"),
 })
@@ -79,7 +82,7 @@ public class ClusterVersionEntity {
 
   @Column(name = "state", nullable = false, insertable = true, updatable = true)
   @Enumerated(value = EnumType.STRING)
-  private ClusterVersionState state = ClusterVersionState.CURRENT;
+  private RepositoryVersionState state = RepositoryVersionState.CURRENT;
 
   @Basic
   @Column(name = "start_time", nullable = false, insertable = true, updatable = true)
@@ -108,7 +111,7 @@ public class ClusterVersionEntity {
    * @param startTime Time the cluster version reached its first state
    * @param userName User who performed the action
    */
-  public ClusterVersionEntity(ClusterEntity cluster, String stack, String version, ClusterVersionState state, long startTime, String userName) {
+  public ClusterVersionEntity(ClusterEntity cluster, String stack, String version, RepositoryVersionState state, long startTime, String userName) {
     this.clusterId = cluster.getClusterId();
     this.clusterEntity = cluster;
     this.stack = stack;
@@ -128,7 +131,7 @@ public class ClusterVersionEntity {
    * @param endTime Time the cluster version finalized its state
    * @param userName User who performed the action
    */
-  public ClusterVersionEntity(ClusterEntity cluster, String stack, String version, ClusterVersionState state, long startTime, long endTime, String userName) {
+  public ClusterVersionEntity(ClusterEntity cluster, String stack, String version, RepositoryVersionState state, long startTime, long endTime, String userName) {
     this(cluster, stack, version, state, startTime, userName);
     this.endTime = endTime;
   }
@@ -173,11 +176,11 @@ public class ClusterVersionEntity {
     this.version = version;
   }
 
-  public ClusterVersionState getState() {
+  public RepositoryVersionState getState() {
     return state;
   }
 
-  public void setState(ClusterVersionState state) {
+  public void setState(RepositoryVersionState state) {
     this.state = state;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java
index 5b1b4f8..c090056 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java
@@ -18,8 +18,7 @@
 
 package org.apache.ambari.server.orm.entities;
 
-import org.apache.ambari.server.state.UpgradeState;
-
+import org.apache.ambari.server.state.RepositoryVersionState;
 import javax.persistence.Basic;
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -54,6 +53,10 @@ import static org.apache.commons.lang.StringUtils.defaultString;
         "SELECT hostVersion FROM HostVersionEntity hostVersion JOIN hostVersion.hostEntity host JOIN ClusterEntity cluster " +
             "WHERE cluster.clusterName=:clusterName AND hostVersion.hostName=:hostName"),
 
+    @NamedQuery(name = "hostVersionByHostname", query =
+        "SELECT hostVersion FROM HostVersionEntity hostVersion JOIN hostVersion.hostEntity host " +
+            "WHERE hostVersion.hostName=:hostName"),
+
     @NamedQuery(name = "hostVersionByClusterHostnameAndState", query =
         "SELECT hostVersion FROM HostVersionEntity hostVersion JOIN hostVersion.hostEntity host JOIN ClusterEntity cluster " +
             "WHERE cluster.clusterName=:clusterName AND hostVersion.hostName=:hostName AND hostVersion.state=:state"),
@@ -87,7 +90,7 @@ public class HostVersionEntity {
 
   @Column(name = "state", nullable = false, insertable = true, updatable = true)
   @Enumerated(value = EnumType.STRING)
-  private UpgradeState state = UpgradeState.NONE;
+  private RepositoryVersionState state;
 
   /**
    * Empty constructor is needed by unit tests.
@@ -95,7 +98,7 @@ public class HostVersionEntity {
   public HostVersionEntity() {
   }
 
-  public HostVersionEntity(String hostName, String stack, String version, UpgradeState state) {
+  public HostVersionEntity(String hostName, String stack, String version, RepositoryVersionState state) {
     this.hostName = hostName;
     this.stack = stack;
     this.version = version;
@@ -152,11 +155,11 @@ public class HostVersionEntity {
     this.version = version;
   }
 
-  public UpgradeState getState() {
+  public RepositoryVersionState getState() {
     return state;
   }
 
-  public void setState(UpgradeState state) {
+  public void setState(RepositoryVersionState state) {
     this.state = state;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterVersionState.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterVersionState.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterVersionState.java
deleted file mode 100644
index 72cd541..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterVersionState.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ambari.server.state;
-
-/**
- * There must be exactly one cluster version that is in a CURRENT state.
- * There may be 0 or more cluster versions in an INSTALLED state.
- * A new cluster version transitions from UPGRADING -> CURRENT | UPGRADE_FAILED
- * The operation to transition a new cluster version into CURRENT must be atomic and change the existing cluster version
- * from CURRENT to INSTALLED.
- *
- * <pre>
- * Step 1: Initial Configuration
- * Version 1 is CURRENT
- *
- * Step 2: Add another repository and start an upgrade from Version 1 to Version 2
- * Version 1: CURRENT
- * Version 2: UPGRADING
- *
- * Step 3: Upgrade can either complete successfully or fail
- * Version 1: CURRENT
- * Version 2: UPGRADE_FAILED (a retry can set this back to UPGRADING)
- *
- * or
- *
- * Version 1: INSTALLED
- * Version 2: CURRENT
- *
- * Step 4: May revert to the original version via a downgrade, which is technically still an upgrade to a version.
- * Version 1: UPGRADING
- * Version 2: CURRENT
- *
- * and eventually becomes
- *
- * Version 1: CURRENT
- * Version 2: INSTALLED
- *
- * *********************************************
- * Start states: CURRENT, UPGRADING
- * Allowed Transitions:
- * UPGRADING -> CURRENT | UPGRADE_FAILED
- * UPGRADE_FAILED -> UPGRADING
- * CURRENT -> INSTALLED
- * INSTALLED -> UPGRADING
- * </pre>
- */
-public enum ClusterVersionState {
-  /**
-   * Cluster version that is installed and supported but not the active version.
-   */
-  INSTALLED,
-  /**
-   * Cluster version that is installed and supported and is the active version.
-   */
-  CURRENT,
-  /**
-   * Cluster version that is in the process of upgrading to become the CURRENT active version,
-   * and the previous active version transitions to an INSTALLED state.
-   */
-  UPGRADING,
-  /**
-   * Cluster version that during the upgrade process failed to become the active version and must be remedied.
-   */
-  UPGRADE_FAILED;
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/main/java/org/apache/ambari/server/state/RepositoryVersionState.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/RepositoryVersionState.java b/ambari-server/src/main/java/org/apache/ambari/server/state/RepositoryVersionState.java
new file mode 100644
index 0000000..f518622
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/RepositoryVersionState.java
@@ -0,0 +1,81 @@
+/**
+ * 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.state;
+
+/**
+ * There must be exactly one repository version that is in a CURRENT state for a particular cluster or host.
+ * There may be 0 or more repository versions in an INSTALLED state.
+ * A repository version state transitions from UPGRADING -> CURRENT | UPGRADE_FAILED
+ * The operation to transition a repository version state into CURRENT must be atomic and change the existing
+ * relation between repository version and cluster or host from CURRENT to INSTALLED.
+ *
+ * <pre>
+ * Step 1: Initial Configuration
+ * Version 1 is CURRENT
+ *
+ * Step 2: Add another repository and start an upgrade from Version 1 to Version 2
+ * Version 1: CURRENT
+ * Version 2: UPGRADING
+ *
+ * Step 3: Upgrade can either complete successfully or fail
+ * Version 1: CURRENT
+ * Version 2: UPGRADE_FAILED (a retry can set this back to UPGRADING)
+ *
+ * or
+ *
+ * Version 1: INSTALLED
+ * Version 2: CURRENT
+ *
+ * Step 4: May revert to the original version via a downgrade, which is technically still an upgrade to a version.
+ * Version 1: UPGRADING
+ * Version 2: CURRENT
+ *
+ * and eventually becomes
+ *
+ * Version 1: CURRENT
+ * Version 2: INSTALLED
+ *
+ * *********************************************
+ * Start states: CURRENT, UPGRADING
+ * Allowed Transitions:
+ * UPGRADING -> CURRENT | UPGRADE_FAILED
+ * UPGRADE_FAILED -> UPGRADING
+ * CURRENT -> INSTALLED
+ * INSTALLED -> UPGRADING
+ * </pre>
+ */
+public enum RepositoryVersionState {
+  /**
+   * Repository version that is installed and supported but not the active version.
+   */
+  INSTALLED,
+  /**
+   * Repository version that is installed and supported and is the active version.
+   */
+  CURRENT,
+  /**
+   * Repository version that is in the process of upgrading to become the CURRENT active version,
+   * and the previous active version transitions to an INSTALLED state.
+   */
+  UPGRADING,
+  /**
+   * Repository version that during the upgrade process failed to become the active version and must be remedied.
+   */
+  UPGRADE_FAILED;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ClusterResourceDefinitionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ClusterResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ClusterResourceDefinitionTest.java
index 7296e8d..6d897b2 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ClusterResourceDefinitionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ClusterResourceDefinitionTest.java
@@ -50,7 +50,7 @@ public class ClusterResourceDefinitionTest {
     ResourceDefinition resource = new ClusterResourceDefinition();
     Set<SubResourceDefinition> subResources = resource.getSubResourceDefinitions();
 
-    assertEquals(10, subResources.size());
+    assertEquals(11, subResources.size());
     assertTrue(includesType(subResources, Resource.Type.Service));
     assertTrue(includesType(subResources, Resource.Type.Host));
     assertTrue(includesType(subResources, Resource.Type.Configuration));
@@ -61,6 +61,7 @@ public class ClusterResourceDefinitionTest {
     assertTrue(includesType(subResources, Resource.Type.ServiceConfigVersion));
     assertTrue(includesType(subResources, Resource.Type.ClusterPrivilege));
     assertTrue(includesType(subResources, Resource.Type.Alert));
+    assertTrue(includesType(subResources, Resource.Type.ClusterStackVersion));
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ComponentStackVersionResourceDefinitionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ComponentStackVersionResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ComponentStackVersionResourceDefinitionTest.java
new file mode 100644
index 0000000..0097e8b
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ComponentStackVersionResourceDefinitionTest.java
@@ -0,0 +1,48 @@
+/**
+ * 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 org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Set;
+
+/**
+ * ComponentStackVersionResourceDefinition tests.
+ */
+public class ComponentStackVersionResourceDefinitionTest {
+  @Test
+  public void testGetPluralName() throws Exception {
+    final ComponentStackVersionResourceDefinition resourceDefinition = new ComponentStackVersionResourceDefinition(null);
+    Assert.assertEquals("stack_versions", resourceDefinition.getPluralName());
+  }
+
+  @Test
+  public void testGetSingularName() throws Exception {
+    final ComponentStackVersionResourceDefinition resourceDefinition = new ComponentStackVersionResourceDefinition(null);
+    Assert.assertEquals("stack_version", resourceDefinition.getSingularName());
+  }
+
+  @Test
+  public void testGetSubResourceDefinitions() throws Exception {
+    final ComponentStackVersionResourceDefinition resourceDefinition = new ComponentStackVersionResourceDefinition(null);
+    final Set<SubResourceDefinition> subResourceDefinitions = resourceDefinition.getSubResourceDefinitions ();
+    Assert.assertEquals(0, subResourceDefinitions.size());
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/test/java/org/apache/ambari/server/api/resources/HostResourceDefinitionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/HostResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/HostResourceDefinitionTest.java
new file mode 100644
index 0000000..b3851eb
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/HostResourceDefinitionTest.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.api.resources;
+
+import org.apache.ambari.server.controller.spi.Resource;
+import org.junit.Test;
+
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * HostResourceDefinition unit tests.
+ */
+public class HostResourceDefinitionTest {
+
+  @Test
+  public void testGetPluralName() {
+    assertEquals("hosts", new HostResourceDefinition().getPluralName());
+  }
+
+  @Test
+  public void testGetSingularName() {
+    assertEquals("host", new HostResourceDefinition().getSingularName());
+  }
+
+  @Test
+  public void testGetSubResourceDefinitions() {
+    final ResourceDefinition resource = new HostResourceDefinition();
+    Set<SubResourceDefinition> subResources = resource.getSubResourceDefinitions();
+
+    assertEquals(3, subResources.size());
+    assertTrue(includesType(subResources, Resource.Type.HostComponent));
+    assertTrue(includesType(subResources, Resource.Type.Alert));
+    assertTrue(includesType(subResources, Resource.Type.HostStackVersion));
+  }
+
+  private boolean includesType(Set<SubResourceDefinition> resources, Resource.Type type) {
+    for (SubResourceDefinition subResource : resources) {
+      if (subResource.getType() == type) {
+        return true;
+      }
+    }
+    return false;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/test/java/org/apache/ambari/server/api/resources/RepositoryVersionResourceDefinitionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/RepositoryVersionResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/RepositoryVersionResourceDefinitionTest.java
index c0e625a..98f3e49 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/RepositoryVersionResourceDefinitionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/RepositoryVersionResourceDefinitionTest.java
@@ -29,20 +29,20 @@ import java.util.Set;
 public class RepositoryVersionResourceDefinitionTest {
   @Test
   public void testGetPluralName() throws Exception {
-    final RepositoryVersionResourceDefinition RepositoryVersionResourceDefinition = new RepositoryVersionResourceDefinition();
-    Assert.assertEquals("repository_versions", RepositoryVersionResourceDefinition.getPluralName());
+    final RepositoryVersionResourceDefinition resourceDefinition = new RepositoryVersionResourceDefinition();
+    Assert.assertEquals("repository_versions", resourceDefinition.getPluralName());
   }
 
   @Test
   public void testGetSingularName() throws Exception {
-    RepositoryVersionResourceDefinition RepositoryVersionResourceDefinition = new RepositoryVersionResourceDefinition();
-    Assert.assertEquals("repository_version", RepositoryVersionResourceDefinition.getSingularName());
+    RepositoryVersionResourceDefinition resourceDefinition = new RepositoryVersionResourceDefinition();
+    Assert.assertEquals("repository_version", resourceDefinition.getSingularName());
   }
 
   @Test
   public void testGetSubResourceDefinitions() throws Exception {
-    RepositoryVersionResourceDefinition RepositoryVersionResourceDefinition = new RepositoryVersionResourceDefinition();
-    Set<SubResourceDefinition> subResourceDefinitions = RepositoryVersionResourceDefinition.getSubResourceDefinitions ();
+    RepositoryVersionResourceDefinition resourceDefinition = new RepositoryVersionResourceDefinition();
+    Set<SubResourceDefinition> subResourceDefinitions = resourceDefinition.getSubResourceDefinitions ();
 
     Assert.assertEquals(0, subResourceDefinitions.size());
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/test/java/org/apache/ambari/server/api/services/ClusterStackVersionServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/ClusterStackVersionServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/ClusterStackVersionServiceTest.java
new file mode 100644
index 0000000..7972bd1
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/ClusterStackVersionServiceTest.java
@@ -0,0 +1,86 @@
+/**
+ * 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 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;
+import org.apache.ambari.server.controller.spi.Resource.Type;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Unit tests for ClusterStackVersionService.
+ */
+public class ClusterStackVersionServiceTest extends BaseServiceTest {
+
+  public List<ServiceTestInvocation> getTestInvocations() throws Exception {
+    List<ServiceTestInvocation> listInvocations = new ArrayList<ServiceTestInvocation>();
+
+    ClusterStackVersionService clusterStackVersionService;
+    Method m;
+    Object[] args;
+
+    //getClusterStackVersions
+    clusterStackVersionService = new TestClusterStackVersionService("cluster");
+    m = clusterStackVersionService.getClass().getMethod("getClusterStackVersions", HttpHeaders.class, UriInfo.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo()};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, clusterStackVersionService, m, args, null));
+
+    //getClusterStackVersion
+    clusterStackVersionService = new TestClusterStackVersionService("cluster");
+    m = clusterStackVersionService.getClass().getMethod("getClusterStackVersion", HttpHeaders.class, UriInfo.class, String.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo(), "1"};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, clusterStackVersionService, m, args, null));
+
+    return listInvocations;
+  }
+
+  private class TestClusterStackVersionService extends ClusterStackVersionService {
+    public TestClusterStackVersionService(String clusterName) {
+      super(clusterName);
+    }
+
+    @Override
+    protected ResourceInstance createResource(Type type, Map<Type, String> mapIds) {
+      return getTestResource();
+    }
+
+    @Override
+    RequestFactory getRequestFactory() {
+      return getTestRequestFactory();
+    }
+
+    @Override
+    protected RequestBodyParser getBodyParser() {
+      return getTestBodyParser();
+    }
+
+    @Override
+    protected ResultSerializer getResultSerializer() {
+      return getTestResultSerializer();
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/test/java/org/apache/ambari/server/api/services/HostStackVersionServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/HostStackVersionServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/HostStackVersionServiceTest.java
new file mode 100644
index 0000000..960a485
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/HostStackVersionServiceTest.java
@@ -0,0 +1,86 @@
+/**
+ * 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 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;
+import org.apache.ambari.server.controller.spi.Resource.Type;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Unit tests for HostStackVersionService.
+ */
+public class HostStackVersionServiceTest extends BaseServiceTest {
+
+  public List<ServiceTestInvocation> getTestInvocations() throws Exception {
+    List<ServiceTestInvocation> listInvocations = new ArrayList<ServiceTestInvocation>();
+
+    HostStackVersionService hostStackVersionService;
+    Method m;
+    Object[] args;
+
+    //getHostStackVersions
+    hostStackVersionService = new TestHostStackVersionService("host");
+    m = hostStackVersionService.getClass().getMethod("getHostStackVersions", HttpHeaders.class, UriInfo.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo()};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, hostStackVersionService, m, args, null));
+
+    //getHostStackVersion
+    hostStackVersionService = new TestHostStackVersionService("host");
+    m = hostStackVersionService.getClass().getMethod("getHostStackVersion", HttpHeaders.class, UriInfo.class, String.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo(), "1"};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, hostStackVersionService, m, args, null));
+
+    return listInvocations;
+  }
+
+  private class TestHostStackVersionService extends HostStackVersionService {
+    public TestHostStackVersionService(String hostName) {
+      super(hostName);
+    }
+
+    @Override
+    protected ResourceInstance createResource(Type type, Map<Type, String> mapIds) {
+      return getTestResource();
+    }
+
+    @Override
+    RequestFactory getRequestFactory() {
+      return getTestRequestFactory();
+    }
+
+    @Override
+    protected RequestBodyParser getBodyParser() {
+      return getTestBodyParser();
+    }
+
+    @Override
+    protected ResultSerializer getResultSerializer() {
+      return getTestResultSerializer();
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f00656c/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RepositoryVersionResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RepositoryVersionResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RepositoryVersionResourceProviderTest.java
index 3cd54f5..fbed7ff 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RepositoryVersionResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RepositoryVersionResourceProviderTest.java
@@ -50,7 +50,6 @@ import org.mockito.stubbing.Answer;
 
 import com.google.common.collect.Sets;
 import com.google.gson.Gson;
-import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.persist.PersistService;
@@ -69,7 +68,7 @@ public class RepositoryVersionResourceProviderTest {
   public void before() throws Exception {
     final Set<String> validVersions = Sets.newHashSet("1.1", "1.1-17", "1.1.1.1", "1.1.343432.2", "1.1.343432.2-234234324");
     final AmbariMetaInfo ambariMetaInfo = Mockito.mock(AmbariMetaInfo.class);
-    final AbstractModule injectorModule = new InMemoryDefaultTestModule() {
+    final InMemoryDefaultTestModule injectorModule = new InMemoryDefaultTestModule() {
       protected void configure() {
         super.configure();
         bind(AmbariMetaInfo.class).toInstance(ambariMetaInfo);
@@ -136,7 +135,7 @@ public class RepositoryVersionResourceProviderTest {
 
   @Test
   public void testCreateResources() throws Exception {
-    final ResourceProvider provider = injector.getInstance(ResourceProviderFactory.class).getRepositoryVersionProvider();
+    final ResourceProvider provider = injector.getInstance(ResourceProviderFactory.class).getRepositoryVersionResourceProvider();
 
     final Set<Map<String, Object>> propertySet = new LinkedHashSet<Map<String, Object>>();
     final Map<String, Object> properties = new LinkedHashMap<String, Object>();
@@ -158,7 +157,7 @@ public class RepositoryVersionResourceProviderTest {
 
   @Test
   public void testGetResources() throws Exception {
-    final ResourceProvider provider = injector.getInstance(ResourceProviderFactory.class).getRepositoryVersionProvider();
+    final ResourceProvider provider = injector.getInstance(ResourceProviderFactory.class).getRepositoryVersionResourceProvider();
     final RepositoryVersionDAO repositoryVersionDAO = injector.getInstance(RepositoryVersionDAO.class);
     final RepositoryVersionEntity entity = new RepositoryVersionEntity();
     entity.setDisplayName("name");
@@ -178,7 +177,7 @@ public class RepositoryVersionResourceProviderTest {
   @Test
   public void testValidateRepositoryVersion() throws Exception {
     final RepositoryVersionResourceProvider provider = (RepositoryVersionResourceProvider)
-        injector.getInstance(ResourceProviderFactory.class).getRepositoryVersionProvider();
+        injector.getInstance(ResourceProviderFactory.class).getRepositoryVersionResourceProvider();
 
     final RepositoryVersionEntity entity = new RepositoryVersionEntity();
     entity.setDisplayName("name");
@@ -237,7 +236,7 @@ public class RepositoryVersionResourceProviderTest {
 
   @Test
   public void testDeleteResources() throws Exception {
-    final ResourceProvider provider = injector.getInstance(ResourceProviderFactory.class).getRepositoryVersionProvider();
+    final ResourceProvider provider = injector.getInstance(ResourceProviderFactory.class).getRepositoryVersionResourceProvider();
 
     final Set<Map<String, Object>> propertySet = new LinkedHashSet<Map<String, Object>>();
     final Map<String, Object> properties = new LinkedHashMap<String, Object>();
@@ -264,7 +263,7 @@ public class RepositoryVersionResourceProviderTest {
 
   @Test
   public void testUpdateResources() throws Exception {
-    final ResourceProvider provider = injector.getInstance(ResourceProviderFactory.class).getRepositoryVersionProvider();
+    final ResourceProvider provider = injector.getInstance(ResourceProviderFactory.class).getRepositoryVersionResourceProvider();
 
     final Set<Map<String, Object>> propertySet = new LinkedHashSet<Map<String, Object>>();
     final Map<String, Object> properties = new LinkedHashMap<String, Object>();