Kaynağa Gözat

AMBARI-3552. Define ConfigGroup DAO and the relational schema. (swagle)

Siddharth Wagle 11 yıl önce
ebeveyn
işleme
0321de69c6

+ 88 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ConfigGroupConfigMappingDAO.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.orm.dao;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+import org.apache.ambari.server.orm.entities.ConfigGroupConfigMappingEntity;
+import org.apache.ambari.server.orm.entities.ConfigGroupConfigMappingEntityPK;
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+import java.util.List;
+
+@Singleton
+public class ConfigGroupConfigMappingDAO {
+  @Inject
+  Provider<EntityManager> entityManagerProvider;
+  @Inject
+  DaoUtils daoUtils;
+
+  @Transactional
+  public ConfigGroupConfigMappingEntity findByPK
+    (ConfigGroupConfigMappingEntityPK configGroupConfigMappingEntityPK) {
+    return entityManagerProvider.get().find(ConfigGroupConfigMappingEntity.class,
+      configGroupConfigMappingEntityPK);
+  }
+
+  @Transactional
+  public List<ConfigGroupConfigMappingEntity> findByGroup(Long groupId) {
+    TypedQuery<ConfigGroupConfigMappingEntity> query = entityManagerProvider
+      .get().createNamedQuery("configsByGroup", ConfigGroupConfigMappingEntity.class);
+
+    query.setParameter("groupId", groupId);
+    try {
+      return query.getResultList();
+    } catch (NoResultException ignored) {
+    }
+    return null;
+  }
+
+  @Transactional
+  public void create(ConfigGroupConfigMappingEntity
+                         configGroupConfigMappingEntity) {
+    entityManagerProvider.get().persist(configGroupConfigMappingEntity);
+  }
+
+  @Transactional
+  public ConfigGroupConfigMappingEntity merge(ConfigGroupConfigMappingEntity
+                        configGroupConfigMappingEntity) {
+    return entityManagerProvider.get().merge(configGroupConfigMappingEntity);
+  }
+
+  @Transactional
+  public void refresh(ConfigGroupConfigMappingEntity
+                          configGroupConfigMappingEntity) {
+    entityManagerProvider.get().refresh(configGroupConfigMappingEntity);
+  }
+
+  @Transactional
+  public void remove(ConfigGroupConfigMappingEntity
+                         configGroupConfigMappingEntity) {
+    entityManagerProvider.get().remove(merge(configGroupConfigMappingEntity));
+  }
+
+  @Transactional
+  public void removeByPK(ConfigGroupConfigMappingEntityPK
+                           configGroupConfigMappingEntityPK) {
+    entityManagerProvider.get().remove(findByPK
+      (configGroupConfigMappingEntityPK));
+  }
+}

+ 119 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ConfigGroupDAO.java

@@ -0,0 +1,119 @@
+/**
+ * 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 com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+import org.apache.ambari.server.orm.entities.ConfigGroupEntity;
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+import java.util.List;
+
+@Singleton
+public class ConfigGroupDAO {
+  @Inject
+  Provider<EntityManager> entityManagerProvider;
+
+  // DAO methods on config group
+
+  /**
+   * Find config group by its unique name
+   * @param groupName
+   * @return ConfigGroupEntity
+   */
+  @Transactional
+  public ConfigGroupEntity findByName(String groupName) {
+    TypedQuery<ConfigGroupEntity> query = entityManagerProvider.get()
+      .createNamedQuery("configGroupByName", ConfigGroupEntity.class);
+    query.setParameter("groupName", groupName);
+    try {
+      return query.getSingleResult();
+    } catch (NoResultException ignored) {
+      return null;
+    }
+  }
+
+  /**
+   * Find config group by its id
+   * @param id
+   * @return
+   */
+  @Transactional
+  public ConfigGroupEntity findById(Long id) {
+    return entityManagerProvider.get().find(ConfigGroupEntity.class, id);
+  }
+
+  @Transactional
+  public List<ConfigGroupEntity> findAll() {
+    TypedQuery<ConfigGroupEntity> query = entityManagerProvider.get()
+      .createNamedQuery("allConfigGroups", ConfigGroupEntity.class);
+    try {
+      return query.getResultList();
+    } catch (NoResultException ignored) {
+    }
+    return null;
+  }
+
+  @Transactional
+  public void create(ConfigGroupEntity configGroupEntity) {
+    entityManagerProvider.get().persist(configGroupEntity);
+  }
+
+  @Transactional
+  public ConfigGroupEntity merge(ConfigGroupEntity configGroupEntity) {
+    return entityManagerProvider.get().merge(configGroupEntity);
+  }
+
+  @Transactional
+  public void remove(ConfigGroupEntity configGroupEntity) {
+    entityManagerProvider.get().remove(merge(configGroupEntity));
+  }
+
+  @Transactional
+  public void removeByPK(Long id) {
+    entityManagerProvider.get().remove(findById(id));
+  }
+
+  @Transactional
+  public void refresh(ConfigGroupEntity configGroupEntity) {
+    entityManagerProvider.get().refresh(configGroupEntity);
+  }
+
+  // DAO methods on associated objects
+
+  /**
+   * Find config groups by service name and so on
+   * @param tag
+   * @return
+   */
+  @Transactional
+  public List<ConfigGroupEntity> findAllByTag(String tag) {
+    TypedQuery<ConfigGroupEntity> query = entityManagerProvider.get()
+      .createNamedQuery("configGroupsByTag", ConfigGroupEntity.class);
+    query.setParameter("tagName", tag);
+    try {
+      return query.getResultList();
+    } catch (NoResultException ignored) {
+    }
+    return null;
+  }
+
+}

