Browse Source

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

Nate Cole 10 năm trước cách đây
mục cha
commit
1bf2795a46
20 tập tin đã thay đổi với 1111 bổ sung46 xóa
  1. 38 0
      ambari-server/src/main/java/org/apache/ambari/server/api/resources/RepositoryVersionResourceDefinition.java
  2. 4 0
      ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
  3. 95 0
      ambari-server/src/main/java/org/apache/ambari/server/api/services/RepositoryVersionService.java
  4. 3 1
      ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
  5. 3 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
  6. 2 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
  7. 204 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RepositoryVersionResourceProvider.java
  8. 2 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
  9. 124 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RepositoryVersionDAO.java
  10. 147 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RepositoryVersionEntity.java
  11. 29 6
      ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
  12. 13 0
      ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
  13. 13 0
      ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
  14. 14 0
      ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
  15. 15 0
      ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
  16. 40 39
      ambari-server/src/main/resources/META-INF/persistence.xml
  17. 49 0
      ambari-server/src/test/java/org/apache/ambari/server/api/resources/RepositoryVersionResourceDefinitionTest.java
  18. 88 0
      ambari-server/src/test/java/org/apache/ambari/server/api/services/RepositoryVersionServiceTest.java
  19. 103 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RepositoryVersionResourceProviderTest.java
  20. 125 0
      ambari-server/src/test/java/org/apache/ambari/server/orm/dao/RepositoryVersionDAOTest.java

+ 38 - 0
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";
+  }
+
+}

+ 4 - 0
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;

+ 95 - 0
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));
+  }
+}

+ 3 - 1
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 {
     }
   }
 
-}
+}

+ 3 - 0
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();
 }

+ 2 - 0
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);
     }

+ 204 - 0
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;
+  }
+}

+ 2 - 0
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();
 

+ 124 - 0
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));
+  }
+}

+ 147 - 0
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;
+  }
+}

+ 29 - 6
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)");
   }
 
   /**

+ 13 - 0
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'

+ 13 - 0
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}');
 

+ 14 - 0
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

+ 15 - 0
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

+ 40 - 39
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" />-->

+ 49 - 0
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());
+  }
+}

+ 88 - 0
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();
+    }
+  }
+}

+ 103 - 0
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;
+  }
+}

+ 125 - 0
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;
+  }
+}