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/02 22:06:46 UTC

[1/2] ambari git commit: AMBARI-22345. Add service dependencies.(vbrodetskyi)

Repository: ambari
Updated Branches:
  refs/heads/branch-feature-AMBARI-14714 adc7060a6 -> 72bac1f7f


http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/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 b1990df..70a6543 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -215,6 +215,17 @@ CREATE TABLE clusterservices (
   CONSTRAINT PK_clusterservices PRIMARY KEY (id, service_group_id, cluster_id),
   CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (service_group_id, cluster_id) REFERENCES servicegroups (id, cluster_id));
 
+CREATE TABLE servicedependencies (
+  service_id BIGINT NOT NULL,
+  service_group_id BIGINT NOT NULL,
+  service_cluster_id BIGINT NOT NULL,
+  dependent_service_id BIGINT NOT NULL,
+  dependent_service_group_id BIGINT NOT NULL,
+  dependent_service_cluster_id BIGINT NOT NULL,
+  CONSTRAINT PK_servicedependencies PRIMARY KEY (service_id, service_group_id, service_cluster_id, dependent_service_id, dependent_service_group_id, dependent_service_cluster_id),
+  CONSTRAINT FK_servicedependencies_service_group_cluster_id FOREIGN KEY (service_id, service_group_id, service_cluster_id) REFERENCES clusterservices  (id, service_group_id, cluster_id));
+  CONSTRAINT FK_servicedependencies_dependent_service_group_cluster_id FOREIGN KEY (dependent_service_id, dependent_service_group_id, dependent_service_cluster_id) REFERENCES clusterservices (id, service_group_id, cluster_id));
+
 CREATE TABLE clusterstate (
   cluster_id BIGINT NOT NULL,
   current_cluster_state VARCHAR(255) NOT NULL,

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/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 015d6ac..7c5f0fd 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -197,6 +197,17 @@ CREATE TABLE clusterservices (
   CONSTRAINT PK_clusterservices PRIMARY KEY (id, service_group_id, cluster_id),
   CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (service_group_id, cluster_id) REFERENCES servicegroups (id, cluster_id));
 
+CREATE TABLE servicedependencies (
+  service_id NUMBER(19) NOT NULL,
+  service_group_id NUMBER(19) NOT NULL,
+  service_cluster_id NUMBER(19) NOT NULL,
+  dependent_service_id NUMBER(19) NOT NULL,
+  dependent_service_group_id NUMBER(19) NOT NULL,
+  dependent_service_cluster_id NUMBER(19) NOT NULL,
+  CONSTRAINT PK_servicedependencies PRIMARY KEY (service_id, service_group_id, service_cluster_id, dependent_service_id, dependent_service_group_id, dependent_service_cluster_id),
+  CONSTRAINT FK_servicedependencies_service_group_cluster_id FOREIGN KEY (service_id, service_group_id, service_cluster_id) REFERENCES clusterservices  (id, service_group_id, cluster_id));
+  CONSTRAINT FK_servicedependencies_dependent_service_group_cluster_id FOREIGN KEY (dependent_service_id, dependent_service_group_id, dependent_service_cluster_id) REFERENCES clusterservices (id, service_group_id, cluster_id));
+
 CREATE TABLE clusterstate (
   cluster_id NUMBER(19) NOT NULL,
   current_cluster_state VARCHAR2(255) NULL,

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/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 d3c7ff6..dfef1ce 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -197,6 +197,17 @@ CREATE TABLE clusterservices (
   CONSTRAINT PK_clusterservices PRIMARY KEY (id, service_group_id, cluster_id),
   CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (service_group_id, cluster_id) REFERENCES servicegroups (id, cluster_id));
 
+CREATE TABLE servicedependencies (
+  service_id BIGINT NOT NULL,
+  service_group_id BIGINT NOT NULL,
+  service_cluster_id BIGINT NOT NULL,
+  dependent_service_id BIGINT NOT NULL,
+  dependent_service_group_id BIGINT NOT NULL,
+  dependent_service_cluster_id BIGINT NOT NULL,
+  CONSTRAINT PK_servicedependencies PRIMARY KEY (service_id, service_group_id, service_cluster_id, dependent_service_id, dependent_service_group_id, dependent_service_cluster_id),
+  CONSTRAINT FK_servicedependencies_service_group_cluster_id FOREIGN KEY (service_id, service_group_id, service_cluster_id) REFERENCES clusterservices  (id, service_group_id, cluster_id));
+  CONSTRAINT FK_servicedependencies_dependent_service_group_cluster_id FOREIGN KEY (dependent_service_id, dependent_service_group_id, dependent_service_cluster_id) REFERENCES clusterservices (id, service_group_id, cluster_id));
+
 CREATE TABLE clusterstate (
   cluster_id BIGINT NOT NULL,
   current_cluster_state VARCHAR(255) NOT NULL,

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/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 6bfe205..870555d 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -195,6 +195,17 @@ CREATE TABLE clusterservices (
   CONSTRAINT PK_clusterservices PRIMARY KEY (id, service_group_id, cluster_id),
   CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (service_group_id, cluster_id) REFERENCES servicegroups (id, cluster_id));
 
+CREATE TABLE servicedependencies (
+  service_id NUMERIC(19) NOT NULL,
+  service_group_id NUMERIC(19) NOT NULL,
+  service_cluster_id NUMERIC(19) NOT NULL,
+  dependent_service_id NUMERIC(19) NOT NULL,
+  dependent_service_group_id NUMERIC(19) NOT NULL,
+  dependent_service_cluster_id NUMERIC(19) NOT NULL,
+  CONSTRAINT PK_servicedependencies PRIMARY KEY (service_id, service_group_id, service_cluster_id, dependent_service_id, dependent_service_group_id, dependent_service_cluster_id),
+  CONSTRAINT FK_servicedependencies_service_group_cluster_id FOREIGN KEY (service_id, service_group_id, service_cluster_id) REFERENCES clusterservices  (id, service_group_id, cluster_id));
+  CONSTRAINT FK_servicedependencies_dependent_service_group_cluster_id FOREIGN KEY (dependent_service_id, dependent_service_group_id, dependent_service_cluster_id) REFERENCES clusterservices (id, service_group_id, cluster_id));
+
 CREATE TABLE clusterstate (
   cluster_id NUMERIC(19) NOT NULL,
   current_cluster_state VARCHAR(255) NOT NULL,

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/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 65315ec..641b959 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -209,6 +209,17 @@ CREATE TABLE clusterservices (
   CONSTRAINT PK_clusterservices PRIMARY KEY (id, service_group_id, cluster_id),
   CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (service_group_id, cluster_id) REFERENCES servicegroups (id, cluster_id));
 
+CREATE TABLE servicedependencies (
+  service_id BIGINT NOT NULL,
+  service_group_id BIGINT NOT NULL,
+  service_cluster_id BIGINT NOT NULL,
+  dependent_service_id BIGINT NOT NULL,
+  dependent_service_group_id BIGINT NOT NULL,
+  dependent_service_cluster_id BIGINT NOT NULL,
+  CONSTRAINT PK_servicedependencies PRIMARY KEY (service_id, service_group_id, service_cluster_id, dependent_service_id, dependent_service_group_id, dependent_service_cluster_id),
+  CONSTRAINT FK_servicedependencies_service_group_cluster_id FOREIGN KEY (service_id, service_group_id, service_cluster_id) REFERENCES clusterservices  (id, service_group_id, cluster_id));
+  CONSTRAINT FK_servicedependencies_dependent_service_group_cluster_id FOREIGN KEY (dependent_service_id, dependent_service_group_id, dependent_service_cluster_id) REFERENCES clusterservices (id, service_group_id, cluster_id));
+
 CREATE TABLE clusterstate (
   cluster_id BIGINT NOT NULL,
   current_cluster_state VARCHAR(255) NOT NULL,


[2/2] ambari git commit: AMBARI-22345. Add service dependencies.(vbrodetskyi)

Posted by vb...@apache.org.
AMBARI-22345. Add service dependencies.(vbrodetskyi)


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

Branch: refs/heads/branch-feature-AMBARI-14714
Commit: 72bac1f7f580c3c5ac4160cbc0418002b683bda0
Parents: adc7060
Author: Vitaly Brodetskyi <vb...@hortonworks.com>
Authored: Fri Nov 3 00:06:23 2017 +0200
Committer: Vitaly Brodetskyi <vb...@hortonworks.com>
Committed: Fri Nov 3 00:06:23 2017 +0200

----------------------------------------------------------------------
 .../resources/ResourceInstanceFactoryImpl.java  |   4 +
 .../ServiceDependencyResourceDefinition.java    |  45 ++
 .../resources/ServiceResourceDefinition.java    |   1 +
 .../ambari/server/api/services/ServiceKey.java  | 118 +++++
 .../server/api/services/ServiceService.java     | 111 ++++
 .../server/controller/ControllerModule.java     |   2 +
 .../controller/ResourceProviderFactory.java     |   3 +
 .../controller/ServiceDependencyRequest.java    |  87 ++++
 .../controller/ServiceDependencyResponse.java   | 197 +++++++
 .../AbstractControllerResourceProvider.java     |   2 +
 .../internal/DefaultProviderModule.java         |   2 +
 .../ServiceDependencyResourceProvider.java      | 511 +++++++++++++++++++
 .../ambari/server/controller/spi/Resource.java  |   2 +
 .../orm/entities/ClusterServiceEntity.java      |  36 +-
 .../org/apache/ambari/server/state/Cluster.java |   6 +
 .../org/apache/ambari/server/state/Service.java |   8 +
 .../ambari/server/state/ServiceFactory.java     |   4 +
 .../apache/ambari/server/state/ServiceImpl.java |  87 ++++
 .../server/state/cluster/ClusterImpl.java       |  86 +++-
 .../ambari/server/topology/AmbariContext.java   |  10 +
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  |  11 +
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |  11 +
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |  11 +
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |  11 +
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |  11 +
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |  11 +
 26 files changed, 1386 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
index 6096fa5..7ac41a5 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
@@ -120,6 +120,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
         resourceDefinition = new ServiceResourceDefinition();
         break;
 
+      case ServiceDependency:
+        resourceDefinition = new ServiceDependencyResourceDefinition();
+        break;
+
       case Host:
         resourceDefinition = mapIds.containsKey(Resource.Type.Cluster) ?
             new HostResourceDefinition() : new DetachedHostResourceDefinition();

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

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceResourceDefinition.java
index 8255674..0009c70 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceResourceDefinition.java
@@ -50,6 +50,7 @@ public class ServiceResourceDefinition extends BaseResourceDefinition {
   public Set<SubResourceDefinition> getSubResourceDefinitions() {
     Set<SubResourceDefinition> subs = new HashSet<>();
     subs.add(new SubResourceDefinition(Resource.Type.Component));
+    subs.add(new SubResourceDefinition(Resource.Type.ServiceDependency));
     subs.add(new SubResourceDefinition(Resource.Type.Alert));
     //todo: dynamic sub-resource definition
     subs.add(new SubResourceDefinition(Resource.Type.Artifact));

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceKey.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceKey.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceKey.java
new file mode 100644
index 0000000..ace7098
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceKey.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.api.services;
+
+public class ServiceKey {
+
+  private Long serviceId;
+  private Long serviceGroupId;
+  private Long clusterId;
+  private String serviceName;
+  private String serviceGroupName;
+  private String clusterName;
+
+  public ServiceKey() {
+  }
+
+  public ServiceKey(Long clusterId, String clusterName, Long serviceGroupId, String serviceGroupName, Long serviceId, String serviceName) {
+    this.clusterId = clusterId;
+    this.clusterName = clusterName;
+    this.serviceGroupId = serviceGroupId;
+    this.serviceGroupName = serviceGroupName;
+    this.serviceId = serviceId;
+    this.serviceName = serviceName;
+  }
+
+  public Long getClusterId() {
+    return clusterId;
+  }
+
+  public void setClusterId(Long clusterId) {
+    this.clusterId = clusterId;
+  }
+
+  public String getClusterName() {
+    return clusterName;
+  }
+
+  public void setClusterName(String clusterName) {
+    this.clusterName = clusterName;
+  }
+
+  public Long getServiceGroupId() {
+    return serviceGroupId;
+  }
+
+  public void setServiceGroupId(Long serviceGroupId) {
+    this.serviceGroupId = serviceGroupId;
+  }
+
+  public String getServiceGroupName() {
+    return serviceGroupName;
+  }
+
+  public void setServiceGroupName(String serviceGroupName) {
+    this.serviceGroupName = serviceGroupName;
+  }
+
+  public Long getServiceId() {
+    return serviceId;
+  }
+
+  public void setServiceId(Long serviceId) {
+    this.serviceId = serviceId;
+  }
+
+  public String getServiceName() {
+    return serviceName;
+  }
+
+  public void setServiceName(String serviceName) {
+    this.serviceName = serviceName;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (!(o instanceof ServiceKey)) return false;
+
+    ServiceKey that = (ServiceKey) o;
+
+    if (clusterId != null ? !clusterId.equals(that.clusterId) : that.clusterId != null) return false;
+    if (clusterName != null ? !clusterName.equals(that.clusterName) : that.clusterName != null) return false;
+    if (serviceGroupId != null ? !serviceGroupId.equals(that.serviceGroupId) : that.serviceGroupId != null)
+      return false;
+    if (serviceGroupName != null ? !serviceGroupName.equals(that.serviceGroupName) : that.serviceGroupName != null)
+      return false;
+    if (serviceId != null ? !serviceId.equals(that.serviceId) : that.serviceId != null) return false;
+    if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = serviceId != null ? serviceId.hashCode() : 0;
+    result = 31 * result + (serviceGroupId != null ? serviceGroupId.hashCode() : 0);
+    result = 31 * result + (clusterId != null ? clusterId.hashCode() : 0);
+    result = 31 * result + (serviceName != null ? serviceName.hashCode() : 0);
+    result = 31 * result + (serviceGroupName != null ? serviceGroupName.hashCode() : 0);
+    result = 31 * result + (clusterName != null ? clusterName.hashCode() : 0);
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceService.java
index cb0ad20..afdfcc4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceService.java
@@ -305,6 +305,106 @@ public class ServiceService extends BaseService {
     return handleRequest(headers, null, ui, Request.Type.DELETE, createServiceResource(m_clusterName, m_serviceGroupName, serviceName));
   }
 
+
+  @GET
+  @Path("{serviceName}/dependencies")
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Get all service dependencies",
+          nickname = "ServiceService#getServiceDependencies",
+          notes = "Returns all service dependencies.",
+          response = ServiceResponse.ServiceResponseSwagger.class,
+          responseContainer = RESPONSE_CONTAINER_LIST)
+  @ApiImplicitParams({
+          @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION,
+                  defaultValue = "ServiceInfo/service_group_name, ServiceInfo/service_name, ServiceInfo/cluster_name",
+                  dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
+          @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION,
+                  defaultValue = "ServiceInfo/service_group_name.asc, ServiceInfo/service_name.asc, ServiceInfo/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),
+          @ApiImplicitParam(name = QUERY_TO, value = QUERY_TO_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
+  })
+  @ApiResponses(value = {
+          @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+          @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR)
+  })
+  public Response getServiceDependencies(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                              @PathParam("serviceName") String serviceName) {
+    return handleRequest(headers, body, ui, Request.Type.GET,
+            createServiceDependencyResource(m_clusterName, m_serviceGroupName, serviceName, null));
+  }
+
+  @GET
+  @Path("{serviceName}/dependencies/{dependencyServiceName}")
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Get the details of a service dependency",
+          nickname = "ServiceService#getServiceDependency",
+          notes = "Returns the details of a service dependency.",
+          response = ServiceResponse.ServiceResponseSwagger.class,
+          responseContainer = RESPONSE_CONTAINER_LIST)
+  @ApiImplicitParams({
+          @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "ServiceInfo/*",
+                  dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
+  })
+  @ApiResponses(value = {
+          @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+          @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+          @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR)
+  })
+  public Response getServiceDependency(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                              @PathParam("serviceName") String serviceName,
+                                              @PathParam("dependencyServiceName") String dependencyServiceName) {
+    return handleRequest(headers, body, ui, Request.Type.GET,
+            createServiceDependencyResource(m_clusterName, m_serviceGroupName, serviceName, dependencyServiceName));
+  }
+
+
+  @POST
+  @Path("{serviceName}/dependencies")
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Creates a service dependency",
+          nickname = "ServiceService#createServiceDependency"
+  )
+  @ApiImplicitParams({
+          @ApiImplicitParam(dataType = SERVICE_REQUEST_TYPE, paramType = PARAM_TYPE_BODY, allowMultiple = true)
+  })
+  @ApiResponses({
+          @ApiResponse(code = HttpStatus.SC_CREATED, message = MSG_SUCCESSFUL_OPERATION),
+          @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED),
+          @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS),
+          @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+          @ApiResponse(code = HttpStatus.SC_CONFLICT, message = MSG_RESOURCE_ALREADY_EXISTS),
+          @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+          @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+          @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
+  })
+  public Response createServiceDependency(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                              @PathParam("serviceName") String serviceName) {
+    return handleRequest(headers, body, ui, Request.Type.POST,
+            createServiceDependencyResource(m_clusterName, m_serviceGroupName, serviceName, null));
+  }
+
+  @DELETE
+  @Path("{serviceName}/dependencies")
+  @Produces(MediaType.TEXT_PLAIN)
+  @ApiOperation(value = "Deletes a service dependency",
+          nickname = "ServiceService#deleteServiceDependency"
+  )
+  @ApiResponses({
+          @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+          @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+          @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+          @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+          @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
+  })
+  public Response deleteServiceDependency(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                              @PathParam("serviceName") String serviceName,
+                                              @PathParam("dependencyServiceName") String dependencyServiceName) {
+    return handleRequest(headers, body, ui, Request.Type.DELETE,
+            createServiceDependencyResource(m_clusterName, m_serviceGroupName, serviceName, dependencyServiceName));
+  }
+
   /**
    * Get the components sub-resource.
    *
@@ -652,4 +752,15 @@ public class ServiceService extends BaseService {
 
     return createResource(Resource.Type.Artifact, mapIds);
   }
+
+  ResourceInstance createServiceDependencyResource(String clusterName, String serviceGroupName, String serviceName, String serviceDependencyName) {
+    Map<Resource.Type, String> mapIds = new HashMap<>();
+    mapIds.put(Resource.Type.Cluster, clusterName);
+    mapIds.put(Resource.Type.ServiceGroup, serviceGroupName);
+    mapIds.put(Resource.Type.Service, serviceName);
+    mapIds.put(Resource.Type.ServiceDependency, serviceDependencyName);
+
+
+    return createResource(Resource.Type.ServiceDependency, mapIds);
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index 3db55d4..0303a71 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -73,6 +73,7 @@ import org.apache.ambari.server.controller.internal.HostResourceProvider;
 import org.apache.ambari.server.controller.internal.KerberosDescriptorResourceProvider;
 import org.apache.ambari.server.controller.internal.MemberResourceProvider;
 import org.apache.ambari.server.controller.internal.RepositoryVersionResourceProvider;
+import org.apache.ambari.server.controller.internal.ServiceDependencyResourceProvider;
 import org.apache.ambari.server.controller.internal.ServiceGroupDependencyResourceProvider;
 import org.apache.ambari.server.controller.internal.ServiceGroupResourceProvider;
 import org.apache.ambari.server.controller.internal.ServiceResourceProvider;
@@ -478,6 +479,7 @@ public class ControllerModule extends AbstractModule {
         .implement(ResourceProvider.class, Names.named("hostComponent"), HostComponentResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("service"), ServiceResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("servicegroup"), ServiceGroupResourceProvider.class)
+        .implement(ResourceProvider.class, Names.named("servicedependency"), ServiceDependencyResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("servicegroupdependency"), ServiceGroupDependencyResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("component"), ComponentResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("member"), MemberResourceProvider.class)

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
index 20f4864..0fbea9a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
@@ -45,6 +45,9 @@ public interface ResourceProviderFactory {
   @Named("service")
   ResourceProvider getServiceResourceProvider(AmbariManagementController managementController);
 
+  @Named("servicedependency")
+  ResourceProvider getServiceDependencyResourceProvider(AmbariManagementController managementController);
+
   @Named("servicegroup")
   ResourceProvider getServiceGroupResourceProvider(AmbariManagementController managementController);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceDependencyRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceDependencyRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceDependencyRequest.java
new file mode 100644
index 0000000..97fe502
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceDependencyRequest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.controller;
+
+public class ServiceDependencyRequest {
+
+  private String clusterName;
+  private String serviceName;
+  private String serviceGroupName;
+  private String dependencyServiceName;
+  private String dependencyServiceGroupName;
+
+  public ServiceDependencyRequest(String clusterName, String serviceName, String serviceGroupName,
+                                  String dependencyServiceName, String dependencyServiceGroupName) {
+    this.clusterName = clusterName;
+    this.serviceName = serviceName;
+    this.serviceGroupName = serviceGroupName;
+    this.dependencyServiceName = dependencyServiceName;
+    this.dependencyServiceGroupName = dependencyServiceGroupName;
+  }
+
+  public String getClusterName() {
+    return clusterName;
+  }
+
+  public void setClusterName(String clusterName) {
+    this.clusterName = clusterName;
+  }
+
+  public String getDependencyServiceName() {
+    return dependencyServiceName;
+  }
+
+  public void setDependencyServiceName(String dependencyServiceName) {
+    this.dependencyServiceName = dependencyServiceName;
+  }
+
+  public String getServiceGroupName() {
+    return serviceGroupName;
+  }
+
+  public void setServiceGroupName(String serviceGroupName) {
+    this.serviceGroupName = serviceGroupName;
+  }
+
+  public String getServiceName() {
+    return serviceName;
+  }
+
+  public void setServiceName(String serviceName) {
+    this.serviceName = serviceName;
+  }
+
+  public String getDependencyServiceGroupName() {
+    return dependencyServiceGroupName;
+  }
+
+  public void setDependencyServiceGroupName(String dependencyServiceGroupName) {
+    this.dependencyServiceGroupName = dependencyServiceGroupName;
+  }
+
+  @Override
+  public String toString() {
+    return "ServiceDependencyRequest{" +
+            "clusterName='" + clusterName + '\'' +
+            ", serviceName='" + serviceName + '\'' +
+            ", serviceGroupName='" + serviceGroupName + '\'' +
+            ", dependencyServiceName='" + dependencyServiceName + '\'' +
+            ", dependencyServiceGroupName='" + dependencyServiceGroupName + '\'' +
+            '}';
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceDependencyResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceDependencyResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceDependencyResponse.java
new file mode 100644
index 0000000..b6d40e3
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceDependencyResponse.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.controller;
+
+
+public class ServiceDependencyResponse {
+
+  private Long clusterId;
+  private Long serviceId;
+  private Long serviceGroupId;
+  private Long dependencyClusterId;
+  private Long dependencyServiceId;
+  private Long dependencyServiceGroupId;
+  private String clusterName;
+  private String serviceName;
+  private String serviceGroupName;
+  private String dependencyServiceName;
+  private String dependencyClusterName;
+  private String dependencyServiceGroupName;
+
+  public ServiceDependencyResponse(Long clusterId, String clusterName, Long dependencyClusterId, String dependencyClusterName,
+                                   Long dependencyServiceGroupId, String dependencyServiceGroupName, Long dependencyServiceId,
+                                   String dependencyServiceName, Long serviceGroupId, String serviceGroupName,
+                                   Long serviceId, String serviceName) {
+    this.clusterId = clusterId;
+    this.clusterName = clusterName;
+    this.dependencyClusterId = dependencyClusterId;
+    this.dependencyClusterName = dependencyClusterName;
+    this.dependencyServiceGroupId = dependencyServiceGroupId;
+    this.dependencyServiceGroupName = dependencyServiceGroupName;
+    this.dependencyServiceId = dependencyServiceId;
+    this.dependencyServiceName = dependencyServiceName;
+    this.serviceGroupId = serviceGroupId;
+    this.serviceGroupName = serviceGroupName;
+    this.serviceId = serviceId;
+    this.serviceName = serviceName;
+  }
+
+  public Long getClusterId() {
+    return clusterId;
+  }
+
+  public void setClusterId(Long clusterId) {
+    this.clusterId = clusterId;
+  }
+
+  public String getClusterName() {
+    return clusterName;
+  }
+
+  public void setClusterName(String clusterName) {
+    this.clusterName = clusterName;
+  }
+
+  public Long getDependencyClusterId() {
+    return dependencyClusterId;
+  }
+
+  public void setDependencyClusterId(Long dependencyClusterId) {
+    this.dependencyClusterId = dependencyClusterId;
+  }
+
+  public String getDependencyClusterName() {
+    return dependencyClusterName;
+  }
+
+  public void setDependencyClusterName(String dependencyClusterName) {
+    this.dependencyClusterName = dependencyClusterName;
+  }
+
+  public Long getDependencyServiceGroupId() {
+    return dependencyServiceGroupId;
+  }
+
+  public void setDependencyServiceGroupId(Long dependencyServiceGroupId) {
+    this.dependencyServiceGroupId = dependencyServiceGroupId;
+  }
+
+  public String getDependencyServiceGroupName() {
+    return dependencyServiceGroupName;
+  }
+
+  public void setDependencyServiceGroupName(String dependencyServiceGroupName) {
+    this.dependencyServiceGroupName = dependencyServiceGroupName;
+  }
+
+  public Long getDependencyServiceId() {
+    return dependencyServiceId;
+  }
+
+  public void setDependencyServiceId(Long dependencyServiceId) {
+    this.dependencyServiceId = dependencyServiceId;
+  }
+
+  public String getDependencyServiceName() {
+    return dependencyServiceName;
+  }
+
+  public void setDependencyServiceName(String dependencyServiceName) {
+    this.dependencyServiceName = dependencyServiceName;
+  }
+
+  public Long getServiceGroupId() {
+    return serviceGroupId;
+  }
+
+  public void setServiceGroupId(Long serviceGroupId) {
+    this.serviceGroupId = serviceGroupId;
+  }
+
+  public String getServiceGroupName() {
+    return serviceGroupName;
+  }
+
+  public void setServiceGroupName(String serviceGroupName) {
+    this.serviceGroupName = serviceGroupName;
+  }
+
+  public Long getServiceId() {
+    return serviceId;
+  }
+
+  public void setServiceId(Long serviceId) {
+    this.serviceId = serviceId;
+  }
+
+  public String getServiceName() {
+    return serviceName;
+  }
+
+  public void setServiceName(String serviceName) {
+    this.serviceName = serviceName;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (!(o instanceof ServiceDependencyResponse)) return false;
+
+    ServiceDependencyResponse that = (ServiceDependencyResponse) o;
+
+    if (clusterId != null ? !clusterId.equals(that.clusterId) : that.clusterId != null) return false;
+    if (clusterName != null ? !clusterName.equals(that.clusterName) : that.clusterName != null) return false;
+    if (dependencyClusterId != null ? !dependencyClusterId.equals(that.dependencyClusterId) : that.dependencyClusterId != null)
+      return false;
+    if (dependencyClusterName != null ? !dependencyClusterName.equals(that.dependencyClusterName) : that.dependencyClusterName != null)
+      return false;
+    if (dependencyServiceGroupId != null ? !dependencyServiceGroupId.equals(that.dependencyServiceGroupId) : that.dependencyServiceGroupId != null)
+      return false;
+    if (dependencyServiceGroupName != null ? !dependencyServiceGroupName.equals(that.dependencyServiceGroupName) : that.dependencyServiceGroupName != null)
+      return false;
+    if (dependencyServiceId != null ? !dependencyServiceId.equals(that.dependencyServiceId) : that.dependencyServiceId != null)
+      return false;
+    if (dependencyServiceName != null ? !dependencyServiceName.equals(that.dependencyServiceName) : that.dependencyServiceName != null)
+      return false;
+    if (serviceGroupId != null ? !serviceGroupId.equals(that.serviceGroupId) : that.serviceGroupId != null)
+      return false;
+    if (serviceGroupName != null ? !serviceGroupName.equals(that.serviceGroupName) : that.serviceGroupName != null)
+      return false;
+    if (serviceId != null ? !serviceId.equals(that.serviceId) : that.serviceId != null) return false;
+    if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = clusterId != null ? clusterId.hashCode() : 0;
+    result = 31 * result + (serviceId != null ? serviceId.hashCode() : 0);
+    result = 31 * result + (serviceGroupId != null ? serviceGroupId.hashCode() : 0);
+    result = 31 * result + (dependencyClusterId != null ? dependencyClusterId.hashCode() : 0);
+    result = 31 * result + (dependencyServiceId != null ? dependencyServiceId.hashCode() : 0);
+    result = 31 * result + (dependencyServiceGroupId != null ? dependencyServiceGroupId.hashCode() : 0);
+    result = 31 * result + (clusterName != null ? clusterName.hashCode() : 0);
+    result = 31 * result + (serviceName != null ? serviceName.hashCode() : 0);
+    result = 31 * result + (serviceGroupName != null ? serviceGroupName.hashCode() : 0);
+    result = 31 * result + (dependencyServiceName != null ? dependencyServiceName.hashCode() : 0);
+    result = 31 * result + (dependencyClusterName != null ? dependencyClusterName.hashCode() : 0);
+    result = 31 * result + (dependencyServiceGroupName != null ? dependencyServiceGroupName.hashCode() : 0);
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
index 9050e3d..0acf78f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
@@ -156,6 +156,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori
         return new RootClusterSettingsResourceProvider(managementController);
       case Service:
         return resourceProviderFactory.getServiceResourceProvider(managementController);
+      case ServiceDependency:
+        return resourceProviderFactory.getServiceDependencyResourceProvider(managementController);
       case ServiceGroup:
         return resourceProviderFactory.getServiceGroupResourceProvider(managementController);
       case ServiceGroupDependency:

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
index c219d23..2f8f65f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
@@ -88,6 +88,8 @@ public class DefaultProviderModule extends AbstractProviderModule {
         return new AlertResourceProvider(managementController);
       case ServiceGroup:
         return new ServiceGroupResourceProvider(managementController);
+      case ServiceDependency:
+        return new ServiceDependencyResourceProvider(managementController);
       case ServiceGroupDependency:
         return new ServiceGroupDependencyResourceProvider(managementController);
       case Registry:

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceDependencyResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceDependencyResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceDependencyResourceProvider.java
new file mode 100644
index 0000000..d8d89da
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceDependencyResourceProvider.java
@@ -0,0 +1,511 @@
+/**
+ * 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.controller.internal;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ClusterNotFoundException;
+import org.apache.ambari.server.ObjectNotFoundException;
+import org.apache.ambari.server.ParentObjectNotFoundException;
+import org.apache.ambari.server.ServiceGroupNotFoundException;
+import org.apache.ambari.server.api.services.ServiceKey;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.KerberosHelper;
+import org.apache.ambari.server.controller.RequestStatusResponse;
+import org.apache.ambari.server.controller.ServiceDependencyRequest;
+import org.apache.ambari.server.controller.ServiceDependencyResponse;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.security.authorization.ResourceType;
+import org.apache.ambari.server.security.authorization.RoleAuthorization;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.ServiceGroup;
+import org.apache.ambari.server.utils.StageUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.Validate;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.Gson;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+import com.google.inject.assistedinject.AssistedInject;
+
+public class ServiceDependencyResourceProvider extends AbstractControllerResourceProvider {
+
+
+  // ----- Property ID constants ---------------------------------------------
+
+  public static final String RESPONSE_KEY = "ServiceDependencyInfo";
+  public static final String ALL_PROPERTIES = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "*";
+  public static final String SERVICE_DEPENDENCY_CLUSTER_ID_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "cluster_id";
+  public static final String SERVICE_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "cluster_name";
+  public static final String SERVICE_DEPENDENCY_SERVICE_ID_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "service_id";
+  public static final String SERVICE_DEPENDENCY_SERVICE_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "service_name";
+  public static final String SERVICE_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "service_group_name";
+  public static final String SERVICE_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "service_group_id";
+  public static final String SERVICE_DEPENDENCY_DEPENDENCY_CLUSTER_ID_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "dependency_cluster_id";
+  public static final String SERVICE_DEPENDENCY_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "dependency_cluster_name";
+  public static final String SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_ID_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "dependency_service_id";
+  public static final String SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "dependency_service_name";
+  public static final String SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "dependency_service_group_name";
+  public static final String SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "dependency_service_group_id";
+
+  protected ObjectMapper mapper = new ObjectMapper();;
+
+  private static Set<String> pkPropertyIds =
+          new HashSet<String>(Arrays.asList(new String[]{
+                  SERVICE_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID,
+                  SERVICE_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID,
+                  SERVICE_DEPENDENCY_SERVICE_NAME_PROPERTY_ID,
+                  SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_NAME_PROPERTY_ID}));
+
+  private static Gson gson = StageUtils.getGson();
+
+  /**
+   * The property ids for an service group resource.
+   */
+  private static final Set<String> PROPERTY_IDS = new HashSet<>();
+
+  /**
+   * The key property ids for an service group resource.
+   */
+  private static final Map<Resource.Type, String> KEY_PROPERTY_IDS = new HashMap<>();
+
+  static {
+    // properties
+    PROPERTY_IDS.add(SERVICE_DEPENDENCY_CLUSTER_ID_PROPERTY_ID);
+    PROPERTY_IDS.add(SERVICE_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID);
+    PROPERTY_IDS.add(SERVICE_DEPENDENCY_SERVICE_ID_PROPERTY_ID);
+    PROPERTY_IDS.add(SERVICE_DEPENDENCY_SERVICE_NAME_PROPERTY_ID);
+    PROPERTY_IDS.add(SERVICE_DEPENDENCY_DEPENDENCY_CLUSTER_ID_PROPERTY_ID);
+    PROPERTY_IDS.add(SERVICE_DEPENDENCY_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID);
+    PROPERTY_IDS.add(SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_ID_PROPERTY_ID);
+    PROPERTY_IDS.add(SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_NAME_PROPERTY_ID);
+    PROPERTY_IDS.add(SERVICE_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID);
+    PROPERTY_IDS.add(SERVICE_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID);
+    PROPERTY_IDS.add(SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID);
+    PROPERTY_IDS.add(SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID);
+
+    // keys
+    KEY_PROPERTY_IDS.put(Resource.Type.Cluster, SERVICE_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID);
+    KEY_PROPERTY_IDS.put(Resource.Type.Service, SERVICE_DEPENDENCY_SERVICE_NAME_PROPERTY_ID);
+    KEY_PROPERTY_IDS.put(Resource.Type.ServiceGroup, SERVICE_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID);
+    KEY_PROPERTY_IDS.put(Resource.Type.ServiceDependency, SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_NAME_PROPERTY_ID);
+  }
+
+  private Clusters clusters;
+
+  /**
+   * kerberos helper
+   */
+  @Inject
+  private KerberosHelper kerberosHelper;
+
+  // ----- Constructors ----------------------------------------------------
+
+  /**
+   * Create a  new resource provider for the given management controller.
+   *
+   * @param managementController the management controller
+   */
+  @AssistedInject
+  public ServiceDependencyResourceProvider(@Assisted AmbariManagementController managementController) {
+    super(Resource.Type.ServiceDependency, PROPERTY_IDS, KEY_PROPERTY_IDS, managementController);
+  }
+
+  // ----- ResourceProvider ------------------------------------------------
+
+  @Override
+  protected RequestStatus createResourcesAuthorized(Request request)
+          throws SystemException,
+          UnsupportedPropertyException,
+          ResourceAlreadyExistsException,
+          NoSuchParentResourceException {
+
+    final Set<ServiceDependencyRequest> requests = new HashSet<>();
+    for (Map<String, Object> propertyMap : request.getProperties()) {
+      requests.add(getRequest(propertyMap));
+    }
+    Set<ServiceDependencyResponse> createServiceGroups = null;
+    createServiceGroups = createResources(new Command<Set<ServiceDependencyResponse>>() {
+      @Override
+      public Set<ServiceDependencyResponse> invoke() throws AmbariException, AuthorizationException {
+        return createServiceDependencies(requests);
+      }
+    });
+    Set<Resource> associatedResources = new HashSet<>();
+    if (createServiceGroups != null) {
+      Iterator<ServiceDependencyResponse> itr = createServiceGroups.iterator();
+      while (itr.hasNext()) {
+        ServiceDependencyResponse response = itr.next();
+        notifyCreate(Resource.Type.ServiceDependency, request);
+        Resource resource = new ResourceImpl(Resource.Type.ServiceDependency);
+        resource.setProperty(SERVICE_DEPENDENCY_CLUSTER_ID_PROPERTY_ID,
+                response.getClusterId());
+        resource.setProperty(SERVICE_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID,
+                response.getClusterName());
+        resource.setProperty(SERVICE_DEPENDENCY_SERVICE_ID_PROPERTY_ID,
+                response.getServiceId());
+        resource.setProperty(SERVICE_DEPENDENCY_SERVICE_NAME_PROPERTY_ID,
+                response.getServiceName());
+        resource.setProperty(SERVICE_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID,
+                response.getServiceGroupId());
+        resource.setProperty(SERVICE_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID,
+                response.getServiceGroupName());
+        resource.setProperty(SERVICE_DEPENDENCY_DEPENDENCY_CLUSTER_ID_PROPERTY_ID,
+                response.getDependencyClusterId());
+        resource.setProperty(SERVICE_DEPENDENCY_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID,
+                response.getDependencyClusterName());
+        resource.setProperty(SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_ID_PROPERTY_ID,
+                response.getDependencyServiceId());
+        resource.setProperty(SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_NAME_PROPERTY_ID,
+                response.getDependencyServiceName());
+        resource.setProperty(SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID,
+                response.getDependencyServiceGroupId());
+        resource.setProperty(SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID,
+                response.getDependencyServiceGroupName());
+
+        associatedResources.add(resource);
+      }
+      return getRequestStatus(null, associatedResources);
+    }
+
+    return getRequestStatus(null);
+  }
+
+  @Override
+  protected Set<Resource> getResourcesAuthorized(Request request, Predicate predicate) throws
+          SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+    final Set<ServiceDependencyRequest> requests = new HashSet<>();
+
+    for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+      requests.add(getRequest(propertyMap));
+    }
+
+    Set<ServiceDependencyResponse> responses = getResources(new Command<Set<ServiceDependencyResponse>>() {
+      @Override
+      public Set<ServiceDependencyResponse> invoke() throws AmbariException {
+        return getServiceDependencies(requests);
+      }
+    });
+
+    Set<String> requestedIds = getRequestPropertyIds(request, predicate);
+    Set<Resource> resources = new HashSet<Resource>();
+
+    for (ServiceDependencyResponse response : responses) {
+      Resource resource = new ResourceImpl(Resource.Type.ServiceDependency);
+      setResourceProperty(resource, SERVICE_DEPENDENCY_CLUSTER_ID_PROPERTY_ID,
+              response.getClusterId(), requestedIds);
+      setResourceProperty(resource, SERVICE_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID,
+              response.getClusterName(), requestedIds);
+      setResourceProperty(resource, SERVICE_DEPENDENCY_SERVICE_ID_PROPERTY_ID,
+              response.getServiceId(), requestedIds);
+      setResourceProperty(resource, SERVICE_DEPENDENCY_SERVICE_NAME_PROPERTY_ID,
+              response.getServiceName(), requestedIds);
+      setResourceProperty(resource, SERVICE_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID,
+              response.getServiceGroupId(), requestedIds);
+      setResourceProperty(resource, SERVICE_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID,
+              response.getServiceGroupName(), requestedIds);
+      setResourceProperty(resource, SERVICE_DEPENDENCY_DEPENDENCY_CLUSTER_ID_PROPERTY_ID,
+              response.getDependencyClusterId(), requestedIds);
+      setResourceProperty(resource, SERVICE_DEPENDENCY_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID,
+              response.getDependencyClusterName(), requestedIds);
+      setResourceProperty(resource, SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_ID_PROPERTY_ID,
+              response.getDependencyServiceId(), requestedIds);
+      setResourceProperty(resource, SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_NAME_PROPERTY_ID,
+              response.getDependencyServiceName(), requestedIds);
+      setResourceProperty(resource, SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID,
+              response.getDependencyServiceGroupId(), requestedIds);
+      setResourceProperty(resource, SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID,
+              response.getDependencyServiceGroupName(), requestedIds);
+
+      resources.add(resource);
+    }
+    return resources;
+  }
+
+  @Override
+  protected RequestStatus updateResourcesAuthorized(final Request request, Predicate predicate)
+          throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+    // TODO : Add functionality for updating SG : RENAME, START ALL, STOP ALL services.
+    RequestStatusResponse response = null;
+    return getRequestStatus(response);
+  }
+
+  @Override
+  protected RequestStatus deleteResourcesAuthorized(Request request, Predicate predicate)
+          throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+    final Set<ServiceDependencyRequest> requests = new HashSet<>();
+    DeleteStatusMetaData deleteStatusMetaData = null;
+
+    for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+      requests.add(getRequest(propertyMap));
+    }
+    deleteStatusMetaData = modifyResources(new Command<DeleteStatusMetaData>() {
+      @Override
+      public DeleteStatusMetaData invoke() throws AmbariException, AuthorizationException {
+        deleteServiceDependencies(requests);
+        return new DeleteStatusMetaData();
+      }
+    });
+
+    notifyDelete(Resource.Type.ServiceDependency, predicate);
+    for(ServiceDependencyRequest svgReq : requests) {
+      deleteStatusMetaData.addDeletedKey("cluster_name: " + svgReq.getClusterName() + ", " + " service_name: " + svgReq.getServiceName()
+              + " dependency_service_name: " + svgReq.getDependencyServiceName());
+    }
+    return getRequestStatus(null, null, deleteStatusMetaData);
+  }
+
+  @Override
+  public Set<String> checkPropertyIds(Set<String> propertyIds) {
+    propertyIds = super.checkPropertyIds(propertyIds);
+
+    if (propertyIds.isEmpty()) {
+      return propertyIds;
+    }
+    Set<String> unsupportedProperties = new HashSet<String>();
+    return unsupportedProperties;
+  }
+
+
+  // ----- AbstractResourceProvider ----------------------------------------
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return pkPropertyIds;
+  }
+
+  // ----- utility methods -------------------------------------------------
+
+  /**
+   * Get a service group request object from a map of property values.
+   *
+   * @param properties the predicate
+   * @return the service request object
+   */
+  private ServiceDependencyRequest getRequest(Map<String, Object> properties) {
+    String clusterName = (String) properties.get(SERVICE_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID);
+    String serviceName = (String) properties.get(SERVICE_DEPENDENCY_SERVICE_NAME_PROPERTY_ID);
+    String serviceGroupName = (String) properties.get(SERVICE_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID);
+    String dependencyServiceName = (String) properties.get(SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_NAME_PROPERTY_ID);
+    String dependencyServiceGroupName = (String) properties.get(SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID);
+    ServiceDependencyRequest svcRequest = new ServiceDependencyRequest(clusterName, serviceName, serviceGroupName,
+                                                                       dependencyServiceName, dependencyServiceGroupName);
+    return svcRequest;
+  }
+
+  // Create services from the given request.
+  public synchronized Set<ServiceDependencyResponse> createServiceDependencies(Set<ServiceDependencyRequest> requests)
+          throws AmbariException, AuthorizationException {
+
+    if (requests.isEmpty()) {
+      LOG.warn("Received an empty requests set");
+      return null;
+    }
+    AmbariManagementController controller = getManagementController();
+    Clusters clusters = controller.getClusters();
+
+    // do all validation checks
+    validateCreateRequests(requests, clusters);
+
+    Set<ServiceDependencyResponse> createdServiceDependencies = new HashSet<>();
+    for (ServiceDependencyRequest request : requests) {
+      Cluster cluster = clusters.getCluster(request.getClusterName());
+
+
+      Service updatedService = cluster.addDependencyToService(request.getServiceGroupName(), request.getServiceName(), request.getDependencyServiceGroupName(),
+              request.getDependencyServiceName());
+      createdServiceDependencies.addAll(updatedService.getServiceDependencyResponses());   //!!!!!
+    }
+    return createdServiceDependencies;
+  }
+
+  // Get services from the given set of requests.
+  protected Set<ServiceDependencyResponse> getServiceDependencies(Set<ServiceDependencyRequest> requests)
+          throws AmbariException {
+    Set<ServiceDependencyResponse> response = new HashSet<ServiceDependencyResponse>();
+    for (ServiceDependencyRequest request : requests) {
+      try {
+        response.addAll(getServiceDependencies(request));
+      } catch (ServiceGroupNotFoundException e) {
+        if (requests.size() == 1) {
+          // only throw exception if 1 request.
+          // there will be > 1 request in case of OR predicate
+          throw e;
+        }
+      }
+    }
+    return response;
+  }
+
+  // Get services from the given request.
+  private Set<ServiceDependencyResponse> getServiceDependencies(ServiceDependencyRequest request)
+          throws AmbariException {
+    if (request.getClusterName() == null) {
+      throw new AmbariException("Invalid arguments, cluster id"
+              + " cannot be null");
+    }
+    AmbariManagementController controller = getManagementController();
+    Clusters clusters = controller.getClusters();
+    String clusterName = request.getClusterName();
+
+    final Cluster cluster;
+    try {
+      cluster = clusters.getCluster(clusterName);
+    } catch (ObjectNotFoundException e) {
+      throw new ParentObjectNotFoundException("Parent Cluster resource doesn't exist", e);
+    }
+
+    ServiceGroup serviceGroup = cluster.getServiceGroup(request.getServiceGroupName());
+
+    Set<ServiceDependencyResponse> responses = new HashSet<>();
+    if (request.getServiceName() != null) {
+      Collection<Service> services = cluster.getServices().values();
+      Service currentService = null;
+      for (Service service : services) {
+        if (service.getServiceGroupId() == serviceGroup.getServiceGroupId()) {
+          currentService = service;
+          break;
+        }
+      }
+
+      responses.addAll(currentService.getServiceDependencyResponses());
+      return responses;
+    }
+    return responses;
+  }
+
+
+  // Delete services based on the given set of requests
+  protected void deleteServiceDependencies(Set<ServiceDependencyRequest> request)
+          throws AmbariException, AuthorizationException {
+
+    Clusters clusters = getManagementController().getClusters();
+
+    Set<ServiceDependencyRequest> removable = new HashSet<>();
+
+    for (ServiceDependencyRequest serviceDependencyRequest : request) {
+      if (null == serviceDependencyRequest.getClusterName()
+              || StringUtils.isEmpty(serviceDependencyRequest.getServiceGroupName())) {
+        throw new AmbariException("invalid arguments");
+      } else {
+
+        if (!AuthorizationHelper.isAuthorized(
+                ResourceType.CLUSTER, getClusterResourceId(serviceDependencyRequest.getClusterName()),
+                RoleAuthorization.SERVICE_ADD_DELETE_SERVICES)) {
+          throw new AuthorizationException("The user is not authorized to delete service groups");
+        }
+
+        Cluster cluster = clusters.getCluster(serviceDependencyRequest.getClusterName());
+        Service service = cluster.getService(serviceDependencyRequest.getServiceName());
+        List<ServiceKey> serviceKeys = service.getServiceDependencies();
+        if (serviceKeys == null || serviceKeys.isEmpty()) {
+          throw new AmbariException("Service name " + serviceDependencyRequest.getServiceName() + " has no" +
+                  "dependencies, so nothing to remove.");
+        } else {
+          boolean dependencyAvailable = false;
+          for (ServiceKey serviceKey : serviceKeys) {
+            if (serviceKey.getServiceName().equals(serviceDependencyRequest.getDependencyServiceName())) {
+              dependencyAvailable = true;
+            }
+          }
+          if (!dependencyAvailable) {
+            throw new AmbariException("Servcie name " + serviceDependencyRequest.getServiceName() + " has no" +
+                    "dependency " + serviceDependencyRequest.getDependencyServiceName() + ", so nothing to remove.");
+          }
+
+          service.getCluster().removeDependencyFromService(serviceDependencyRequest.getServiceGroupName(), serviceDependencyRequest.getServiceName(),
+                  serviceDependencyRequest.getDependencyServiceGroupName(), serviceDependencyRequest.getDependencyServiceName());
+        }
+      }
+    }
+  }
+
+
+  private void validateCreateRequests(Set<ServiceDependencyRequest> requests, Clusters clusters)
+          throws AuthorizationException, AmbariException {
+
+    Map<String, Set<String>> serviceGroupNames = new HashMap<>();
+    Set<String> duplicates = new HashSet<>();
+    for (ServiceDependencyRequest request : requests) {
+      final String clusterName = request.getClusterName();
+      final String serviceGroupName = request.getServiceGroupName();
+      final String dependencyServiceGroupName = request.getDependencyServiceGroupName();
+
+      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!");
+      } else {
+        Cluster cluster = clusters.getCluster(clusterName);
+        //throws service group not found exception
+        ServiceGroup serviceGroup = cluster.getServiceGroup(dependencyServiceGroupName);
+
+      }
+
+      Validate.notEmpty(serviceGroupName, "Service group name should be provided when adding a service group dependency");
+
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Received a createServiceGroupDependency request" +
+                ", clusterName=" + clusterName + ", serviceGroupName=" + serviceGroupName + ", request=" + request);
+      }
+
+      if (!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER,
+              getClusterResourceId(clusterName), RoleAuthorization.SERVICE_ADD_DELETE_SERVICES)) {
+        throw new AuthorizationException("The user is not authorized to create service groups");
+      }
+
+
+      Cluster cluster;
+      try {
+        cluster = clusters.getCluster(clusterName);
+      } catch (ClusterNotFoundException e) {
+        throw new ParentObjectNotFoundException("Attempted to add a service group to a cluster which doesn't exist", e);
+      }
+
+
+
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
index bd6d7bb..31b7517 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
@@ -77,6 +77,7 @@ public interface Resource {
     Cluster,
     RootClusterSetting,
     Service,
+    ServiceDependency,
     ServiceGroup,
     ServiceGroupDependency,
     Setting,
@@ -212,6 +213,7 @@ public interface Resource {
     public static final Type ServiceGroup = InternalType.ServiceGroup.getType();
     public static final Type ServiceGroupDependency = InternalType.ServiceGroupDependency.getType();
     public static final Type Service = InternalType.Service.getType();
+    public static final Type ServiceDependency = InternalType.ServiceDependency.getType();
     public static final Type Setting = InternalType.Setting.getType();
     public static final Type Host = InternalType.Host.getType();
     public static final Type Component = InternalType.Component.getType();

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterServiceEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterServiceEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterServiceEntity.java
index 9fca099..b6c60be 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterServiceEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterServiceEntity.java
@@ -19,6 +19,7 @@
 package org.apache.ambari.server.orm.entities;
 
 import java.util.Collection;
+import java.util.List;
 
 import javax.persistence.Basic;
 import javax.persistence.CascadeType;
@@ -29,6 +30,8 @@ import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.JoinColumns;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
 import javax.persistence.ManyToOne;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
@@ -94,6 +97,21 @@ public class ClusterServiceEntity {
   @OneToMany(mappedBy = "clusterServiceEntity")
   private Collection<ServiceComponentDesiredStateEntity> serviceComponentDesiredStateEntities;
 
+  @ManyToMany
+  @JoinTable(
+    name = "servicedependencies",
+    joinColumns = {@JoinColumn(name = "service_id", referencedColumnName = "id", nullable = false, insertable = true, updatable = true),
+            @JoinColumn(name = "service_cluster_id", referencedColumnName = "cluster_id", nullable = false, insertable = false, updatable = false),
+            @JoinColumn(name = "service_group_id", referencedColumnName = "service_group_id", nullable = false, insertable = false, updatable = false)},
+    inverseJoinColumns = {@JoinColumn(name = "dependent_service_id", referencedColumnName = "id", nullable = false, insertable = true, updatable = true),
+            @JoinColumn(name = "dependent_service_cluster_id", referencedColumnName = "cluster_id", nullable = false, insertable = false, updatable = false),
+            @JoinColumn(name = "dependent_service_group_id", referencedColumnName = "service_group_id", nullable = false, insertable = false, updatable = false)}
+  )
+  private List<ClusterServiceEntity> serviceDependencies;
+
+  @ManyToMany(mappedBy="serviceDependencies")
+  private List<ClusterServiceEntity> dependencies;
+
   public Long getClusterId() {
     return clusterId;
   }
@@ -142,6 +160,22 @@ public class ClusterServiceEntity {
     this.serviceEnabled = serviceEnabled;
   }
 
+  public List<ClusterServiceEntity> getDependencies() {
+    return dependencies;
+  }
+
+  public void setDependencies(List<ClusterServiceEntity> dependencies) {
+    this.dependencies = dependencies;
+  }
+
+  public List<ClusterServiceEntity> getServiceDependencies() {
+    return serviceDependencies;
+  }
+
+  public void setServiceDependencies(List<ClusterServiceEntity> serviceDependencies) {
+    this.serviceDependencies = serviceDependencies;
+  }
+
   @Override
   public boolean equals(Object o) {
     if (this == o) return true;
@@ -201,4 +235,4 @@ public class ClusterServiceEntity {
     this.serviceComponentDesiredStateEntities = serviceComponentDesiredStateEntities;
   }
 
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/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 5ba61b7..2193c3a 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
@@ -72,6 +72,12 @@ public interface Cluster {
   Service addService(ServiceGroup serviceGroup, String serviceName, String serviceType,
                      RepositoryVersionEntity repositoryVersion) throws AmbariException;
 
+  Service addDependencyToService(String  serviceGroupName, String serviceName,
+                                        String dependencyServiceGroupName, String dependencyServiceName);
+
+  Service removeDependencyFromService(String  serviceGroupName, String serviceName, String dependencyServiceGroupName,
+                                      String dependencyServiceName);
+
   /**
    * Add service group to the cluster
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/state/Service.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/Service.java b/ambari-server/src/main/java/org/apache/ambari/server/state/Service.java
index b9ab79f..c4c2d84 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/Service.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/Service.java
@@ -18,9 +18,13 @@
 
 package org.apache.ambari.server.state;
 
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.api.services.ServiceKey;
+import org.apache.ambari.server.controller.ServiceDependencyResponse;
 import org.apache.ambari.server.controller.ServiceResponse;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 
@@ -42,6 +46,10 @@ public interface Service {
 
   Cluster getCluster();
 
+  Set<ServiceDependencyResponse> getServiceDependencyResponses();
+
+  List<ServiceKey> getServiceDependencies();
+
   ServiceComponent getServiceComponent(String componentName)
       throws AmbariException;
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceFactory.java
index b48d825..69eb21d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceFactory.java
@@ -18,6 +18,9 @@
 
 package org.apache.ambari.server.state;
 
+import java.util.List;
+
+import org.apache.ambari.server.api.services.ServiceKey;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 
@@ -41,6 +44,7 @@ public interface ServiceFactory {
    * @return
    */
   Service createNew(Cluster cluster, ServiceGroup serviceGroup,
+                    @Assisted List<ServiceKey> serviceDependencies,
                     @Assisted("serviceName") String serviceName,
                     @Assisted("serviceType") String serviceType,
                     RepositoryVersionEntity desiredRepositoryVersion);

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
index 167e4ca..0321701 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
@@ -21,8 +21,10 @@ package org.apache.ambari.server.state;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.locks.Lock;
@@ -32,6 +34,8 @@ import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ObjectNotFoundException;
 import org.apache.ambari.server.ServiceComponentNotFoundException;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.api.services.ServiceKey;
+import org.apache.ambari.server.controller.ServiceDependencyResponse;
 import org.apache.ambari.server.controller.ServiceResponse;
 import org.apache.ambari.server.events.MaintenanceModeEvent;
 import org.apache.ambari.server.events.ServiceInstalledEvent;
@@ -74,6 +78,7 @@ public class ServiceImpl implements Service {
   private final Cluster cluster;
   private final ServiceGroup serviceGroup;
   private final ConcurrentMap<String, ServiceComponent> components = new ConcurrentHashMap<>();
+  private List<ServiceKey> serviceDependencies = new ArrayList<>();
   private boolean isClientOnlyService;
   private boolean isCredentialStoreSupported;
   private boolean isCredentialStoreRequired;
@@ -111,6 +116,7 @@ public class ServiceImpl implements Service {
 
   @AssistedInject
   ServiceImpl(@Assisted Cluster cluster, @Assisted ServiceGroup serviceGroup,
+              @Assisted List<ServiceKey> serviceDependencies,
               @Assisted("serviceName") String serviceName, @Assisted("serviceType") String serviceType,
               @Assisted RepositoryVersionEntity desiredRepositoryVersion,
               ClusterDAO clusterDAO, ServiceGroupDAO serviceGroupDAO,
@@ -129,12 +135,31 @@ public class ServiceImpl implements Service {
     this.serviceType = serviceType;
     this.ambariMetaInfo = ambariMetaInfo;
 
+
     ClusterServiceEntity serviceEntity = new ClusterServiceEntity();
     serviceEntity.setClusterId(cluster.getClusterId());
     serviceEntity.setServiceGroupId(serviceGroup.getServiceGroupId());
     serviceEntity.setServiceName(serviceName);
     serviceEntity.setServiceType(serviceType);
 
+    if (serviceDependencies != null) {
+      for (ServiceKey serviceKey : serviceDependencies) {
+        Cluster dependencyCluster = cluster;
+        ServiceGroup dependencyServiceGroup = dependencyCluster.getServiceGroup(serviceKey.getServiceGroupName());
+        ServiceGroupEntity dependencyServiceGroupEntity = serviceGroupDAO.findByClusterAndServiceGroupIds(dependencyCluster.getClusterId(),
+                dependencyServiceGroup.getServiceGroupId());
+
+        for (Service service : dependencyCluster.getServices().values()) {
+          if (service.getName().equals(serviceName) && service.getServiceGroupId() == dependencyServiceGroup.getServiceGroupId()) {
+            serviceEntity.getServiceDependencies().add(clusterServiceDAO.findById(dependencyCluster.getClusterId(),
+                    dependencyServiceGroup.getServiceGroupId(), service.getServiceId()));
+            break;
+          }
+        }
+
+      }
+    }
+
     ServiceDesiredStateEntity serviceDesiredStateEntity = new ServiceDesiredStateEntity();
     serviceDesiredStateEntity.setClusterId(cluster.getClusterId());
     serviceDesiredStateEntity.setServiceGroupId(serviceGroup.getServiceGroupId());
@@ -177,6 +202,7 @@ public class ServiceImpl implements Service {
     this.serviceName = serviceEntity.getServiceName();
     this.serviceType = serviceEntity.getServiceType();
     this.ambariMetaInfo = ambariMetaInfo;
+    this.serviceDependencies = getServiceDependencies(serviceEntity.getServiceDependencies());
 
     ServiceDesiredStateEntity serviceDesiredStateEntity = serviceEntity.getServiceDesiredStateEntity();
     serviceDesiredStateEntityPK = getServiceDesiredStateEntityPK(serviceDesiredStateEntity);
@@ -274,6 +300,15 @@ public class ServiceImpl implements Service {
   }
 
   @Override
+  public List<ServiceKey> getServiceDependencies() {
+    return serviceDependencies;
+  }
+
+  public void setServiceDependencies(List<ServiceKey> serviceDependencies) {
+    this.serviceDependencies = serviceDependencies;
+  }
+
+  @Override
   public void addServiceComponent(ServiceComponent component) throws AmbariException {
     if (components.containsKey(component.getName())) {
       throw new AmbariException("Cannot add duplicate ServiceComponent"
@@ -308,6 +343,58 @@ public class ServiceImpl implements Service {
   }
 
   @Override
+  public Set<ServiceDependencyResponse> getServiceDependencyResponses() {
+    Set<ServiceDependencyResponse> responses = new HashSet<>();
+    if (getServiceDependencies() != null) {
+      for (ServiceKey sk : getServiceDependencies()) {
+        responses.add(new ServiceDependencyResponse(cluster.getClusterId(), cluster.getClusterName(),
+                 sk.getClusterId(), sk.getClusterName(), sk.getServiceGroupId(), sk.getServiceGroupName(),
+                 sk.getServiceId(), sk.getServiceName(), getServiceGroupId(), getServiceGroupName(),
+                 getServiceId(), getName()));
+      }
+    }
+    return responses;
+  }
+
+  public List<ServiceKey> getServiceDependencies(List<ClusterServiceEntity> clusterServiceEntities) throws AmbariException {
+    List<ServiceKey> serviceDependenciesList = new ArrayList<>();
+
+    if (clusterServiceEntities != null) {
+      for (ClusterServiceEntity cse : clusterServiceEntities) {
+        ServiceKey serviceKey = new ServiceKey();
+        String clusterName = "";
+        Long clusterId = null;
+        if (cse.getClusterId() == cluster.getClusterId()) {
+          clusterName = cluster.getClusterName();
+          clusterId = cluster.getClusterId();
+        } else {
+          ClusterEntity clusterEntity = clusterDAO.findById(cse.getClusterId());
+          if (clusterEntity != null) {
+            clusterName = clusterEntity.getClusterName();
+            clusterId = clusterEntity.getClusterId();
+          } else {
+            LOG.error("Unable to get cluster id for service " + cse.getServiceName());
+          }
+        }
+
+
+        Cluster dependencyCluster = cluster;
+        ServiceGroup dependencyServiceGroup = dependencyCluster.getServiceGroup(cse.getServiceGroupId());
+
+
+        serviceKey.setServiceGroupName(dependencyServiceGroup.getServiceGroupName());
+        serviceKey.setServiceGroupId(dependencyServiceGroup.getServiceGroupId());
+        serviceKey.setClusterName(clusterName);
+        serviceKey.setClusterId(clusterId);
+        serviceKey.setServiceName(cse.getServiceName());
+        serviceKey.setServiceId(cse.getServiceId());
+        serviceDependenciesList.add(serviceKey);
+      }
+    }
+    return serviceDependenciesList;
+  }
+
+  @Override
   public State getDesiredState() {
     ServiceDesiredStateEntity serviceDesiredStateEntity = getServiceDesiredStateEntity();
     return serviceDesiredStateEntity.getDesiredState();

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/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 e896d0e..881f172 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
@@ -77,6 +77,7 @@ import org.apache.ambari.server.orm.cache.HostConfigMapping;
 import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
 import org.apache.ambari.server.orm.dao.AlertDispatchDAO;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
+import org.apache.ambari.server.orm.dao.ClusterServiceDAO;
 import org.apache.ambari.server.orm.dao.ClusterStateDAO;
 import org.apache.ambari.server.orm.dao.HostConfigMappingDAO;
 import org.apache.ambari.server.orm.dao.HostDAO;
@@ -279,6 +280,9 @@ public class ClusterImpl implements Cluster {
   @Inject
   private ServiceGroupDAO serviceGroupDAO;
 
+  @Inject
+  private ClusterServiceDAO clusterServiceDAO;
+
   /**
    * Data access object used for looking up stacks from the database.
    */
@@ -887,13 +891,93 @@ public class ClusterImpl implements Cluster {
     }
 
     @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES)
-    Service service = serviceFactory.createNew(this, serviceGroup, serviceName, serviceType, repositoryVersion);
+    Service service = serviceFactory.createNew(this, serviceGroup, new ArrayList<>(), serviceName, serviceType, repositoryVersion);
     addService(service);
 
     return service;
   }
 
   @Override
+  public Service addDependencyToService(String  serviceGroupName, String serviceName, String dependencyServiceGroupName,
+                                        String dependencyServiceName) {
+    Service currentService = null;
+    Service dependentService = null;
+    for (Service service : services.values()) {
+
+      if (service.getName().equals(serviceName) && service.getServiceGroupName().equals(serviceGroupName)) {
+        currentService = service;
+      }
+
+      if (service.getName().equals(dependencyServiceName) && service.getServiceGroupName().equals(dependencyServiceGroupName)) {
+        dependentService = service;
+      }
+    }
+
+    Service updatedService = null;
+    clusterGlobalLock.writeLock().lock();
+    try {
+      ClusterServiceEntity currentServiceEntity = clusterServiceDAO.findById(getClusterId(),
+              currentService.getServiceGroupId(), currentService.getServiceId());
+      ClusterServiceEntity dependentServiceEntity = clusterServiceDAO.findById(getClusterId(),
+              dependentService.getServiceGroupId(), dependentService.getServiceId());
+
+      currentServiceEntity.getServiceDependencies().add(dependentServiceEntity);
+      ClusterServiceEntity updatedServiceEntity = clusterServiceDAO.merge(currentServiceEntity);
+      updatedService = serviceFactory.createExisting(this, getServiceGroup(currentService.getServiceGroupName()),
+                                                      updatedServiceEntity);
+      addService(updatedService);
+    } catch (ServiceGroupNotFoundException e) {
+      e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+    } finally {
+      clusterGlobalLock.writeLock().unlock();
+    }
+    return updatedService;
+
+  }
+
+  @Override
+  public Service removeDependencyFromService(String  serviceGroupName, String serviceName, String dependencyServiceGroupName,
+                                        String dependencyServiceName) {
+    Service currentService = null;
+
+    for (Service service : services.values()) {
+
+      if (service.getName().equals(serviceName) && service.getServiceGroupName().equals(serviceGroupName)) {
+        currentService = service;
+      }
+
+    }
+
+    Service updatedService = null;
+    clusterGlobalLock.writeLock().lock();
+    try {
+      ClusterServiceEntity currentServiceEntity = clusterServiceDAO.findById(getClusterId(),
+              currentService.getServiceGroupId(), currentService.getServiceId());
+
+
+
+      ClusterServiceEntity serviceEntityToRemove = null;
+      for (ClusterServiceEntity cse : currentServiceEntity.getServiceDependencies()) {
+        if (cse.getServiceName().equals(dependencyServiceName) /*&& cse.getClusterServiceGroupEntity().getServiceGroupName().equals(dependencyServiceGroupName)*/) {
+          serviceEntityToRemove = cse;
+          break;
+        }
+      }
+      currentServiceEntity.getServiceDependencies().remove(serviceEntityToRemove);
+      ClusterServiceEntity updatedServiceEntity = clusterServiceDAO.merge(currentServiceEntity);
+      updatedService = serviceFactory.createExisting(this, getServiceGroup(currentService.getServiceGroupName()),
+              updatedServiceEntity);
+      addService(updatedService);
+    } catch (ServiceGroupNotFoundException e) {
+      e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+    } finally {
+      clusterGlobalLock.writeLock().unlock();
+    }
+    return updatedService;
+
+  }
+
+  @Override
   public void addServiceGroup(ServiceGroup serviceGroup) {
     if (LOG.isDebugEnabled()) {
       LOG.debug("Adding a new service group" + ", clusterName=" + getClusterName()

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
index fda0566..e5eb11c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
@@ -61,6 +61,7 @@ import org.apache.ambari.server.controller.internal.HostComponentResourceProvide
 import org.apache.ambari.server.controller.internal.HostResourceProvider;
 import org.apache.ambari.server.controller.internal.ProvisionClusterRequest;
 import org.apache.ambari.server.controller.internal.RequestImpl;
+import org.apache.ambari.server.controller.internal.ServiceDependencyResourceProvider;
 import org.apache.ambari.server.controller.internal.ServiceGroupDependencyResourceProvider;
 import org.apache.ambari.server.controller.internal.ServiceGroupResourceProvider;
 import org.apache.ambari.server.controller.internal.ServiceResourceProvider;
@@ -129,6 +130,7 @@ public class AmbariContext {
   private static HostRoleCommandFactory hostRoleCommandFactory;
   private static HostResourceProvider hostResourceProvider;
   private static ServiceGroupResourceProvider serviceGroupResourceProvider;
+  private static ServiceDependencyResourceProvider serviceDependencyResourceProvider;
   private static ServiceGroupDependencyResourceProvider serviceGroupDependencyResourceProvider;
   private static ServiceResourceProvider serviceResourceProvider;
   private static ComponentResourceProvider componentResourceProvider;
@@ -781,6 +783,14 @@ public class AmbariContext {
     return serviceGroupDependencyResourceProvider;
   }
 
+  private synchronized ServiceDependencyResourceProvider getServiceDependencyResourceProvider() {
+    if (serviceDependencyResourceProvider == null) {
+      serviceDependencyResourceProvider = (ServiceDependencyResourceProvider) ClusterControllerHelper.
+              getClusterController().ensureResourceProvider(Resource.Type.ServiceGroup);
+    }
+    return serviceDependencyResourceProvider;
+  }
+
   private synchronized ServiceResourceProvider getServiceResourceProvider() {
     if (serviceResourceProvider == null) {
       serviceResourceProvider = (ServiceResourceProvider) ClusterControllerHelper.

http://git-wip-us.apache.org/repos/asf/ambari/blob/72bac1f7/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 19e23c5..36ff3b7 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
@@ -196,6 +196,17 @@ CREATE TABLE clusterservices (
   CONSTRAINT PK_clusterservices PRIMARY KEY (id, service_group_id, cluster_id),
   CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (service_group_id, cluster_id) REFERENCES servicegroups (id, cluster_id));
 
+CREATE TABLE servicedependencies (
+  service_id BIGINT NOT NULL,
+  service_group_id BIGINT NOT NULL,
+  service_cluster_id BIGINT NOT NULL,
+  dependent_service_id BIGINT NOT NULL,
+  dependent_service_group_id BIGINT NOT NULL,
+  dependent_service_cluster_id BIGINT NOT NULL,
+  CONSTRAINT PK_servicedependencies PRIMARY KEY (service_id, service_group_id, service_cluster_id, dependent_service_id, dependent_service_group_id, dependent_service_cluster_id),
+  CONSTRAINT FK_servicedependencies_service_group_cluster_id FOREIGN KEY (service_id, service_group_id, service_cluster_id) REFERENCES clusterservices  (id, service_group_id, cluster_id));
+  CONSTRAINT FK_servicedependencies_dependent_service_group_cluster_id FOREIGN KEY (dependent_service_id, dependent_service_group_id, dependent_service_cluster_id) REFERENCES clusterservices (id, service_group_id, cluster_id));
+
 CREATE TABLE clusterstate (
   cluster_id BIGINT NOT NULL,
   current_cluster_state VARCHAR(255) NOT NULL,