+ 103 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ConfigGroupHostMappingDAO.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.orm.dao;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+import org.apache.ambari.server.orm.entities.ConfigGroupHostMappingEntity;
+import org.apache.ambari.server.orm.entities.ConfigGroupHostMappingEntityPK;
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+import java.util.List;
+
+@Singleton
+public class ConfigGroupHostMappingDAO {
+  @Inject
+  Provider<EntityManager> entityManagerProvider;
+  @Inject
+  DaoUtils daoUtils;
+
+  @Transactional
+  public ConfigGroupHostMappingEntity findByPK(ConfigGroupHostMappingEntityPK
+        configGroupHostMappingEntityPK) {
+    return entityManagerProvider.get().find(ConfigGroupHostMappingEntity
+      .class, configGroupHostMappingEntityPK);
+  }
+
+  @Transactional
+  public List<ConfigGroupHostMappingEntity> findByHost(String hostname) {
+    TypedQuery<ConfigGroupHostMappingEntity> query = entityManagerProvider
+      .get().createNamedQuery("groupsByHost", ConfigGroupHostMappingEntity
+        .class);
+
+    query.setParameter("hostname", hostname);
+    try {
+      return query.getResultList();
+    } catch (NoResultException ignored) {
+    }
+    return null;
+  }
+
+  @Transactional
+  public List<ConfigGroupHostMappingEntity> findByGroup(Long groupId) {
+    TypedQuery<ConfigGroupHostMappingEntity> query = entityManagerProvider
+      .get().createNamedQuery("hostsByGroup", ConfigGroupHostMappingEntity
+        .class);
+
+    query.setParameter("groupId", groupId);
+    try {
+      return query.getResultList();
+    } catch (NoResultException ignored) {
+    }
+    return null;
+  }
+
+  @Transactional
+  public void create(ConfigGroupHostMappingEntity
+                         configGroupHostMappingEntity) {
+    entityManagerProvider.get().persist(configGroupHostMappingEntity);
+  }
+
+  @Transactional
+  public ConfigGroupHostMappingEntity merge(ConfigGroupHostMappingEntity
+                         configGroupHostMappingEntity) {
+    return entityManagerProvider.get().merge(configGroupHostMappingEntity);
+  }
+
+  @Transactional
+  public void refresh(ConfigGroupHostMappingEntity
+                         configGroupHostMappingEntity) {
+    entityManagerProvider.get().refresh(configGroupHostMappingEntity);
+  }
+
+  @Transactional
+  public void remove(ConfigGroupHostMappingEntity
+                         configGroupHostMappingEntity) {
+    entityManagerProvider.get().remove(merge(configGroupHostMappingEntity));
+  }
+
+  @Transactional
+  public void removeByPK(ConfigGroupHostMappingEntityPK
+                         configGroupHostMappingEntityPK) {
+    entityManagerProvider.get().remove(findByPK
+      (configGroupHostMappingEntityPK));
+  }
+}

+ 12 - 1
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterConfigEntity.java

