You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by vb...@apache.org on 2017/11/13 16:22:59 UTC

ambari git commit: AMBARI-22249. Add service group dependencies. Part 2.(vbrodetskyi)

Repository: ambari
Updated Branches:
  refs/heads/branch-feature-AMBARI-14714 55e450eea -> 6a78e1a1a


AMBARI-22249. Add service group dependencies. Part 2.(vbrodetskyi)


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

Branch: refs/heads/branch-feature-AMBARI-14714
Commit: 6a78e1a1ab5ed046678c9fc4c907ac925cb6bbd5
Parents: 55e450e
Author: Vitaly Brodetskyi <vb...@hortonworks.com>
Authored: Mon Nov 13 18:20:50 2017 +0200
Committer: Vitaly Brodetskyi <vb...@hortonworks.com>
Committed: Mon Nov 13 18:20:50 2017 +0200

----------------------------------------------------------------------
 .../api/services/ServiceGroupService.java       |  38 +++---
 .../ServiceGroupDependencyRequest.java          |  14 +--
 .../ServiceGroupDependencyResourceProvider.java |  66 +++++------
 .../ambari/server/orm/dao/ServiceGroupDAO.java  |  35 +++++-
 .../entities/ServiceGroupDependencyEntity.java  | 111 ++++++++++++++++++
 .../server/orm/entities/ServiceGroupEntity.java |  31 +++--
 .../org/apache/ambari/server/state/Cluster.java |  26 ++++-
 .../ambari/server/state/ServiceGroup.java       |  12 +-
 .../ambari/server/state/ServiceGroupImpl.java   | 117 ++++++++++++-------
 .../server/state/cluster/ClusterImpl.java       |  46 +++-----
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  |   8 +-
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |   7 +-
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |   7 +-
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |   7 +-
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |   7 +-
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |   7 +-
 .../src/main/resources/META-INF/persistence.xml |   1 +
 17 files changed, 372 insertions(+), 168 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceGroupService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceGroupService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceGroupService.java
