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/07 15:12:06 UTC

ambari git commit: AMBARI-8164. Repository Version Management - Create API and BE support for creating/retrieving repo versions (Yurii Shylov via ncole)

Repository: ambari
Updated Branches:
  refs/heads/trunk b67ddc7c1 -> 1bf2795a4


AMBARI-8164. Repository Version Management - Create API and BE support for creating/retrieving repo versions (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/1bf2795a
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/1bf2795a
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/1bf2795a

Branch: refs/heads/trunk
Commit: 1bf2795a462e9780f482de306b7eeaf3c6e51f13
Parents: b67ddc7
Author: Nate Cole <nc...@hortonworks.com>
Authored: Fri Nov 7 08:33:16 2014 -0500
Committer: Nate Cole <nc...@hortonworks.com>
Committed: Fri Nov 7 08:33:16 2014 -0500

----------------------------------------------------------------------
 .../RepositoryVersionResourceDefinition.java    |  38 ++++
 .../resources/ResourceInstanceFactoryImpl.java  |   4 +
 .../api/services/RepositoryVersionService.java  |  95 +++++++++
 .../server/controller/ControllerModule.java     |   4 +-
 .../controller/ResourceProviderFactory.java     |   3 +
 .../AbstractControllerResourceProvider.java     |   2 +
 .../RepositoryVersionResourceProvider.java      | 204 +++++++++++++++++++
 .../ambari/server/controller/spi/Resource.java  |   2 +
 .../server/orm/dao/RepositoryVersionDAO.java    | 124 +++++++++++
 .../orm/entities/RepositoryVersionEntity.java   | 147 +++++++++++++
 .../server/upgrade/UpgradeCatalog200.java       |  35 +++-
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |  13 ++
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |  13 ++
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |  14 ++
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |  15 ++
 .../src/main/resources/META-INF/persistence.xml |  79 +++----
 ...RepositoryVersionResourceDefinitionTest.java |  49 +++++
 .../services/RepositoryVersionServiceTest.java  |  88 ++++++++
 .../RepositoryVersionResourceProviderTest.java  | 103 ++++++++++
 .../orm/dao/RepositoryVersionDAOTest.java       | 125 ++++++++++++
 20 files changed, 1111 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RepositoryVersionResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RepositoryVersionResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RepositoryVersionResourceDefinition.java
new file mode 100644
index 0000000..34e9561
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RepositoryVersionResourceDefinition.java
@@ -0,0 +1,38 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.api.resources;
+
+import org.apache.ambari.server.controller.spi.Resource;
+
+public class RepositoryVersionResourceDefinition extends BaseResourceDefinition {
+
+  public RepositoryVersionResourceDefinition() {
+    super(Resource.Type.RepositoryVersion);
+  }
+
+  @Override
+  public String getPluralName() {
+    return "repository_versions";
+  }
+
+  @Override
+  public String getSingularName() {
+    return "repository_version";
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/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 c611191..9ad37ec 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
@@ -305,6 +305,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
         resourceDefinition = new LdapSyncEventResourceDefinition();
         break;
 
+      case RepositoryVersion:
+        resourceDefinition = new RepositoryVersionResourceDefinition();
+        break;
+
       case Upgrade:
         resourceDefinition = new UpgradeResourceDefinition();
         break;

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RepositoryVersionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/RepositoryVersionService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RepositoryVersionService.java
new file mode 100644
index 0000000..f9e8885
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/RepositoryVersionService.java
@@ -0,0 +1,95 @@
+/**
+ * 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 javax.ws.rs.GET;
+import javax.ws.rs.POST;
+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;
+
+import java.util.Collections;
+
+/**
+ * Service responsible for repository versions requests.
+ */
+@Path("/repository_versions/")
+public class RepositoryVersionService extends BaseService {
+  /**
+   * Gets all repository versions.
+   * Handles: GET /repository_versions requests.
+   *
+   * @param headers http headers
+   * @param ui      uri info
+   */
+  @GET
+  @Produces("text/plain")
+  public Response getRepositoryVersions(@Context HttpHeaders headers, @Context UriInfo ui) {
+    return handleRequest(headers, null, ui, Request.Type.GET, createResource(null));
+  }
+
+  /**
+   * Gets a single repository version.
+   * Handles: GET /repository_versions/{repositoryVersionId} requests.
+   *
+   * @param headers               http headers
+   * @param ui                    uri info
+   * @param repositoryVersionId   the repository version id
+   * @return information regarding the specified repository
+   */
+  @GET
+  @Path("{repositoryVersionId}")
+  @Produces("text/plain")
+  public Response getRepositoryVersion(@Context HttpHeaders headers, @Context UriInfo ui,
+      @PathParam("repositoryVersionId") String repositoryVersionId) {
+    return handleRequest(headers, null, ui, Request.Type.GET, createResource(repositoryVersionId));
+  }
+
+  /**
+   * Creates a repository version.
+   * Handles: POST /repository_versions requests.
+   *
+   * @param headers      http headers
+   * @param ui           uri info
+   * @return information regarding the created repository
+   */
+   @POST
+   @Produces("text/plain")
+   public Response createRepositoryVersion(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+    return handleRequest(headers, body, ui, Request.Type.POST, createResource(null));
+  }
+
+  /**
+   * Create a repository version resource instance.
+   *
+   * @param repositoryVersionId repository version id
+   *
+   * @return a repository resource instance
+   */
+  private ResourceInstance createResource(String repositoryVersionId) {
+    return createResource(Resource.Type.RepositoryVersion,
+        Collections.singletonMap(Resource.Type.RepositoryVersion, repositoryVersionId));
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index 52b0ba6..d74510a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -56,6 +56,7 @@ import org.apache.ambari.server.controller.internal.ComponentResourceProvider;
 import org.apache.ambari.server.controller.internal.HostComponentResourceProvider;
 import org.apache.ambari.server.controller.internal.HostResourceProvider;
 import org.apache.ambari.server.controller.internal.MemberResourceProvider;
+import org.apache.ambari.server.controller.internal.RepositoryVersionResourceProvider;
 import org.apache.ambari.server.controller.internal.ServiceResourceProvider;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
 import org.apache.ambari.server.orm.DBAccessor;
@@ -302,6 +303,7 @@ public class ControllerModule extends AbstractModule {
         .implement(ResourceProvider.class, Names.named("service"), ServiceResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("component"), ComponentResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("member"), MemberResourceProvider.class)
+        .implement(ResourceProvider.class, Names.named("repositoryVersion"), RepositoryVersionResourceProvider.class)
         .build(ResourceProviderFactory.class));
 
 
@@ -395,4 +397,4 @@ public class ControllerModule extends AbstractModule {
     }
   }
 
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/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 a5f5b05..212f944 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
@@ -52,4 +52,7 @@ public interface ResourceProviderFactory {
   ResourceProvider getMemberResourceProvider(Set<String> propertyIds,
       Map<Type, String> keyPropertyIds,
       AmbariManagementController managementController);
+
+  @Named("repositoryVersion")
+  ResourceProvider getRepositoryVersionProvider();
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/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 cb6c271..ae20f56 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
@@ -153,6 +153,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractResourc
         return new AlertResourceProvider(propertyIds, keyPropertyIds, managementController);
       case ClientConfig:
         return new ClientConfigResourceProvider(propertyIds, keyPropertyIds, managementController);
+      case RepositoryVersion:
+        return resourceProviderFactory.getRepositoryVersionProvider();
       default:
         throw new IllegalArgumentException("Unknown type " + type);
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RepositoryVersionResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RepositoryVersionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RepositoryVersionResourceProvider.java
new file mode 100644
index 0000000..6fb1448
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RepositoryVersionResourceProvider.java
@@ -0,0 +1,204 @@
+/**
+ * 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.AmbariException;
+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.Resource.Type;
+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.utilities.PropertyHelper;
+import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
+
+import com.google.gson.Gson;
+import com.google.inject.Inject;
+
+/**
+ * Resource provider for repository versions resources.
+ */
+public class RepositoryVersionResourceProvider extends AbstractResourceProvider {
+
+  // ----- Property ID constants ---------------------------------------------
+
+  protected static final String REPOSITORY_VERSION_ID_PROPERTY_ID           = PropertyHelper.getPropertyId("RepositoryVersions", "id");
+  protected static final String REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID = PropertyHelper.getPropertyId("RepositoryVersions", "display_name");
+  protected static final String REPOSITORY_VERSION_STACK_PROPERTY_ID        = PropertyHelper.getPropertyId("RepositoryVersions", "stack");
+  protected static final String REPOSITORY_VERSION_VERSION_PROPERTY_ID      = PropertyHelper.getPropertyId("RepositoryVersions", "version");
+  protected static final String REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID = PropertyHelper.getPropertyId("RepositoryVersions", "upgrade_pack");
+  protected static final String REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID = PropertyHelper.getPropertyId("RepositoryVersions", "repositories");
+
+  @SuppressWarnings("serial")
+  private static Set<String> pkPropertyIds = new HashSet<String>() {
+    {
+      add(REPOSITORY_VERSION_ID_PROPERTY_ID);
+    }
+  };
+
+  @SuppressWarnings("serial")
+  private static Set<String> propertyIds = new HashSet<String>() {
+    {
+      add(REPOSITORY_VERSION_ID_PROPERTY_ID);
+      add(REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID);
+      add(REPOSITORY_VERSION_STACK_PROPERTY_ID);
+      add(REPOSITORY_VERSION_VERSION_PROPERTY_ID);
+      add(REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID);
+      add(REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID);
+    }
+  };
+
+  @SuppressWarnings("serial")
+  private static Map<Type, String> keyPropertyIds = new HashMap<Type, String>() {
+    {
+      put(Resource.Type.RepositoryVersion, REPOSITORY_VERSION_ID_PROPERTY_ID);
+    }
+  };
+
+  @Inject
+  private RepositoryVersionDAO repositoryVersionDAO;
+
+  /**
+   * Create a new resource provider.
+   *
+   */
+  public RepositoryVersionResourceProvider() {
+    super(propertyIds, keyPropertyIds);
+  }
+
+  @Override
+  public RequestStatus createResources(final Request request)
+      throws SystemException,
+      UnsupportedPropertyException,
+      ResourceAlreadyExistsException,
+      NoSuchParentResourceException {
+
+    for (final Map<String, Object> properties : request.getProperties()) {
+      createResources(new Command<Void>() {
+
+        @Override
+        public Void invoke() throws AmbariException {
+          final RepositoryVersionEntity entity = new RepositoryVersionEntity();
+          final String[] requiredProperties = {
+              REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID,
+              REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID,
+              REPOSITORY_VERSION_STACK_PROPERTY_ID,
+              REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID,
+              REPOSITORY_VERSION_VERSION_PROPERTY_ID
+          };
+          for (String propertyName: requiredProperties) {
+            if (properties.get(propertyName) == null) {
+              throw new AmbariException("Property " + propertyName + " should be provided");
+            }
+          }
+          entity.setDisplayName(properties.get(REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID).toString());
+          entity.setStack(properties.get(REPOSITORY_VERSION_STACK_PROPERTY_ID).toString());
+          entity.setUpgradePackage(properties.get(REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID).toString());
+          entity.setVersion(properties.get(REPOSITORY_VERSION_VERSION_PROPERTY_ID).toString());
+          final Object repositories = properties.get(REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID);
+          entity.setRepositories(new Gson().toJson(repositories));
+
+          if (repositoryVersionDAO.findByDisplayName(entity.getDisplayName()) != null) {
+            throw new AmbariException("Repository version with name " + entity.getDisplayName() + " already exists");
+          }
+          if (repositoryVersionDAO.findByStackAndVersion(entity.getStack(), entity.getVersion()) != null) {
+            throw new AmbariException("Repository version for stack " + entity.getStack() + " and version " + entity.getVersion() + " already exists");
+          }
+          repositoryVersionDAO.create(entity);
+          notifyCreate(Resource.Type.RepositoryVersion, request);
+          return null;
+        }
+      });
+    }
+
+    return getRequestStatus(null);
+  }
+
+  @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<RepositoryVersionEntity> requestedEntities = new ArrayList<RepositoryVersionEntity>();
+    if (propertyMaps.isEmpty()) {
+      requestedEntities = repositoryVersionDAO.findAll();
+    } else {
+      for (Map<String, Object> propertyMap: propertyMaps) {
+        final Long id;
+        try {
+          id = Long.parseLong(propertyMap.get(REPOSITORY_VERSION_ID_PROPERTY_ID).toString());
+        } catch (Exception ex) {
+          throw new SystemException("Repository version should have numerical id");
+        }
+        final RepositoryVersionEntity entity = repositoryVersionDAO.findByPK(id);
+        if (entity == null) {
+          throw new NoSuchResourceException("There is no repository version with id " + id);
+        } else {
+          requestedEntities.add(entity);
+        }
+      }
+    }
+
+    for (RepositoryVersionEntity entity: requestedEntities) {
+      final Resource resource = new ResourceImpl(Resource.Type.RepositoryVersion);
+
+      setResourceProperty(resource, REPOSITORY_VERSION_ID_PROPERTY_ID, entity.getId(), requestedIds);
+      setResourceProperty(resource, REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID, entity.getDisplayName(), requestedIds);
+      setResourceProperty(resource, REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID, new Gson().fromJson(entity.getRepositories(), Object.class), requestedIds);
+      setResourceProperty(resource, REPOSITORY_VERSION_STACK_PROPERTY_ID, entity.getStack(), requestedIds);
+      setResourceProperty(resource, REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID, entity.getUpgradePackage(), requestedIds);
+      setResourceProperty(resource, REPOSITORY_VERSION_VERSION_PROPERTY_ID, entity.getVersion(), requestedIds);
+
+      if (predicate == null || predicate.evaluate(resource)) {
+        resources.add(resource);
+      }
+    }
+    return resources;
+  }
+
+  @Override
+  public RequestStatus updateResources(Request request, Predicate predicate)
+    throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public RequestStatus deleteResources(Predicate predicate)
+      throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return pkPropertyIds;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/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 fe4729e..dbac906 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
@@ -128,6 +128,7 @@ public interface Resource {
     StackLevelConfiguration,
     LdapSyncEvent,
     UserPrivilege,
+    RepositoryVersion,
     Upgrade,
     UpgradeItem;
 
@@ -218,6 +219,7 @@ public interface Resource {
     public static final Type StackLevelConfiguration = InternalType.StackLevelConfiguration.getType();
     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 Upgrade = InternalType.Upgrade.getType();
     public static final Type UpgradeItem = InternalType.UpgradeItem.getType();
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RepositoryVersionDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RepositoryVersionDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RepositoryVersionDAO.java
new file mode 100644
index 0000000..f0dcb44
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RepositoryVersionDAO.java
@@ -0,0 +1,124 @@
+/**
+ * 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.orm.dao;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+
+/**
+ * DAO for repository versions.
+ *
+ */
+@Singleton
+public class RepositoryVersionDAO {
+  @Inject
+  Provider<EntityManager> entityManagerProvider;
+  @Inject
+  DaoUtils daoUtils;
+
+  /**
+   * Retrieves repository version by primary key.
+   *
+   * @param repositoryVersionPK primary key
+   * @return null if there is no suitable repository version
+   */
+  @RequiresSession
+  public RepositoryVersionEntity findByPK(Long repositoryVersionPK) {
+    return entityManagerProvider.get().find(RepositoryVersionEntity.class, repositoryVersionPK);
+  }
+
+  /**
+   * Retrieves all repository versions.
+   *
+   * @return list of all repository versions
+   */
+  @RequiresSession
+  public List<RepositoryVersionEntity> findAll() {
+    final TypedQuery<RepositoryVersionEntity> query = entityManagerProvider.get().createQuery("SELECT repoversion FROM RepositoryVersionEntity repoversion", RepositoryVersionEntity.class);
+    return daoUtils.selectList(query);
+  }
+
+  /**
+   * Retrieves repository version by name.
+   *
+   * @param displayName display name
+   * @return null if there is no suitable repository version
+   */
+  @RequiresSession
+  public RepositoryVersionEntity findByDisplayName(String displayName) {
+    final TypedQuery<RepositoryVersionEntity> query = entityManagerProvider.get().createNamedQuery("repositoryVersionByDisplayName", RepositoryVersionEntity.class);
+    query.setParameter("displayname", displayName);
+    return daoUtils.selectSingle(query);
+  }
+
+  /**
+   * Retrieves repository version by stack and version.
+   *
+   * @param stack stack
+   * @param version version
+   * @return null if there is no suitable repository version
+   */
+  @RequiresSession
+  public RepositoryVersionEntity findByStackAndVersion(String stack, String version) {
+    final TypedQuery<RepositoryVersionEntity> query = entityManagerProvider.get().createNamedQuery("repositoryVersionByStackVersion", RepositoryVersionEntity.class);
+    query.setParameter("stack", stack);
+    query.setParameter("version", version);
+    return daoUtils.selectSingle(query);
+  }
+
+  /**
+   * Create repository version.
+   *
+   * @param repositoryVersion entity to create
+   */
+  @Transactional
+  public void create(RepositoryVersionEntity repositoryVersion) {
+    entityManagerProvider.get().persist(repositoryVersion);
+  }
+
+  /**
+   * Update repository version.
+   *
+   * @param repositoryVersion entity to update
+   * @return updated repository version
+   */
+  @Transactional
+  public RepositoryVersionEntity merge(RepositoryVersionEntity repositoryVersion) {
+    return entityManagerProvider.get().merge(repositoryVersion);
+  }
+
+  /**
+   * Deletes repository version.
+   *
+   * @param repositoryVersion entity to delete
+   */
+  @Transactional
+  public void remove(RepositoryVersionEntity repositoryVersion) {
+    entityManagerProvider.get().remove(merge(repositoryVersion));
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RepositoryVersionEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RepositoryVersionEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RepositoryVersionEntity.java
new file mode 100644
index 0000000..4578668
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RepositoryVersionEntity.java
@@ -0,0 +1,147 @@
+/**
+ * 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.orm.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.UniqueConstraint;
+
+@Entity
+@Table(name = "repo_version", uniqueConstraints = {
+    @UniqueConstraint(columnNames = {"display_name"}),
+    @UniqueConstraint(columnNames = {"stack", "version"})
+})
+@TableGenerator(name = "repository_version_id_generator",
+    table = "ambari_sequences",
+    pkColumnName = "sequence_name",
+    valueColumnName = "sequence_value",
+    pkColumnValue = "repo_version_id_seq",
+    initialValue = 0,
+    allocationSize = 1
+    )
+@NamedQueries({
+  @NamedQuery(name = "repositoryVersionByDisplayName", query = "SELECT repoversion FROM RepositoryVersionEntity repoversion WHERE repoversion.displayName=:displayname"),
+  @NamedQuery(name = "repositoryVersionByStackVersion", query = "SELECT repoversion FROM RepositoryVersionEntity repoversion WHERE repoversion.stack=:stack AND repoversion.version=:version")
+})
+public class RepositoryVersionEntity {
+
+  @Id
+  @Column(name = "repo_version_id")
+  @GeneratedValue(strategy = GenerationType.TABLE, generator = "repository_version_id_generator")
+  private Long id;
+
+  @Column(name = "stack")
+  private String stack;
+
+  @Column(name = "version")
+  private String version;
+
+  @Column(name = "display_name")
+  private String displayName;
+
+  @Column(name = "upgrade_package")
+  private String upgradePackage;
+
+  @Column(name = "repositories")
+  private String repositories;
+
+  // ----- RepositoryVersionEntity -------------------------------------------------------
+
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public String getStack() {
+    return stack;
+  }
+
+  public void setStack(String stack) {
+    this.stack = stack;
+  }
+
+  public String getVersion() {
+    return version;
+  }
+
+  public void setVersion(String version) {
+    this.version = version;
+  }
+
+  public String getDisplayName() {
+    return displayName;
+  }
+
+  public void setDisplayName(String displayName) {
+    this.displayName = displayName;
+  }
+
+  public String getUpgradePackage() {
+    return upgradePackage;
+  }
+
+  public void setUpgradePackage(String upgradePackage) {
+    this.upgradePackage = upgradePackage;
+  }
+
+  public String getRepositories() {
+    return repositories;
+  }
+
+  public void setRepositories(String repositories) {
+    this.repositories = repositories;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    RepositoryVersionEntity that = (RepositoryVersionEntity) o;
+
+    if (id != null ? !id.equals(that.id) : that.id != null) return false;
+    if (stack != null ? !stack.equals(that.stack) : that.stack != null) return false;
+    if (version != null ? !version.equals(that.version) : that.version != null) return false;
+    if (displayName != null ? !displayName.equals(that.displayName) : that.displayName != null) return false;
+    if (upgradePackage != null ? !upgradePackage.equals(that.upgradePackage) : that.upgradePackage != null) return false;
+    if (repositories != null ? !repositories.equals(that.repositories) : that.repositories != null) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = id != null ? id.hashCode() : 0;
+    result = 31 * result + (stack != null ? stack.hashCode() : 0);
+    result = 31 * result + (version != null ? version.hashCode() : 0);
+    result = 31 * result + (displayName != null ? displayName.hashCode() : 0);
+    result = 31 * result + (upgradePackage != null ? upgradePackage.hashCode() : 0);
+    result = 31 * result + (repositories != null ? repositories.hashCode() : 0);
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
index b1523fe..8e14bc1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
@@ -18,17 +18,19 @@
 
 package org.apache.ambari.server.upgrade;
 
-import com.google.inject.Inject;
-import com.google.inject.Injector;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.orm.DBAccessor.DBColumnInfo;
 import org.apache.ambari.server.orm.DBAccessor;
+import org.apache.ambari.server.orm.DBAccessor.DBColumnInfo;
 import org.apache.ambari.server.orm.dao.DaoUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.List;
+
+import com.google.inject.Inject;
+import com.google.inject.Injector;
 
 
 /**
@@ -87,6 +89,27 @@ public class UpgradeCatalog200 extends AbstractUpgradeCatalog {
     // add ignore_host column to alert_definition
     dbAccessor.addColumn(ALERT_TABLE_DEFINITION, new DBColumnInfo(
         "ignore_host", Short.class, 1, 0, false));
+
+    ddlUpdateRepositoryVersion();
+  }
+
+  /**
+   * Creates repoversion table and all its constraints and dependencies.
+   *
+   * @throws SQLException if SQL error happens
+   */
+  private void ddlUpdateRepositoryVersion() throws SQLException {
+    final List<DBColumnInfo> columns = new ArrayList<DBColumnInfo>();
+    columns.add(new DBColumnInfo("repoversion_id",  Long.class,    null,  null, false));
+    columns.add(new DBColumnInfo("stack",           String.class,  255,   null, false));
+    columns.add(new DBColumnInfo("version",         String.class,  255,   null, false));
+    columns.add(new DBColumnInfo("display_name",    String.class,  128,   null, false));
+    columns.add(new DBColumnInfo("upgrade_package", String.class,  255,   null, false));
+    columns.add(new DBColumnInfo("repositories",    char[].class,  32672, null, false));
+    dbAccessor.createTable("repoversion", columns, "repoversion_id");
+    dbAccessor.executeQuery("INSERT INTO ambari_sequences(sequence_name, sequence_value) VALUES('repoversion_id_seq', 0)", false);
+    dbAccessor.executeQuery("ALTER TABLE repoversion ADD CONSTRAINT UQ_repoversion_display_name UNIQUE (display_name)");
+    dbAccessor.executeQuery("ALTER TABLE repoversion ADD CONSTRAINT UQ_repoversion_stack_version UNIQUE (stack, version)");
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index 7646b73..dc58b81 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -111,6 +111,16 @@ CREATE TABLE adminprincipal (principal_id BIGINT NOT NULL, principal_type_id INT
 CREATE TABLE adminpermission (permission_id BIGINT NOT NULL, permission_name VARCHAR(255) NOT NULL, resource_type_id INTEGER NOT NULL, PRIMARY KEY(permission_id));
 CREATE TABLE adminprivilege (privilege_id BIGINT, permission_id BIGINT NOT NULL, resource_id BIGINT NOT NULL, principal_id BIGINT NOT NULL, PRIMARY KEY(privilege_id));
 
+CREATE TABLE repo_version (
+  repo_version_id BIGINT NOT NULL,
+  stack VARCHAR(255) NOT NULL,
+  version VARCHAR(255) NOT NULL,
+  display_name VARCHAR(128) NOT NULL,
+  upgrade_package VARCHAR(255) NOT NULL,
+  repositories LONGTEXT NOT NULL,
+  PRIMARY KEY(repo_version_id)
+);
+
 -- altering tables by creating unique constraints----------
 ALTER TABLE users ADD CONSTRAINT UNQ_users_0 UNIQUE (user_name, ldap_user);
 ALTER TABLE groups ADD CONSTRAINT UNQ_groups_0 UNIQUE (group_name, ldap_group);
@@ -121,6 +131,8 @@ ALTER TABLE viewinstance ADD CONSTRAINT UQ_viewinstance_name UNIQUE (view_name,
 ALTER TABLE viewinstance ADD CONSTRAINT UQ_viewinstance_name_id UNIQUE (view_instance_id, view_name, name);
 ALTER TABLE serviceconfig ADD CONSTRAINT UQ_scv_service_version UNIQUE (cluster_id, service_name, version);
 ALTER TABLE adminpermission ADD CONSTRAINT UQ_perm_name_resource_type_id UNIQUE (permission_name, resource_type_id);
+ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_display_name UNIQUE (display_name);
+ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_stack_version UNIQUE (stack, version);
 
 -- altering tables by creating foreign keys----------
 ALTER TABLE members ADD CONSTRAINT FK_members_group_id FOREIGN KEY (group_id) REFERENCES groups (group_id);
@@ -313,6 +325,7 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('alert_targe
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('alert_history_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('alert_notice_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('alert_current_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('repo_version_id_seq', 0);
 
 insert into adminresourcetype (resource_type_id, resource_type_name)
   select 1, 'AMBARI'

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index 6e5e68b..1857f8e 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -101,6 +101,16 @@ CREATE TABLE adminprincipal (principal_id NUMBER(19) NOT NULL, principal_type_id
 CREATE TABLE adminpermission (permission_id NUMBER(19) NOT NULL, permission_name VARCHAR(255) NOT NULL, resource_type_id NUMBER(10) NOT NULL, PRIMARY KEY(permission_id));
 CREATE TABLE adminprivilege (privilege_id NUMBER(19), permission_id NUMBER(19) NOT NULL, resource_id NUMBER(19) NOT NULL, principal_id NUMBER(19) NOT NULL, PRIMARY KEY(privilege_id));
 
+CREATE TABLE repo_version (
+  repo_version_id NUMBER(19) NOT NULL,
+  stack VARCHAR2(255) NOT NULL,
+  version VARCHAR2(255) NOT NULL,
+  display_name VARCHAR2(128) NOT NULL,
+  upgrade_package VARCHAR2(255) NOT NULL,
+  repositories CLOB NOT NULL,
+  PRIMARY KEY(repo_version_id)
+);
+
 --------altering tables by creating unique constraints----------
 ALTER TABLE users ADD CONSTRAINT UNQ_users_0 UNIQUE (user_name, ldap_user);
 ALTER TABLE groups ADD CONSTRAINT UNQ_groups_0 UNIQUE (group_name, ldap_group);
@@ -111,6 +121,8 @@ ALTER TABLE viewinstance ADD CONSTRAINT UQ_viewinstance_name UNIQUE (view_name,
 ALTER TABLE viewinstance ADD CONSTRAINT UQ_viewinstance_name_id UNIQUE (view_instance_id, view_name, name);
 ALTER TABLE serviceconfig ADD CONSTRAINT UQ_scv_service_version UNIQUE (cluster_id, service_name, version);
 ALTER TABLE adminpermission ADD CONSTRAINT UQ_perm_name_resource_type_id UNIQUE (permission_name, resource_type_id);
+ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_display_name UNIQUE (display_name);
+ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_stack_version UNIQUE (stack, version);
 
 --------altering tables by creating foreign keys----------
 ALTER TABLE members ADD CONSTRAINT FK_members_group_id FOREIGN KEY (group_id) REFERENCES groups (group_id);
@@ -304,6 +316,7 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('alert_targe
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('alert_history_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('alert_notice_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('alert_current_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('repo_version_id_seq', 0);
 
 INSERT INTO metainfo("metainfo_key", "metainfo_value") values ('version', '${ambariVersion}');
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index 226b9b5..641e3f0 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -133,6 +133,16 @@ CREATE TABLE adminprincipal (principal_id BIGINT NOT NULL, principal_type_id INT
 CREATE TABLE adminpermission (permission_id BIGINT NOT NULL, permission_name VARCHAR(255) NOT NULL, resource_type_id INTEGER NOT NULL, PRIMARY KEY(permission_id));
 CREATE TABLE adminprivilege (privilege_id BIGINT, permission_id BIGINT NOT NULL, resource_id BIGINT NOT NULL, principal_id BIGINT NOT NULL, PRIMARY KEY(privilege_id));
 
+CREATE TABLE repo_version (
+  repo_version_id BIGINT NOT NULL,
+  stack VARCHAR(255) NOT NULL,
+  version VARCHAR(255) NOT NULL,
+  display_name VARCHAR(128) NOT NULL,
+  upgrade_package VARCHAR(255) NOT NULL,
+  repositories TEXT NOT NULL,
+  PRIMARY KEY(repo_version_id)
+);
+
 --------altering tables by creating unique constraints----------
 ALTER TABLE clusterconfig ADD CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag);
 ALTER TABLE clusterconfig ADD CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version);
@@ -140,6 +150,8 @@ ALTER TABLE viewinstance ADD CONSTRAINT UQ_viewinstance_name UNIQUE (view_name,
 ALTER TABLE viewinstance ADD CONSTRAINT UQ_viewinstance_name_id UNIQUE (view_instance_id, view_name, name);
 ALTER TABLE serviceconfig ADD CONSTRAINT UQ_scv_service_version UNIQUE (cluster_id, service_name, version);
 ALTER TABLE adminpermission ADD CONSTRAINT UQ_perm_name_resource_type_id UNIQUE (permission_name, resource_type_id);
+ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_display_name UNIQUE (display_name);
+ALTER TABLE repo_version ADD CONSTRAINT UQ_repo_version_stack_version UNIQUE (stack, version);
 
 --------altering tables by creating foreign keys----------
 ALTER TABLE members ADD CONSTRAINT FK_members_group_id FOREIGN KEY (group_id) REFERENCES groups (group_id);
@@ -355,6 +367,8 @@ BEGIN;
   union all
   select 'config_id_seq', 1
   union all
+  select 'repo_version_id_seq', 0;
+  union all
   select 'cluster_version_id_seq', 0
   union all
   select 'host_version_id_seq', 0

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
index 0996ab1..c0cdc6d 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
@@ -198,6 +198,17 @@ GRANT ALL PRIVILEGES ON TABLE ambari.adminprincipal TO :username;
 GRANT ALL PRIVILEGES ON TABLE ambari.adminpermission TO :username;
 GRANT ALL PRIVILEGES ON TABLE ambari.adminprivilege TO :username;
 
+CREATE TABLE ambari.repo_version (
+  repo_version_id BIGINT,
+  stack VARCHAR(255) NOT NULL,
+  version VARCHAR(255) NOT NULL,
+  display_name VARCHAR(128) NOT NULL,
+  upgrade_package VARCHAR(255) NOT NULL,
+  repositories VARCHAR NOT NULL,
+  PRIMARY KEY(repo_version_id)
+);
+GRANT ALL PRIVILEGES ON TABLE ambari.repo_version TO :username;
+
 --------altering tables by creating unique constraints----------
 ALTER TABLE ambari.clusterconfig ADD CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag);
 ALTER TABLE ambari.clusterconfig ADD CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version);
@@ -205,6 +216,8 @@ ALTER TABLE ambari.viewinstance ADD CONSTRAINT UQ_viewinstance_name UNIQUE (view
 ALTER TABLE ambari.viewinstance ADD CONSTRAINT UQ_viewinstance_name_id UNIQUE (view_instance_id, view_name, name);
 ALTER TABLE ambari.serviceconfig ADD CONSTRAINT UQ_scv_service_version UNIQUE (cluster_id, service_name, version);
 ALTER TABLE ambari.adminpermission ADD CONSTRAINT UQ_perm_name_resource_type_id UNIQUE (permission_name, resource_type_id);
+ALTER TABLE ambari.repo_version ADD CONSTRAINT UQ_repo_version_display_name UNIQUE (display_name);
+ALTER TABLE ambari.repo_version ADD CONSTRAINT UQ_repo_version_stack_version UNIQUE (stack, version);
 
 --------altering tables by creating foreign keys----------
 ALTER TABLE ambari.members ADD CONSTRAINT FK_members_group_id FOREIGN KEY (group_id) REFERENCES ambari.groups (group_id);
@@ -430,6 +443,8 @@ INSERT INTO ambari.ambari_sequences (sequence_name, sequence_value)
   union all
   select 'config_id_seq', 1
   union all
+  select 'repo_version_id_seq', 0;
+  union all
   select 'cluster_version_id_seq', 0
   union all
   select 'host_version_id_seq', 0

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/ambari-server/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/META-INF/persistence.xml b/ambari-server/src/main/resources/META-INF/persistence.xml
index 77b50f8..0efba2d 100644
--- a/ambari-server/src/main/resources/META-INF/persistence.xml
+++ b/ambari-server/src/main/resources/META-INF/persistence.xml
@@ -14,63 +14,64 @@
 
   <persistence-unit name="ambari-server" transaction-type="RESOURCE_LOCAL">
     <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
-    <class>org.apache.ambari.server.orm.entities.ClusterEntity</class>
+    <class>org.apache.ambari.server.orm.entities.AlertCurrentEntity</class>
+    <class>org.apache.ambari.server.orm.entities.AlertDefinitionEntity</class>
+    <class>org.apache.ambari.server.orm.entities.AlertGroupEntity</class>
+    <class>org.apache.ambari.server.orm.entities.AlertHistoryEntity</class>
+    <class>org.apache.ambari.server.orm.entities.AlertNoticeEntity</class>
+    <class>org.apache.ambari.server.orm.entities.AlertTargetEntity</class>
+    <class>org.apache.ambari.server.orm.entities.BlueprintConfigEntity</class>
+    <class>org.apache.ambari.server.orm.entities.BlueprintEntity</class>
     <class>org.apache.ambari.server.orm.entities.ClusterConfigEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ClusterConfigMappingEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ClusterEntity</class>
     <class>org.apache.ambari.server.orm.entities.ClusterServiceEntity</class>
     <class>org.apache.ambari.server.orm.entities.ClusterStateEntity</class>
     <class>org.apache.ambari.server.orm.entities.ClusterVersionEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ConfigGroupConfigMappingEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ConfigGroupEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ConfigGroupHostMappingEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ExecutionCommandEntity</class>
+    <class>org.apache.ambari.server.orm.entities.GroupEntity</class>
     <class>org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity</class>
     <class>org.apache.ambari.server.orm.entities.HostComponentStateEntity</class>
+    <class>org.apache.ambari.server.orm.entities.HostConfigMappingEntity</class>
     <class>org.apache.ambari.server.orm.entities.HostEntity</class>
+    <class>org.apache.ambari.server.orm.entities.HostGroupComponentEntity</class>
+    <class>org.apache.ambari.server.orm.entities.HostGroupConfigEntity</class>
+    <class>org.apache.ambari.server.orm.entities.HostGroupEntity</class>
+    <class>org.apache.ambari.server.orm.entities.HostRoleCommandEntity</class>
     <class>org.apache.ambari.server.orm.entities.HostStateEntity</class>
     <class>org.apache.ambari.server.orm.entities.HostVersionEntity</class>
-    <class>org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity</class>
-    <class>org.apache.ambari.server.orm.entities.ServiceDesiredStateEntity</class>
-    <class>org.apache.ambari.server.orm.entities.UserEntity</class>
-    <class>org.apache.ambari.server.orm.entities.GroupEntity</class>
-    <class>org.apache.ambari.server.orm.entities.MemberEntity</class>
-    <class>org.apache.ambari.server.orm.entities.ExecutionCommandEntity</class>
-    <class>org.apache.ambari.server.orm.entities.HostRoleCommandEntity</class>
-    <class>org.apache.ambari.server.orm.entities.RoleSuccessCriteriaEntity</class>
-    <class>org.apache.ambari.server.orm.entities.StageEntity</class>
-    <class>org.apache.ambari.server.orm.entities.RequestEntity</class>
     <class>org.apache.ambari.server.orm.entities.KeyValueEntity</class>
-    <class>org.apache.ambari.server.orm.entities.ClusterConfigMappingEntity</class>
-    <class>org.apache.ambari.server.orm.entities.HostConfigMappingEntity</class>
+    <class>org.apache.ambari.server.orm.entities.MemberEntity</class>
     <class>org.apache.ambari.server.orm.entities.MetainfoEntity</class>
-    <class>org.apache.ambari.server.orm.entities.ConfigGroupEntity</class>
-    <class>org.apache.ambari.server.orm.entities.ConfigGroupConfigMappingEntity</class>
-    <class>org.apache.ambari.server.orm.entities.ConfigGroupHostMappingEntity</class>
-    <class>org.apache.ambari.server.orm.entities.RequestScheduleEntity</class>
-    <class>org.apache.ambari.server.orm.entities.RequestScheduleBatchRequestEntity</class>
-    <class>org.apache.ambari.server.orm.entities.BlueprintEntity</class>
-    <class>org.apache.ambari.server.orm.entities.BlueprintConfigEntity</class>
-    <class>org.apache.ambari.server.orm.entities.HostGroupEntity</class>
-    <class>org.apache.ambari.server.orm.entities.HostGroupComponentEntity</class>
-    <class>org.apache.ambari.server.orm.entities.HostGroupConfigEntity</class>
-    <class>org.apache.ambari.server.orm.entities.RequestResourceFilterEntity</class>
+    <class>org.apache.ambari.server.orm.entities.PermissionEntity</class>
+    <class>org.apache.ambari.server.orm.entities.PrincipalEntity</class>
+    <class>org.apache.ambari.server.orm.entities.PrincipalTypeEntity</class>
+    <class>org.apache.ambari.server.orm.entities.PrivilegeEntity</class>
+    <class>org.apache.ambari.server.orm.entities.RepositoryVersionEntity</class>
+    <class>org.apache.ambari.server.orm.entities.RequestEntity</class>
     <class>org.apache.ambari.server.orm.entities.RequestOperationLevelEntity</class>
+    <class>org.apache.ambari.server.orm.entities.RequestResourceFilterEntity</class>
+    <class>org.apache.ambari.server.orm.entities.RequestScheduleBatchRequestEntity</class>
+    <class>org.apache.ambari.server.orm.entities.RequestScheduleEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ResourceEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ResourceTypeEntity</class>
+    <class>org.apache.ambari.server.orm.entities.RoleSuccessCriteriaEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ServiceConfigApplicationEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ServiceConfigEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ServiceDesiredStateEntity</class>
+    <class>org.apache.ambari.server.orm.entities.StageEntity</class>
+    <class>org.apache.ambari.server.orm.entities.UserEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ViewEntityEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewInstanceDataEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewInstanceEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewInstancePropertyEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewParameterEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewResourceEntity</class>
-    <class>org.apache.ambari.server.orm.entities.ViewEntityEntity</class>
-    <class>org.apache.ambari.server.orm.entities.AlertCurrentEntity</class>
-    <class>org.apache.ambari.server.orm.entities.AlertDefinitionEntity</class>
-    <class>org.apache.ambari.server.orm.entities.AlertGroupEntity</class>
-    <class>org.apache.ambari.server.orm.entities.AlertHistoryEntity</class>
-    <class>org.apache.ambari.server.orm.entities.AlertNoticeEntity</class>
-    <class>org.apache.ambari.server.orm.entities.AlertTargetEntity</class>
-    <class>org.apache.ambari.server.orm.entities.ResourceTypeEntity</class>
-    <class>org.apache.ambari.server.orm.entities.ResourceEntity</class>
-    <class>org.apache.ambari.server.orm.entities.PrincipalTypeEntity</class>
-    <class>org.apache.ambari.server.orm.entities.PrincipalEntity</class>
-    <class>org.apache.ambari.server.orm.entities.PermissionEntity</class>
-    <class>org.apache.ambari.server.orm.entities.PrivilegeEntity</class>
-    <class>org.apache.ambari.server.orm.entities.ServiceConfigEntity</class>
-    <class>org.apache.ambari.server.orm.entities.ServiceConfigApplicationEntity</class>
 
     <properties>
       <!--<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost/ambari" />-->

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/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
new file mode 100644
index 0000000..c0e625a
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/RepositoryVersionResourceDefinitionTest.java
@@ -0,0 +1,49 @@
+/**
+ * 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;
+
+/**
+ * RepositoryVersionResourceDefinition tests.
+ */
+public class RepositoryVersionResourceDefinitionTest {
+  @Test
+  public void testGetPluralName() throws Exception {
+    final RepositoryVersionResourceDefinition RepositoryVersionResourceDefinition = new RepositoryVersionResourceDefinition();
+    Assert.assertEquals("repository_versions", RepositoryVersionResourceDefinition.getPluralName());
+  }
+
+  @Test
+  public void testGetSingularName() throws Exception {
+    RepositoryVersionResourceDefinition RepositoryVersionResourceDefinition = new RepositoryVersionResourceDefinition();
+    Assert.assertEquals("repository_version", RepositoryVersionResourceDefinition.getSingularName());
+  }
+
+  @Test
+  public void testGetSubResourceDefinitions() throws Exception {
+    RepositoryVersionResourceDefinition RepositoryVersionResourceDefinition = new RepositoryVersionResourceDefinition();
+    Set<SubResourceDefinition> subResourceDefinitions = RepositoryVersionResourceDefinition.getSubResourceDefinitions ();
+
+    Assert.assertEquals(0, subResourceDefinitions.size());
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/ambari-server/src/test/java/org/apache/ambari/server/api/services/RepositoryVersionServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/RepositoryVersionServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/RepositoryVersionServiceTest.java
new file mode 100644
index 0000000..94b4963
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/RepositoryVersionServiceTest.java
@@ -0,0 +1,88 @@
+/**
+ * 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 RepositoryVersionService.
+ */
+public class RepositoryVersionServiceTest extends BaseServiceTest {
+
+  public List<ServiceTestInvocation> getTestInvocations() throws Exception {
+    List<ServiceTestInvocation> listInvocations = new ArrayList<ServiceTestInvocation>();
+
+    RepositoryVersionService RepositoryVersionService;
+    Method m;
+    Object[] args;
+
+    //getRepositoryVersions
+    RepositoryVersionService = new TestRepositoryVersionService();
+    m = RepositoryVersionService.getClass().getMethod("getRepositoryVersions", HttpHeaders.class, UriInfo.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo()};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, RepositoryVersionService, m, args, null));
+
+    //getRepositoryVersion
+    RepositoryVersionService = new TestRepositoryVersionService();
+    m = RepositoryVersionService.getClass().getMethod("getRepositoryVersion", HttpHeaders.class, UriInfo.class, String.class);
+    args = new Object[] {getHttpHeaders(), getUriInfo(), "RepositoryVersionname"};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.GET, RepositoryVersionService, m, args, null));
+
+    //createRepositoryVersion
+    RepositoryVersionService = new TestRepositoryVersionService();
+    m = RepositoryVersionService.getClass().getMethod("createRepositoryVersion", String.class, HttpHeaders.class, UriInfo.class);
+    args = new Object[] {"body", getHttpHeaders(), getUriInfo()};
+    listInvocations.add(new ServiceTestInvocation(Request.Type.POST, RepositoryVersionService, m, args, "body"));
+
+    return listInvocations;
+  }
+
+  private class TestRepositoryVersionService extends RepositoryVersionService {
+    @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/1bf2795a/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
new file mode 100644
index 0000000..9dc4996
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RepositoryVersionResourceProviderTest.java
@@ -0,0 +1,103 @@
+/**
+ * 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.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import junit.framework.Assert;
+
+import org.apache.ambari.server.controller.ResourceProviderFactory;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.orm.GuiceJpaInitializer;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+
+/**
+ * RepositoryVersionResourceProvider tests.
+ */
+public class RepositoryVersionResourceProviderTest {
+
+  private static Injector injector;
+
+  @Before
+  public void before() {
+    injector = Guice.createInjector(new InMemoryDefaultTestModule());
+    injector.getInstance(GuiceJpaInitializer.class);
+  }
+
+  @Test
+  public void testCreateResources() throws Exception {
+    final ResourceProvider provider = injector.getInstance(ResourceProviderFactory.class).getRepositoryVersionProvider();
+
+    final Set<Map<String, Object>> propertySet = new LinkedHashSet<Map<String, Object>>();
+    final Map<String, Object> properties = new LinkedHashMap<String, Object>();
+    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID, "name");
+    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_REPOSITORIES_PROPERTY_ID, "repositories");
+    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_PROPERTY_ID, "stack");
+    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_UPGRADE_PACK_PROPERTY_ID, "upgrade");
+    properties.put(RepositoryVersionResourceProvider.REPOSITORY_VERSION_VERSION_PROPERTY_ID, "version");
+    propertySet.add(properties);
+
+    final Request getRequest = PropertyHelper.getReadRequest(RepositoryVersionResourceProvider.REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID);
+    Assert.assertEquals(0, provider.getResources(getRequest, null).size());
+
+    final Request createRequest = PropertyHelper.getCreateRequest(propertySet, null);
+    provider.createResources(createRequest);
+
+    Assert.assertEquals(1, provider.getResources(getRequest, null).size());
+  }
+
+  @Test
+  public void testGetResources() throws Exception {
+    final ResourceProvider provider = injector.getInstance(ResourceProviderFactory.class).getRepositoryVersionProvider();
+    final RepositoryVersionDAO repositoryVersionDAO = injector.getInstance(RepositoryVersionDAO.class);
+    final RepositoryVersionEntity entity = new RepositoryVersionEntity();
+    entity.setDisplayName("name");
+    entity.setRepositories("repositories");
+    entity.setStack("stack");
+    entity.setUpgradePackage("upgrade");
+    entity.setVersion("version");
+
+    final Request getRequest = PropertyHelper.getReadRequest(RepositoryVersionResourceProvider.REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID);
+    Assert.assertEquals(0, provider.getResources(getRequest, null).size());
+
+    repositoryVersionDAO.create(entity);
+
+    Assert.assertEquals(1, provider.getResources(getRequest, null).size());
+  }
+
+  @After
+  public void after() {
+    injector.getInstance(PersistService.class).stop();
+    injector = null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/1bf2795a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/RepositoryVersionDAOTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/RepositoryVersionDAOTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/RepositoryVersionDAOTest.java
new file mode 100644
index 0000000..7dd3fab
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/RepositoryVersionDAOTest.java
@@ -0,0 +1,125 @@
+/**
+ * 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.orm.dao;
+
+import org.apache.ambari.server.orm.GuiceJpaInitializer;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+
+/**
+ * RepositoryVersionDAO unit tests.
+ */
+public class RepositoryVersionDAOTest {
+
+  private static Injector injector;
+  private RepositoryVersionDAO repositoryVersionDAO;
+  private int uniqueCounter = 0;
+  private static final long FIRST_ID = 1L;
+
+  @Before
+  public void before() {
+    injector = Guice.createInjector(new InMemoryDefaultTestModule());
+    repositoryVersionDAO = injector.getInstance(RepositoryVersionDAO.class);
+    injector.getInstance(GuiceJpaInitializer.class);
+  }
+
+  private void createSingleRecord() {
+    final RepositoryVersionEntity entity = new RepositoryVersionEntity();
+    entity.setDisplayName("display name" + uniqueCounter);
+    entity.setRepositories("repositories");
+    entity.setStack("stack" + uniqueCounter);
+    entity.setUpgradePackage("upgrade package");
+    entity.setVersion("version");
+    repositoryVersionDAO.create(entity);
+    uniqueCounter++;
+  }
+
+  @Test
+  public void testFindByPK() {
+    Assert.assertNull(repositoryVersionDAO.findByPK(FIRST_ID));
+    createSingleRecord();
+    Assert.assertNotNull(repositoryVersionDAO.findByPK(FIRST_ID));
+  }
+
+  @Test
+  public void testFindAll() {
+    Assert.assertEquals(0, repositoryVersionDAO.findAll().size());
+    createSingleRecord();
+    createSingleRecord();
+    Assert.assertEquals(2, repositoryVersionDAO.findAll().size());
+    repositoryVersionDAO.remove(repositoryVersionDAO.findByPK(FIRST_ID));
+    Assert.assertEquals(1, repositoryVersionDAO.findAll().size());
+  }
+
+  @Test
+  public void testFindByDisplayName() {
+    createSingleRecord();
+    Assert.assertNull(repositoryVersionDAO.findByDisplayName("non existing"));
+    Assert.assertNotNull(repositoryVersionDAO.findByDisplayName("display name0"));
+  }
+
+  @Test
+  public void testFindByStackAndVersion() {
+    createSingleRecord();
+    Assert.assertNull(repositoryVersionDAO.findByStackAndVersion("non existing", "non existing"));
+    Assert.assertNotNull(repositoryVersionDAO.findByStackAndVersion("stack0", "version"));
+  }
+
+  @Test
+  public void testCreate() {
+    createSingleRecord();
+    Assert.assertTrue(repositoryVersionDAO.findAll().size() == 1);
+    createSingleRecord();
+    Assert.assertTrue(repositoryVersionDAO.findAll().size() == 2);
+  }
+
+  @Test
+  public void testMerge() {
+    createSingleRecord();
+    RepositoryVersionEntity entity = repositoryVersionDAO.findByPK(FIRST_ID);
+    entity.setDisplayName("newname");
+    repositoryVersionDAO.merge(entity);
+    entity = repositoryVersionDAO.findByPK(FIRST_ID);
+    Assert.assertEquals("newname", entity.getDisplayName());
+  }
+
+  @Test
+  public void testRemove() {
+    createSingleRecord();
+    createSingleRecord();
+    Assert.assertEquals(2, repositoryVersionDAO.findAll().size());
+    repositoryVersionDAO.remove(repositoryVersionDAO.findByPK(FIRST_ID));
+    Assert.assertEquals(1, repositoryVersionDAO.findAll().size());
+    Assert.assertNull(repositoryVersionDAO.findByPK(1L));
+  }
+
+  @After
+  public void after() {
+    injector.getInstance(PersistService.class).stop();
+    injector = null;
+  }
+}