@@ -61,7 +61,10 @@ public class ClusterConfigEntity {
 
   @OneToMany(mappedBy = "clusterConfigEntity")
   private Collection<ComponentConfigMappingEntity> componentConfigMappingEntities;
-  
+
+  @OneToMany(mappedBy = "clusterConfigEntity")
+  private Collection<ConfigGroupConfigMappingEntity> configGroupConfigMappingEntities;
+
   public Long getClusterId() {
     return clusterId;
   }
@@ -162,4 +165,12 @@ public class ClusterConfigEntity {
   public void setComponentConfigMappingEntities(Collection<ComponentConfigMappingEntity> componentConfigMappingEntities) {
     this.componentConfigMappingEntities = componentConfigMappingEntities;
   }
+
+  public Collection<ConfigGroupConfigMappingEntity> getConfigGroupConfigMappingEntities() {
+    return configGroupConfigMappingEntities;
+  }
+
+  public void setConfigGroupConfigMappingEntities(Collection<ConfigGroupConfigMappingEntity> configGroupConfigMappingEntities) {
+    this.configGroupConfigMappingEntities = configGroupConfigMappingEntities;
+  }
 }

+ 148 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ConfigGroupConfigMappingEntity.java

@@ -0,0 +1,148 @@
+/**
+ * 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.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "configgroupclusterconfigmapping")
+@IdClass(ConfigGroupConfigMappingEntityPK.class)
+@NamedQueries({
+  @NamedQuery(name = "configsByGroup", query =
+  "SELECT configs FROM ConfigGroupConfigMappingEntity configs " +
+    "WHERE configs.configGroupId=:groupId")
+})
+public class ConfigGroupConfigMappingEntity {
+  @Id
+  @Column(name = "config_group_id", nullable = false, insertable = true, updatable = true)
+  private Long configGroupId;
+
+  @Id
+  @Column(name = "cluster_id", nullable = false, insertable = true, updatable = false)
+  private Long clusterId;
+
+  @Id
+  @Column(name = "config_type", nullable = false, insertable = true, updatable = false)
+  private String configType;
+
+  @Column(name = "version_tag", nullable = false, insertable = true, updatable = false)
+  private String versionTag;
+
+  @Column(name = "create_timestamp", nullable = false, insertable = true, updatable = true)
+  private Long timestamp;
+
+  @ManyToOne
+  @JoinColumns({
+    @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false, insertable = false, updatable = false),
+    @JoinColumn(name = "config_type", referencedColumnName = "type_name", nullable = false, insertable = false, updatable = false),
+    @JoinColumn(name = "version_tag", referencedColumnName = "version_tag", nullable = false, insertable = false, updatable = false)
+  })
+  private ClusterConfigEntity clusterConfigEntity;
+
+  @ManyToOne
+  @JoinColumns({
+    @JoinColumn(name = "config_group_id", referencedColumnName = "group_id", nullable = false, insertable = false, updatable = false)})
+  private ConfigGroupEntity configGroupEntity;
+
+  public Long getConfigGroupId() {
+    return configGroupId;
+  }
+
+  public void setConfigGroupId(Long configGroupId) {
+    this.configGroupId = configGroupId;
+  }
+
+  public Long getClusterId() {
+    return clusterId;
+  }
+
+  public void setClusterId(Long clusterId) {
+    this.clusterId = clusterId;
+  }
+
+  public String getConfigType() {
+    return configType;
+  }
+
+  public void setConfigType(String configType) {
+    this.configType = configType;
+  }
+
+  public String getVersionTag() {
+    return versionTag;
+  }
+
+  public void setVersionTag(String versionTag) {
+    this.versionTag = versionTag;
+  }
+
+  public Long getTimestamp() {
+    return timestamp;
+  }
+
+  public void setTimestamp(Long timestamp) {
+    this.timestamp = timestamp;
+  }
+
+  public ClusterConfigEntity getClusterConfigEntity() {
+    return clusterConfigEntity;
+  }
+
+  public void setClusterConfigEntity(ClusterConfigEntity clusterConfigEntity) {
+    this.clusterConfigEntity = clusterConfigEntity;
+  }
+
+  public ConfigGroupEntity getConfigGroupEntity() {
+    return configGroupEntity;
+  }
+
+  public void setConfigGroupEntity(ConfigGroupEntity configGroupEntity) {
+    this.configGroupEntity = configGroupEntity;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ConfigGroupConfigMappingEntity that = (ConfigGroupConfigMappingEntity) o;
+
+    if (!clusterId.equals(that.clusterId)) return false;
+    if (!configGroupId.equals(that.configGroupId)) return false;
+    if (!configType.equals(that.configType)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = configGroupId.hashCode();
+    result = 31 * result + clusterId.hashCode();
+    result = 31 * result + configType.hashCode();
+    return result;
+  }
+}

+ 80 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ConfigGroupConfigMappingEntityPK.java

@@ -0,0 +1,80 @@
+/**
+ * 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.Id;
+import java.io.Serializable;
+
+public class ConfigGroupConfigMappingEntityPK implements Serializable {
+  private Long configGroupId;
+  private Long clusterId;
+  private String configType;
+
+  @Id
+  @Column(name = "config_group_id", nullable = false, insertable = true, updatable = true)
+  public Long getConfigGroupId() {
+    return configGroupId;
+  }
+
+  public void setConfigGroupId(Long configGroupId) {
+    this.configGroupId = configGroupId;
+  }
+
+  @Id
+  @Column(name = "cluster_id", nullable = false, insertable = true, updatable = true, length = 10)
+  public Long getClusterId() {
+    return clusterId;
+  }
+
+  public void setClusterId(Long clusterId) {
+    this.clusterId = clusterId;
+  }
+
+  @Id
+  @Column(name = "config_type", nullable = false, insertable = true, updatable = true)
+  public String getConfigType() {
+    return configType;
+  }
+
+  public void setConfigType(String configType) {
+    this.configType = configType;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ConfigGroupConfigMappingEntityPK that = (ConfigGroupConfigMappingEntityPK) o;
+
+    if (!clusterId.equals(that.clusterId)) return false;
+    if (!configGroupId.equals(that.configGroupId)) return false;
+    if (!configType.equals(that.configType)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = configGroupId.hashCode();
+    result = 31 * result + clusterId.hashCode();
+    result = 31 * result + configType.hashCode();
+    return result;
+  }
+}

+ 181 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ConfigGroupEntity.java

@@ -0,0 +1,181 @@
+/**
+ * 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.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import java.util.Collection;
+
+@Table(name = "configgroup")
+@Entity
+@NamedQueries({
+  @NamedQuery(name = "configGroupByName", query =
+    "SELECT configgroup " +
+      "FROM ConfigGroupEntity configgroup " +
+      "WHERE configgroup.groupName=:groupName"),
+  @NamedQuery(name = "allConfigGroups", query =
+    "SELECT configgroup " +
+      "FROM ConfigGroupEntity configgroup"),
+  @NamedQuery(name = "configGroupsByTag", query =
+    "SELECT configgroup FROM ConfigGroupEntity configgroup " +
+    "WHERE configgroup.tag=:tagName")
+})
+@TableGenerator(name = "configgroup_id_generator",
+  table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "value"
+  , pkColumnValue = "configgroup_id_seq"
+  , initialValue = 1
+  , allocationSize = 1
+)
+public class ConfigGroupEntity {
+  @Id
+  @Column(name = "group_id", nullable = false, insertable = true, updatable = true)
+  @GeneratedValue(strategy = GenerationType.TABLE, generator = "configgroup_id_generator")
+  private Long groupId;
+
+  @Column(name = "cluster_id", insertable = false, updatable = false, nullable = false)
+  private Long clusterId;
+
+  @Column(name = "group_name", nullable = false, unique = true, updatable = true)
+  private String groupName;
+
+  @Column(name = "tag", nullable = false)
+  private String tag;
+
+  @Column(name = "description")
+  private String description;
+
+  @Column(name = "create_timestamp", nullable=false, insertable=true, updatable=false)
+  private long timestamp;
+
+  @ManyToOne
+  @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false)
+  private ClusterEntity clusterEntity;
+
+  @OneToMany(mappedBy = "configGroupEntity", cascade = CascadeType.ALL)
+  private Collection<ConfigGroupHostMappingEntity> configGroupHostMappingEntities;
+
+  @OneToMany(mappedBy = "configGroupEntity", cascade = CascadeType.ALL)
+  private Collection<ConfigGroupConfigMappingEntity> configGroupConfigMappingEntities;
+
+  public Long getGroupId() {
+    return groupId;
+  }
+
+  public void setGroupId(Long groupId) {
+    this.groupId = groupId;
+  }
+
+  public Long getClusterId() {
+    return clusterId;
+  }
+
+  public void setClusterId(Long clusterId) {
+    this.clusterId = clusterId;
+  }
+
+  public String getGroupName() {
+    return groupName;
+  }
+
+  public void setGroupName(String groupName) {
+    this.groupName = groupName;
+  }
+
+  public String getTag() {
+    return tag;
+  }
+
+  public void setTag(String tag) {
+    this.tag = tag;
+  }
+
+  public String getDescription() {
+    return description;
+  }
+
+  public void setDescription(String description) {
+    this.description = description;
+  }
+
+  public long getTimestamp() {
+    return timestamp;
+  }
+
+  public void setTimestamp(long timestamp) {
+    this.timestamp = timestamp;
+  }
+
+  public ClusterEntity getClusterEntity() {
+    return clusterEntity;
+  }
+
+  public void setClusterEntity(ClusterEntity clusterEntity) {
+    this.clusterEntity = clusterEntity;
+  }
+
+  public Collection<ConfigGroupHostMappingEntity> getConfigGroupHostMappingEntities() {
+    return configGroupHostMappingEntities;
+  }
+
+  public void setConfigGroupHostMappingEntities(Collection<ConfigGroupHostMappingEntity> configGroupHostMappingEntities) {
+    this.configGroupHostMappingEntities = configGroupHostMappingEntities;
+  }
+
+  public Collection<ConfigGroupConfigMappingEntity> getConfigGroupConfigMappingEntities() {
+    return configGroupConfigMappingEntities;
+  }
+
+  public void setConfigGroupConfigMappingEntities(Collection<ConfigGroupConfigMappingEntity> configGroupConfigMappingEntities) {
+    this.configGroupConfigMappingEntities = configGroupConfigMappingEntities;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ConfigGroupEntity that = (ConfigGroupEntity) o;
+
+    if (!clusterId.equals(that.clusterId)) return false;
+    if (!groupId.equals(that.groupId)) return false;
+    if (!groupName.equals(that.groupName)) return false;
+    if (!tag.equals(that.tag)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = groupId.hashCode();
+    result = 31 * result + clusterId.hashCode();
+    result = 31 * result + groupName.hashCode();
+    result = 31 * result + tag.hashCode();
+    return result;
+  }
+}

+ 113 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ConfigGroupHostMappingEntity.java

@@ -0,0 +1,113 @@
+/**
+ * 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.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+
+@IdClass(ConfigGroupHostMappingEntityPK.class)
+@Entity
+@Table(name = "configgrouphostmapping")
+@NamedQueries({
+  @NamedQuery(name = "groupsByHost", query =
+  "SELECT confighosts FROM ConfigGroupHostMappingEntity confighosts " +
+    "WHERE confighosts.hostname=:hostname"),
+  @NamedQuery(name = "hostsByGroup", query =
+  "SELECT confighosts FROM ConfigGroupHostMappingEntity confighosts " +
+    "WHERE confighosts.configGroupId=:groupId")
+})
+public class ConfigGroupHostMappingEntity {
+
+  @Id
+  @Column(name = "config_group_id", nullable = false, insertable = true, updatable = true)
+  private Long configGroupId;
+
+  @Id
+  @Column(name = "host_name", nullable = false, insertable = true, updatable = true)
+  private String hostname;
+
+  @ManyToOne
+  @JoinColumns({
+    @JoinColumn(name = "host_name", referencedColumnName = "host_name", nullable = false, insertable = false, updatable = false) })
+  private HostEntity hostEntity;
+
+  @ManyToOne
+  @JoinColumns({
+    @JoinColumn(name = "config_group_id", referencedColumnName = "group_id", nullable = false, insertable = false, updatable = false) })
+  private ConfigGroupEntity configGroupEntity;
+
+  public Long getConfigGroupId() {
+    return configGroupId;
+  }
+
+  public void setConfigGroupId(Long configGroupId) {
+    this.configGroupId = configGroupId;
+  }
+
+  public String getHostname() {
+    return hostname;
+  }
+
+  public void setHostname(String hostname) {
+    this.hostname = hostname;
+  }
+
+  public HostEntity getHostEntity() {
+    return hostEntity;
+  }
+
+  public void setHostEntity(HostEntity hostEntity) {
+    this.hostEntity = hostEntity;
+  }
+
+  public ConfigGroupEntity getConfigGroupEntity() {
+    return configGroupEntity;
+  }
+
+  public void setConfigGroupEntity(ConfigGroupEntity configGroupEntity) {
+    this.configGroupEntity = configGroupEntity;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ConfigGroupHostMappingEntity that = (ConfigGroupHostMappingEntity) o;
+
+    if (!configGroupId.equals(that.configGroupId)) return false;
+    if (!hostname.equals(that.hostname)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = configGroupId.hashCode();
+    result = 31 * result + hostname.hashCode();
+    return result;
+  }
+}

+ 67 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ConfigGroupHostMappingEntityPK.java

@@ -0,0 +1,67 @@
+/**
+ * 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.Id;
+import java.io.Serializable;
+
+public class ConfigGroupHostMappingEntityPK implements Serializable {
+  private Long configGroupId;
+  private String hostname;
+
+  @Id
+  @Column(name = "config_group_id", nullable = false, insertable = true, updatable = true)
+  public Long getConfigGroupId() {
+    return configGroupId;
+  }
+
+  public void setConfigGroupId(Long configGroupId) {
+    this.configGroupId = configGroupId;
+  }
+
+  @Id
+  @Column(name = "host_name", nullable = false, insertable = true, updatable = true)
+  public String getHostname() {
+    return hostname;
+  }
+
+  public void setHostname(String hostname) {
+    this.hostname = hostname;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ConfigGroupHostMappingEntityPK that = (ConfigGroupHostMappingEntityPK) o;
+
+    if (!configGroupId.equals(that.configGroupId)) return false;
+    if (!hostname.equals(that.hostname)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = configGroupId.hashCode();
+    result = 31 * result + hostname.hashCode();
+    return result;
+  }
+}

+ 8 - 0
ambari-server/src/main/resources/Ambari-DDL-Postgres-REMOTE-CREATE.sql

@@ -46,6 +46,9 @@ CREATE TABLE ambari.key_value_store ("key" VARCHAR(255), "value" VARCHAR, PRIMAR
 CREATE TABLE ambari.hostconfigmapping (cluster_id bigint NOT NULL, host_name VARCHAR(255) NOT NULL, type_name VARCHAR(255) NOT NULL, version_tag VARCHAR(255) NOT NULL, service_name VARCHAR(255), create_timestamp BIGINT NOT NULL, selected INTEGER NOT NULL DEFAULT 0, user_name VARCHAR(255) NOT NULL DEFAULT '_db', PRIMARY KEY (cluster_id, host_name, type_name, create_timestamp));
 CREATE TABLE ambari.metainfo ("metainfo_key" VARCHAR(255), "metainfo_value" VARCHAR, PRIMARY KEY("metainfo_key"));
 CREATE TABLE ambari.ambari_sequences (sequence_name VARCHAR(255) PRIMARY KEY, "value" BIGINT NOT NULL);
+CREATE TABLE ambari.configgroup (group_id BIGINT, cluster_id BIGINT NOT NULL, group_name VARCHAR(255) NOT NULL, tag VARCHAR(1024) NOT NULL, description VARCHAR(1024), create_timestamp BIGINT NOT NULL, PRIMARY KEY(group_id), UNIQUE(group_name));
+CREATE TABLE ambari.configgroupclusterconfigmapping (config_group_id BIGINT NOT NULL, cluster_id BIGINT NOT NULL, config_type VARCHAR(255) NOT NULL, version_tag VARCHAR(255) NOT NULL, user_name VARCHAR(255) DEFAULT '_db', create_timestamp BIGINT NOT NULL, PRIMARY KEY(config_group_id, cluster_id, config_type));
+CREATE TABLE ambari.configgrouphostmapping (config_group_id BIGINT NOT NULL, host_name VARCHAR(255) NOT NULL, PRIMARY KEY(config_group_id, host_name));
 
 ALTER TABLE ambari.clusterconfig ADD CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
 ALTER TABLE ambari.clusterservices ADD CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
@@ -77,6 +80,11 @@ ALTER TABLE ambari.user_roles ADD CONSTRAINT FK_user_roles_user_id FOREIGN KEY (
 ALTER TABLE ambari.user_roles ADD CONSTRAINT FK_user_roles_role_name FOREIGN KEY (role_name) REFERENCES ambari.roles (role_name);
 ALTER TABLE ambari.hostconfigmapping ADD CONSTRAINT FK_hostconfigmapping_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
 ALTER TABLE ambari.hostconfigmapping ADD CONSTRAINT FK_hostconfigmapping_host_name FOREIGN KEY (host_name) REFERENCES ambari.hosts (host_name);
+ALTER TABLE ambari.configgroup ADD CONSTRAINT FK_configgroup_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
+ALTER TABLE ambari.configgroupclusterconfigmapping ADD CONSTRAINT FK_configgroupclusterconfigmapping_config_tag FOREIGN KEY (version_tag, config_type, cluster_id) REFERENCES ambari.clusterconfig (version_tag, type_name, cluster_id);
+ALTER TABLE ambari.configgroupclusterconfigmapping ADD CONSTRAINT FK_configgroupclusterconfigmapping_group_id FOREIGN KEY (config_group_id) REFERENCES ambari.configgroup (group_id);
+ALTER TABLE ambari.configgrouphostmapping ADD CONSTRAINT FK_configgrouphostmapping_configgroup_id FOREIGN KEY (config_group_id) REFERENCES ambari.configgroup (group_id);
+ALTER TABLE ambari.configgrouphostmapping ADD CONSTRAINT FK_configgrouphostmapping_host_name FOREIGN KEY (host_name) REFERENCES ambari.hosts (host_name);
 
 BEGIN;
 

+ 3 - 0
ambari-server/src/main/resources/META-INF/persistence.xml

@@ -38,6 +38,9 @@
     <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.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>
 
     <properties>
       <!--<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost/ambari" />-->

+ 230 - 0
ambari-server/src/test/java/org/apache/ambari/server/orm/dao/ConfigGroupDAOTest.java

@@ -0,0 +1,230 @@
+/**
+ * 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 com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import junit.framework.Assert;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.orm.GuiceJpaInitializer;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
+import org.apache.ambari.server.orm.entities.ClusterEntity;
+import org.apache.ambari.server.orm.entities.ConfigGroupConfigMappingEntity;
+import org.apache.ambari.server.orm.entities.ConfigGroupEntity;
+import org.apache.ambari.server.orm.entities.ConfigGroupHostMappingEntity;
+import org.apache.ambari.server.orm.entities.HostEntity;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ConfigGroupDAOTest {
+  private Injector injector;
+  private ConfigGroupDAO configGroupDAO;
+  private ClusterDAO clusterDAO;
+  private ConfigGroupConfigMappingDAO configGroupConfigMappingDAO;
+  private ConfigGroupHostMappingDAO configGroupHostMappingDAO;
+  private HostDAO hostDAO;
+
+  @Before
+  public void setup() throws Exception {
+    injector = Guice.createInjector(new InMemoryDefaultTestModule());
+    injector.getInstance(GuiceJpaInitializer.class);
+
+    clusterDAO = injector.getInstance(ClusterDAO.class);
+    configGroupDAO = injector.getInstance(ConfigGroupDAO.class);
+    configGroupConfigMappingDAO = injector.getInstance
+      (ConfigGroupConfigMappingDAO.class);
+    configGroupHostMappingDAO = injector.getInstance
+      (ConfigGroupHostMappingDAO.class);
+    hostDAO = injector.getInstance(HostDAO.class);
+  }
+
+  @After
+  public void teardown() throws AmbariException {
+    injector.getInstance(PersistService.class).stop();
+  }
+
+  private ConfigGroupEntity createConfigGroup(String clusterName,
+         String groupName, String tag, String desc, List<HostEntity> hosts,
+         List<ClusterConfigEntity> configs) throws Exception {
+    ConfigGroupEntity configGroupEntity = new ConfigGroupEntity();
+
+    ClusterEntity clusterEntity = new ClusterEntity();
+    clusterEntity.setClusterName(clusterName);
+    clusterDAO.create(clusterEntity);
+
+    configGroupEntity.setClusterEntity(clusterEntity);
+    configGroupEntity.setClusterId(clusterEntity.getClusterId());
+    configGroupEntity.setGroupName(groupName);
+    configGroupEntity.setDescription(desc);
+    configGroupEntity.setTag(tag);
+
+    configGroupDAO.create(configGroupEntity);
+
+    if (hosts != null && !hosts.isEmpty()) {
+      List<ConfigGroupHostMappingEntity> hostMappingEntities = new
+        ArrayList<ConfigGroupHostMappingEntity>();
+
+      for (HostEntity host : hosts) {
+        hostDAO.create(host);
+
+        ConfigGroupHostMappingEntity hostMappingEntity = new
+          ConfigGroupHostMappingEntity();
+        hostMappingEntity.setHostname(host.getHostName());
+        hostMappingEntity.setHostEntity(host);
+        hostMappingEntity.setConfigGroupEntity(configGroupEntity);
+        hostMappingEntity.setConfigGroupId(configGroupEntity.getGroupId());
+        hostMappingEntities.add(hostMappingEntity);
+        configGroupHostMappingDAO.create(hostMappingEntity);
+      }
+      configGroupEntity.setConfigGroupHostMappingEntities(hostMappingEntities);
+      configGroupDAO.merge(configGroupEntity);
+    }
+
+    if (configs != null && !configs.isEmpty()) {
+      List<ConfigGroupConfigMappingEntity> configMappingEntities = new
+        ArrayList<ConfigGroupConfigMappingEntity>();
+
+      for (ClusterConfigEntity config : configs) {
+        config.setClusterEntity(clusterEntity);
+        config.setClusterId(clusterEntity.getClusterId());
+        clusterDAO.createConfig(config);
+
+        ConfigGroupConfigMappingEntity configMappingEntity = new
+          ConfigGroupConfigMappingEntity();
+        configMappingEntity.setClusterId(clusterEntity.getClusterId());
+        configMappingEntity.setClusterConfigEntity(config);
+        configMappingEntity.setConfigGroupEntity(configGroupEntity);
+        configMappingEntity.setConfigGroupId(configGroupEntity.getGroupId());
+        configMappingEntity.setVersionTag(config.getTag());
+        configMappingEntity.setConfigType(config.getType());
+        configMappingEntity.setTimestamp(System.currentTimeMillis());
+        configMappingEntities.add(configMappingEntity);
+        configGroupConfigMappingDAO.create(configMappingEntity);
+      }
+      configGroupEntity.setConfigGroupConfigMappingEntities(configMappingEntities);
+      configGroupDAO.merge(configGroupEntity);
+    }
+    return configGroupEntity;
+  }
+
+  @Test
+  public void testCreatePlaneJaneCG() throws Exception {
+    ConfigGroupEntity configGroupEntity = createConfigGroup("c1", "hdfs-1",
+      "HDFS", "some description", null, null);
+
+    Assert.assertNotNull(configGroupEntity);
+    Assert.assertEquals("c1", configGroupEntity.getClusterEntity().getClusterName());
+    Assert.assertEquals(Long.valueOf(1), configGroupEntity.getClusterEntity()
+      .getClusterId());
+    Assert.assertEquals("hdfs-1", configGroupEntity.getGroupName());
+    Assert.assertEquals("HDFS", configGroupEntity.getTag());
+    Assert.assertEquals("some description", configGroupEntity.getDescription());
+  }
+
+  @Test
+  public void testFindByTag() throws Exception {
+    createConfigGroup("c1", "hdfs-1", "HDFS", "some description", null, null);
+
+    List<ConfigGroupEntity> configGroupEntities = configGroupDAO.findAllByTag
+      ("HDFS");
+
+    Assert.assertNotNull(configGroupEntities);
+    ConfigGroupEntity configGroupEntity = configGroupEntities.get(0);
+    Assert.assertNotNull(configGroupEntity);
+    Assert.assertEquals("c1", configGroupEntity.getClusterEntity().getClusterName());
+    Assert.assertEquals(Long.valueOf(1), configGroupEntity.getClusterEntity()
+      .getClusterId());
+    Assert.assertEquals("hdfs-1", configGroupEntity.getGroupName());
+    Assert.assertEquals("HDFS", configGroupEntity.getTag());
+    Assert.assertEquals("some description", configGroupEntity.getDescription());
+  }
+
+  @Test
+  public void testFindByName() throws Exception {
+    createConfigGroup("c1", "hdfs-1", "HDFS", "some description", null, null);
+
+    ConfigGroupEntity configGroupEntity = configGroupDAO.findByName("hdfs-1");
+
+    Assert.assertNotNull(configGroupEntity);
+    Assert.assertEquals("c1", configGroupEntity.getClusterEntity().getClusterName());
+    Assert.assertEquals(Long.valueOf(1), configGroupEntity.getClusterEntity()
+      .getClusterId());
+    Assert.assertEquals("hdfs-1", configGroupEntity.getGroupName());
+    Assert.assertEquals("HDFS", configGroupEntity.getTag());
+    Assert.assertEquals("some description", configGroupEntity.getDescription());
+  }
+
+  @Test
+  public void testFindByHost() throws Exception {
+    List<HostEntity> hosts = new ArrayList<HostEntity>();
+    HostEntity hostEntity = new HostEntity();
+    hostEntity.setHostName("h1");
+    hostEntity.setOsType("centOS");
+    hosts.add(hostEntity);
+    ConfigGroupEntity configGroupEntity =
+      createConfigGroup("c1", "hdfs-1", "HDFS", "some description", hosts, null);
+
+    Assert.assertNotNull(configGroupEntity);
+    Assert.assertTrue(configGroupEntity.getConfigGroupHostMappingEntities()
+      .size() > 0);
+    Assert.assertNotNull(configGroupEntity
+      .getConfigGroupHostMappingEntities().iterator().next());
+
+    List<ConfigGroupHostMappingEntity> hostMappingEntities = configGroupHostMappingDAO
+      .findByHost("h1");
+
+    Assert.assertNotNull(hostMappingEntities);
+    Assert.assertEquals("h1", hostMappingEntities.get(0).getHostname());
+    Assert.assertEquals("centOS", hostMappingEntities.get(0).getHostEntity()
+      .getOsType());
+  }
+
+  @Test
+  public void testFindConfigsByGroup() throws Exception {
+    ClusterConfigEntity configEntity = new ClusterConfigEntity();
+    configEntity.setType("core-site");
+    configEntity.setTag("version1");
+    configEntity.setData("someData");
+
+    List<ClusterConfigEntity> configEntities = new
+      ArrayList<ClusterConfigEntity>();
+    configEntities.add(configEntity);
+
+    ConfigGroupEntity configGroupEntity =
+      createConfigGroup("c1", "hdfs-1", "HDFS", "some description", null,
+        configEntities);
+
+    Assert.assertNotNull(configGroupEntity);
+    Assert.assertTrue(configGroupEntity.getConfigGroupConfigMappingEntities()
+      .size() > 0);
+
+    List<ConfigGroupConfigMappingEntity> configMappingEntities =
+      configGroupConfigMappingDAO.findByGroup(configGroupEntity.getGroupId());
+
+    Assert.assertNotNull(configEntities);
+    Assert.assertEquals("core-site", configEntities.get(0).getType());
+    Assert.assertEquals("version1", configEntities.get(0).getTag());
+    Assert.assertEquals("someData", configEntities.get(0).getData());
+  }
+}