index 0638a06..ec63aec 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceGroupService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceGroupService.java
@@ -298,10 +298,10 @@ public class ServiceGroupService extends BaseService {
           responseContainer = RESPONSE_CONTAINER_LIST)
   @ApiImplicitParams({
           @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION,
-                  defaultValue = "ServiceGroupInfo/service_group_name, ServiceGroupInfo/cluster_name",
+                  defaultValue = "ServiceGroupDependencyInfo/dependency_service_group_id, ServiceGroupInfo/service_group_name, ServiceGroupInfo/cluster_name",
                   dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
           @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION,
-                  defaultValue = "ServiceGroupInfo/service_group_name.asc, ServiceGroupInfo/cluster_name.asc",
+                  defaultValue = "ServiceGroupDependencyInfo/dependency_service_group_id.asc, ServiceGroupInfo/service_group_name.asc, ServiceGroupInfo/cluster_name.asc",
                   dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
           @ApiImplicitParam(name = QUERY_PAGE_SIZE, value = QUERY_PAGE_SIZE_DESCRIPTION, defaultValue = DEFAULT_PAGE_SIZE, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY),
           @ApiImplicitParam(name = QUERY_FROM, value = QUERY_FROM_DESCRIPTION, defaultValue = DEFAULT_FROM, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
@@ -322,14 +322,14 @@ public class ServiceGroupService extends BaseService {
    * Handles URL: /clusters/{clusterName}/servicegroups/{serviceGroupName}/dependencies/{serviceGroupDependency}
    * Get a specific servicegroupdependency.
    *
-   * @param headers                 http headers
-   * @param ui                      uri info
-   * @param serviceGroupName        service group name
-   * @param serviceGroupDependency  service group dependency name
+   * @param headers                    http headers
+   * @param ui                         uri info
+   * @param serviceGroupName           service group name
+   * @param serviceGroupDependencyId   service group dependency id
    * @return servicegroupdependency    resource representation
    */
   @GET
-  @Path("{serviceGroupName}/dependencies/{serviceGroupDependency}")
+  @Path("{serviceGroupName}/dependencies/{serviceGroupDependencyId}")
   @Produces(MediaType.TEXT_PLAIN)
   @ApiOperation(value = "Get the details of a servicegroupdependency",
           nickname = "ServiceGroupService#getServiceGroupDependency",
@@ -347,10 +347,10 @@ public class ServiceGroupService extends BaseService {
   })
   public Response getServiceGroupDependency(String body, @Context HttpHeaders headers, @Context UriInfo ui,
                                               @PathParam("serviceGroupName") String serviceGroupName,
-                                              @PathParam("serviceGroupDependency") String serviceGroupDependency) {
+                                              @PathParam("serviceGroupDependencyId") String serviceGroupDependencyId) {
 
     return handleRequest(headers, body, ui, Request.Type.GET,
-            createServiceGroupDependencyResource(m_clusterName, serviceGroupName, serviceGroupDependency));
+            createServiceGroupDependencyResource(m_clusterName, serviceGroupName, serviceGroupDependencyId));
   }
 
   /**
@@ -392,14 +392,14 @@ public class ServiceGroupService extends BaseService {
    * Handles: DELETE /clusters/{clusterName}/servicegroups/{serviceGroupName}/dependencies/{serviceGroupDependency}
    * Delete a specific servicegroupdependency.
 
-   * @param headers                 http headers
-   * @param ui                      uri info
-   * @param serviceGroupName        service group name
-   * @param serviceGroupDependency  service group dependency name
+   * @param headers                   http headers
+   * @param ui                        uri info
+   * @param serviceGroupName          service group name
+   * @param serviceGroupDependencyId  service group dependency id
    * @return information regarding the deleted servicegroupdependency
    */
   @DELETE
-  @Path("{serviceGroupName}/dependencies/{serviceGroupDependency}")
+  @Path("{serviceGroupName}/dependencies/{serviceGroupDependencyId}")
   @Produces(MediaType.TEXT_PLAIN)
   @ApiOperation(value = "Deletes a servicegroupdependency",
           nickname = "ServiceGroupService#deleteServiceGroupDependency"
@@ -413,9 +413,9 @@ public class ServiceGroupService extends BaseService {
   })
   public Response deleteServiceGroupDependency(@Context HttpHeaders headers, @Context UriInfo ui,
                                      @PathParam("serviceGroupName") String serviceGroupName,
-                                     @PathParam("serviceGroupDependency") String serviceGroupDependency) {
+                                     @PathParam("serviceGroupDependencyId") String serviceGroupDependencyId) {
 
-    return handleRequest(headers, null, ui, Request.Type.DELETE, createServiceGroupDependencyResource(m_clusterName, serviceGroupName, serviceGroupDependency));
+    return handleRequest(headers, null, ui, Request.Type.DELETE, createServiceGroupDependencyResource(m_clusterName, serviceGroupName, serviceGroupDependencyId));
   }
   /**
    * Create a service resource instance.
@@ -434,13 +434,13 @@ public class ServiceGroupService extends BaseService {
     return createResource(Resource.Type.ServiceGroup, mapIds);
   }
 
-  ResourceInstance createServiceGroupDependencyResource(String clusterName, String serviceGroupName, String serviceGroupDependency) {
+  ResourceInstance createServiceGroupDependencyResource(String clusterName, String serviceGroupName, String serviceGroupDependencyId) {
     Map<Resource.Type, String> mapIds = new HashMap<>();
     mapIds.put(Resource.Type.Cluster, clusterName);
     mapIds.put(Resource.Type.ServiceGroup, serviceGroupName);
-    mapIds.put(Resource.Type.ServiceGroupDependency, serviceGroupDependency);
+    mapIds.put(Resource.Type.ServiceGroupDependency, serviceGroupDependencyId);
 
 
     return createResource(Resource.Type.ServiceGroupDependency, mapIds);
   }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupDependencyRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupDependencyRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupDependencyRequest.java
index e9cf937..9f4eea3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupDependencyRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupDependencyRequest.java
@@ -22,12 +22,12 @@ public class ServiceGroupDependencyRequest {
 
   private String clusterName; // REF
   private String serviceGroupName; // GET/CREATE/UPDATE/DELETE
-  private String dependencyServiceGroupName;
+  private Long dependencyServiceGroupId;
 
-  public ServiceGroupDependencyRequest(String clusterName, String serviceGroupName, String dependencyServiceGroupName) {
+  public ServiceGroupDependencyRequest(String clusterName, String serviceGroupName, Long dependencyServiceGroupId) {
     this.clusterName = clusterName;
     this.serviceGroupName = serviceGroupName;
-    this.dependencyServiceGroupName = dependencyServiceGroupName;
+    this.dependencyServiceGroupId = dependencyServiceGroupId;
   }
 
   /**
@@ -58,12 +58,12 @@ public class ServiceGroupDependencyRequest {
     this.serviceGroupName = serviceGroupName;
   }
 
-  public String getDependencyServiceGroupName() {
-    return dependencyServiceGroupName;
+  public Long getDependencyServiceGroupId() {
+    return dependencyServiceGroupId;
   }
 
-  public void setDependencyServiceGroupName(String dependencyServiceGroupName) {
-    this.dependencyServiceGroupName = dependencyServiceGroupName;
+  public void setDependencyServiceGroupId(Long dependencyServiceGroupId) {
+    this.dependencyServiceGroupId = dependencyServiceGroupId;
   }
 
   public String toString() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupDependencyResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupDependencyResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupDependencyResourceProvider.java
index 78610d2..aac7102 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupDependencyResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupDependencyResourceProvider.java
@@ -85,7 +85,7 @@ public class ServiceGroupDependencyResourceProvider extends AbstractControllerRe
     new HashSet<String>(Arrays.asList(new String[]{
       SERVICE_GROUP_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID,
       SERVICE_GROUP_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID,
-      SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID}));
+      SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID}));
 
   private static Gson gson = StageUtils.getGson();
 
@@ -113,7 +113,7 @@ public class ServiceGroupDependencyResourceProvider extends AbstractControllerRe
     // keys
     KEY_PROPERTY_IDS.put(Resource.Type.Cluster, SERVICE_GROUP_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID);
     KEY_PROPERTY_IDS.put(Resource.Type.ServiceGroup, SERVICE_GROUP_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID);
-    KEY_PROPERTY_IDS.put(Resource.Type.ServiceGroupDependency, SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID);
+    KEY_PROPERTY_IDS.put(Resource.Type.ServiceGroupDependency, SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID);
   }
 
   private Clusters clusters;
@@ -253,7 +253,7 @@ public class ServiceGroupDependencyResourceProvider extends AbstractControllerRe
     notifyDelete(Resource.Type.ServiceGroupDependency, predicate);
     for(ServiceGroupDependencyRequest svgReq : requests) {
       deleteStatusMetaData.addDeletedKey("cluster_name: " + svgReq.getClusterName() + ", " + " service_group_name: " + svgReq.getServiceGroupName()
-                                        + "dependency_service_group_name: " + svgReq.getDependencyServiceGroupName());
+                                        + " dependency_service_group_id: " + svgReq.getDependencyServiceGroupId());
     }
     return getRequestStatus(null, null, deleteStatusMetaData);
   }
@@ -288,21 +288,12 @@ public class ServiceGroupDependencyResourceProvider extends AbstractControllerRe
   private ServiceGroupDependencyRequest getRequest(Map<String, Object> properties) {
     String clusterName = (String) properties.get(SERVICE_GROUP_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID);
     String serviceGroupName = (String) properties.get(SERVICE_GROUP_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID);
-    String dependencyServiceGroupName = (String) properties.get(SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID);
-    ServiceGroupDependencyRequest svcRequest = new ServiceGroupDependencyRequest(clusterName, serviceGroupName, dependencyServiceGroupName);
+    String strdependencyServiceGroupId = (String)properties.get(SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID);
+    Long dependencyServiceGroupId = strdependencyServiceGroupId == null ? null : Long.valueOf(strdependencyServiceGroupId);
+    ServiceGroupDependencyRequest svcRequest = new ServiceGroupDependencyRequest(clusterName, serviceGroupName, dependencyServiceGroupId);
     return svcRequest;
   }
 
-  protected Set<ServiceGroupKey> getServiceGroupDependenciesSet(Set<Map<String, String>> serviceGroupDependencies) {
-    Set<ServiceGroupKey> serviceGroupKeys = new HashSet<>();
-    if (serviceGroupDependencies != null) {
-      for (Map<String, String> dependencyProperties : serviceGroupDependencies) {
-        ServiceGroupKey serviceGroupKey = mapper.convertValue(dependencyProperties, ServiceGroupKey.class);
-        serviceGroupKeys.add(serviceGroupKey);
-      }
-    }
-    return serviceGroupKeys;
-  }
 
   // Create services from the given request.
   public synchronized Set<ServiceGroupDependencyResponse> createServiceGroupDependencies(Set<ServiceGroupDependencyRequest> requests)
@@ -323,8 +314,8 @@ public class ServiceGroupDependencyResourceProvider extends AbstractControllerRe
       Cluster cluster = clusters.getCluster(request.getClusterName());
 
       // Already checked that service group does not exist
-      ServiceGroup sg = cluster.addServiceGroupDependency(request.getServiceGroupName(), request.getDependencyServiceGroupName());
-      createdServiceGroupDependencies.addAll(sg.getServiceGroupDependencyResponses());
+      cluster.addServiceGroupDependency(request.getServiceGroupName(), request.getDependencyServiceGroupId());
+      createdServiceGroupDependencies.addAll(cluster.getServiceGroup(request.getServiceGroupName()).getServiceGroupDependencyResponses());
     }
     return createdServiceGroupDependencies;
   }
@@ -381,7 +372,6 @@ public class ServiceGroupDependencyResourceProvider extends AbstractControllerRe
 
     Clusters clusters = getManagementController().getClusters();
 
-    Set<ServiceGroupDependencyRequest> removable = new HashSet<>();
 
     for (ServiceGroupDependencyRequest serviceGroupDependencyRequest : request) {
       if (null == serviceGroupDependencyRequest.getClusterName()
@@ -397,24 +387,24 @@ public class ServiceGroupDependencyResourceProvider extends AbstractControllerRe
 
         Cluster cluster = clusters.getCluster(serviceGroupDependencyRequest.getClusterName());
         ServiceGroup serviceGroup = cluster.getServiceGroup(serviceGroupDependencyRequest.getServiceGroupName());
-        Set<ServiceGroupKey> serviceGroupKeys = serviceGroup.getServiceGroupDependencies();
-        if (serviceGroupKeys == null || serviceGroupKeys.isEmpty()) {
+        Set<ServiceGroupKey> dependencyServiceGroupKeys = serviceGroup.getServiceGroupDependencies();
+        if (dependencyServiceGroupKeys == null || dependencyServiceGroupKeys.isEmpty()) {
           throw new AmbariException("Servcie group name " + serviceGroupDependencyRequest.getServiceGroupName() + " has no" +
-                  "dependencies, so nothing to remove.");
+                  " dependencies, so nothing to remove.");
         } else {
           boolean dependencyAvailable = false;
-          for (ServiceGroupKey serviceGroupKey : serviceGroupKeys) {
-            if (serviceGroupKey.getServiceGroupName().equals(serviceGroupDependencyRequest.getDependencyServiceGroupName())) {
+          for (ServiceGroupKey dependencyServiceGroupKey : dependencyServiceGroupKeys) {
+            if (dependencyServiceGroupKey.getServiceGroupId() == serviceGroupDependencyRequest.getDependencyServiceGroupId()) {
               dependencyAvailable = true;
             }
           }
           if (!dependencyAvailable) {
             throw new AmbariException("Servcie group name " + serviceGroupDependencyRequest.getServiceGroupName() + " has no" +
-                    "dependency " + serviceGroupDependencyRequest.getDependencyServiceGroupName() + ", so nothing to remove.");
+                    "dependency with id=" + serviceGroupDependencyRequest.getDependencyServiceGroupId() + ", so nothing to remove.");
           }
 
           serviceGroup.getCluster().deleteServiceGroupDependency(serviceGroupDependencyRequest.getServiceGroupName(),
-                  serviceGroupDependencyRequest.getDependencyServiceGroupName());
+                  serviceGroupDependencyRequest.getDependencyServiceGroupId());
         }
       }
     }
@@ -424,23 +414,26 @@ public class ServiceGroupDependencyResourceProvider extends AbstractControllerRe
   private void validateCreateRequests(Set<ServiceGroupDependencyRequest> requests, Clusters clusters)
     throws AuthorizationException, AmbariException {
 
-    Map<String, Set<String>> serviceGroupNames = new HashMap<>();
-    Set<String> duplicates = new HashSet<>();
     for (ServiceGroupDependencyRequest request : requests) {
       final String clusterName = request.getClusterName();
       final String serviceGroupName = request.getServiceGroupName();
-      final String dependencyServiceGroupName = request.getDependencyServiceGroupName();
+      final Long dependencyServiceGroupId = request.getDependencyServiceGroupId();
 
       Validate.notNull(clusterName, "Cluster name should be provided when creating a service group");
 
       // validating service group dependencies
-      if (StringUtils.isEmpty(dependencyServiceGroupName)) {
-        throw new AmbariException("Service group name is empty or null!");
+      if (dependencyServiceGroupId == null) {
+        throw new AmbariException("Service group name id has is null!");
       } else {
-        Cluster cluster = clusters.getCluster(clusterName);
-        //throws service group not found exception
-        ServiceGroup serviceGroup = cluster.getServiceGroup(dependencyServiceGroupName);
-
+        boolean dependencyServiceGroupAvailable = false;
+        for (Cluster cl : clusters.getClusters().values()) {
+          if (cl.getServiceGroupsById().containsKey(dependencyServiceGroupId)) {
+            dependencyServiceGroupAvailable = true;
+          }
+        }
+        if (!dependencyServiceGroupAvailable) {
+          throw new AmbariException("Service group with id=" + dependencyServiceGroupId + " is not available.");
+        }
       }
 
       Validate.notEmpty(serviceGroupName, "Service group name should be provided when adding a service group dependency");
@@ -463,14 +456,13 @@ public class ServiceGroupDependencyResourceProvider extends AbstractControllerRe
         throw new ParentObjectNotFoundException("Attempted to add a service group to a cluster which doesn't exist", e);
       }
 
-      // throws service group not found exception if theere is no such SG
       ServiceGroup sg = cluster.getServiceGroup(serviceGroupName);
       Set<ServiceGroupKey> dependencies = sg.getServiceGroupDependencies();
       if (dependencies != null) {
         for (ServiceGroupKey serviceGroupKey : dependencies) {
-          if (serviceGroupKey.getServiceGroupName().equals(dependencyServiceGroupName)) {
+          if (serviceGroupKey.getServiceGroupId() == dependencyServiceGroupId) {
             throw new AmbariException("Service group " + serviceGroupName + " already have dependency for service group "
-                    + dependencyServiceGroupName);
+                    + serviceGroupKey.getServiceGroupName());
           }
         }
       }

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceGroupDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceGroupDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceGroupDAO.java
index 63e78d6..97659f7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceGroupDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceGroupDAO.java
@@ -25,6 +25,7 @@ import javax.persistence.NoResultException;
 import javax.persistence.TypedQuery;
 
 import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.ServiceGroupDependencyEntity;
 import org.apache.ambari.server.orm.entities.ServiceGroupEntity;
 import org.apache.ambari.server.orm.entities.ServiceGroupEntityPK;
 
@@ -60,6 +61,23 @@ public class ServiceGroupDAO {
   }
 
   @RequiresSession
+  public ServiceGroupDependencyEntity findDependencyByClustersAndServiceGroupsIds(Long serviceGroupClusterId, Long serviceGroupId,
+                                                               Long dependentServiceGroupClusterId, Long dependenctServiceGroupId) {
+    TypedQuery<ServiceGroupDependencyEntity> query = entityManagerProvider.get()
+            .createNamedQuery("serviceGroupDependencyByServiceGroupsAndClustersIds", ServiceGroupDependencyEntity.class);
+    query.setParameter("serviceGroupClusterId", serviceGroupClusterId);
+    query.setParameter("serviceGroupId", serviceGroupId);
+    query.setParameter("dependentServiceGroupClusterId", dependentServiceGroupClusterId);
+    query.setParameter("dependentServiceGroupId", dependenctServiceGroupId);
+
+    try {
+      return query.getSingleResult();
+    } catch (NoResultException ignored) {
+      return null;
+    }
+  }
+
+  @RequiresSession
   public List<ServiceGroupEntity> findAll() {
     return daoUtils.selectAll(entityManagerProvider.get(), ServiceGroupEntity.class);
   }
@@ -75,19 +93,34 @@ public class ServiceGroupDAO {
   }
 
   @Transactional
+  public void createServiceGroupDependency(ServiceGroupDependencyEntity serviceGroupDependencyEntity) {
+    entityManagerProvider.get().persist(serviceGroupDependencyEntity);
+  }
+
+  @Transactional
   public ServiceGroupEntity merge(ServiceGroupEntity clusterServiceGroupEntity) {
     return entityManagerProvider.get().merge(clusterServiceGroupEntity);
   }
 
   @Transactional
+  public ServiceGroupDependencyEntity mergeServiceGroupDependency(ServiceGroupDependencyEntity serviceGroupDependencyEntity) {
+    return entityManagerProvider.get().merge(serviceGroupDependencyEntity);
+  }
+
+  @Transactional
   public void remove(ServiceGroupEntity clusterServiceGroupEntity) {
     entityManagerProvider.get().remove(merge(clusterServiceGroupEntity));
   }
 
   @Transactional
+  public void removeServiceGroupDependency(ServiceGroupDependencyEntity serviceGroupDependencyEntity) {
+    entityManagerProvider.get().remove(mergeServiceGroupDependency(serviceGroupDependencyEntity));
+  }
+
+  @Transactional
   public void removeByPK(ServiceGroupEntityPK clusterServiceGroupEntityPK) {
     ServiceGroupEntity entity = findByPK(clusterServiceGroupEntityPK);
     entityManagerProvider.get().remove(entity);
   }
 
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupDependencyEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupDependencyEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupDependencyEntity.java
new file mode 100644
index 0000000..ee0beeb
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupDependencyEntity.java
@@ -0,0 +1,111 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+@Entity
+@Table(name = "servicegroupdependencies")
+@NamedQueries({
+        @NamedQuery(name = "serviceGroupDependencyByServiceGroupsAndClustersIds", query =
+                "SELECT serviceGroupDependency " +
+                   "FROM ServiceGroupDependencyEntity serviceGroupDependency " +
+                   "WHERE serviceGroupDependency.serviceGroupId=:serviceGroupId AND serviceGroupDependency.serviceGroupClusterId=:serviceGroupClusterId " +
+                   "AND serviceGroupDependency.dependentServiceGroupId=:dependentServiceGroupId " +
+                   "AND serviceGroupDependency.dependentServiceGroupClusterId=:dependentServiceGroupClusterId")
+})
+@TableGenerator(name = "service_group_dependency_id_generator",
+        table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value"
+        , pkColumnValue = "service_group_dependency_id_seq"
+        , initialValue = 1
+)
+public class ServiceGroupDependencyEntity {
+
+  @Id
+  @Column(name = "id", nullable = false, insertable = true, updatable = true)
+  @GeneratedValue(strategy = GenerationType.TABLE, generator = "service_group_dependency_id_generator")
+  private Long serviceGroupDependencyId;
+
+  @Column(name = "service_group_id", nullable = false, insertable = false, updatable = false)
+  private long serviceGroupId;
+
+  @Column(name = "service_group_cluster_id", nullable = false, insertable = false, updatable = false)
+  private long serviceGroupClusterId;
+
+  @Column(name = "dependent_service_group_id", nullable = false, insertable = false, updatable = false)
+  private long dependentServiceGroupId;
+
+  @Column(name = "dependent_service_group_cluster_id", nullable = false, insertable = false, updatable = false)
+  private long dependentServiceGroupClusterId;
+
+  @ManyToOne
+  @JoinColumns({
+          @JoinColumn(name = "service_group_id", referencedColumnName = "id", nullable = false),
+          @JoinColumn(name = "service_group_cluster_id", referencedColumnName = "cluster_id", nullable = false) })
+  private ServiceGroupEntity serviceGroup;
+
+  @ManyToOne
+  @JoinColumns({
+          @JoinColumn(name = "dependent_service_group_id", referencedColumnName = "id", nullable = false),
+          @JoinColumn(name = "dependent_service_group_cluster_id", referencedColumnName = "cluster_id", nullable = false) })
+  private ServiceGroupEntity serviceGroupDependency;
+
+  public ServiceGroupEntity getServiceGroup() {
+    return serviceGroup;
+  }
+
+  public void setServiceGroup(ServiceGroupEntity serviceGroup) {
+    this.serviceGroup = serviceGroup;
+  }
+
+  public ServiceGroupEntity getServiceGroupDependency() {
+    return serviceGroupDependency;
+  }
+
+  public void setServiceGroupDependency(ServiceGroupEntity serviceGroupDependency) {
+    this.serviceGroupDependency = serviceGroupDependency;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (!(o instanceof ServiceGroupDependencyEntity)) return false;
+
+    ServiceGroupDependencyEntity that = (ServiceGroupDependencyEntity) o;
+
+    if (!serviceGroupDependencyId.equals(that.serviceGroupDependencyId)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return serviceGroupDependencyId.hashCode();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntity.java
index 1bcdd80..fedaee8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntity.java
@@ -18,7 +18,6 @@
 
 package org.apache.ambari.server.orm.entities;
 
-import java.util.ArrayList;
 import java.util.List;
 
 import javax.persistence.Column;
@@ -28,11 +27,10 @@ import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.IdClass;
 import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.ManyToMany;
 import javax.persistence.ManyToOne;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
 import javax.persistence.Table;
 import javax.persistence.TableGenerator;
 
@@ -70,18 +68,11 @@ public class ServiceGroupEntity {
   @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false)
   private ClusterEntity clusterEntity;
 
-  @ManyToMany
-  @JoinTable(
-    name = "servicegroupdependencies",
-    joinColumns = {@JoinColumn(name = "service_group_id", referencedColumnName = "id", nullable = false),
-                   @JoinColumn(name = "service_group_cluster_id", referencedColumnName = "cluster_id", nullable = false)},
-    inverseJoinColumns = {@JoinColumn(name = "dependent_service_group_id", referencedColumnName = "id", nullable = false),
-                          @JoinColumn(name = "dependent_service_group_cluster_id", referencedColumnName = "cluster_id", nullable = false)}
-  )
-  private List<ServiceGroupEntity> serviceGroupDependencies = new ArrayList<>();
+  @OneToMany(mappedBy="serviceGroup")
+  private List<ServiceGroupDependencyEntity> serviceGroupDependencies;
 
-  @ManyToMany(mappedBy="serviceGroupDependencies")
-  private List<ServiceGroupEntity> dependencies = new ArrayList<>();
+  @OneToMany(mappedBy="serviceGroupDependency")
+  private List<ServiceGroupDependencyEntity> dependencies;
 
   public Long getClusterId() {
     return clusterId;
@@ -108,11 +99,19 @@ public class ServiceGroupEntity {
     this.serviceGroupName = serviceGroupName;
   }
 
-  public List<ServiceGroupEntity> getServiceGroupDependencies() {
+  public List<ServiceGroupDependencyEntity> getDependencies() {
+    return dependencies;
+  }
+
+  public void setDependencies(List<ServiceGroupDependencyEntity> dependencies) {
+    this.dependencies = dependencies;
+  }
+
+  public List<ServiceGroupDependencyEntity> getServiceGroupDependencies() {
     return serviceGroupDependencies;
   }
 
-  public void setServiceGroupDependencies(List<ServiceGroupEntity> serviceGroupDependencies) {
+  public void setServiceGroupDependencies(List<ServiceGroupDependencyEntity> serviceGroupDependencies) {
     this.serviceGroupDependencies = serviceGroupDependencies;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java b/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
index 77bf62b..2afb428 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
@@ -98,7 +98,15 @@ public interface Cluster {
    */
   ServiceGroup addServiceGroup(String serviceGroupName) throws AmbariException;
 
-  ServiceGroup addServiceGroupDependency(String serviceGroupName, String dependencyServiceGroupName) throws AmbariException;
+  /**
+   * Add service group dependency to the service group
+   *
+   * @param serviceGroupName Service group name
+   * @param dependencyServiceGroupId Dependency service group id
+   * @return
+   * @throws AmbariException
+   */
+  void addServiceGroupDependency(String serviceGroupName, Long dependencyServiceGroupId) throws AmbariException;
 
 
   ClusterSetting addClusterSetting(String clusterSettingName, String clusterSettingValue) throws AmbariException;
@@ -614,7 +622,21 @@ public interface Cluster {
    */
   void deleteServiceGroup(String serviceGroupName) throws AmbariException;
 
-  void deleteServiceGroupDependency(String serviceGroupName, String dependencyServiceGroupName) throws AmbariException;
+  /**
+   * Delete service group dependency from the service group
+   *
+   * @param serviceGroupName
+   * @param dependencyServiceGroupId
+   * @throws AmbariException
+   */
+  void deleteServiceGroupDependency(String serviceGroupName, Long dependencyServiceGroupId) throws AmbariException;
+
+  /**
+   * Get all service groups
+   *
+   * @return map of service group ids as keys and service group objects as values.
+   */
+  Map<Long, ServiceGroup> getServiceGroupsById();
 
   /**
    * Delete all the cluster settings associated with this cluster

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroup.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroup.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroup.java
index 3d59c96..fcd4c89 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroup.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroup.java
@@ -59,5 +59,15 @@ public interface ServiceGroup {
 
   void delete() throws AmbariException;
 
-  ServiceGroupEntity deleteDependency(String dependencyServiceGroupName) throws AmbariException;
+  /**
+   * @param dependencyServiceGroupId dependency service group id which should be added to current
+   * @return updated service group entity
+   */
+  ServiceGroupEntity addServiceGroupDependency(Long dependencyServiceGroupId) throws AmbariException;
+
+  /**
+   * @param dependencyServiceGroupId dependency service group id which should be removed from current
+   * @return updated service group entity
+   */
+  ServiceGroupEntity deleteServiceGroupDependency(Long dependencyServiceGroupId) throws AmbariException;
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java
index f12128f..914b65a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java
@@ -18,14 +18,12 @@
 
 package org.apache.ambari.server.state;
 
-import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.api.services.ServiceGroupKey;
-import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.ServiceGroupDependencyResponse;
 import org.apache.ambari.server.controller.ServiceGroupResponse;
 import org.apache.ambari.server.events.ServiceGroupInstalledEvent;
@@ -34,6 +32,7 @@ import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.ServiceGroupDAO;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
+import org.apache.ambari.server.orm.entities.ServiceGroupDependencyEntity;
 import org.apache.ambari.server.orm.entities.ServiceGroupEntity;
 import org.apache.ambari.server.orm.entities.ServiceGroupEntityPK;
 import org.slf4j.Logger;
@@ -55,10 +54,11 @@ public class ServiceGroupImpl implements ServiceGroup {
   private final ClusterDAO clusterDAO;
   private final ServiceGroupDAO serviceGroupDAO;
   private final AmbariEventPublisher eventPublisher;
+  private final Clusters clusters;
 
   private Long serviceGroupId;
   private String serviceGroupName;
-  private Set<ServiceGroupKey> serviceGroupDependencies = new HashSet<>();
+  private Set<ServiceGroupKey> serviceGroupDependencies;
 
   @AssistedInject
   public ServiceGroupImpl(@Assisted Cluster cluster,
@@ -67,9 +67,10 @@ public class ServiceGroupImpl implements ServiceGroup {
                           ClusterDAO clusterDAO,
                           ServiceGroupDAO serviceGroupDAO,
                           AmbariEventPublisher eventPublisher,
-                          AmbariManagementController controller) throws AmbariException {
+                          Clusters clusters) throws AmbariException {
 
     this.cluster = cluster;
+    this.clusters = clusters;
     this.clusterDAO = clusterDAO;
     this.serviceGroupDAO = serviceGroupDAO;
     this.eventPublisher = eventPublisher;
@@ -81,28 +82,14 @@ public class ServiceGroupImpl implements ServiceGroup {
     serviceGroupEntity.setServiceGroupId(serviceGroupId);
     serviceGroupEntity.setServiceGroupName(serviceGroupName);
 
-    List<ServiceGroupEntity> serviceGroupEntities = new ArrayList<>();
-    if (serviceGroupDependencies != null) {
-      this.serviceGroupDependencies = serviceGroupDependencies;
-      for (ServiceGroupKey serviceGroupKey : serviceGroupDependencies) {
-        Clusters clusters = controller.getClusters();
-        Cluster dependencyCluster = serviceGroupKey.getClusterName() == null ? cluster :
-                clusters.getCluster(serviceGroupKey.getClusterName());
-        serviceGroupKey.setClusterName(dependencyCluster.getClusterName());
-        ServiceGroup dependencyServiceGroup = dependencyCluster.getServiceGroup(serviceGroupKey.getServiceGroupName());
-
-        ServiceGroupEntityPK serviceGroupEntityPK = new ServiceGroupEntityPK();
-        serviceGroupEntityPK.setServiceGroupId(dependencyServiceGroup.getServiceGroupId());
-        serviceGroupEntityPK.setClusterId(dependencyServiceGroup.getClusterId());
-        ServiceGroupEntity dependentServiceGroupEntity = serviceGroupDAO.findByPK(serviceGroupEntityPK);
-        serviceGroupEntities.add(dependentServiceGroupEntity);
-      }
-    } else {
+    if (serviceGroupDependencies == null) {
       this.serviceGroupDependencies = new HashSet<>();
+    } else {
+      this.serviceGroupDependencies = serviceGroupDependencies;
     }
-    serviceGroupEntity.setServiceGroupDependencies(serviceGroupEntities);
 
     this.serviceGroupEntityPK = getServiceGroupEntityPK(serviceGroupEntity);
+
     persist(serviceGroupEntity);
   }
 
@@ -111,8 +98,10 @@ public class ServiceGroupImpl implements ServiceGroup {
                           @Assisted ServiceGroupEntity serviceGroupEntity,
                           ClusterDAO clusterDAO,
                           ServiceGroupDAO serviceGroupDAO,
-                          AmbariEventPublisher eventPublisher) throws AmbariException {
+                          AmbariEventPublisher eventPublisher,
+                          Clusters clusters) throws AmbariException {
     this.cluster = cluster;
+    this.clusters = clusters;
     this.clusterDAO = clusterDAO;
     this.serviceGroupDAO = serviceGroupDAO;
     this.eventPublisher = eventPublisher;
@@ -176,29 +165,30 @@ public class ServiceGroupImpl implements ServiceGroup {
     return responses;
   }
 
-  public Set<ServiceGroupKey> getServiceGroupDependencies(List<ServiceGroupEntity> serviceGroupDependencies) {
+  public Set<ServiceGroupKey> getServiceGroupDependencies(List<ServiceGroupDependencyEntity> serviceGroupDependencies) {
     Set<ServiceGroupKey> serviceGroupDependenciesList = new HashSet<>();
     if (serviceGroupDependencies != null) {
-      for (ServiceGroupEntity sge : serviceGroupDependencies) {
+      for (ServiceGroupDependencyEntity sgde : serviceGroupDependencies) {
         ServiceGroupKey serviceGroupKey = new ServiceGroupKey();
+        ServiceGroupEntity dependencyServiceGroupEntity = sgde.getServiceGroupDependency();
         String clusterName = "";
         Long clusterId = null;
-        if (sge.getClusterId() == cluster.getClusterId()) {
+        if (dependencyServiceGroupEntity.getClusterId() == cluster.getClusterId()) {
           clusterName = cluster.getClusterName();
           clusterId = cluster.getClusterId();
         } else {
-          ClusterEntity clusterEntity = clusterDAO.findById(sge.getClusterId());
+          ClusterEntity clusterEntity = clusterDAO.findById(dependencyServiceGroupEntity.getClusterId());
           if (clusterEntity != null) {
             clusterName = clusterEntity.getClusterName();
             clusterId = clusterEntity.getClusterId();
           } else {
-            LOG.error("Unable to get cluster id for service group " + sge.getServiceGroupName());
+            LOG.error("Unable to get cluster id for service group " + dependencyServiceGroupEntity.getServiceGroupName());
           }
         }
 
         ServiceGroupEntityPK serviceGroupEntityPK = new ServiceGroupEntityPK();
-        serviceGroupEntityPK.setClusterId(sge.getClusterId());
-        serviceGroupEntityPK.setServiceGroupId(sge.getServiceGroupId());
+        serviceGroupEntityPK.setClusterId(dependencyServiceGroupEntity.getClusterId());
+        serviceGroupEntityPK.setServiceGroupId(dependencyServiceGroupEntity.getServiceGroupId());
         ServiceGroupEntity serviceGroupEntity = serviceGroupDAO.findByPK(serviceGroupEntityPK);
         String serviceGroupDependencyName = "";
         Long serviceGroupDependencId = null;
@@ -206,7 +196,7 @@ public class ServiceGroupImpl implements ServiceGroup {
           serviceGroupDependencyName = serviceGroupEntity.getServiceGroupName();
           serviceGroupDependencId = serviceGroupEntity.getServiceGroupId();
         } else {
-          LOG.error("Unable to get service group entity for service group " + sge.getServiceGroupName());
+          LOG.error("Unable to get service group entity for service group " + dependencyServiceGroupEntity.getServiceGroupName());
         }
 
         serviceGroupKey.setServiceGroupName(serviceGroupDependencyName);
@@ -235,8 +225,8 @@ public class ServiceGroupImpl implements ServiceGroup {
    * perform the JPA merges inside of a transaction. Because of this, a
    * transaction is not necessary before this calling this method.
    */
-  private void persist(ServiceGroupEntity serviceGroupEntity) {
-    persistEntities(serviceGroupEntity);
+  private ServiceGroupEntity persist(ServiceGroupEntity serviceGroupEntity) {
+    ServiceGroupEntity createdServiceGroupEntity = persistEntities(serviceGroupEntity);
     refresh();
 
     cluster.addServiceGroup(this);
@@ -245,10 +235,11 @@ public class ServiceGroupImpl implements ServiceGroup {
     ServiceGroupInstalledEvent event = new ServiceGroupInstalledEvent(
       getClusterId(), getServiceGroupName());
     eventPublisher.publish(event);
+    return createdServiceGroupEntity;
   }
 
   @Transactional
-  protected void persistEntities(ServiceGroupEntity serviceGroupEntity) {
+  protected ServiceGroupEntity persistEntities(ServiceGroupEntity serviceGroupEntity) {
     long clusterId = cluster.getClusterId();
 
     ClusterEntity clusterEntity = clusterDAO.findById(clusterId);
@@ -257,7 +248,7 @@ public class ServiceGroupImpl implements ServiceGroup {
     serviceGroupId = serviceGroupEntity.getServiceGroupId();
     clusterEntity.getServiceGroupEntities().add(serviceGroupEntity);
     clusterDAO.merge(clusterEntity);
-    serviceGroupDAO.merge(serviceGroupEntity);
+    return serviceGroupDAO.merge(serviceGroupEntity);
   }
 
   @Override
@@ -276,7 +267,6 @@ public class ServiceGroupImpl implements ServiceGroup {
     return true;
   }
 
-
   @Override
   @Transactional
   public void delete() throws AmbariException {
@@ -287,20 +277,67 @@ public class ServiceGroupImpl implements ServiceGroup {
   }
 
   @Override
+  public ServiceGroupEntity addServiceGroupDependency(Long dependencyServiceGroupId) throws AmbariException {
+    ServiceGroupEntityPK serviceGroupEntityPK = new ServiceGroupEntityPK();
+    serviceGroupEntityPK.setClusterId(getClusterId());
+    serviceGroupEntityPK.setServiceGroupId(getServiceGroupId());
+    ServiceGroupEntity serviceGroupEntity = serviceGroupDAO.findByPK(serviceGroupEntityPK);
+
+    ServiceGroupEntityPK dependencyServiceGroupEntityPK = new ServiceGroupEntityPK();
+    dependencyServiceGroupEntityPK.setClusterId(getServiceGroupClusterId(dependencyServiceGroupId));
+    dependencyServiceGroupEntityPK.setServiceGroupId(dependencyServiceGroupId);
+    ServiceGroupEntity dependencyServiceGroupEntity = serviceGroupDAO.findByPK(dependencyServiceGroupEntityPK);
+
+
+    ServiceGroupDependencyEntity newDependency = new ServiceGroupDependencyEntity();
+    newDependency.setServiceGroup(serviceGroupEntity);
+    newDependency.setServiceGroupDependency(dependencyServiceGroupEntity);
+    createServiceGroupDependency(newDependency);
+
+
+    serviceGroupEntity.getServiceGroupDependencies().add(newDependency);
+    serviceGroupEntity = serviceGroupDAO.merge(serviceGroupEntity);
+
+    return serviceGroupEntity;
+  }
+
   @Transactional
-  public ServiceGroupEntity deleteDependency(String dependencyServiceGroupName) throws AmbariException {
+  public void createServiceGroupDependency(ServiceGroupDependencyEntity serviceGroupDependencyEntity) {
+    serviceGroupDAO.createServiceGroupDependency(serviceGroupDependencyEntity);
+  }
+
+
+  private Long getServiceGroupClusterId(Long serviceGroupId) throws AmbariException {
+    for (Cluster cl : clusters.getClusters().values()) {
+      if (cl.getServiceGroupsById().containsKey(serviceGroupId)) {
+        return cl.getClusterId();
+      }
+    }
+    throw new AmbariException("Service group with id=" + serviceGroupId + " is not available.");
+  }
+
+  @Override
+  public ServiceGroupEntity deleteServiceGroupDependency(Long dependencyServiceGroupId) throws AmbariException {
     ServiceGroupEntityPK pk = new ServiceGroupEntityPK();
     pk.setClusterId(getClusterId());
     pk.setServiceGroupId(getServiceGroupId());
     ServiceGroupEntity serviceGroupEntity = serviceGroupDAO.findByPK(pk);
-    ServiceGroupEntity dependencyToRemove = null;
-    for (ServiceGroupEntity dependency : serviceGroupEntity.getServiceGroupDependencies()) {
-      if (dependency.getServiceGroupName().equals(dependencyServiceGroupName)) {
+    ServiceGroupDependencyEntity dependencyToRemove = null;
+    for (ServiceGroupDependencyEntity dependency : serviceGroupEntity.getServiceGroupDependencies()) {
+      if (dependency.getServiceGroupDependency().getServiceGroupId() == dependencyServiceGroupId) {
         dependencyToRemove = dependency;
         break;
       }
     }
+
+    return removeServcieGroupDependencyEntity(serviceGroupEntity, dependencyToRemove);
+  }
+
+  @Transactional
+  protected ServiceGroupEntity removeServcieGroupDependencyEntity(ServiceGroupEntity serviceGroupEntity,
+                                                                  ServiceGroupDependencyEntity dependencyToRemove) {
     serviceGroupEntity.getServiceGroupDependencies().remove(dependencyToRemove);
+    serviceGroupDAO.removeServiceGroupDependency(dependencyToRemove);
     serviceGroupEntity = serviceGroupDAO.merge(serviceGroupEntity);
     return serviceGroupEntity;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
index dcead7a..4a8cdee 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
@@ -105,7 +105,6 @@ import org.apache.ambari.server.orm.entities.ResourceEntity;
 import org.apache.ambari.server.orm.entities.ServiceConfigEntity;
 import org.apache.ambari.server.orm.entities.ServiceDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.ServiceGroupEntity;
-import org.apache.ambari.server.orm.entities.ServiceGroupEntityPK;
 import org.apache.ambari.server.orm.entities.StackEntity;
 import org.apache.ambari.server.orm.entities.TopologyRequestEntity;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
@@ -1043,39 +1042,16 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
-  public ServiceGroup addServiceGroupDependency(String serviceGroupName, String dependencyServiceGroupName) throws AmbariException {
-    if (!serviceGroups.containsKey(serviceGroupName)) {
-      throw new AmbariException("Service group doesn't exist" + ", clusterName=" + getClusterName()
-              + ", clusterId=" + getClusterId() + ", serviceGroupName=" + serviceGroupName);
-    }
-
-    if (!serviceGroups.containsKey(dependencyServiceGroupName)) {
-      throw new AmbariException("Dependent service group doesn't exist" + ", clusterName=" + getClusterName()
-              + ", clusterId=" + getClusterId() + ", serviceGroupName=" + serviceGroupName);
-    }
-
-    ServiceGroupEntity serviceGroupEntity = null;
+  public void addServiceGroupDependency(String serviceGroupName, Long dependencyServiceGroupId) throws AmbariException {
     clusterGlobalLock.writeLock().lock();
     try {
-      ServiceGroupEntityPK serviceGroupEntityPK = new ServiceGroupEntityPK();
-      serviceGroupEntityPK.setClusterId(getClusterId());
-      serviceGroupEntityPK.setServiceGroupId(serviceGroups.get(serviceGroupName).getServiceGroupId());
-      serviceGroupEntity = serviceGroupDAO.findByPK(serviceGroupEntityPK);
-
-      ServiceGroupEntityPK dependencyServiceGroupEntityPK = new ServiceGroupEntityPK();
-      dependencyServiceGroupEntityPK.setClusterId(getClusterId());
-      dependencyServiceGroupEntityPK.setServiceGroupId(serviceGroups.get(dependencyServiceGroupName).getServiceGroupId());
-      ServiceGroupEntity dependencyServiceGroupEntity = serviceGroupDAO.findByPK(dependencyServiceGroupEntityPK);
-
-      serviceGroupEntity.getServiceGroupDependencies().add(dependencyServiceGroupEntity);
-      serviceGroupEntity = serviceGroupDAO.merge(serviceGroupEntity);
+      ServiceGroupEntity updatedServiceGroupEntity = getServiceGroup(serviceGroupName).addServiceGroupDependency(dependencyServiceGroupId);
+
+      ServiceGroup serviceGroup = serviceGroupFactory.createExisting(this, updatedServiceGroupEntity);
+      addServiceGroup(serviceGroup);
     } finally {
       clusterGlobalLock.writeLock().unlock();
     }
-
-    ServiceGroup serviceGroup = serviceGroupFactory.createExisting(this, serviceGroupEntity);
-    addServiceGroup(serviceGroup);
-    return serviceGroup;
   }
 
   @Override
@@ -1773,15 +1749,14 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
-  public void deleteServiceGroupDependency(String serviceGroupName, String dependencyServiceGroupName) throws AmbariException {
+  public void deleteServiceGroupDependency(String serviceGroupName, Long dependencyServiceGroupId) throws AmbariException {
     clusterGlobalLock.writeLock().lock();
     try {
       ServiceGroup serviceGroup = getServiceGroup(serviceGroupName);
-      LOG.info("Deleting service group dependency, dependencyServiceGroupName=" + dependencyServiceGroupName + " in cluster" + ", clusterName="
+      LOG.info("Deleting service group dependency, dependencyServiceGroupId=" + dependencyServiceGroupId + " in cluster" + ", clusterName="
               + getClusterName() + ", serviceGroupName=" + serviceGroup.getServiceGroupName());
 
-      Long serviceGroupId = serviceGroup.getServiceGroupId();
-      ServiceGroupEntity serviceGroupEntity = serviceGroup.deleteDependency(dependencyServiceGroupName);
+      ServiceGroupEntity serviceGroupEntity = serviceGroup.deleteServiceGroupDependency(dependencyServiceGroupId);
       ServiceGroup updatedServiceGroup = serviceGroupFactory.createExisting(this, serviceGroupEntity);
       serviceGroups.put(updatedServiceGroup.getServiceGroupName(), updatedServiceGroup);
       serviceGroupsById.put(updatedServiceGroup.getServiceGroupId(), updatedServiceGroup);
@@ -1817,6 +1792,11 @@ public class ClusterImpl implements Cluster {
     }
   }
 
+  @Override
+  public Map<Long, ServiceGroup> getServiceGroupsById() {
+    return serviceGroupsById;
+  }
+
   /**
    * Deletes the specified service also removes references to it from {@link this.serviceComponentHosts}
    * and references to ServiceComponentHost objects that belong to the service from {@link this.serviceComponentHostsByHost}

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
index a591bbf..06f3387 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
@@ -139,12 +139,14 @@ CREATE TABLE servicegroups (
   CONSTRAINT FK_servicegroups_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id));
 
 CREATE TABLE servicegroupdependencies (
+  id BIGINT NOT NULL,
   service_group_id BIGINT NOT NULL,
   service_group_cluster_id BIGINT NOT NULL,
   dependent_service_group_id BIGINT NOT NULL,
   dependent_service_group_cluster_id BIGINT NOT NULL,
-  CONSTRAINT PK_servicegroupdependencies PRIMARY KEY (service_group_id, service_group_cluster_id, dependent_service_group_id, dependent_service_group_cluster_id),
-  CONSTRAINT FK_servicegroupdependencies_service_group_cluster_id FOREIGN KEY (service_group_id, service_group_cluster_id) REFERENCES servicegroups (id, cluster_id));
+  CONSTRAINT PK_servicegroupdependencies PRIMARY KEY (id),
+  CONSTRAINT UQ_servicegroupdependencies UNIQUE (service_group_id, service_group_cluster_id, dependent_service_group_id, dependent_service_group_cluster_id),
+  CONSTRAINT FK_servicegroupdependencies_service_group_cluster_id FOREIGN KEY (service_group_id, service_group_cluster_id) REFERENCES servicegroups (id, cluster_id),
   CONSTRAINT FK_servicegroupdependencies_dependent_service_group_cluster_id FOREIGN KEY (dependent_service_group_id, dependent_service_group_cluster_id) REFERENCES servicegroups (id, cluster_id));
 
 CREATE TABLE clusterservices (
@@ -1158,6 +1160,8 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value)
   UNION ALL
   SELECT 'service_group_id_seq', 1 FROM SYSIBM.SYSDUMMY1
   UNION ALL
+  SELECT 'service_group_dependency_id_seq', 1 FROM SYSIBM.SYSDUMMY1
+  UNION ALL
   SELECT 'service_id_seq', 1 FROM SYSIBM.SYSDUMMY1
   UNION ALL
   SELECT 'host_id_seq', 0 FROM SYSIBM.SYSDUMMY1

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index 6c2c0f4..e204aab 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -158,12 +158,14 @@ CREATE TABLE servicegroups (
   CONSTRAINT FK_servicegroups_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id));
 
 CREATE TABLE servicegroupdependencies (
+  id BIGINT NOT NULL,
   service_group_id BIGINT NOT NULL,
   service_group_cluster_id BIGINT NOT NULL,
   dependent_service_group_id BIGINT NOT NULL,
   dependent_service_group_cluster_id BIGINT NOT NULL,
-  CONSTRAINT PK_servicegroupdependencies PRIMARY KEY (service_group_id, service_group_cluster_id, dependent_service_group_id, dependent_service_group_cluster_id),
-  CONSTRAINT FK_servicegroupdependencies_service_group_cluster_id FOREIGN KEY (service_group_id, service_group_cluster_id) REFERENCES servicegroups (id, cluster_id));
+  CONSTRAINT PK_servicegroupdependencies PRIMARY KEY (id),
+  CONSTRAINT UQ_servicegroupdependencies UNIQUE (service_group_id, service_group_cluster_id, dependent_service_group_id, dependent_service_group_cluster_id),
+  CONSTRAINT FK_servicegroupdependencies_service_group_cluster_id FOREIGN KEY (service_group_id, service_group_cluster_id) REFERENCES servicegroups (id, cluster_id),
   CONSTRAINT FK_servicegroupdependencies_dependent_service_group_cluster_id FOREIGN KEY (dependent_service_group_id, dependent_service_group_cluster_id) REFERENCES servicegroups (id, cluster_id));
 
 CREATE TABLE clusterservices (
@@ -1170,6 +1172,7 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) VALUES
   ('cluster_id_seq', 1),
   ('cluster_setting_id_seq', 1),
   ('service_group_id_seq', 1),
+  ('service_group_dependency_id_seq', 1),
   ('service_id_seq', 1),
   ('host_id_seq', 0),
   ('host_role_command_id_seq', 1),

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index d697e05..4cd4ba4 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -139,12 +139,14 @@ CREATE TABLE servicegroups (
   CONSTRAINT FK_servicegroups_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id));
 
 CREATE TABLE servicegroupdependencies (
+  id NUMBER(19) NOT NULL,
   service_group_id NUMBER(19) NOT NULL,
   service_group_cluster_id NUMBER(19) NOT NULL,
   dependent_service_group_id NUMBER(19) NOT NULL,
   dependent_service_group_cluster_id NUMBER(19) NOT NULL,
-  CONSTRAINT PK_servicegroupdependencies PRIMARY KEY (service_group_id, service_group_cluster_id, dependent_service_group_id, dependent_service_group_cluster_id),
-  CONSTRAINT FK_servicegroupdependencies_service_group_cluster_id FOREIGN KEY (service_group_id, service_group_cluster_id) REFERENCES servicegroups (id, cluster_id));
+  CONSTRAINT PK_servicegroupdependencies PRIMARY KEY (id),
+  CONSTRAINT UQ_servicegroupdependencies UNIQUE (service_group_id, service_group_cluster_id, dependent_service_group_id, dependent_service_group_cluster_id),
+  CONSTRAINT FK_servicegroupdependencies_service_group_cluster_id FOREIGN KEY (service_group_id, service_group_cluster_id) REFERENCES servicegroups (id, cluster_id),
   CONSTRAINT FK_servicegroupdependencies_dependent_service_group_cluster_id FOREIGN KEY (dependent_service_group_id, dependent_service_group_cluster_id) REFERENCES servicegroups (id, cluster_id));
 
 CREATE TABLE clusterservices (
@@ -1149,6 +1151,7 @@ CREATE INDEX idx_alert_notice_state on alert_notice(notify_state);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('host_role_command_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('cluster_setting_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_group_id_seq', 1);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_group_dependency_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('user_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('group_id_seq', 0);

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index f9544a5..1c296ee 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -140,12 +140,14 @@ CREATE TABLE servicegroups (
   CONSTRAINT FK_servicegroups_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id));
 
 CREATE TABLE servicegroupdependencies (
+  id BIGINT NOT NULL,
   service_group_id BIGINT NOT NULL,
   service_group_cluster_id BIGINT NOT NULL,
   dependent_service_group_id BIGINT NOT NULL,
   dependent_service_group_cluster_id BIGINT NOT NULL,
-  CONSTRAINT PK_servicegroupdependencies PRIMARY KEY (service_group_id, service_group_cluster_id, dependent_service_group_id, dependent_service_group_cluster_id),
-  CONSTRAINT FK_servicegroupdependencies_service_group_cluster_id FOREIGN KEY (service_group_id, service_group_cluster_id) REFERENCES servicegroups (id, cluster_id));
+  CONSTRAINT PK_servicegroupdependencies PRIMARY KEY (id),
+  CONSTRAINT UQ_servicegroupdependencies UNIQUE (service_group_id, service_group_cluster_id, dependent_service_group_id, dependent_service_group_cluster_id),
+  CONSTRAINT FK_servicegroupdependencies_service_group_cluster_id FOREIGN KEY (service_group_id, service_group_cluster_id) REFERENCES servicegroups (id, cluster_id),
   CONSTRAINT FK_servicegroupdependencies_dependent_service_group_cluster_id FOREIGN KEY (dependent_service_group_id, dependent_service_group_cluster_id) REFERENCES servicegroups (id, cluster_id));
 
 CREATE TABLE clusterservices (
@@ -1154,6 +1156,7 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value) VALUES
   ('cluster_id_seq', 1),
   ('cluster_setting_id_seq', 1),
   ('service_group_id_seq', 1),
+  ('service_group_dependency_id_seq', 1),
   ('service_id_seq', 1),
   ('host_id_seq', 0),
   ('user_id_seq', 2),

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
index fb98cbd..7dfe929 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -138,12 +138,14 @@ CREATE TABLE servicegroups (
   CONSTRAINT FK_servicegroups_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id));
 
 CREATE TABLE servicegroupdependencies (
+  id NUMBER(19) NOT NULL,
   service_group_id NUMBER(19) NOT NULL,
   service_group_cluster_id NUMBER(19) NOT NULL,
   dependent_service_group_id NUMBER(19) NOT NULL,
   dependent_service_group_cluster_id NUMBER(19) NOT NULL,
-  CONSTRAINT PK_servicegroupdependencies PRIMARY KEY (service_group_id, service_group_cluster_id, dependent_service_group_id, dependent_service_group_cluster_id),
-  CONSTRAINT FK_servicegroupdependencies_service_group_cluster_id FOREIGN KEY (service_group_id, service_group_cluster_id) REFERENCES servicegroups (id, cluster_id));
+  CONSTRAINT PK_servicegroupdependencies PRIMARY KEY (id),
+  CONSTRAINT UQ_servicegroupdependencies UNIQUE (service_group_id, service_group_cluster_id, dependent_service_group_id, dependent_service_group_cluster_id),
+  CONSTRAINT FK_servicegroupdependencies_service_group_cluster_id FOREIGN KEY (service_group_id, service_group_cluster_id) REFERENCES servicegroups (id, cluster_id),
   CONSTRAINT FK_servicegroupdependencies_dependent_service_group_cluster_id FOREIGN KEY (dependent_service_group_id, dependent_service_group_cluster_id) REFERENCES servicegroups (id, cluster_id));
 
 CREATE TABLE clusterservices (
@@ -1148,6 +1150,7 @@ CREATE INDEX idx_alert_notice_state on alert_notice(notify_state);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('cluster_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('cluster_setting_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_group_id_seq', 1);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_group_dependency_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('host_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('host_role_command_id_seq', 1);

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
index 9f93fbb..7ad4251 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -152,12 +152,14 @@ CREATE TABLE servicegroups (
   CONSTRAINT FK_servicegroups_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id));
 
 CREATE TABLE servicegroupdependencies (
+  id BIGINT NOT NULL,
   service_group_id BIGINT NOT NULL,
   service_group_cluster_id BIGINT NOT NULL,
   dependent_service_group_id BIGINT NOT NULL,
   dependent_service_group_cluster_id BIGINT NOT NULL,
-  CONSTRAINT PK_servicegroupdependencies PRIMARY KEY (service_group_id, service_group_cluster_id, dependent_service_group_id, dependent_service_group_cluster_id),
-  CONSTRAINT FK_servicegroupdependencies_service_group_cluster_id FOREIGN KEY (service_group_id, service_group_cluster_id) REFERENCES servicegroups (id, cluster_id));
+  CONSTRAINT PK_servicegroupdependencies PRIMARY KEY (id),
+  CONSTRAINT UQ_servicegroupdependencies UNIQUE (service_group_id, service_group_cluster_id, dependent_service_group_id, dependent_service_group_cluster_id),
+  CONSTRAINT FK_servicegroupdependencies_service_group_cluster_id FOREIGN KEY (service_group_id, service_group_cluster_id) REFERENCES servicegroups (id, cluster_id),
   CONSTRAINT FK_servicegroupdependencies_dependent_service_group_cluster_id FOREIGN KEY (dependent_service_group_id, dependent_service_group_cluster_id) REFERENCES servicegroups (id, cluster_id));
 
 CREATE TABLE clusterservices (
@@ -1174,6 +1176,7 @@ BEGIN TRANSACTION
     ('cluster_id_seq', 1),
     ('cluster_setting_id_seq', 1),
     ('service_group_id_seq', 1),
+    ('service_group_dependency_id_seq', 1),
     ('service_id_seq', 1),
     ('host_id_seq', 0),
     ('user_id_seq', 2),

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/META-INF/persistence.xml b/ambari-server/src/main/resources/META-INF/persistence.xml
index 218b0d2..5b0d439 100644
--- a/ambari-server/src/main/resources/META-INF/persistence.xml
+++ b/ambari-server/src/main/resources/META-INF/persistence.xml
@@ -27,6 +27,7 @@
     <class>org.apache.ambari.server.orm.entities.ClusterConfigEntity</class>
     <class>org.apache.ambari.server.orm.entities.ClusterEntity</class>
     <class>org.apache.ambari.server.orm.entities.ServiceGroupEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ServiceGroupDependencyEntity</class>
     <class>org.apache.ambari.server.orm.entities.ClusterSettingEntity</class>
     <class>org.apache.ambari.server.orm.entities.ClusterServiceEntity</class>
     <class>org.apache.ambari.server.orm.entities.ClusterStateEntity</class>