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

[01/17] ambari git commit: AMBARI-22355 : New endpoint at ServiceLevel for configurations - POST, GET (mradhakrishnan) [Forced Update!]

Repository: ambari
Updated Branches:
  refs/heads/branch-feature-AMBARI-14714-blueprintv2 7711c51b3 -> 8a5518740 (forced update)


AMBARI-22355 : New endpoint at ServiceLevel for configurations - POST, GET (mradhakrishnan)


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: 5301b3f5c8d5ab826a89d83968cb64642d8347e9
Parents: 527c4a2
Author: Madhuvanthi Radhakrishnan <mr...@hortonworks.com>
Authored: Wed Nov 8 09:48:20 2017 -0800
Committer: Madhuvanthi Radhakrishnan <mr...@hortonworks.com>
Committed: Wed Nov 8 09:48:20 2017 -0800

----------------------------------------------------------------------
 .../resources/ServiceResourceDefinition.java    |   2 +-
 .../api/services/ConfigurationService.java      |  36 ++++-
 .../server/api/services/ServiceService.java     |  13 ++
 .../controller/AmbariManagementController.java  |   2 +-
 .../AmbariManagementControllerImpl.java         | 130 +++++++++++++------
 .../server/controller/ConfigurationRequest.java |  40 +++++-
 .../controller/ConfigurationResponse.java       |  66 ++++++++++
 .../internal/ConfigurationResourceProvider.java | 100 ++++++++++++--
 .../server/orm/dao/ClusterServiceDAO.java       |  16 +++
 .../orm/entities/ClusterConfigEntity.java       |  11 ++
 .../orm/entities/ClusterServiceEntity.java      |  10 +-
 .../org/apache/ambari/server/state/Cluster.java |  38 ++++++
 .../ambari/server/state/ConfigFactory.java      |   2 +-
 .../ambari/server/state/ConfigHelper.java       |   4 +-
 .../apache/ambari/server/state/ConfigImpl.java  |  15 ++-
 .../server/state/cluster/ClusterImpl.java       | 112 +++++++++++++++-
 .../state/configgroup/ConfigGroupImpl.java      |   3 +-
 .../server/upgrade/AbstractUpgradeCatalog.java  |   3 +-
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  |   2 +
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |   2 +
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |   2 +
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |   2 +
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |   2 +
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |   2 +
 24 files changed, 546 insertions(+), 69 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/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 0009c70..5f6b6ba 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
@@ -54,7 +54,7 @@ public class ServiceResourceDefinition extends BaseResourceDefinition {
     subs.add(new SubResourceDefinition(Resource.Type.Alert));
     //todo: dynamic sub-resource definition
     subs.add(new SubResourceDefinition(Resource.Type.Artifact));
-
+    subs.add(new SubResourceDefinition(Resource.Type.Configuration));
     return subs;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/api/services/ConfigurationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ConfigurationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ConfigurationService.java
index 0eb8bd6..79128a2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ConfigurationService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ConfigurationService.java
@@ -44,14 +44,38 @@ public class ConfigurationService extends BaseService {
   private String m_clusterName;
 
   /**
+   * Parent service group name.
+   */
+  private String m_serviceGroupName = null;
+
+  /**
+   * Parent service name.
+   */
+  private String m_serviceName = null;
+
+
+  /**
    * Constructor.
    *
-   * @param clusterName cluster id
+   * @param clusterName cluster name
    */
   public ConfigurationService(String clusterName) {
     m_clusterName = clusterName;
   }
 
+  /**
+   * Constructor.
+   *
+   * @param clusterName cluster name
+   * @param serviceGroupName service group name
+   * @param serviceName service name
+   */
+  public ConfigurationService(String clusterName, String serviceGroupName, String serviceName) {
+    m_clusterName = clusterName;
+    m_serviceGroupName = serviceGroupName;
+    m_serviceName = serviceName;
+  }
+
   @Path("service_config_versions")
   public ServiceConfigVersionService getServiceConfigVersionService() {
     return new ServiceConfigVersionService(m_clusterName);
@@ -68,7 +92,7 @@ public class ConfigurationService extends BaseService {
   @GET @ApiIgnore // until documented
   @Produces("text/plain")
   public Response getConfigurations(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
-    return handleRequest(headers, body, ui, Request.Type.GET, createConfigurationResource(m_clusterName));
+    return handleRequest(headers, body, ui, Request.Type.GET, createConfigurationResource(m_clusterName, m_serviceGroupName, m_serviceName));
   }
 
   /**
@@ -97,7 +121,7 @@ public class ConfigurationService extends BaseService {
   @Produces("text/plain")
   public Response createConfigurations(String body,@Context HttpHeaders headers, @Context UriInfo ui) {
 
-    return handleRequest(headers, body, ui, Request.Type.POST, createConfigurationResource(m_clusterName));
+    return handleRequest(headers, body, ui, Request.Type.POST, createConfigurationResource(m_clusterName, m_serviceGroupName, m_serviceName));
   }
 
   /**
@@ -107,10 +131,14 @@ public class ConfigurationService extends BaseService {
    *
    * @return a service resource instance
    */
-  ResourceInstance createConfigurationResource(String clusterName) {
+  ResourceInstance createConfigurationResource(String clusterName, String serviceGroupName, String serviceName) {
     Map<Resource.Type,String> mapIds = new HashMap<>();
     mapIds.put(Resource.Type.Cluster, clusterName);
     mapIds.put(Resource.Type.Configuration, null);
+    if (serviceName != null && serviceGroupName != null) {
+      mapIds.put(Resource.Type.ServiceGroup, serviceGroupName);
+      mapIds.put(Resource.Type.Service, serviceName);
+    }
 
     return createResource(Resource.Type.Configuration, mapIds);
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/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 afdfcc4..1f3332f 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
@@ -718,6 +718,19 @@ public class ServiceService extends BaseService {
   }
 
   /**
+   * Gets the configurations sub-resource.
+   *
+   * @param request      the request
+   * @param serviceName  the serviceName
+   *
+   * @return the configuration service
+   */
+  @Path("{serviceName}/configurations")
+  public ConfigurationService getConfigurationHandler (@Context javax.ws.rs.core.Request request, @PathParam("serviceName") String serviceName) {
+    return new ConfigurationService(m_clusterName, m_serviceGroupName, serviceName);
+  }
+
+  /**
    * Create a service resource instance.
    *
    * @param clusterName         cluster name

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
index 358b1bf..86ac3c4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
@@ -125,7 +125,7 @@ public interface AmbariManagementController {
    * @return config created
    */
   Config createConfig(Cluster cluster, StackId stackId, String type, Map<String, String> properties,
-                      String versionTag, Map<String, Map<String, String>> propertiesAttributes);
+                      String versionTag, Map<String, Map<String, String>> propertiesAttributes, Long serviceId);
 
   /**
    * Creates users.

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index 7f5c051..dc16f22 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -1011,22 +1011,27 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     }
 
     Config config = createConfig(cluster, stackId, request.getType(), requestProperties,
-      request.getVersionTag(), propertiesAttributes);
+      request.getVersionTag(), propertiesAttributes, request.getServiceId() == null? null : request.getServiceId());
 
     LOG.info(MessageFormat.format("Creating configuration with tag ''{0}'' to cluster ''{1}''  for configuration type {2}",
         request.getVersionTag(),
         request.getClusterName(),
         configType));
 
-    return new ConfigurationResponse(cluster.getClusterName(), config);
+    if(request.getServiceId() == null) {
+      return new ConfigurationResponse(cluster.getClusterName(), config);
+    }
+    else {
+      return new ConfigurationResponse(cluster.getClusterName(), config, request.getServiceId(), request.getServiceGroupId());
+    }
   }
 
   @Override
   public Config createConfig(Cluster cluster, StackId stackId, String type, Map<String, String> properties,
-                             String versionTag, Map<String, Map<String, String>> propertiesAttributes) {
+                             String versionTag, Map<String, Map<String, String>> propertiesAttributes, Long serviceId) {
 
     Config config = configFactory.createNew(stackId, cluster, type, versionTag, properties,
-        propertiesAttributes);
+        propertiesAttributes, serviceId);
 
     cluster.addConfig(config);
     return config;
@@ -1470,52 +1475,101 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
 
     // !!! if only one, then we need full properties
     if (null != request.getType() && null != request.getVersionTag()) {
-      Config config = cluster.getConfig(request.getType(),
-          request.getVersionTag());
-      if (null != config) {
-        ConfigurationResponse response = new ConfigurationResponse(
-            cluster.getClusterName(), config);
-        responses.add(response);
+      ConfigurationResponse response = null;
+      Config config = null;
+      //TODO : Remove after getting rid of cluster configurations
+      if (request.getServiceId() == null) {
+        config = cluster.getConfig(request.getType(),
+                request.getVersionTag());
+        if (null != config) {
+          response = new ConfigurationResponse(
+                  cluster.getClusterName(), config);
+        }
       }
+      else {
+        config = cluster.getConfigByServiceId(request.getType(), request.getVersionTag(), request.getServiceId());
+        if (null != config) {
+          response = new ConfigurationResponse(
+                  cluster.getClusterName(), config, request.getServiceId(), request.getServiceGroupId());
+        }
+      }
+      responses.add(response);
     }
     else {
+      ConfigurationResponse response = null;
       boolean includeProps = request.includeProperties();
+      Map<String, Config> configs = null;
+      //Get by type
       if (null != request.getType()) {
-        Map<String, Config> configs = cluster.getConfigsByType(
-            request.getType());
-
-        if (null != configs) {
-          for (Entry<String, Config> entry : configs.entrySet()) {
-            Config config = entry.getValue();
-            ConfigurationResponse response = new ConfigurationResponse(
-                cluster.getClusterName(), config.getStackId(),
-                request.getType(),
-                config.getTag(), entry.getValue().getVersion(),
-                includeProps ? config.getProperties() : new HashMap<>(),
-                includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
-                config.getPropertiesTypes());
-            responses.add(response);
+        //TODO : Remove after getting rid of cluster configurations
+        if (request.getServiceId() == null) {
+          configs = cluster.getConfigsByType(
+                  request.getType());
+          if (null != configs) {
+            for (Entry<String, Config> entry : configs.entrySet()) {
+              Config config = entry.getValue();
+              response = new ConfigurationResponse(
+                      cluster.getClusterName(), config.getStackId(),
+                      request.getType(),
+                      config.getTag(), entry.getValue().getVersion(),
+                      includeProps ? config.getProperties() : new HashMap<>(),
+                      includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
+                      config.getPropertiesTypes());
+              responses.add(response);
+            }
+          }
+        }
+        else {
+          configs = cluster.getConfigsByServiceIdType(
+                  request.getType(), request.getServiceId());
+          if (null != configs) {
+            for (Entry<String, Config> entry : configs.entrySet()) {
+              Config config = entry.getValue();
+              response = new ConfigurationResponse(
+                      cluster.getClusterName(), config.getStackId(),
+                      request.getType(),
+                      config.getTag(), entry.getValue().getVersion(),
+                      includeProps ? config.getProperties() : new HashMap<>(),
+                      includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
+                      config.getPropertiesTypes(), request.getServiceId(), request.getServiceGroupId());
+              responses.add(response);
+            }
           }
         }
-      } else {
-        // !!! all configuration
-        Collection<Config> all = cluster.getAllConfigs();
-
-        for (Config config : all) {
-          ConfigurationResponse response = new ConfigurationResponse(
-              cluster.getClusterName(), config.getStackId(), config.getType(),
-              config.getTag(), config.getVersion(),
-              includeProps ? config.getProperties() : new HashMap<>(),
-              includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
-              config.getPropertiesTypes());
 
-          responses.add(response);
+      }
+      else {
+        // !!! all configuration
+        Collection<Config> all = null;
+        //TODO : Remove after getting rid of cluster configurations
+        if (request.getServiceId() == null) {
+          all = cluster.getAllConfigs();
+          for (Config config : all) {
+            response = new ConfigurationResponse(
+                    cluster.getClusterName(), config.getStackId(), config.getType(),
+                    config.getTag(), config.getVersion(),
+                    includeProps ? config.getProperties() : new HashMap<>(),
+                    includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
+                    config.getPropertiesTypes());
+            responses.add(response);
+          }
+        }
+        else {
+          all = cluster.getConfigsByServiceId(request.getServiceId());
+          for (Config config : all) {
+            response = new ConfigurationResponse(
+                    cluster.getClusterName(), config.getStackId(), config.getType(),
+                    config.getTag(), config.getVersion(),
+                    includeProps ? config.getProperties() : new HashMap<>(),
+                    includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
+                    config.getPropertiesTypes(), request.getServiceId(), request.getServiceGroupId());
+            responses.add(response);
+          }
         }
+
       }
     }
-
     return responses;
-
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationRequest.java
index cf035b0..d26cf16 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationRequest.java
@@ -36,6 +36,8 @@ public class ConfigurationRequest {
   private boolean selected = true;
   private Map<String, Map<String, String>> configsAttributes;
   private boolean includeProperties;
+  private Long serviceId;
+  private Long serviceGroupId;
 
   public ConfigurationRequest() {
     configs = new HashMap<>();
@@ -46,7 +48,7 @@ public class ConfigurationRequest {
                               String type,
                               String tag,
                               Map<String, String> configs,
-                              Map<String, Map<String, String>> configsAttributes) {
+                              Map<String, Map<String, String>> configsAttributes, Long serviceId, Long serviceGroupId) {
 
     this.clusterName = clusterName;
     this.configs = configs;
@@ -55,6 +57,23 @@ public class ConfigurationRequest {
     this.configs = configs;
     this.configsAttributes = configsAttributes;
     this.includeProperties = (type != null && tag != null);
+    this.serviceId = serviceId == null ? null : serviceId;
+    this.serviceGroupId = serviceGroupId == null ? null : serviceGroupId;
+
+  }
+
+  /**
+   * @return service id
+   */
+  public Long getServiceId() {
+    return serviceId;
+  }
+
+  /**
+   * @param serviceId
+   */
+  public void setServiceId(Long serviceId) {
+    this.serviceId = serviceId;
   }
 
   /**
@@ -121,7 +140,24 @@ public class ConfigurationRequest {
   public void setSelected(boolean selected) {
     this.selected = selected;
   }
-  
+
+
+  /**
+   *
+   * @return serviceGroupId
+   */
+  public Long getServiceGroupId() {
+    return serviceGroupId;
+  }
+
+  /**
+   *
+   * @param serviceGroupId
+   */
+  public void setServiceGroupId(Long serviceGroupId) {
+    this.serviceGroupId = serviceGroupId;
+  }
+
   /**
    * Gets if the configuration is to be selected.
    * @return <code>true</code> if the configuration is selected.

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationResponse.java
index abf2096..cbf6685 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationResponse.java
@@ -43,6 +43,10 @@ public class ConfigurationResponse {
 
   private Long version;
 
+  private Long serviceId;
+
+  private Long serviceGroupId;
+
   private List<Long> serviceConfigVersions;
 
   private Map<String, String> configs;
@@ -94,6 +98,41 @@ public class ConfigurationResponse {
     this(clusterName, config.getStackId(), config.getType(), config.getTag(),
         config.getVersion(), config.getProperties(),
         config.getPropertiesAttributes(), config.getPropertiesTypes());
+
+  }
+
+
+  /**
+   * Constructor.
+   *
+   * @param clusterName
+   * @param config
+   */
+  public ConfigurationResponse(String clusterName, Config config, Long serviceId, Long serviceGroupId) {
+    this(clusterName, config.getStackId(), config.getType(), config.getTag(),
+            config.getVersion(), config.getProperties(),
+            config.getPropertiesAttributes(), config.getPropertiesTypes(), serviceId, serviceGroupId);
+
+  }
+
+  public ConfigurationResponse(String clusterName, StackId stackId,
+                               String type, String versionTag, Long version,
+                               Map<String, String> configs,
+                               Map<String, Map<String, String>> configAttributes,
+                               Map<PropertyInfo.PropertyType, Set<String>> propertiesTypes, Long serviceId, Long serviceGroupId) {
+    this.clusterName = clusterName;
+    this.stackId = stackId;
+    this.configs = configs;
+    this.type = type;
+    this.versionTag = versionTag;
+    this.version = version;
+    this.configs = configs;
+    this.configAttributes = configAttributes;
+    this.propertiesTypes = propertiesTypes;
+    this.serviceId = serviceId;
+    this.serviceGroupId = serviceGroupId;
+    SecretReference.replacePasswordsWithReferences(propertiesTypes, configs, type, version);
+    SecretReference.replacePasswordsWithReferencesForCustomProperties(configAttributes, configs, type, version);
   }
 
   /**
@@ -154,6 +193,22 @@ public class ConfigurationResponse {
     this.version = version;
   }
 
+  public Long getServiceId() {
+    return serviceId;
+  }
+
+  public void setServiceId(Long serviceId) {
+    this.serviceId = serviceId;
+  }
+
+  public Long getServiceGroupId() {
+    return serviceGroupId;
+  }
+
+  public void setServiceGroupId(Long serviceGroupId) {
+    this.serviceGroupId = serviceGroupId;
+  }
+
   /**
    * Gets the Stack ID that this configuration is scoped for.
    *
@@ -190,6 +245,15 @@ public class ConfigurationResponse {
       return false;
     }
 
+    if (serviceId != null ? !serviceId.equals(that.serviceId) : that.serviceId != null) {
+      return false;
+    }
+
+    if (serviceGroupId != null ? !serviceGroupId.equals(that.serviceGroupId) : that.serviceGroupId != null) {
+      return false;
+    }
+
+
     return true;
   }
 
@@ -199,6 +263,8 @@ public class ConfigurationResponse {
     result = 31 * result + (stackId != null ? stackId.hashCode() : 0);
     result = 31 * result + (type != null ? type.hashCode() : 0);
     result = 31 * result + (version != null ? version.hashCode() : 0);
+    result = 31 * result + (serviceId != null ? serviceId.hashCode() : 0);
+    result = 31 * result + (serviceGroupId != null ? serviceGroupId.hashCode() : 0);
     return result;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigurationResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigurationResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigurationResourceProvider.java
index 0f26085..4e70a8e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigurationResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigurationResourceProvider.java
@@ -28,6 +28,7 @@ import java.util.Set;
 import java.util.regex.Pattern;
 
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.StaticallyInject;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.ConfigurationRequest;
 import org.apache.ambari.server.controller.ConfigurationResponse;
@@ -41,12 +42,17 @@ import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.orm.dao.ClusterServiceDAO;
+import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.security.authorization.RoleAuthorization;
 
+import com.google.inject.Inject;
+
 /**
  * Resource provider for configuration resources.
  */
+@StaticallyInject
 public class ConfigurationResourceProvider extends
     AbstractControllerResourceProvider {
 
@@ -62,12 +68,21 @@ public class ConfigurationResourceProvider extends
   public static final String CONFIGURATION_CONFIG_TYPE_PROPERTY_ID = PropertyHelper.getPropertyId(null, "type");
   public static final String CONFIGURATION_CONFIG_TAG_PROPERTY_ID = PropertyHelper.getPropertyId(null, "tag");
   public static final String CONFIGURATION_CONFIG_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId(null, "version");
+  public static final String CONFIGURATION_SERVICE_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(null, "service_name");
+  public static final String CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID = PropertyHelper.getPropertyId(null, "service_group_name");
+  public static final String CONFIGURATION_SERVICE_ID_PROPERTY_ID = PropertyHelper.getPropertyId("Config", "service_id");
+  public static final String CONFIGURATION_SERVICE_GROUP_ID_PROPERTY_ID = PropertyHelper.getPropertyId("Config", "service_group_id");
+
 
   /**
    * The property ids for a configuration resource.
    */
   private static final Set<String> PROPERTY_IDS = new HashSet<>();
 
+  @Inject
+  protected static ClusterServiceDAO clusterServiceDAO;
+
+
   /**
    * The key property ids for a configuration resource.
    */
@@ -80,10 +95,16 @@ public class ConfigurationResourceProvider extends
     PROPERTY_IDS.add(CONFIGURATION_CONFIG_TYPE_PROPERTY_ID);
     PROPERTY_IDS.add(CONFIGURATION_CONFIG_TAG_PROPERTY_ID);
     PROPERTY_IDS.add(CONFIGURATION_CONFIG_VERSION_PROPERTY_ID);
+    PROPERTY_IDS.add(CONFIGURATION_SERVICE_NAME_PROPERTY_ID);
+    PROPERTY_IDS.add(CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID);
+    PROPERTY_IDS.add(CONFIGURATION_SERVICE_ID_PROPERTY_ID);
+    PROPERTY_IDS.add(CONFIGURATION_SERVICE_GROUP_ID_PROPERTY_ID);
 
     // keys
     KEY_PROPERTY_IDS.put(Resource.Type.Configuration,CONFIGURATION_CONFIG_TYPE_PROPERTY_ID);
     KEY_PROPERTY_IDS.put(Resource.Type.Cluster,CONFIGURATION_CLUSTER_NAME_PROPERTY_ID);
+    KEY_PROPERTY_IDS.put(Resource.Type.Service,CONFIGURATION_SERVICE_NAME_PROPERTY_ID);
+    KEY_PROPERTY_IDS.put(Resource.Type.ServiceGroup,CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID);
   }
 
   /**
@@ -92,7 +113,7 @@ public class ConfigurationResourceProvider extends
   private static Set<String> pkPropertyIds =
     new HashSet<>(Arrays.asList(new String[]{
       CONFIGURATION_CLUSTER_NAME_PROPERTY_ID,
-      CONFIGURATION_CONFIG_TYPE_PROPERTY_ID}));
+      CONFIGURATION_CONFIG_TYPE_PROPERTY_ID, CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID, CONFIGURATION_SERVICE_NAME_PROPERTY_ID}));
 
 
   // ----- Constructors ------------------------------------------------------
@@ -122,10 +143,23 @@ public class ConfigurationResourceProvider extends
              ResourceAlreadyExistsException,
              NoSuchParentResourceException {
 
+    Set<Resource> associatedResources = new HashSet<>();
+
     for (Map<String, Object> map : request.getProperties()) {
       String cluster = (String) map.get(CONFIGURATION_CLUSTER_NAME_PROPERTY_ID);
       String type = (String) map.get(CONFIGURATION_CONFIG_TYPE_PROPERTY_ID);
-      String tag  = (String) map.get(CONFIGURATION_CONFIG_TAG_PROPERTY_ID);
+      String tag = (String) map.get(CONFIGURATION_CONFIG_TAG_PROPERTY_ID);
+      String serviceName = null;
+      String serviceGroupName = null;
+      Long serviceId = null;
+      Long serviceGroupId = null;
+      if (map.containsKey(CONFIGURATION_SERVICE_NAME_PROPERTY_ID) && map.containsKey(CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID)) {
+        serviceName = (String) map.get(CONFIGURATION_SERVICE_NAME_PROPERTY_ID);
+        serviceGroupName = (String) map.get(CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID);
+        ClusterServiceEntity clusterServiceEntity = clusterServiceDAO.findByName(cluster, serviceGroupName, serviceName);
+        serviceId = clusterServiceEntity.getServiceId();
+        serviceGroupId = clusterServiceEntity.getServiceGroupId();
+      }
 
       Map<String, String> configMap = new HashMap<>();
       Map<String, Map<String, String>> configAttributesMap = null;
@@ -136,8 +170,8 @@ public class ConfigurationResourceProvider extends
           configMap.put(PropertyHelper.getPropertyName(entry.getKey()), entry.getValue().toString());
         }
         if (propertyCategory != null
-            && PROPERTIES_ATTRIBUTES_PATTERN.matcher(propertyCategory).matches()
-            && null != entry.getValue()) {
+                && PROPERTIES_ATTRIBUTES_PATTERN.matcher(propertyCategory).matches()
+                && null != entry.getValue()) {
           if (null == configAttributesMap) {
             configAttributesMap = new HashMap<>();
           }
@@ -151,18 +185,35 @@ public class ConfigurationResourceProvider extends
         }
       }
 
-      final ConfigurationRequest configRequest = new ConfigurationRequest(cluster, type, tag, configMap, configAttributesMap);
+      final ConfigurationRequest configRequest = new ConfigurationRequest(cluster, type, tag, configMap, configAttributesMap, serviceId, serviceGroupId);
 
-      createResources(new Command<Void>() {
+      ConfigurationResponse configurationResponse = createResources(new Command<ConfigurationResponse>() {
         @Override
-        public Void invoke() throws AmbariException, AuthorizationException {
-          getManagementController().createConfiguration(configRequest);
-          return null;
+        public ConfigurationResponse invoke() throws AmbariException, AuthorizationException {
+          return getManagementController().createConfiguration(configRequest);
+
         }
       });
 
+      if (configurationResponse != null) {
+        Resource resource = new ResourceImpl(Resource.Type.Configuration);
+        resource.setProperty(CONFIGURATION_CLUSTER_NAME_PROPERTY_ID, configurationResponse.getClusterName());
+        resource.setProperty(CONFIGURATION_STACK_ID_PROPERTY_ID, configurationResponse.getStackId().getStackId());
+        resource.setProperty(CONFIGURATION_CONFIG_TYPE_PROPERTY_ID, configurationResponse.getType());
+        resource.setProperty(CONFIGURATION_CONFIG_TAG_PROPERTY_ID, configurationResponse.getVersionTag());
+        resource.setProperty(CONFIGURATION_CONFIG_VERSION_PROPERTY_ID, configurationResponse.getVersion());
+        if (configurationResponse.getServiceId() != null) {
+          resource.setProperty(CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID, serviceGroupName);
+          resource.setProperty(CONFIGURATION_SERVICE_NAME_PROPERTY_ID, serviceName);
+          resource.setProperty(CONFIGURATION_SERVICE_ID_PROPERTY_ID, serviceId);
+          resource.setProperty(CONFIGURATION_SERVICE_GROUP_ID_PROPERTY_ID, serviceGroupId);
+        }
+        associatedResources.add(resource);
+      }
     }
-    return getRequestStatus(null);
+        return getRequestStatus(null, associatedResources);
+
+
   }
 
   @Override
@@ -170,9 +221,16 @@ public class ConfigurationResourceProvider extends
     throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
 
     final Set<ConfigurationRequest> requests = new HashSet<>();
+    String serviceName = null;
+    String serviceGroupName = null;
 
     for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
-      requests.add(getRequest(request, propertyMap));
+      ConfigurationRequest configurationRequest = getRequest(request, propertyMap);
+      if (configurationRequest.getServiceId() != null) {
+        serviceGroupName = (String) propertyMap.get(CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID);
+        serviceName = (String) propertyMap.get(CONFIGURATION_SERVICE_NAME_PROPERTY_ID);
+      }
+      requests.add(configurationRequest);
     }
 
     Set<ConfigurationResponse> responses = getResources(new Command<Set<ConfigurationResponse>>() {
@@ -193,6 +251,12 @@ public class ConfigurationResourceProvider extends
       resource.setProperty(CONFIGURATION_CONFIG_TYPE_PROPERTY_ID, response.getType());
       resource.setProperty(CONFIGURATION_CONFIG_TAG_PROPERTY_ID, response.getVersionTag());
       resource.setProperty(CONFIGURATION_CONFIG_VERSION_PROPERTY_ID, response.getVersion());
+      if (response.getServiceId() != null) {
+        resource.setProperty(CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID, serviceGroupName );
+        resource.setProperty(CONFIGURATION_SERVICE_NAME_PROPERTY_ID, serviceName );
+        resource.setProperty(CONFIGURATION_SERVICE_ID_PROPERTY_ID, response.getServiceId());
+        resource.setProperty(CONFIGURATION_SERVICE_GROUP_ID_PROPERTY_ID, response.getServiceGroupId());
+      }
 
       if (null != response.getConfigs() && response.getConfigs().size() > 0) {
         Map<String, String> configs = response.getConfigs();
@@ -281,10 +345,22 @@ public class ConfigurationResourceProvider extends
   private ConfigurationRequest getRequest(Request request, Map<String, Object> properties) {
     String type = (String) properties.get(CONFIGURATION_CONFIG_TYPE_PROPERTY_ID);
     String tag  = (String) properties.get(CONFIGURATION_CONFIG_TAG_PROPERTY_ID);
+    String cluster  = (String) properties.get(CONFIGURATION_CLUSTER_NAME_PROPERTY_ID);
+    String serviceName = null;
+    String serviceGroupName = null;
+    Long serviceId = null;
+    Long serviceGroupId = null;
+    if (properties.containsKey(CONFIGURATION_SERVICE_NAME_PROPERTY_ID) && properties.containsKey(CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID)) {
+      serviceName = (String) properties.get(CONFIGURATION_SERVICE_NAME_PROPERTY_ID);
+      serviceGroupName = (String) properties.get(CONFIGURATION_SERVICE_GROUP_NAME_PROPERTY_ID);
+      ClusterServiceEntity clusterServiceEntity = clusterServiceDAO.findByName(cluster, serviceGroupName, serviceName);
+      serviceId = clusterServiceEntity.getServiceId();
+      serviceGroupId = clusterServiceEntity.getServiceGroupId();
+    }
 
     ConfigurationRequest configRequest = new ConfigurationRequest(
         (String) properties.get(CONFIGURATION_CLUSTER_NAME_PROPERTY_ID),
-        type, tag, new HashMap<>(), new HashMap<>());
+        type, tag, new HashMap<>(), new HashMap<>(), serviceId, serviceGroupId);
 
     Set<String> requestedIds = request.getPropertyIds();
     if (requestedIds.contains("properties") || requestedIds.contains("*")) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
index 0eeb19b..c7032aa 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
@@ -61,6 +61,22 @@ public class ClusterServiceDAO {
   }
 
   @RequiresSession
+  public ClusterServiceEntity findByName(String clusterName, String serviceGroupName, String serviceName) {
+    TypedQuery<ClusterServiceEntity> query = entityManagerProvider.get()
+            .createNamedQuery("clusterServiceByName" , ClusterServiceEntity.class);
+    query.setParameter("clusterName", clusterName);
+    query.setParameter("serviceGroupName", serviceGroupName);
+    query.setParameter("serviceName", serviceName);
+
+    try {
+      return query.getSingleResult();
+    }
+    catch (NoResultException ignored) {
+      return null;
+    }
+  }
+
+  @RequiresSession
   public List<ClusterServiceEntity> findAll() {
     return daoUtils.selectAll(entityManagerProvider.get(), ClusterServiceEntity.class);
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterConfigEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterConfigEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterConfigEntity.java
index beecf4e..4a0e84c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterConfigEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterConfigEntity.java
@@ -90,6 +90,17 @@ public class ClusterConfigEntity {
   @Column(name = "cluster_id", nullable = false, insertable = false, updatable = false, length = 10)
   private Long clusterId;
 
+  @Column(name = "service_id", nullable = true)
+  private Long serviceId;
+
+  public Long getServiceId() {
+    return serviceId;
+  }
+
+  public void setServiceId(Long serviceId) {
+    this.serviceId = serviceId;
+  }
+
   @Column(name = "type_name")
   private String type;
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/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 976bb67..e5a1618 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
@@ -48,7 +48,15 @@ import javax.persistence.TableGenerator;
       "JOIN clusterService.serviceGroupEntity serviceGroup " +
       "WHERE clusterService.serviceId=:serviceId " +
       "AND  serviceGroup.serviceGroupId=:serviceGroupId " +
-      "AND serviceGroup.clusterId=:clusterId")
+      "AND serviceGroup.clusterId=:clusterId"),
+   @NamedQuery(name = "clusterServiceByName", query =
+     "SELECT clusterService " +
+      "FROM ClusterServiceEntity clusterService " +
+       "JOIN clusterService.serviceGroupEntity serviceGroup " +
+        "JOIN clusterService.clusterEntity clusterEntity " +
+       "WHERE clusterService.serviceName=:serviceName " +
+       "AND  serviceGroup.serviceGroupName=:serviceGroupName " +
+        "AND clusterEntity.clusterName=:clusterName")
 })
 @Entity
 @TableGenerator(name = "service_id_generator",

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/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 27d37e3..f12759e 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
@@ -325,6 +325,16 @@ public interface Cluster {
   Map<String, Config> getConfigsByType(String configType);
 
   /**
+   * Gets all configs that match the specified type.  Result is not the
+   * DESIRED configuration for a cluster.
+   *
+   * @param configType the config type to return
+   *        serviceId the serviceid for the config
+   * @return a map of configuration objects that have been set for the given type
+   */
+  Map<String, Config> getConfigsByServiceIdType(String configType, Long serviceId);
+
+  /**
    * Gets all properties types that mach the specified type.
    *
    * @param configType the config type to return
@@ -344,6 +354,18 @@ public interface Cluster {
   Config getConfig(String configType, String versionTag);
 
   /**
+   * Gets the specific config that matches the specified type and tag.  This not
+   * necessarily a DESIRED configuration that applies to a cluster.
+   *
+   * @param configType the config type to find
+   * @param versionTag the config version tag to find
+   * @param serviceId the service for the config
+   * @return a {@link Config} object, or <code>null</code> if the specific type
+   * and version have not been set.
+   */
+  Config getConfigByServiceId(String configType, String versionTag, Long serviceId);
+
+  /**
    * Get latest (including inactive ones) configurations with any of the given types.
    * This method does not take into account the configuration being enabled.
    *
@@ -371,6 +393,15 @@ public interface Cluster {
   void addConfig(Config config);
 
   /**
+   * Sets a specific config.  NOTE:  This is not a DESIRED configuration that
+   * applies to a cluster.
+   *
+   * @param config the config instance to add
+   *        serviceId service id for the config
+   */
+  void addConfig(Config config, Long serviceId);
+
+  /**
    * Gets all configurations defined for a cluster.
    *
    * @return the collection of all configs that have been defined.
@@ -378,6 +409,13 @@ public interface Cluster {
   Collection<Config> getAllConfigs();
 
   /**
+   * Gets all configurations defined for a cluster service.
+   *
+   * @return the collection of all configs that have been defined.
+   */
+  List<Config> getConfigsByServiceId(Long serviceId);
+
+  /**
    * Adds and sets a DESIRED configuration to be applied to a cluster.  There
    * can be only one selected config per type.
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigFactory.java
index 2879345..4c21820 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigFactory.java
@@ -50,7 +50,7 @@ public interface ConfigFactory {
    * @return
    */
   Config createNew(StackId stackId, Cluster cluster, @Assisted("type") String type, @Assisted("tag") String tag,
-      Map<String, String> map, Map<String, Map<String, String>> mapAttributes);
+      Map<String, String> map, Map<String, Map<String, String>> mapAttributes, Long serviceId);
 
   /**
    * Creates a new {@link Config} object using provided entity

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
index 8c0e656..e999e24 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
@@ -1197,8 +1197,8 @@ public class ConfigHelper {
         }
       }
     }
-
-    return controller.createConfig(cluster, stackId, type, properties, tag, propertyAttributes);
+    //TODO check at the right use case
+    return controller.createConfig(cluster, stackId, type, properties, tag, propertyAttributes, null);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java
index 44d76af..2d2e7b8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java
@@ -105,16 +105,15 @@ public class ConfigImpl implements Config {
       @Assisted @Nullable Map<String, Map<String, String>> propertiesAttributes,
       ClusterDAO clusterDAO, StackDAO stackDAO,
       Gson gson, AmbariEventPublisher eventPublisher, LockFactory lockFactory) {
-    this(cluster.getDesiredStackVersion(), cluster, type, tag, properties, propertiesAttributes,
+    this(cluster.getDesiredStackVersion(), cluster, type, tag, properties, propertiesAttributes,null,
         clusterDAO, stackDAO, gson, eventPublisher, lockFactory);
   }
 
-
   @AssistedInject
   ConfigImpl(@Assisted @Nullable StackId stackId, @Assisted Cluster cluster, @Assisted("type") String type,
       @Assisted("tag") @Nullable String tag,
       @Assisted Map<String, String> properties,
-      @Assisted @Nullable Map<String, Map<String, String>> propertiesAttributes,
+      @Assisted @Nullable Map<String, Map<String, String>> propertiesAttributes,@Assisted @Nullable Long serviceId,
       ClusterDAO clusterDAO, StackDAO stackDAO,
       Gson gson, AmbariEventPublisher eventPublisher, LockFactory lockFactory) {
 
@@ -150,6 +149,10 @@ public class ConfigImpl implements Config {
     entity.setStack(stackEntity);
     entity.setData(gson.toJson(properties));
 
+    if (null != serviceId) {
+      entity.setServiceId(serviceId);
+    }
+
     if (null != propertiesAttributes) {
       entity.setAttributes(gson.toJson(propertiesAttributes));
     }
@@ -347,7 +350,11 @@ public class ConfigImpl implements Config {
     persistEntitiesInTransaction(entity);
 
     // ensure that the in-memory state of the cluster is kept consistent
-    cluster.addConfig(this);
+    if(entity.getServiceId() == null) {
+      cluster.addConfig(this);
+    }else{
+      cluster.addConfig(this,entity.getServiceId());
+    }
 
     // re-load the entity associations for the cluster
     cluster.refresh();

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/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 755a80f..78201f0 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
@@ -189,6 +189,11 @@ public class ClusterImpl implements Cluster {
   private final ConcurrentMap<String, ConcurrentMap<String, Config>> allConfigs = new ConcurrentHashMap<>();
 
   /**
+   * [ Service -> [ allConfigs ] ]
+   */
+  private final ConcurrentMap<Long, ConcurrentMap<String, ConcurrentMap<String, Config>>>  serviceConfigs = new ConcurrentHashMap<>();
+
+  /**
    * [ ServiceName -> [ ServiceComponentName -> [ HostName -> [ ... ] ] ] ]
    */
   private final ConcurrentMap<String, ConcurrentMap<String, ConcurrentMap<String, ServiceComponentHost>>> serviceComponentHosts = new ConcurrentHashMap<>();
@@ -1402,6 +1407,71 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
+  public Config getConfigByServiceId(String configType, String versionTag, Long serviceId) {
+    clusterGlobalLock.readLock().lock();
+    try {
+      if (!serviceConfigs.containsKey(serviceId)) {
+        return null;
+      }
+      else {
+        ConcurrentMap<String, ConcurrentMap<String, Config>> allServiceConfigs = serviceConfigs.get(serviceId);
+        if (!allServiceConfigs.containsKey(configType)
+                || !allServiceConfigs.get(configType).containsKey(versionTag)) {
+          return null;
+        }
+        return allServiceConfigs.get(configType).get(versionTag);
+      }
+    }
+    finally {
+        clusterGlobalLock.readLock().unlock();
+    }
+  }
+
+  @Override
+  public List<Config> getConfigsByServiceId(Long serviceId) {
+    clusterGlobalLock.readLock().lock();
+    try {
+      if (!serviceConfigs.containsKey(serviceId)) {
+        return null;
+      }
+      else {
+        List<Config> list = new ArrayList<>();
+        ConcurrentMap<String, ConcurrentMap<String, Config>> allServiceConfigs = serviceConfigs.get(serviceId);
+        for (Entry<String, ConcurrentMap<String, Config>> entry : allServiceConfigs.entrySet()) {
+          for (Config config : entry.getValue().values()) {
+            list.add(config);
+          }
+        }
+        return Collections.unmodifiableList(list);
+      }
+    }
+    finally {
+        clusterGlobalLock.readLock().unlock();
+    }
+  }
+
+  @Override
+  public Map<String, Config> getConfigsByServiceIdType(String configType, Long serviceId) {
+    clusterGlobalLock.readLock().lock();
+    try {
+      if (!serviceConfigs.containsKey(serviceId)) {
+        return null;
+      }
+      else {
+        List<Config> list = new ArrayList<>();
+        ConcurrentMap<String, ConcurrentMap<String, Config>> allServiceConfigs = serviceConfigs.get(serviceId);
+        if (!allServiceConfigs.containsKey(configType)) {
+          return null;
+        }
+        return Collections.unmodifiableMap(allServiceConfigs.get(configType));
+      }
+    }
+    finally {
+      clusterGlobalLock.readLock().unlock();
+    }
+  }
+
+  @Override
   public List<Config> getLatestConfigsWithTypes(Collection<String> types) {
     return clusterDAO.getLatestConfigurationsWithTypes(clusterId, getDesiredStackVersion(), types)
       .stream()
@@ -1448,6 +1518,26 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
+  public void addConfig(Config config, Long serviceId) {
+    if (config.getType() == null || config.getType().isEmpty()) {
+      throw new IllegalArgumentException("Config type cannot be empty");
+    }
+    clusterGlobalLock.writeLock().lock();
+    try {
+      if (!serviceConfigs.containsKey(serviceId)) {
+        ConcurrentMap<String, ConcurrentMap<String, Config>> allServiceConfigs = new ConcurrentHashMap<>();
+        serviceConfigs.put(serviceId, allServiceConfigs);
+      }
+      ConcurrentMap<String, ConcurrentMap<String, Config>> allServiceConfigs = serviceConfigs.get(serviceId);
+      allServiceConfigs.put(config.getType(), new ConcurrentHashMap<>());
+      allServiceConfigs.get(config.getType()).put(config.getTag(), config);
+      serviceConfigs.put(serviceId,allServiceConfigs);
+    } finally {
+        clusterGlobalLock.writeLock().unlock();
+    }
+  }
+
+  @Override
   public Collection<Config> getAllConfigs() {
     clusterGlobalLock.readLock().lock();
     try {
@@ -2855,10 +2945,30 @@ public class ClusterImpl implements Cluster {
     try {
       ClusterEntity clusterEntity = getClusterEntity();
       allConfigs.clear();
+      serviceConfigs.clear();
 
       if (!clusterEntity.getClusterConfigEntities().isEmpty()) {
         for (ClusterConfigEntity entity : clusterEntity.getClusterConfigEntities()) {
-
+          if (entity.getServiceId() != null) {
+            if(!serviceConfigs.containsKey(entity.getServiceId())) {
+              ConcurrentMap<String, ConcurrentMap<String, Config>> allServiceConfigs = new ConcurrentHashMap<>();
+              if (!allServiceConfigs.containsKey(entity.getType())) {
+                allServiceConfigs.put(entity.getType(), new ConcurrentHashMap<>());
+              }
+              Config config = configFactory.createExisting(this, entity);
+              allServiceConfigs.get(entity.getType()).put(entity.getTag(), config);
+              serviceConfigs.put(entity.getServiceId(), allServiceConfigs);
+            }
+            else {
+              ConcurrentMap<String, ConcurrentMap<String, Config>> allServiceConfigs = serviceConfigs.get(entity.getServiceId());
+              if (!allServiceConfigs.containsKey(entity.getType())) {
+                allServiceConfigs.put(entity.getType(), new ConcurrentHashMap<>());
+              }
+              Config config = configFactory.createExisting(this, entity);
+              allServiceConfigs.get(entity.getType()).put(entity.getTag(), config);
+              serviceConfigs.put(entity.getServiceId(), allServiceConfigs);
+            }
+          }
           if (!allConfigs.containsKey(entity.getType())) {
             allConfigs.put(entity.getType(), new ConcurrentHashMap<>());
           }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/state/configgroup/ConfigGroupImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/configgroup/ConfigGroupImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/configgroup/ConfigGroupImpl.java
index 33902af..2536d8b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/configgroup/ConfigGroupImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/configgroup/ConfigGroupImpl.java
@@ -435,8 +435,9 @@ public class ConfigGroupImpl implements ConfigGroup {
         if (clusterConfigEntity == null) {
           Service service = cluster.getService(serviceId);
 
+          //TODO check the serviceid = null for the right use case
           config = configFactory.createNew(service.getDesiredStackId(), cluster, config.getType(),
-              config.getTag(), config.getProperties(), config.getPropertiesAttributes());
+              config.getTag(), config.getProperties(), config.getPropertiesAttributes(), null);
 
           entry.setValue(config);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
index 5a2b92a..ebb0362 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/AbstractUpgradeCatalog.java
@@ -587,8 +587,9 @@ public abstract class AbstractUpgradeCatalog implements UpgradeCatalog {
             propertiesAttributes = Collections.emptyMap();
           }
 
+          //TODO check the serviceid = null for the right use case
           controller.createConfig(cluster, cluster.getDesiredStackVersion(), configType,
-              mergedProperties, newTag, propertiesAttributes);
+              mergedProperties, newTag, propertiesAttributes, null);
 
           Config baseConfig = cluster.getConfig(configType, newTag);
           if (baseConfig != null) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/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 e1e7c9e..5bc419e 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
@@ -99,9 +99,11 @@ CREATE TABLE clusterconfig (
   create_timestamp BIGINT NOT NULL,
   unmapped SMALLINT NOT NULL DEFAULT 0,
   selected_timestamp BIGINT NOT NULL DEFAULT 0,
+  service_id BIGINT,
   CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
   CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
   CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
   CONSTRAINT UQ_config_type_tag UNIQUE (version_tag, type_name, cluster_id),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/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 b438e69..b3bd221 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -118,9 +118,11 @@ CREATE TABLE clusterconfig (
   create_timestamp BIGINT NOT NULL,
   unmapped SMALLINT NOT NULL DEFAULT 0,
   selected_timestamp BIGINT NOT NULL DEFAULT 0,
+  service_id BIGINT,
   CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
   CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
   CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
   CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/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 aab7f95..f6294c7 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -99,9 +99,11 @@ CREATE TABLE clusterconfig (
   create_timestamp NUMBER(19) NOT NULL,
   unmapped SMALLINT DEFAULT 0 NOT NULL,
   selected_timestamp NUMBER(19) DEFAULT 0 NOT NULL,
+  service_id BIGINT,
   CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
   CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
   CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
   CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/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 8832818..e2bf5f3 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -117,9 +117,11 @@ CREATE TABLE clusterconfig (
   create_timestamp BIGINT NOT NULL,
   unmapped SMALLINT NOT NULL DEFAULT 0,
   selected_timestamp BIGINT NOT NULL DEFAULT 0,
+  service_id BIGINT,
   CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
   CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
   CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
   CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/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 135707b..1379112 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -98,9 +98,11 @@ CREATE TABLE clusterconfig (
   create_timestamp NUMERIC(19) NOT NULL,
   unmapped SMALLINT NOT NULL DEFAULT 0,
   selected_timestamp NUMERIC(19) NOT NULL DEFAULT 0,
+  service_id BIGINT,
   CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
   CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
   CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
   CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5301b3f5/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 7d93aad..5f03331 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -112,9 +112,11 @@ CREATE TABLE clusterconfig (
   create_timestamp BIGINT NOT NULL,
   unmapped SMALLINT NOT NULL DEFAULT 0,
   selected_timestamp BIGINT NOT NULL DEFAULT 0,
+  service_id BIGINT,
   CONSTRAINT PK_clusterconfig PRIMARY KEY CLUSTERED (config_id),
   CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
   CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
   CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 


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

Posted by be...@apache.org.
AMBARI-22345. Add service dependencies.Part 2.(vbrodetskyi)


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: 19513a85f12fb235a01cecce12e68f405785a177
Parents: 6a78e1a
Author: Vitaly Brodetskyi <vb...@hortonworks.com>
Authored: Mon Nov 13 19:45:46 2017 +0200
Committer: Vitaly Brodetskyi <vb...@hortonworks.com>
Committed: Mon Nov 13 19:45:46 2017 +0200

----------------------------------------------------------------------
 .../server/api/services/ServiceService.java     |  22 +--
 .../controller/ServiceDependencyRequest.java    |  28 +---
 .../ServiceDependencyResourceProvider.java      | 102 ++++++------
 .../server/orm/dao/ClusterServiceDAO.java       |  16 ++
 .../orm/entities/ClusterServiceEntity.java      |  29 ++--
 .../orm/entities/ServiceDependencyEntity.java   | 154 +++++++++++++++++++
 .../org/apache/ambari/server/state/Cluster.java |   5 +-
 .../org/apache/ambari/server/state/Service.java |   5 +
 .../apache/ambari/server/state/ServiceImpl.java | 110 ++++++++++---
 .../server/state/cluster/ClusterImpl.java       |  61 +++-----
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  |   8 +-
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |   7 +-
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |   7 +-
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |   7 +-
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |  19 ++-
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |   7 +-
 .../src/main/resources/META-INF/persistence.xml |   1 +
 17 files changed, 411 insertions(+), 177 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/19513a85/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 1f3332f..76782d5 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
@@ -316,10 +316,10 @@ public class ServiceService extends BaseService {
           responseContainer = RESPONSE_CONTAINER_LIST)
   @ApiImplicitParams({
           @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION,
-                  defaultValue = "ServiceInfo/service_group_name, ServiceInfo/service_name, ServiceInfo/cluster_name",
+                  defaultValue = "ServiceDependencyInfo/dependency_service_id, 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",
+                  defaultValue = "ServiceDependencyInfo/dependency_service_id.asc, 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),
@@ -336,7 +336,7 @@ public class ServiceService extends BaseService {
   }
 
   @GET
-  @Path("{serviceName}/dependencies/{dependencyServiceName}")
+  @Path("{serviceName}/dependencies/{dependencyServiceId}")
   @Produces(MediaType.TEXT_PLAIN)
   @ApiOperation(value = "Get the details of a service dependency",
           nickname = "ServiceService#getServiceDependency",
@@ -344,7 +344,7 @@ public class ServiceService extends BaseService {
           response = ServiceResponse.ServiceResponseSwagger.class,
           responseContainer = RESPONSE_CONTAINER_LIST)
   @ApiImplicitParams({
-          @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "ServiceInfo/*",
+          @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "ServiceDependencyInfo/*",
                   dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY)
   })
   @ApiResponses(value = {
@@ -354,9 +354,9 @@ public class ServiceService extends BaseService {
   })
   public Response getServiceDependency(String body, @Context HttpHeaders headers, @Context UriInfo ui,
                                               @PathParam("serviceName") String serviceName,
-                                              @PathParam("dependencyServiceName") String dependencyServiceName) {
+                                              @PathParam("dependencyServiceId") String dependencyServiceId) {
     return handleRequest(headers, body, ui, Request.Type.GET,
-            createServiceDependencyResource(m_clusterName, m_serviceGroupName, serviceName, dependencyServiceName));
+            createServiceDependencyResource(m_clusterName, m_serviceGroupName, serviceName, dependencyServiceId));
   }
 
 
@@ -386,7 +386,7 @@ public class ServiceService extends BaseService {
   }
 
   @DELETE
-  @Path("{serviceName}/dependencies")
+  @Path("{serviceName}/dependencies/{dependencyServiceId}")
   @Produces(MediaType.TEXT_PLAIN)
   @ApiOperation(value = "Deletes a service dependency",
           nickname = "ServiceService#deleteServiceDependency"
@@ -400,9 +400,9 @@ public class ServiceService extends BaseService {
   })
   public Response deleteServiceDependency(String body, @Context HttpHeaders headers, @Context UriInfo ui,
                                               @PathParam("serviceName") String serviceName,
-                                              @PathParam("dependencyServiceName") String dependencyServiceName) {
+                                              @PathParam("dependencyServiceId") String dependencyServiceId) {
     return handleRequest(headers, body, ui, Request.Type.DELETE,
-            createServiceDependencyResource(m_clusterName, m_serviceGroupName, serviceName, dependencyServiceName));
+            createServiceDependencyResource(m_clusterName, m_serviceGroupName, serviceName, dependencyServiceId));
   }
 
   /**
@@ -766,12 +766,12 @@ public class ServiceService extends BaseService {
     return createResource(Resource.Type.Artifact, mapIds);
   }
 
-  ResourceInstance createServiceDependencyResource(String clusterName, String serviceGroupName, String serviceName, String serviceDependencyName) {
+  ResourceInstance createServiceDependencyResource(String clusterName, String serviceGroupName, String serviceName, String serviceDependencyId) {
     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);
+    mapIds.put(Resource.Type.ServiceDependency, serviceDependencyId);
 
 
     return createResource(Resource.Type.ServiceDependency, mapIds);

http://git-wip-us.apache.org/repos/asf/ambari/blob/19513a85/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
index 97fe502..6cf46b4 100644
--- 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
@@ -22,16 +22,13 @@ public class ServiceDependencyRequest {
   private String clusterName;
   private String serviceName;
   private String serviceGroupName;
-  private String dependencyServiceName;
-  private String dependencyServiceGroupName;
+  private Long dependencyServiceId;
 
-  public ServiceDependencyRequest(String clusterName, String serviceName, String serviceGroupName,
-                                  String dependencyServiceName, String dependencyServiceGroupName) {
+  public ServiceDependencyRequest(String clusterName, String serviceName, String serviceGroupName, Long dependencyServiceId) {
     this.clusterName = clusterName;
     this.serviceName = serviceName;
     this.serviceGroupName = serviceGroupName;
-    this.dependencyServiceName = dependencyServiceName;
-    this.dependencyServiceGroupName = dependencyServiceGroupName;
+    this.dependencyServiceId = dependencyServiceId;
   }
 
   public String getClusterName() {
@@ -42,12 +39,12 @@ public class ServiceDependencyRequest {
     this.clusterName = clusterName;
   }
 
-  public String getDependencyServiceName() {
-    return dependencyServiceName;
+  public Long getDependencyServiceId() {
+    return dependencyServiceId;
   }
 
-  public void setDependencyServiceName(String dependencyServiceName) {
-    this.dependencyServiceName = dependencyServiceName;
+  public void setDependencyServiceId(Long dependencyServiceId) {
+    this.dependencyServiceId = dependencyServiceId;
   }
 
   public String getServiceGroupName() {
@@ -66,22 +63,13 @@ public class ServiceDependencyRequest {
     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 + '\'' +
+            ", dependencyServiceId=" + dependencyServiceId +
             '}';
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/19513a85/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
index d8d89da..dd48875 100644
--- 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
@@ -28,13 +28,11 @@ 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;
@@ -62,7 +60,6 @@ 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;
 
@@ -93,7 +90,7 @@ public class ServiceDependencyResourceProvider extends AbstractControllerResourc
                   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}));
+                  SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_ID_PROPERTY_ID}));
 
   private static Gson gson = StageUtils.getGson();
 
@@ -126,16 +123,11 @@ public class ServiceDependencyResourceProvider extends AbstractControllerResourc
     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);
+    KEY_PROPERTY_IDS.put(Resource.Type.ServiceDependency, SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_ID_PROPERTY_ID);
   }
 
   private Clusters clusters;
 
-  /**
-   * kerberos helper
-   */
-  @Inject
-  private KerberosHelper kerberosHelper;
 
   // ----- Constructors ----------------------------------------------------
 
@@ -291,7 +283,7 @@ public class ServiceDependencyResourceProvider extends AbstractControllerResourc
     notifyDelete(Resource.Type.ServiceDependency, predicate);
     for(ServiceDependencyRequest svgReq : requests) {
       deleteStatusMetaData.addDeletedKey("cluster_name: " + svgReq.getClusterName() + ", " + " service_name: " + svgReq.getServiceName()
-              + " dependency_service_name: " + svgReq.getDependencyServiceName());
+              + " dependency_service_ID: " + svgReq.getDependencyServiceId());
     }
     return getRequestStatus(null, null, deleteStatusMetaData);
   }
@@ -327,10 +319,9 @@ public class ServiceDependencyResourceProvider extends AbstractControllerResourc
     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);
+    String strdependencyServiceId = (String) properties.get(SERVICE_DEPENDENCY_DEPENDENCY_SERVICE_ID_PROPERTY_ID);
+    Long dependencyServiceId = strdependencyServiceId == null ? null : Long.valueOf(strdependencyServiceId);
+    ServiceDependencyRequest svcRequest = new ServiceDependencyRequest(clusterName, serviceName, serviceGroupName, dependencyServiceId);
     return svcRequest;
   }
 
@@ -353,9 +344,8 @@ public class ServiceDependencyResourceProvider extends AbstractControllerResourc
       Cluster cluster = clusters.getCluster(request.getClusterName());
 
 
-      Service updatedService = cluster.addDependencyToService(request.getServiceGroupName(), request.getServiceName(), request.getDependencyServiceGroupName(),
-              request.getDependencyServiceName());
-      createdServiceDependencies.addAll(updatedService.getServiceDependencyResponses());   //!!!!!
+      Service updatedService = cluster.addDependencyToService(request.getServiceGroupName(), request.getServiceName(), request.getDependencyServiceId());
+      createdServiceDependencies.addAll(updatedService.getServiceDependencyResponses());
     }
     return createdServiceDependencies;
   }
@@ -403,7 +393,8 @@ public class ServiceDependencyResourceProvider extends AbstractControllerResourc
       Collection<Service> services = cluster.getServices().values();
       Service currentService = null;
       for (Service service : services) {
-        if (service.getServiceGroupId() == serviceGroup.getServiceGroupId()) {
+        if (service.getServiceGroupId() == serviceGroup.getServiceGroupId() &&
+                service.getName().equals(request.getServiceName())) {
           currentService = service;
           break;
         }
@@ -416,7 +407,6 @@ public class ServiceDependencyResourceProvider extends AbstractControllerResourc
   }
 
 
-  // Delete services based on the given set of requests
   protected void deleteServiceDependencies(Set<ServiceDependencyRequest> request)
           throws AmbariException, AuthorizationException {
 
@@ -437,7 +427,17 @@ public class ServiceDependencyResourceProvider extends AbstractControllerResourc
         }
 
         Cluster cluster = clusters.getCluster(serviceDependencyRequest.getClusterName());
-        Service service = cluster.getService(serviceDependencyRequest.getServiceName());
+        ServiceGroup serviceGroup = cluster.getServiceGroup(serviceDependencyRequest.getServiceGroupName());
+        Service service = null;
+
+        for (Service srv : cluster.getServicesById().values()) {
+          if (srv.getName().equals(serviceDependencyRequest.getServiceName()) &&
+                  srv.getServiceGroupName().equals(serviceDependencyRequest.getServiceGroupName())) {
+            service = srv;
+            break;
+          }
+        }
+
         List<ServiceKey> serviceKeys = service.getServiceDependencies();
         if (serviceKeys == null || serviceKeys.isEmpty()) {
           throw new AmbariException("Service name " + serviceDependencyRequest.getServiceName() + " has no" +
@@ -445,17 +445,17 @@ public class ServiceDependencyResourceProvider extends AbstractControllerResourc
         } else {
           boolean dependencyAvailable = false;
           for (ServiceKey serviceKey : serviceKeys) {
-            if (serviceKey.getServiceName().equals(serviceDependencyRequest.getDependencyServiceName())) {
+            if (serviceKey.getServiceId() == serviceDependencyRequest.getDependencyServiceId()) {
               dependencyAvailable = true;
             }
           }
           if (!dependencyAvailable) {
             throw new AmbariException("Servcie name " + serviceDependencyRequest.getServiceName() + " has no" +
-                    "dependency " + serviceDependencyRequest.getDependencyServiceName() + ", so nothing to remove.");
+                    "dependency service with id" + serviceDependencyRequest.getDependencyServiceId() + ", so nothing to remove.");
           }
 
           service.getCluster().removeDependencyFromService(serviceDependencyRequest.getServiceGroupName(), serviceDependencyRequest.getServiceName(),
-                  serviceDependencyRequest.getDependencyServiceGroupName(), serviceDependencyRequest.getDependencyServiceName());
+                  serviceDependencyRequest.getDependencyServiceId());
         }
       }
     }
@@ -470,24 +470,34 @@ public class ServiceDependencyResourceProvider extends AbstractControllerResourc
     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);
-
+      final String serviceName = request.getServiceName();
+      final Long dependencyServiceId = request.getDependencyServiceId();
+
+      Validate.notNull(clusterName, "Cluster name should be provided when creating a service dependency");
+      Validate.notNull(serviceGroupName, "Service group name should be provided when creating a service dependency");
+      Validate.notNull(serviceName, "Service name should be provided when creating a service dependency");
+      Validate.notNull(dependencyServiceId, "Dependency service id should be provided when creating a service dependency");
+
+      //throws cluster not found exception
+      Cluster cluster = clusters.getCluster(clusterName);
+      //throws service group not found exception
+      ServiceGroup serviceGroup = cluster.getServiceGroup(serviceGroupName);
+      //throws service not found exception
+      Service service = cluster.getService(serviceName);
+
+      boolean dependencyServiceAvailable = false;
+      for (Cluster cl : clusters.getClusters().values()) {
+        if (cl.getServicesById().containsKey(dependencyServiceId)) {
+          dependencyServiceAvailable = true;
+        }
       }
 
-      Validate.notEmpty(serviceGroupName, "Service group name should be provided when adding a service group dependency");
+      if (!dependencyServiceAvailable) {
+        throw new AmbariException("There is no service with id=" + dependencyServiceId);
+      }
 
       if (LOG.isDebugEnabled()) {
-        LOG.debug("Received a createServiceGroupDependency request" +
+        LOG.debug("Received a createServiceDependency request" +
                 ", clusterName=" + clusterName + ", serviceGroupName=" + serviceGroupName + ", request=" + request);
       }
 
@@ -497,15 +507,15 @@ public class ServiceDependencyResourceProvider extends AbstractControllerResourc
       }
 
 
-      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);
-      }
-
-
+      if (service.getServiceDependencies() != null) {
+        for (ServiceKey sk : service.getServiceDependencies()) {
+          if (sk.getServiceId() == dependencyServiceId) {
+            throw new AmbariException("Service with id=" + dependencyServiceId + " already added to dependencies for " +
+                    serviceName + " service");
+          }
+        }
 
+      }
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/19513a85/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
index c7032aa..5bb1da7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
@@ -27,6 +27,7 @@ import javax.persistence.TypedQuery;
 import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntityPK;
+import org.apache.ambari.server.orm.entities.ServiceDependencyEntity;
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
@@ -92,16 +93,31 @@ public class ClusterServiceDAO {
   }
 
   @Transactional
+  public void createServiceDependency(ServiceDependencyEntity serviceDependencyEntity) {
+    entityManagerProvider.get().persist(serviceDependencyEntity);
+  }
+
+  @Transactional
   public ClusterServiceEntity merge(ClusterServiceEntity clusterServiceEntity) {
     return entityManagerProvider.get().merge(clusterServiceEntity);
   }
 
   @Transactional
+  public ServiceDependencyEntity mergeServiceDependency(ServiceDependencyEntity serviceDependencyEntity) {
+    return entityManagerProvider.get().merge(serviceDependencyEntity);
+  }
+
+  @Transactional
   public void remove(ClusterServiceEntity clusterServiceEntity) {
     entityManagerProvider.get().remove(merge(clusterServiceEntity));
   }
 
   @Transactional
+  public void removeServiceDependency(ServiceDependencyEntity serviceDependencyEntity) {
+    entityManagerProvider.get().remove(mergeServiceDependency(serviceDependencyEntity));
+  }
+
+  @Transactional
   public void removeByPK(ClusterServiceEntityPK clusterServiceEntityPK) {
     ClusterServiceEntity entity = findByPK(clusterServiceEntityPK);
     entityManagerProvider.get().remove(entity);

http://git-wip-us.apache.org/repos/asf/ambari/blob/19513a85/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 e5a1618..843aa1e 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
@@ -30,8 +30,6 @@ 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;
@@ -105,20 +103,11 @@ 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;
+  @OneToMany(mappedBy="service")
+  private List<ServiceDependencyEntity> serviceDependencies;
+
+  @OneToMany(mappedBy="serviceDependency")
+  private List<ServiceDependencyEntity> dependencies;
 
   public Long getClusterId() {
     return clusterId;
@@ -168,19 +157,19 @@ public class ClusterServiceEntity {
     this.serviceEnabled = serviceEnabled;
   }
 
-  public List<ClusterServiceEntity> getDependencies() {
+  public List<ServiceDependencyEntity> getDependencies() {
     return dependencies;
   }
 
-  public void setDependencies(List<ClusterServiceEntity> dependencies) {
+  public void setDependencies(List<ServiceDependencyEntity> dependencies) {
     this.dependencies = dependencies;
   }
 
-  public List<ClusterServiceEntity> getServiceDependencies() {
+  public List<ServiceDependencyEntity> getServiceDependencies() {
     return serviceDependencies;
   }
 
-  public void setServiceDependencies(List<ClusterServiceEntity> serviceDependencies) {
+  public void setServiceDependencies(List<ServiceDependencyEntity> serviceDependencies) {
     this.serviceDependencies = serviceDependencies;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/19513a85/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceDependencyEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceDependencyEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceDependencyEntity.java
new file mode 100644
index 0000000..47dc435
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceDependencyEntity.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.orm.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+@Entity
+@Table(name = "servicedependencies")
+@TableGenerator(name = "service_dependency_id_generator",
+        table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value"
+        , pkColumnValue = "service_dependency_id_seq"
+        , initialValue = 1
+)
+public class ServiceDependencyEntity {
+
+  @Id
+  @Column(name = "id", nullable = false, insertable = true, updatable = true)
+  @GeneratedValue(strategy = GenerationType.TABLE, generator = "service_dependency_id_generator")
+  private Long serviceDependencyId;
+
+  @Column(name = "service_id", nullable = false, insertable = false, updatable = false)
+  private long serviceId;
+
+  @Column(name = "service_cluster_id", nullable = false, insertable = false, updatable = false)
+  private long serviceClusterId;
+
+  @Column(name = "service_group_id", nullable = false, insertable = false, updatable = false)
+  private long serviceGroupId;
+
+  @Column(name = "dependent_service_id", nullable = false, insertable = false, updatable = false)
+  private long dependentServiceId;
+
+  @Column(name = "dependent_service_group_id", nullable = false, insertable = false, updatable = false)
+  private long dependentServiceGroupId;
+
+  @Column(name = "dependent_service_cluster_id", nullable = false, insertable = false, updatable = false)
+  private long dependentServiceClusterId;
+
+  @ManyToOne
+  @JoinColumns({
+          @JoinColumn(name = "service_id", referencedColumnName = "id", nullable = false),
+          @JoinColumn(name = "service_cluster_id", referencedColumnName = "cluster_id", nullable = false),
+          @JoinColumn(name = "service_group_id", referencedColumnName = "service_group_id", nullable = false) })
+  private ClusterServiceEntity service;
+
+  @ManyToOne
+  @JoinColumns({
+          @JoinColumn(name = "dependent_service_id", referencedColumnName = "id", nullable = false),
+          @JoinColumn(name = "dependent_service_cluster_id", referencedColumnName = "cluster_id", nullable = false),
+          @JoinColumn(name = "dependent_service_group_id", referencedColumnName = "service_group_id", nullable = false) })
+  private ClusterServiceEntity serviceDependency;
+
+  public Long getServiceDependencyId() {
+    return serviceDependencyId;
+  }
+
+  public long getDependentServiceGroupId() {
+    return dependentServiceGroupId;
+  }
+
+  public void setDependentServiceGroupId(long dependentServiceGroupId) {
+    this.dependentServiceGroupId = dependentServiceGroupId;
+  }
+
+  public long getDependentServiceId() {
+    return dependentServiceId;
+  }
+
+  public void setDependentServiceId(long dependentServiceId) {
+    this.dependentServiceId = dependentServiceId;
+  }
+
+  public long getDependentServiceClusterId() {
+    return dependentServiceClusterId;
+  }
+
+  public void setDependentServiceClusterId(long dependentServiceClusterId) {
+    this.dependentServiceClusterId = dependentServiceClusterId;
+  }
+
+  public ClusterServiceEntity getService() {
+    return service;
+  }
+
+  public void setService(ClusterServiceEntity service) {
+    this.service = service;
+  }
+
+  public ClusterServiceEntity getServiceDependency() {
+    return serviceDependency;
+  }
+
+  public void setServiceDependency(ClusterServiceEntity serviceDependency) {
+    this.serviceDependency = serviceDependency;
+  }
+
+  public long getServiceGroupId() {
+    return serviceGroupId;
+  }
+
+  public void setServiceGroupId(long serviceGroupId) {
+    this.serviceGroupId = serviceGroupId;
+  }
+
+  public long getServiceId() {
+    return serviceId;
+  }
+
+  public void setServiceId(long serviceId) {
+    this.serviceId = serviceId;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (!(o instanceof ServiceDependencyEntity)) return false;
+
+    ServiceDependencyEntity that = (ServiceDependencyEntity) o;
+
+    if (serviceDependencyId != null ? !serviceDependencyId.equals(that.serviceDependencyId) : that.serviceDependencyId != null)
+      return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return serviceDependencyId != null ? serviceDependencyId.hashCode() : 0;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/19513a85/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 2afb428..c8768dd 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
@@ -75,10 +75,9 @@ public interface Cluster {
                      RepositoryVersionEntity repositoryVersion) throws AmbariException;
 
   Service addDependencyToService(String  serviceGroupName, String serviceName,
-                                        String dependencyServiceGroupName, String dependencyServiceName);
+                                        Long dependencyServiceId) throws AmbariException;
 
-  Service removeDependencyFromService(String  serviceGroupName, String serviceName, String dependencyServiceGroupName,
-                                      String dependencyServiceName);
+  Service removeDependencyFromService(String  serviceGroupName, String serviceName, Long dependencyServiceId);
 
   /**
    * Add service group to the cluster

http://git-wip-us.apache.org/repos/asf/ambari/blob/19513a85/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 c4c2d84..0ba80cc 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
@@ -26,6 +26,7 @@ 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.ClusterServiceEntity;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 
 public interface Service {
@@ -88,6 +89,10 @@ public interface Service {
 
   boolean isClientOnlyService();
 
+  ClusterServiceEntity removeDependencyService(Long dependencyServiceId);
+
+  ClusterServiceEntity addDependencyService(Long dependencyServiceId) throws AmbariException;
+
   void delete() throws AmbariException;
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/19513a85/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 bfb04be..c6b187a 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
@@ -53,6 +53,7 @@ import org.apache.ambari.server.orm.entities.ClusterServiceEntityPK;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.ServiceConfigEntity;
+import org.apache.ambari.server.orm.entities.ServiceDependencyEntity;
 import org.apache.ambari.server.orm.entities.ServiceDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.ServiceDesiredStateEntityPK;
 import org.apache.ambari.server.orm.entities.ServiceGroupEntity;
@@ -85,6 +86,9 @@ public class ServiceImpl implements Service {
   private AmbariMetaInfo ambariMetaInfo;
 
   @Inject
+  private Clusters clusters;
+
+  @Inject
   private ServiceConfigDAO serviceConfigDAO;
 
   private final ClusterServiceDAO clusterServiceDAO;
@@ -144,19 +148,27 @@ public class ServiceImpl implements Service {
 
     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()));
+
+        Cluster dependencyCluster = null;
+
+        for (Cluster cl : clusters.getClusters().values()) {
+          if (cl.getServicesById().containsKey(serviceKey.getServiceId())) {
+            dependencyCluster = cl;
+
             break;
           }
         }
 
+
+        ClusterServiceEntity dependencyServiceEntity = clusterServiceDAO.findById(serviceKey.getClusterId(), serviceKey.getServiceGroupId(), serviceKey.getServiceId());
+        ServiceDependencyEntity serviceDependencyEntity = new ServiceDependencyEntity();
+        serviceDependencyEntity.setService(serviceEntity);
+        serviceDependencyEntity.setServiceDependency(dependencyServiceEntity);
+
+        clusterServiceDAO.createServiceDependency(serviceDependencyEntity);
+
+        serviceEntity.getServiceDependencies().add(serviceDependencyEntity);
+
       }
     }
 
@@ -235,6 +247,8 @@ public class ServiceImpl implements Service {
   }
 
 
+
+
   /***
    * Refresh Service info due to current stack
    * @throws AmbariException
@@ -356,38 +370,39 @@ public class ServiceImpl implements Service {
     return responses;
   }
 
-  public List<ServiceKey> getServiceDependencies(List<ClusterServiceEntity> clusterServiceEntities) throws AmbariException {
+  public List<ServiceKey> getServiceDependencies(List<ServiceDependencyEntity> serviceDependencyEntities) throws AmbariException {
     List<ServiceKey> serviceDependenciesList = new ArrayList<>();
 
-    if (clusterServiceEntities != null) {
-      for (ClusterServiceEntity cse : clusterServiceEntities) {
+    if (serviceDependencyEntities != null) {
+      for (ServiceDependencyEntity sde : serviceDependencyEntities) {
         ServiceKey serviceKey = new ServiceKey();
+        ClusterServiceEntity dependencyService = sde.getServiceDependency();
         String clusterName = "";
         Long clusterId = null;
-        if (cse.getClusterId() == cluster.getClusterId()) {
+        if (dependencyService.getClusterId() == cluster.getClusterId()) {
           clusterName = cluster.getClusterName();
           clusterId = cluster.getClusterId();
         } else {
-          ClusterEntity clusterEntity = clusterDAO.findById(cse.getClusterId());
+          ClusterEntity clusterEntity = clusterDAO.findById(dependencyService.getClusterId());
           if (clusterEntity != null) {
             clusterName = clusterEntity.getClusterName();
             clusterId = clusterEntity.getClusterId();
           } else {
-            LOG.error("Unable to get cluster id for service " + cse.getServiceName());
+            LOG.error("Unable to get cluster id for service " + dependencyService.getServiceName());
           }
         }
 
 
         Cluster dependencyCluster = cluster;
-        ServiceGroup dependencyServiceGroup = dependencyCluster.getServiceGroup(cse.getServiceGroupId());
+        ServiceGroup dependencyServiceGroup = dependencyCluster.getServiceGroup(dependencyService.getServiceGroupId());
 
 
         serviceKey.setServiceGroupName(dependencyServiceGroup.getServiceGroupName());
         serviceKey.setServiceGroupId(dependencyServiceGroup.getServiceGroupId());
         serviceKey.setClusterName(clusterName);
         serviceKey.setClusterId(clusterId);
-        serviceKey.setServiceName(cse.getServiceName());
-        serviceKey.setServiceId(cse.getServiceId());
+        serviceKey.setServiceName(dependencyService.getServiceName());
+        serviceKey.setServiceId(dependencyService.getServiceId());
         serviceDependenciesList.add(serviceKey);
       }
     }
@@ -567,6 +582,65 @@ public class ServiceImpl implements Service {
   }
 
   @Override
+  public ClusterServiceEntity removeDependencyService(Long dependencyServiceId) {
+    ClusterServiceEntity currentServiceEntity = clusterServiceDAO.findById(getClusterId(), getServiceGroupId(), getServiceId());
+
+    ServiceDependencyEntity dependencyEntityToRemove = null;
+    if (currentServiceEntity.getServiceDependencies() != null) {
+      for (ServiceDependencyEntity sde : currentServiceEntity.getServiceDependencies()) {
+        if (sde.getServiceDependency().getServiceId() == dependencyServiceId) {
+          dependencyEntityToRemove = sde;
+          break;
+        }
+      }
+    }
+
+    currentServiceEntity.getServiceDependencies().remove(dependencyEntityToRemove);
+    ClusterServiceEntity updatedServiceEntity = removeServiceDependencyEntity(dependencyEntityToRemove, currentServiceEntity);
+    currentServiceEntity.getServiceDependencies().remove(dependencyEntityToRemove);
+
+    return updatedServiceEntity;
+  }
+
+  @Transactional
+  protected ClusterServiceEntity removeServiceDependencyEntity(ServiceDependencyEntity dependencyEntityToRemove,
+                                                               ClusterServiceEntity currentServiceEntity) {
+    clusterServiceDAO.removeServiceDependency(dependencyEntityToRemove);
+    ClusterServiceEntity updatedServiceEntity = clusterServiceDAO.merge(currentServiceEntity);
+    return updatedServiceEntity;
+  }
+
+  @Override
+  public ClusterServiceEntity addDependencyService(Long dependencyServiceId) throws AmbariException {
+    Service dependentService = null;
+    for (Cluster cl : clusters.getClusters().values()) {
+      if (cl.getServicesById().containsKey(dependencyServiceId)) {
+        dependentService = cl.getService(dependencyServiceId);
+        break;
+      }
+    }
+
+    ClusterServiceEntity currentServiceEntity = clusterServiceDAO.findById(getClusterId(), getServiceGroupId(), getServiceId());
+    ClusterServiceEntity dependentServiceEntity = clusterServiceDAO.findById(dependentService.getClusterId(),
+            dependentService.getServiceGroupId(), dependentService.getServiceId());
+
+    ServiceDependencyEntity newServiceDependency = new ServiceDependencyEntity();
+    newServiceDependency.setService(currentServiceEntity);
+    newServiceDependency.setServiceDependency(dependentServiceEntity);
+
+    return addServiceDependencyEntity(newServiceDependency, currentServiceEntity);
+  }
+
+  @Transactional
+  protected ClusterServiceEntity addServiceDependencyEntity(ServiceDependencyEntity newServiceDependency,
+                                                               ClusterServiceEntity currentServiceEntity) {
+    clusterServiceDAO.createServiceDependency(newServiceDependency);
+    currentServiceEntity.getServiceDependencies().add(newServiceDependency);
+    ClusterServiceEntity updatedServiceEntity = clusterServiceDAO.merge(currentServiceEntity);
+    return updatedServiceEntity;
+  }
+
+  @Override
   public void debugDump(StringBuilder sb) {
     sb.append("Service={ serviceName=").append(getName())
       .append(", serviceType=").append(getServiceType())

http://git-wip-us.apache.org/repos/asf/ambari/blob/19513a85/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 4a8cdee..e3b5d6e 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
@@ -939,36 +939,27 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
-  public Service addDependencyToService(String  serviceGroupName, String serviceName, String dependencyServiceGroupName,
-                                        String dependencyServiceName) {
+  public Service addDependencyToService(String  serviceGroupName, String serviceName, Long dependencyServiceId) throws AmbariException {
     Service currentService = null;
-    Service dependentService = null;
-    for (Service service : services.values()) {
-
+    for (Service service : getServicesById().values()) {
       if (service.getName().equals(serviceName) && service.getServiceGroupName().equals(serviceGroupName)) {
         currentService = service;
       }
-
-      if (service.getName().equals(dependencyServiceName) && service.getServiceGroupName().equals(dependencyServiceGroupName)) {
-        dependentService = service;
-      }
     }
 
+    ClusterServiceEntity updatedServiceEntity = null;
     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);
+      updatedServiceEntity = currentService.addDependencyService(dependencyServiceId);
+
+
+      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.
+      LOG.error("Service group " + currentService.getServiceGroupName() + " was not found.");
+      e.printStackTrace();
     } finally {
       clusterGlobalLock.writeLock().unlock();
     }
@@ -977,40 +968,28 @@ public class ClusterImpl implements Cluster {
   }
 
   @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;
-      }
-
-    }
-
+  public Service removeDependencyFromService(String  serviceGroupName, String serviceName, Long dependencyServiceId) {
     Service updatedService = null;
+    Service currentService = null;
     clusterGlobalLock.writeLock().lock();
     try {
-      ClusterServiceEntity currentServiceEntity = clusterServiceDAO.findById(getClusterId(),
-              currentService.getServiceGroupId(), currentService.getServiceId());
 
+      for (Service service : getServicesById().values()) {
 
-
-      ClusterServiceEntity serviceEntityToRemove = null;
-      for (ClusterServiceEntity cse : currentServiceEntity.getServiceDependencies()) {
-        if (cse.getServiceName().equals(dependencyServiceName) /*&& cse.getClusterServiceGroupEntity().getServiceGroupName().equals(dependencyServiceGroupName)*/) {
-          serviceEntityToRemove = cse;
-          break;
+        if (service.getName().equals(serviceName) && service.getServiceGroupName().equals(serviceGroupName)) {
+          currentService = service;
         }
+
       }
-      currentServiceEntity.getServiceDependencies().remove(serviceEntityToRemove);
-      ClusterServiceEntity updatedServiceEntity = clusterServiceDAO.merge(currentServiceEntity);
+
+      ClusterServiceEntity updatedServiceEntity = currentService.removeDependencyService(dependencyServiceId);
+
       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.
+      LOG.error("Service group " + currentService.getServiceGroupName() + " was not found.");
+      e.printStackTrace();
     } finally {
       clusterGlobalLock.writeLock().unlock();
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/19513a85/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 06f3387..0ddade4 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
@@ -183,14 +183,16 @@ CREATE TABLE clusterconfig (
 
 
 CREATE TABLE servicedependencies (
+  id BIGINT NOT NULL,
   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 PK_servicedependencies PRIMARY KEY (id),
+  CONSTRAINT UQ_servicedependencies UNIQUE (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 serviceconfig (
@@ -1162,6 +1164,8 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value)
   UNION ALL
   SELECT 'service_group_dependency_id_seq', 1 FROM SYSIBM.SYSDUMMY1
   UNION ALL
+  SELECT 'service_dependency_id_seq', 1 FROM SYSIBM.SYSDUMMY1
+  UNION ALL
   SELECT 'service_id_seq', 1 FROM SYSIBM.SYSDUMMY1
   UNION ALL
   SELECT 'host_id_seq', 0 FROM SYSIBM.SYSDUMMY1

http://git-wip-us.apache.org/repos/asf/ambari/blob/19513a85/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 e204aab..c6a6e98 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -202,14 +202,16 @@ CREATE TABLE clusterconfig (
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 
 CREATE TABLE servicedependencies (
+  id BIGINT NOT NULL,
   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 PK_servicedependencies PRIMARY KEY (id),
+  CONSTRAINT UQ_servicedependencies UNIQUE (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 serviceconfig (
@@ -1172,6 +1174,7 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) VALUES
   ('cluster_id_seq', 1),
   ('cluster_setting_id_seq', 1),
   ('service_group_id_seq', 1),
+  ('service_dependency_id_seq', 1),
   ('service_group_dependency_id_seq', 1),
   ('service_id_seq', 1),
   ('host_id_seq', 0),

http://git-wip-us.apache.org/repos/asf/ambari/blob/19513a85/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 4cd4ba4..ece6ef6 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -182,14 +182,16 @@ CREATE TABLE clusterconfig (
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 
 CREATE TABLE servicedependencies (
+  id NUMBER(19) NOT NULL,
   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 PK_servicedependencies PRIMARY KEY (id),
+  CONSTRAINT UQ_servicedependencies UNIQUE (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 serviceconfig (
@@ -1151,6 +1153,7 @@ CREATE INDEX idx_alert_notice_state on alert_notice(notify_state);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('host_role_command_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('cluster_setting_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_group_id_seq', 1);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_dependency_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_group_dependency_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('user_id_seq', 1);

http://git-wip-us.apache.org/repos/asf/ambari/blob/19513a85/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 1c296ee..14e8e6e 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -183,14 +183,16 @@ CREATE TABLE clusterconfig (
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 
 CREATE TABLE servicedependencies (
+  id BIGINT NOT NULL,
   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 PK_servicedependencies PRIMARY KEY (id),
+  CONSTRAINT UQ_servicedependencies UNIQUE (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 serviceconfig (
@@ -1158,6 +1160,7 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value) VALUES
   ('service_group_id_seq', 1),
   ('service_group_dependency_id_seq', 1),
   ('service_id_seq', 1),
+  ('service_dependency_id_seq', 1),
   ('host_id_seq', 0),
   ('user_id_seq', 2),
   ('group_id_seq', 1),

http://git-wip-us.apache.org/repos/asf/ambari/blob/19513a85/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 7dfe929..994d1e7 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -181,14 +181,16 @@ CREATE TABLE clusterconfig (
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 
 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));
+  id NUMBER(19) NOT NULL,
+  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 (id),
+  CONSTRAINT UQ_servicedependencies UNIQUE (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 serviceconfig (
@@ -1150,6 +1152,7 @@ CREATE INDEX idx_alert_notice_state on alert_notice(notify_state);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('cluster_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('cluster_setting_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_group_id_seq', 1);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_dependency_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_group_dependency_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('host_id_seq', 0);

http://git-wip-us.apache.org/repos/asf/ambari/blob/19513a85/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 7ad4251..a399bed 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -195,14 +195,16 @@ CREATE TABLE clusterconfig (
   CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
 
 CREATE TABLE servicedependencies (
+  id BIGINT NOT NULL,
   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 PK_servicedependencies PRIMARY KEY (id),
+  CONSTRAINT UQ_servicedependencies UNIQUE (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 serviceconfig (
@@ -1176,6 +1178,7 @@ BEGIN TRANSACTION
     ('cluster_id_seq', 1),
     ('cluster_setting_id_seq', 1),
     ('service_group_id_seq', 1),
+    ('service_dependency_id_seq', 1),
     ('service_group_dependency_id_seq', 1),
     ('service_id_seq', 1),
     ('host_id_seq', 0),

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


[12/17] ambari git commit: AMBARI-22325. Set stacks in blueprint (adoroszlai)

Posted by be...@apache.org.
AMBARI-22325. Set stacks in blueprint (adoroszlai)


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: c9e2f6e6fd808b538c4f1228e14fcd0c219cec62
Parents: 0c5232a
Author: Attila Doroszlai <ad...@hortonworks.com>
Authored: Mon Nov 13 11:24:47 2017 +0100
Committer: Balazs Bence Sari <be...@apache.org>
Committed: Tue Nov 14 11:31:16 2017 +0100

----------------------------------------------------------------------
 .../server/controller/StackV2Factory.java       |  3 +--
 .../server/topology/BlueprintV2Factory.java     | 23 ++++++++++----------
 2 files changed, 12 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/c9e2f6e6/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2Factory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2Factory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2Factory.java
index 0735171..c7113ae 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2Factory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2Factory.java
@@ -52,8 +52,7 @@ public class StackV2Factory {
     return create(stack.getStackName(), stack.getStackVersion());
   }
 
-  public StackV2 create(String stackId) throws AmbariException {
-    StackId id = new StackId(stackId);
+  public StackV2 create(StackId id) throws AmbariException {
     return create(id.getStackName(), id.getStackVersion());
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c9e2f6e6/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
index 4f22aea..9870dcb 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Optional;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import org.apache.ambari.server.AmbariException;
@@ -102,27 +103,29 @@ public class BlueprintV2Factory {
   public BlueprintV2 convertFromJson(String json) throws IOException {
     BlueprintImplV2 blueprintV2 = createObjectMapper().readValue(json, BlueprintImplV2.class);
     blueprintV2.postDeserialization();
-    blueprintV2.setStacks(
-      blueprintV2.getStackIds().stream().collect(Collectors.toMap(
-        StackId::new,
-        stackId -> parseStack(new StackId(stackId))
-      ))
-    );
+    updateStacks(blueprintV2);
     return blueprintV2;
   }
 
+  private void updateStacks(BlueprintImplV2 blueprintV2) {
+    Map<StackId, StackV2> stacks = blueprintV2.getStackIds().stream()
+      .map(StackId::new)
+      .collect(Collectors.toMap(Function.identity(), this::parseStack));
+    blueprintV2.setStacks(stacks);
+  }
 
   public BlueprintV2 convertFromEntity(BlueprintV2Entity blueprintEntity) throws IOException {
     return convertFromJson(blueprintEntity.getContent());
   }
 
+  @SuppressWarnings("unchecked")
   public Map<String, Object> convertToMap(BlueprintV2Entity entity) throws IOException {
     return createObjectMapper().readValue(entity.getContent(), HashMap.class);
   }
 
   private StackV2 parseStack(StackId stackId) {
     try {
-      return stackFactory.create(stackId.getStackName(), stackId.getStackVersion());
+      return stackFactory.create(stackId);
     } catch (AmbariException e) {
       throw new IllegalArgumentException(
         String.format("Unable to parse stack. name=%s, version=%s", stackId.getStackName(), stackId.getStackVersion()),
@@ -156,7 +159,6 @@ public class BlueprintV2Factory {
    * @param securityConfiguration security related properties
    * @return new blueprint entity
    */
-  @SuppressWarnings("unchecked")
   public BlueprintV2 createBlueprint(Map<String, Object> properties, SecurityConfiguration securityConfiguration) throws NoSuchStackException, IOException {
     String name = String.valueOf(properties.get(BLUEPRINT_NAME_PROPERTY_ID));
     // String.valueOf() will return "null" if value is null
@@ -168,10 +170,7 @@ public class BlueprintV2Factory {
     String json = om.writeValueAsString(properties);
     BlueprintImplV2 blueprint = om.readValue(json, BlueprintImplV2.class);
     blueprint.postDeserialization();
-    Map<String, StackV2> stacks = new HashMap<>();
-    for (String stackId: blueprint.getStackIds()) {
-      stacks.put(stackId, stackFactory.create(stackId));
-    }
+    updateStacks(blueprint);
     blueprint.setSecurityConfiguration(securityConfiguration);
     return blueprint;
   }


[08/17] ambari git commit: AMBARI-22432 : Getting NPE when trying to get services information from service group (mradhakrishnan)

Posted by be...@apache.org.
AMBARI-22432 : Getting NPE when trying to get services information from service group (mradhakrishnan)


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: 35d704cb3aa12fcc887821ee7ccb83e11f3c878b
Parents: 19513a8
Author: Madhuvanthi Radhakrishnan <mr...@hortonworks.com>
Authored: Mon Nov 13 15:26:12 2017 -0800
Committer: Madhuvanthi Radhakrishnan <mr...@hortonworks.com>
Committed: Mon Nov 13 15:26:12 2017 -0800

----------------------------------------------------------------------
 .../AmbariManagementControllerImpl.java         | 63 ++++++++++----------
 1 file changed, 31 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/35d704cb/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index 80b414578..875d9b6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -1481,19 +1481,19 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       ConfigurationResponse response = null;
       Config config = null;
       //TODO : Remove after getting rid of cluster configurations
-      if (request.getServiceId() == null) {
-        config = cluster.getConfig(request.getType(),
-                request.getVersionTag());
+      if (request.getServiceId() != null) {
+        config = cluster.getConfigByServiceId(request.getType(), request.getVersionTag(), request.getServiceId());
         if (null != config) {
           response = new ConfigurationResponse(
-                  cluster.getClusterName(), config);
+                  cluster.getClusterName(), config, request.getServiceId(), request.getServiceGroupId());
         }
       }
-      else {
-        config = cluster.getConfigByServiceId(request.getType(), request.getVersionTag(), request.getServiceId());
+      if (response == null) {
+        config = cluster.getConfig(request.getType(),
+                request.getVersionTag());
         if (null != config) {
           response = new ConfigurationResponse(
-                  cluster.getClusterName(), config, request.getServiceId(), request.getServiceGroupId());
+                  cluster.getClusterName(), config);
         }
       }
       responses.add(response);
@@ -1505,9 +1505,9 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       //Get by type
       if (null != request.getType()) {
         //TODO : Remove after getting rid of cluster configurations
-        if (request.getServiceId() == null) {
-          configs = cluster.getConfigsByType(
-                  request.getType());
+        if (request.getServiceId() != null) {
+          configs = cluster.getConfigsByServiceIdType(
+                  request.getType(), request.getServiceId());
           if (null != configs) {
             for (Entry<String, Config> entry : configs.entrySet()) {
               Config config = entry.getValue();
@@ -1517,14 +1517,14 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
                       config.getTag(), entry.getValue().getVersion(),
                       includeProps ? config.getProperties() : new HashMap<>(),
                       includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
-                      config.getPropertiesTypes());
+                      config.getPropertiesTypes(), request.getServiceId(), request.getServiceGroupId());
               responses.add(response);
             }
           }
         }
-        else {
-          configs = cluster.getConfigsByServiceIdType(
-                  request.getType(), request.getServiceId());
+        if (responses == null || responses.isEmpty()) {
+          configs = cluster.getConfigsByType(
+                  request.getType());
           if (null != configs) {
             for (Entry<String, Config> entry : configs.entrySet()) {
               Config config = entry.getValue();
@@ -1534,42 +1534,41 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
                       config.getTag(), entry.getValue().getVersion(),
                       includeProps ? config.getProperties() : new HashMap<>(),
                       includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
-                      config.getPropertiesTypes(), request.getServiceId(), request.getServiceGroupId());
+                      config.getPropertiesTypes());
               responses.add(response);
             }
           }
         }
-
-      }
-      else {
+      } else {
         // !!! all configuration
         Collection<Config> all = null;
         //TODO : Remove after getting rid of cluster configurations
-        if (request.getServiceId() == null) {
-          all = cluster.getAllConfigs();
-          for (Config config : all) {
-            response = new ConfigurationResponse(
-                    cluster.getClusterName(), config.getStackId(), config.getType(),
-                    config.getTag(), config.getVersion(),
-                    includeProps ? config.getProperties() : new HashMap<>(),
-                    includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
-                    config.getPropertiesTypes());
-            responses.add(response);
+        if (request.getServiceId() != null) {
+          all = cluster.getConfigsByServiceId(request.getServiceId());
+          if (all != null) {
+            for (Config config : all) {
+              response = new ConfigurationResponse(
+                      cluster.getClusterName(), config.getStackId(), config.getType(),
+                      config.getTag(), config.getVersion(),
+                      includeProps ? config.getProperties() : new HashMap<>(),
+                      includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
+                      config.getPropertiesTypes(), request.getServiceId(), request.getServiceGroupId());
+              responses.add(response);
+            }
           }
         }
-        else {
-          all = cluster.getConfigsByServiceId(request.getServiceId());
+        if (responses == null || responses.isEmpty()) {
+          all = cluster.getAllConfigs();
           for (Config config : all) {
             response = new ConfigurationResponse(
                     cluster.getClusterName(), config.getStackId(), config.getType(),
                     config.getTag(), config.getVersion(),
                     includeProps ? config.getProperties() : new HashMap<>(),
                     includeProps ? config.getPropertiesAttributes() : new HashMap<>(),
-                    config.getPropertiesTypes(), request.getServiceId(), request.getServiceGroupId());
+                    config.getPropertiesTypes());
             responses.add(response);
           }
         }
-
       }
     }
     return responses;


[16/17] ambari git commit: AMBARI-22325. Code cleanup: delete useless javadoc (adoroszlai)

Posted by be...@apache.org.
AMBARI-22325. Code cleanup: delete useless javadoc (adoroszlai)


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: 0c5232ae75f8dd99e92bfcf497fd9434f66a509e
Parents: 1a12110
Author: Attila Doroszlai <ad...@hortonworks.com>
Authored: Mon Nov 13 10:49:08 2017 +0100
Committer: Balazs Bence Sari <be...@apache.org>
Committed: Tue Nov 14 11:31:16 2017 +0100

----------------------------------------------------------------------
 .../ambari/server/topology/BlueprintV2.java     | 21 +-------------------
 1 file changed, 1 insertion(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/0c5232ae/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2.java
index 9ca0248..f6314be 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2.java
@@ -27,7 +27,6 @@ import javax.annotation.Nonnull;
 import org.apache.ambari.server.controller.StackV2;
 import org.apache.ambari.server.orm.entities.BlueprintEntity;
 
-
 /**
  * Blueprint representation.
  */
@@ -65,7 +64,7 @@ public interface BlueprintV2 {
   /**
   * @return associated stack ids
   **/
-  public Collection<String> getStackIds();
+  Collection<String> getStackIds();
 
   StackV2 getStackById(String stackId);
 
@@ -82,8 +81,6 @@ public interface BlueprintV2 {
 
   /**
    * Get service by Id
-   * @param serviceId
-   * @return
    */
   Service getServiceById(ServiceId serviceId);
 
@@ -102,8 +99,6 @@ public interface BlueprintV2 {
   @Nonnull
   Collection<String> getAllServiceNames();
 
-
-
   /**
    * Get all of the service types represented in the blueprint.
    *
@@ -122,9 +117,6 @@ public interface BlueprintV2 {
 
   /**
    * Get services by type from a service group.
-   * @param serviceGroup
-   * @param serviceType
-   * @return
    */
   Collection<Service> getServicesFromServiceGroup(ServiceGroup serviceGroup, String serviceType);
 
@@ -149,16 +141,11 @@ public interface BlueprintV2 {
 
   Collection<ComponentV2> getComponents(Service service);
 
-
   /**
    * Get components by type from a service.
-   * @param service
-   * @param componentType
-   * @return
    */
   Collection<ComponentV2> getComponentsByType(Service service, String componentType);
 
-
   /**
    * Get the host groups which contain components for the specified service.
    *
@@ -178,7 +165,6 @@ public interface BlueprintV2 {
    */
   Collection<HostGroupV2> getHostGroupsForComponent(ComponentV2 component);
 
-
   /**
    * Get the Blueprint cluster scoped configuration.
    * The blueprint cluster scoped configuration has the stack
@@ -190,7 +176,6 @@ public interface BlueprintV2 {
   @Deprecated
   Configuration getConfiguration();
 
-
   /**
    * Get the Blueprint cluster scoped setting.
    * The blueprint cluster scoped setting has the setting properties
@@ -200,7 +185,6 @@ public interface BlueprintV2 {
    */
   Setting getSetting();
 
-
   /**
    * Get whether a component is enabled for auto start.
    *
@@ -233,10 +217,7 @@ public interface BlueprintV2 {
   void validateTopology() throws InvalidTopologyException;
 
   /**
-   *
    * A config type is valid if there are services related to except cluster-env and global.
-   * @param configType
-   * @return
    */
   boolean isValidConfigType(String configType);
 


[03/17] ambari git commit: AMBARI-22366. POST, GET and UPDATE API for cluster settings. (/clusters/{clusterName}/settings).

Posted by be...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/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 f12759e..77bf62b 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
@@ -24,6 +24,8 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.ambari.server.AmbariException;
+
+import org.apache.ambari.server.ClusterSettingNotFoundException;
 import org.apache.ambari.server.ServiceGroupNotFoundException;
 import org.apache.ambari.server.controller.ClusterResponse;
 import org.apache.ambari.server.controller.ServiceComponentHostResponse;
@@ -98,6 +100,36 @@ public interface Cluster {
 
   ServiceGroup addServiceGroupDependency(String serviceGroupName, String dependencyServiceGroupName) throws AmbariException;
 
+
+  ClusterSetting addClusterSetting(String clusterSettingName, String clusterSettingValue) throws AmbariException;
+
+  /**
+   * Add 'cluster setting' to the cluster
+   *
+   * @param clusterSetting
+   * @return
+   * @throws AmbariException
+   */
+  void addClusterSetting(ClusterSetting clusterSetting);
+
+  /**
+   * Update 'cluster setting' in the cluster
+   *
+   * @param clusterSettingName Cluster setting name
+   * @return
+   * @throws AmbariException
+   */
+  ClusterSetting updateClusterSetting(String clusterSettingName, String clusterSettingValue) throws AmbariException;
+
+  /**
+   * Add 'cluster setting' in the cluster
+   *
+   * @param clusterSetting
+   * @return
+   * @throws AmbariException
+   */
+  void updateClusterSetting(ClusterSetting clusterSetting);
+
   //TODO remove when UI starts using service groups
   /**
    * Get a service
@@ -153,6 +185,29 @@ public interface Cluster {
   Map<String, ServiceGroup> getServiceGroups() throws AmbariException;
 
   /**
+   * Get a cluster setting
+   *
+   * @param clusterSettingName
+   * @return
+   */
+  ClusterSetting getClusterSetting(String clusterSettingName) throws ClusterSettingNotFoundException;
+
+  /**
+   * Get a cluster setting
+   *
+   * @param clusterSettingId
+   * @return
+   */
+  ClusterSetting getClusterSetting(Long clusterSettingId) throws ClusterSettingNotFoundException;
+
+  /**
+   * Get all cluster settings
+   *
+   * @return
+   */
+  Map<String, ClusterSetting> getClusterSettings() throws AmbariException;
+
+  /**
    * Get all ServiceComponentHosts on a given host
    *
    * @param hostname
@@ -562,6 +617,21 @@ public interface Cluster {
   void deleteServiceGroupDependency(String serviceGroupName, String dependencyServiceGroupName) throws AmbariException;
 
   /**
+   * Delete all the cluster settings associated with this cluster
+   *
+   * @throws AmbariException
+   */
+  void deleteAllClusterSettings() throws AmbariException;
+
+  /**
+   * Delete the named cluster setting associated with this cluster
+   *
+   * @param clusterSettingName
+   * @throws AmbariException
+   */
+  void deleteClusterSetting(String clusterSettingName) throws AmbariException;
+
+  /**
    * Gets if the cluster can be deleted
    *
    * @return

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterSetting.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterSetting.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterSetting.java
new file mode 100644
index 0000000..0a10907
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterSetting.java
@@ -0,0 +1,56 @@
+/**
+ * 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.state;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.ClusterSettingResponse;
+
+public interface ClusterSetting {
+
+    Long getClusterSettingId();
+
+    String getClusterSettingValue();
+
+    void setClusterSettingValue(String clusterSettingValue);
+
+    String getClusterSettingName();
+
+    void setClusterSettingName(String clusterSettingName);
+
+    long getClusterId();
+
+    Cluster getCluster();
+
+    ClusterSettingResponse convertToResponse();
+
+    void debugDump(StringBuilder sb);
+
+    void refresh();
+
+    /**
+     * Find out whether the cluster setting are in a state that
+     * it can be removed from a cluster.
+     *
+     * @return
+     */
+    boolean canBeRemoved();
+
+    void delete() throws AmbariException;
+}
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterSettingFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterSettingFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterSettingFactory.java
new file mode 100644
index 0000000..8b95cf5
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterSettingFactory.java
@@ -0,0 +1,33 @@
+/**
+ * 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.state;
+
+import org.apache.ambari.server.orm.entities.ClusterSettingEntity;
+
+import com.google.inject.assistedinject.Assisted;
+
+public interface ClusterSettingFactory {
+
+    ClusterSetting createNew(Cluster cluster,
+                           @Assisted("clusterSettingName") String clusterSettingName,
+                           @Assisted("clusterSettingValue") String clusterSettingValue);
+
+    ClusterSetting createExisting(Cluster cluster,
+                           ClusterSettingEntity clusterSettingEntity);
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterSettingImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterSettingImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterSettingImpl.java
new file mode 100644
index 0000000..8a9fab8
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterSettingImpl.java
@@ -0,0 +1,201 @@
+/**
+ * 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.state;
+
+
+import org.apache.ambari.server.AmbariException;
+
+import org.apache.ambari.server.controller.ClusterSettingResponse;
+import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
+import org.apache.ambari.server.orm.dao.ClusterDAO;
+import org.apache.ambari.server.orm.dao.ClusterSettingDAO;
+import org.apache.ambari.server.orm.entities.ClusterEntity;
+import org.apache.ambari.server.orm.entities.ClusterSettingEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.assistedinject.Assisted;
+import com.google.inject.assistedinject.AssistedInject;
+import com.google.inject.persist.Transactional;
+
+
+public class ClusterSettingImpl implements ClusterSetting {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ClusterSettingImpl.class);
+
+    private final Cluster cluster;
+
+    private final ClusterDAO clusterDAO;
+    private final ClusterSettingDAO clusterSettingDAO;
+    private final AmbariEventPublisher eventPublisher;
+
+    private Long clusterSettingId;
+    private String clusterSettingName;
+    private String clusterSettingValue;
+
+    @AssistedInject
+    public ClusterSettingImpl(@Assisted Cluster cluster,
+                            @Assisted("clusterSettingName") String clusterSettingName,
+                            @Assisted("clusterSettingValue") String clusterSettingValue,
+                            ClusterDAO clusterDAO,
+                            ClusterSettingDAO clusterSettingDAO,
+                            AmbariEventPublisher eventPublisher) throws AmbariException {
+
+        this.cluster = cluster;
+        this.clusterDAO = clusterDAO;
+        this.clusterSettingDAO = clusterSettingDAO;
+        this.eventPublisher = eventPublisher;
+
+        this.clusterSettingName = clusterSettingName;
+        this.clusterSettingValue = clusterSettingValue;
+
+        ClusterSettingEntity clusterSettingEntity = new ClusterSettingEntity();
+        clusterSettingEntity.setClusterId(cluster.getClusterId());
+        clusterSettingEntity.setClusterSettingId(clusterSettingId);
+        clusterSettingEntity.setClusterSettingName(clusterSettingName);
+        clusterSettingEntity.setClusterSettingValue(clusterSettingValue);
+
+        persist(clusterSettingEntity);
+    }
+
+    @AssistedInject
+    public ClusterSettingImpl(@Assisted Cluster cluster,
+                            @Assisted ClusterSettingEntity clusterSettingEntity,
+                            ClusterDAO clusterDAO,
+                            ClusterSettingDAO clusterSettingDAO,
+                            AmbariEventPublisher eventPublisher) throws AmbariException {
+        this.cluster = cluster;
+        this.clusterDAO = clusterDAO;
+        this.clusterSettingDAO = clusterSettingDAO;
+        this.eventPublisher = eventPublisher;
+
+        this.clusterSettingId = clusterSettingEntity.getClusterSettingId();
+        this.clusterSettingName = clusterSettingEntity.getClusterSettingName();
+        this.clusterSettingValue = clusterSettingEntity.getClusterSettingValue();
+
+        clusterSettingDAO.merge(clusterSettingEntity);
+    }
+
+    @Override
+    public Long getClusterSettingId() {
+        return clusterSettingId;
+    }
+
+    @Override
+    public String getClusterSettingName() {
+        return clusterSettingName;
+    }
+
+    @Override
+    public void setClusterSettingName(String clusterSettingName) {
+        ClusterSettingEntity entity = getClusterSettingEntity();
+        entity.setClusterSettingName(clusterSettingName);
+        clusterSettingDAO.merge(entity);
+        this.clusterSettingName = clusterSettingName;
+    }
+
+    @Override
+    public String getClusterSettingValue() {
+        return clusterSettingValue;
+    }
+
+    @Override
+    public void setClusterSettingValue(String clusterSettingValue) {
+        ClusterSettingEntity entity = getClusterSettingEntity();
+        entity.setClusterSettingValue(clusterSettingValue);
+        clusterSettingDAO.merge(entity);
+        this.clusterSettingValue = clusterSettingValue;
+    }
+
+    @Override
+    public long getClusterId() {
+        return cluster.getClusterId();
+    }
+
+    @Override
+    public ClusterSettingResponse convertToResponse() {
+        ClusterSettingResponse r = new ClusterSettingResponse(cluster.getClusterId(),
+                cluster.getClusterName(), getClusterSettingId(), getClusterSettingName(), getClusterSettingValue());
+        return r;
+    }
+
+    @Override
+    public Cluster getCluster() {
+        return cluster;
+    }
+
+    @Override
+    public void debugDump(StringBuilder sb) {
+        sb.append("ClusterSetting={ clusterSettingName=").append(getClusterSettingName())
+                .append(", clusterSettingValue=").append(getClusterSettingValue())
+                .append(", clusterName=").append(cluster.getClusterName())
+                .append(", clusterId=").append(cluster.getClusterId())
+                .append(" }");
+    }
+
+    private void persist(ClusterSettingEntity clusterSettingEntity) {
+        persistEntities(clusterSettingEntity);
+        refresh();
+
+        cluster.addClusterSetting(this);
+    }
+
+    @Transactional
+    protected void persistEntities(ClusterSettingEntity clusterSettingEntity) {
+        long clusterId = cluster.getClusterId();
+
+        ClusterEntity clusterEntity = clusterDAO.findById(clusterId);
+        clusterSettingEntity.setClusterEntity(clusterEntity);
+        clusterSettingDAO.create(clusterSettingEntity);
+        clusterSettingId = clusterSettingEntity.getClusterSettingId();
+        clusterEntity.getClusterSettingEntities().add(clusterSettingEntity);
+        clusterDAO.merge(clusterEntity);
+        clusterSettingDAO.merge(clusterSettingEntity);
+    }
+
+    @Override
+    @Transactional
+    public void refresh() {
+        ClusterSettingEntity clusterSettingEntity = clusterSettingDAO.findByPK(clusterSettingId);
+        clusterSettingDAO.refresh(clusterSettingEntity);
+    }
+
+    @Override
+    public boolean canBeRemoved() {
+        // TODO: Add check logic
+        return true;
+    }
+
+
+    @Override
+    @Transactional
+    public void delete() throws AmbariException {
+        removeEntities();
+    }
+
+    @Transactional
+    protected void removeEntities() throws AmbariException {
+        clusterSettingDAO.removeByPK(clusterSettingId);
+    }
+
+    // Refresh the cached reference on setters
+    private ClusterSettingEntity getClusterSettingEntity() {
+        return clusterSettingDAO.findByPK(clusterSettingId);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java
index 7737c0d..f12128f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java
@@ -46,7 +46,7 @@ import com.google.inject.persist.Transactional;
 
 public class ServiceGroupImpl implements ServiceGroup {
 
-  private static final Logger LOG = LoggerFactory.getLogger(ServiceImpl.class);
+  private static final Logger LOG = LoggerFactory.getLogger(ServiceGroupImpl.class);
 
   private ServiceGroupEntityPK serviceGroupEntityPK;
 
@@ -231,8 +231,6 @@ public class ServiceGroupImpl implements ServiceGroup {
   }
 
   /**
-   * {@inheritDoc}
-   * <p/>
    * This method uses Java locks and then delegates to internal methods which
    * perform the JPA merges inside of a transaction. Because of this, a
    * transaction is not necessary before this calling this method.

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/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 78201f0..dcead7a 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
@@ -44,6 +44,7 @@ import javax.persistence.RollbackException;
 import org.apache.ambari.annotations.Experimental;
 import org.apache.ambari.annotations.ExperimentalFeature;
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ClusterSettingNotFoundException;
 import org.apache.ambari.server.ConfigGroupNotFoundException;
 import org.apache.ambari.server.ObjectNotFoundException;
 import org.apache.ambari.server.ParentObjectNotFoundException;
@@ -78,6 +79,7 @@ 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.ClusterSettingDAO;
 import org.apache.ambari.server.orm.dao.ClusterStateDAO;
 import org.apache.ambari.server.orm.dao.HostConfigMappingDAO;
 import org.apache.ambari.server.orm.dao.HostDAO;
@@ -90,6 +92,7 @@ import org.apache.ambari.server.orm.dao.UpgradeDAO;
 import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
+import org.apache.ambari.server.orm.entities.ClusterSettingEntity;
 import org.apache.ambari.server.orm.entities.ClusterStateEntity;
 import org.apache.ambari.server.orm.entities.ConfigGroupEntity;
 import org.apache.ambari.server.orm.entities.HostEntity;
@@ -109,6 +112,8 @@ import org.apache.ambari.server.orm.entities.UpgradeEntity;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.ClusterHealthReport;
+import org.apache.ambari.server.state.ClusterSetting;
+import org.apache.ambari.server.state.ClusterSettingFactory;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Config;
 import org.apache.ambari.server.state.ConfigFactory;
@@ -180,9 +185,14 @@ public class ClusterImpl implements Cluster {
   private final ConcurrentSkipListMap<String, Service> services = new ConcurrentSkipListMap<>();
   private final ConcurrentSkipListMap<Long, Service> servicesById = new ConcurrentSkipListMap<>();
 
+  // Service groups
   private Map<String, ServiceGroup> serviceGroups = new ConcurrentSkipListMap<>();
   private final Map<Long, ServiceGroup> serviceGroupsById = new ConcurrentSkipListMap<>();
 
+  // Cluster settings
+  private Map<String, ClusterSetting> clusterSettings = new ConcurrentSkipListMap<>();
+  private final Map<Long, ClusterSetting> clusterSettingsById = new ConcurrentSkipListMap<>();
+
   /**
    * [ Config Type -> [ Config Version Tag -> Config ] ]
    */
@@ -241,6 +251,9 @@ public class ClusterImpl implements Cluster {
   private ServiceGroupFactory serviceGroupFactory;
 
   @Inject
+  private ClusterSettingFactory clusterSettingFactory;
+
+  @Inject
   private ConfigFactory configFactory;
 
   @Inject
@@ -288,6 +301,9 @@ public class ClusterImpl implements Cluster {
   @Inject
   private ClusterServiceDAO clusterServiceDAO;
 
+  @Inject
+  private ClusterSettingDAO clusterSettingDAO;
+
   /**
    * Data access object used for looking up stacks from the database.
    */
@@ -344,6 +360,7 @@ public class ClusterImpl implements Cluster {
 
     loadStackVersion();
     loadServiceGroups();
+    loadClusterSettings();
     loadServices();
     loadServiceHostComponents();
 
@@ -479,6 +496,17 @@ public class ClusterImpl implements Cluster {
     }
   }
 
+  private void loadClusterSettings() {
+    ClusterEntity clusterEntity = getClusterEntity();
+    if (!clusterEntity.getClusterSettingEntities().isEmpty()) {
+      for (ClusterSettingEntity clusterSettingEntity : clusterEntity.getClusterSettingEntities()) {
+        ClusterSetting cs = clusterSettingFactory.createExisting(this, clusterSettingEntity);
+        clusterSettings.put(clusterSettingEntity.getClusterSettingName(), cs);
+        clusterSettingsById.put(clusterSettingEntity.getClusterSettingId(), cs);
+      }
+    }
+  }
+
   private void loadConfigGroups() {
     ClusterEntity clusterEntity = getClusterEntity();
     if (!clusterEntity.getConfigGroupEntities().isEmpty()) {
@@ -995,8 +1023,8 @@ public class ClusterImpl implements Cluster {
   public void addServiceGroup(ServiceGroup serviceGroup) {
     if (LOG.isDebugEnabled()) {
       LOG.debug("Adding a new service group" + ", clusterName=" + getClusterName()
-        + ", clusterId=" + getClusterId() + ", serviceGroupName="
-        + serviceGroup.getServiceGroupName());
+              + ", clusterId=" + getClusterId() + ", serviceGroupName="
+              + serviceGroup.getServiceGroupName());
     }
     serviceGroups.put(serviceGroup.getServiceGroupName(), serviceGroup);
     serviceGroupsById.put(serviceGroup.getServiceGroupId(), serviceGroup);
@@ -1006,7 +1034,7 @@ public class ClusterImpl implements Cluster {
   public ServiceGroup addServiceGroup(String serviceGroupName) throws AmbariException {
     if (serviceGroups.containsKey(serviceGroupName)) {
       throw new AmbariException("Service group already exists" + ", clusterName=" + getClusterName()
-        + ", clusterId=" + getClusterId() + ", serviceGroupName=" + serviceGroupName);
+              + ", clusterId=" + getClusterId() + ", serviceGroupName=" + serviceGroupName);
     }
 
     ServiceGroup serviceGroup = serviceGroupFactory.createNew(this, serviceGroupName, new HashSet<ServiceGroupKey>());
@@ -1051,6 +1079,55 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
+  public void addClusterSetting(ClusterSetting clusterSetting) {
+    LOG.debug("Adding a new cluster setting, clusterName= {}, clusterId : {}, " +
+            "clusterSettingName : {}", getClusterName(), getClusterId(),
+            clusterSetting.getClusterSettingName());
+
+    clusterSettings.put(clusterSetting.getClusterSettingName(), clusterSetting);
+    clusterSettingsById.put(clusterSetting.getClusterSettingId(), clusterSetting);
+  }
+
+  @Override
+  public ClusterSetting addClusterSetting(String clusterSettingName, String clusterSettingValue) throws AmbariException {
+    if (clusterSettings.containsKey(clusterSettingName)) {
+      throw new AmbariException("'Cluster Setting' already exists" + ", clusterName=" + getClusterName()
+              + ", clusterId=" + getClusterId() + ", clusterSettingName=" + clusterSettingName);
+    }
+
+    ClusterSetting clusterSetting = clusterSettingFactory.createNew(this, clusterSettingName, clusterSettingValue);
+    addClusterSetting(clusterSetting);
+    return clusterSetting;
+  }
+
+
+  @Override
+  public void updateClusterSetting(ClusterSetting clusterSetting) {
+    LOG.debug("Updating cluster setting, clusterName= {}, clusterId : {}, " +
+            "clusterSettingName : {}", getClusterName(), getClusterId(), clusterSetting.getClusterSettingName());
+
+    // Update the changed 'clusterSetting' in the below maps, to reflect object with newest changes.
+    clusterSettings.put(clusterSetting.getClusterSettingName(), clusterSetting);
+    clusterSettingsById.put(clusterSetting.getClusterSettingId(), clusterSetting);
+  }
+
+  @Override
+  public ClusterSetting updateClusterSetting(String clusterSettingName, String clusterSettingValue) throws AmbariException {
+    if (!clusterSettings.containsKey(clusterSettingName)) {
+      throw new AmbariException("'ClusterSetting' doesn't exist" + ", clusterName=" + getClusterName()
+              + ", clusterId=" + getClusterId() + ", clusterSettingName=" + clusterSettingName);
+    }
+
+    ClusterSettingEntity clusterSettingEntity = clusterSettingDAO.findByClusterIdAndSettingName(getClusterId(), clusterSettingName);
+    // Update 'cluster setting' value in 'clusterSettingEntity'.
+    clusterSettingEntity.setClusterSettingValue(clusterSettingValue);
+
+    ClusterSetting clusterSetting = clusterSettingFactory.createExisting(this, clusterSettingEntity);
+    updateClusterSetting(clusterSetting);
+    return clusterSetting;
+  }
+
+  @Override
   public Service getService(String serviceName) throws AmbariException {
     Service service = services.get(serviceName);
     if (null == service) {
@@ -1158,6 +1235,31 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
+  public ClusterSetting getClusterSetting(String clusterSettingName) throws ClusterSettingNotFoundException {
+
+    ClusterSetting clusterSetting = clusterSettings.get(clusterSettingName);
+    if (null == clusterSetting) {
+      throw new ClusterSettingNotFoundException(getClusterName(), clusterSettingName);
+    }
+    return clusterSetting;
+  }
+
+
+  @Override
+  public ClusterSetting getClusterSetting(Long clusterSettingId) throws ClusterSettingNotFoundException {
+    ClusterSetting clusterSetting = clusterSettingsById.get(clusterSettingId);
+    if(null == clusterSetting) {
+      throw new ClusterSettingNotFoundException(getClusterName(), clusterSettingId);
+    }
+    return clusterSetting;
+  }
+
+  @Override
+  public Map<String, ClusterSetting> getClusterSettings() throws AmbariException {
+    return new HashMap<>(clusterSettings);
+  }
+
+  @Override
   public StackId getDesiredStackVersion() {
     return desiredStackVersion;
   }
@@ -1688,6 +1790,33 @@ public class ClusterImpl implements Cluster {
     }
   }
 
+  @Override
+  public void deleteAllClusterSettings() throws AmbariException {
+    // TODO : Evaluate if we need a bulk delete feature ?
+  }
+
+  @Override
+  public void deleteClusterSetting(String clusterSettingName) throws AmbariException {
+    clusterGlobalLock.writeLock().lock();
+    try {
+      ClusterSetting clusterSetting = getClusterSetting(clusterSettingName);
+      LOG.info("Deleting 'cluster setting' for cluster" + ", clusterName="
+              + getClusterName() + ", clusterSettingName=" + clusterSetting.getClusterSettingName());
+      // FIXME check dependencies from meta layer
+      if (!clusterSetting.canBeRemoved()) {
+        throw new AmbariException("Could not delete 'cluster setting' from cluster"
+                + ", clusterName=" + getClusterName()
+                + ", clusterSettingName=" + clusterSetting.getClusterSettingName());
+      }
+      Long clusterSettingId = clusterSetting.getClusterSettingId();
+      deleteClusterSetting(clusterSetting);
+      clusterSettings.remove(clusterSettingName);
+      clusterSettingsById.remove(clusterSettingId);
+    } finally {
+      clusterGlobalLock.writeLock().unlock();
+    }
+  }
+
   /**
    * Deletes the specified service also removes references to it from {@link this.serviceComponentHosts}
    * and references to ServiceComponentHost objects that belong to the service from {@link this.serviceComponentHostsByHost}
@@ -1726,12 +1855,24 @@ public class ClusterImpl implements Cluster {
    *
    * @param serviceGroup the service group to be deleted
    * @throws AmbariException
-   * @see ServiceComponentHost
    */
   private void deleteServiceGroup(ServiceGroup serviceGroup) throws AmbariException {
     serviceGroup.delete();
   }
 
+  /**
+   * Deletes the specified 'cluster setting'.
+   * <p>
+   * Note: This method must be called only with write lock acquired.
+   * </p>
+   *
+   * @param clusterSetting the 'cluster setting' to be deleted
+   * @throws AmbariException
+   */
+  private void deleteClusterSetting(ClusterSetting clusterSetting) throws AmbariException {
+    clusterSetting.delete();
+  }
+
   @Override
   public boolean canBeRemoved() {
     clusterGlobalLock.readLock().lock();

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/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 5bc419e..039d8af 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
@@ -144,6 +144,14 @@ CREATE TABLE hosts (
   CONSTRAINT PK_hosts PRIMARY KEY (host_id),
   CONSTRAINT UQ_hosts_host_name UNIQUE (host_name));
 
+CREATE TABLE clustersettings (
+  id BIGINT NOT NULL,
+  setting_name VARCHAR(255) NOT NULL,
+  setting_value VARCHAR(255) NOT NULL,
+  cluster_id BIGINT NOT NULL,
+  CONSTRAINT PK_clustersettings PRIMARY KEY (id),
+  CONSTRAINT FK_clustersettings_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id));
+
 CREATE TABLE servicegroups (
   id BIGINT NOT NULL,
   service_group_name VARCHAR(255) NOT NULL,
@@ -1144,6 +1152,8 @@ CREATE INDEX idx_alert_notice_state on alert_notice(notify_state);
 INSERT INTO ambari_sequences (sequence_name, sequence_value)
   SELECT 'cluster_id_seq', 1 FROM SYSIBM.SYSDUMMY1
   UNION ALL
+  SELECT 'cluster_setting_id_seq', 1 FROM SYSIBM.SYSDUMMY1
+  UNION ALL
   SELECT 'service_group_id_seq', 1 FROM SYSIBM.SYSDUMMY1
   UNION ALL
   SELECT 'service_id_seq', 1 FROM SYSIBM.SYSDUMMY1

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/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 b3bd221..e14f0f1 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -163,6 +163,14 @@ CREATE TABLE hosts (
   CONSTRAINT PK_hosts PRIMARY KEY (host_id),
   CONSTRAINT UQ_hosts_host_name UNIQUE (host_name));
 
+CREATE TABLE clustersettings (
+  id BIGINT NOT NULL,
+  setting_name VARCHAR(255) NOT NULL,
+  setting_value VARCHAR(255) NOT NULL,
+  cluster_id BIGINT NOT NULL,
+  CONSTRAINT PK_clustersettings PRIMARY KEY (id),
+  CONSTRAINT FK_clustersettings_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id));
+
 CREATE TABLE servicegroups (
   id BIGINT NOT NULL,
   service_group_name VARCHAR(255) NOT NULL,
@@ -1158,6 +1166,7 @@ CREATE INDEX idx_alert_notice_state on alert_notice(notify_state);
 -- In order for the first ID to be 1, must initialize the ambari_sequences table with a sequence_value of 0.
 INSERT INTO ambari_sequences(sequence_name, sequence_value) VALUES
   ('cluster_id_seq', 1),
+  ('cluster_setting_id_seq', 1),
   ('service_group_id_seq', 1),
   ('service_id_seq', 1),
   ('host_id_seq', 0),

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/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 f6294c7..a5911eb 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -144,6 +144,14 @@ CREATE TABLE hosts (
   CONSTRAINT PK_hosts PRIMARY KEY (host_id),
   CONSTRAINT UQ_hosts_host_name UNIQUE (host_name));
 
+CREATE TABLE clustersettings (
+  id NUMBER(19) NOT NULL,
+  setting_name VARCHAR2(255) NOT NULL,
+  setting_value VARCHAR2(255) NOT NULL,
+  cluster_id NUMBER(19) NOT NULL,
+  CONSTRAINT PK_clustersettings PRIMARY KEY (id),
+  CONSTRAINT FK_clustersettings_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id));
+
 CREATE TABLE servicegroups (
   id NUMBER(19) NOT NULL,
   service_group_name VARCHAR2(255) NOT NULL,
@@ -1138,6 +1146,7 @@ CREATE INDEX idx_alert_notice_state on alert_notice(notify_state);
 ---------inserting some data-----------
 -- In order for the first ID to be 1, must initialize the ambari_sequences table with a sequence_value of 0.
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('host_role_command_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('cluster_setting_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_group_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('user_id_seq', 1);

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/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 e2bf5f3..c5203e4 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -145,6 +145,14 @@ CREATE TABLE hosts (
   CONSTRAINT PK_hosts PRIMARY KEY (host_id),
   CONSTRAINT UQ_hosts_host_name UNIQUE (host_name));
 
+CREATE TABLE clustersettings (
+  id BIGINT NOT NULL,
+  setting_name VARCHAR(255) NOT NULL,
+  setting_value VARCHAR(255) NOT NULL,
+  cluster_id BIGINT NOT NULL,
+  CONSTRAINT PK_clustersettings PRIMARY KEY (id),
+  CONSTRAINT FK_clustersettings_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id));
+
 CREATE TABLE servicegroups (
   id BIGINT NOT NULL,
   service_group_name VARCHAR(255) NOT NULL,
@@ -1143,6 +1151,7 @@ CREATE INDEX idx_alert_notice_state on alert_notice(notify_state);
 BEGIN;
 INSERT INTO ambari_sequences (sequence_name, sequence_value) VALUES
   ('cluster_id_seq', 1),
+  ('cluster_setting_id_seq', 1),
   ('service_group_id_seq', 1),
   ('service_id_seq', 1),
   ('host_id_seq', 0),

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/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 1379112..a9032f3 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -143,6 +143,14 @@ CREATE TABLE hosts (
   CONSTRAINT PK_hosts PRIMARY KEY (host_id),
   CONSTRAINT UQ_hosts_host_name UNIQUE (host_name));
 
+CREATE TABLE clustersettings (
+  id NUMERIC(19) NOT NULL,
+  setting_name VARCHAR(255) NOT NULL,
+  setting_value VARCHAR(255) NOT NULL,
+  cluster_id NUMERIC(19) NOT NULL,
+  CONSTRAINT PK_clustersettings PRIMARY KEY (id),
+  CONSTRAINT FK_clustersettings_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id));
+
 CREATE TABLE servicegroups (
   id NUMERIC(19) NOT NULL,
   service_group_name VARCHAR(255) NOT NULL,
@@ -1137,6 +1145,7 @@ CREATE INDEX idx_alert_notice_state on alert_notice(notify_state);
 
 -- In order for the first ID to be 1, must initialize the ambari_sequences table with a sequence_value of 0.
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('cluster_id_seq', 1);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('cluster_setting_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_group_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('host_id_seq', 0);

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/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 5f03331..d782155 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -157,6 +157,14 @@ CREATE TABLE hosts (
   CONSTRAINT PK_hosts PRIMARY KEY CLUSTERED (host_id),
   CONSTRAINT UQ_hosts_host_name UNIQUE (host_name));
 
+CREATE TABLE clustersettings (
+  id BIGINT NOT NULL,
+  setting_name VARCHAR(255) NOT NULL,
+  setting_value VARCHAR(255) NOT NULL,
+  cluster_id BIGINT NOT NULL,
+  CONSTRAINT PK_clustersettings PRIMARY KEY (id),
+  CONSTRAINT FK_clustersettings_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id));
+
 CREATE TABLE servicegroups (
   id BIGINT NOT NULL,
   service_group_name VARCHAR(255) NOT NULL,
@@ -1163,6 +1171,7 @@ BEGIN TRANSACTION
   INSERT INTO ambari_sequences (sequence_name, [sequence_value])
   VALUES
     ('cluster_id_seq', 1),
+    ('cluster_setting_id_seq', 1),
     ('service_group_id_seq', 1),
     ('service_id_seq', 1),
     ('host_id_seq', 0),

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


[09/17] ambari git commit: AMBARI-22325. Simplify lambdas (adoroszlai)

Posted by be...@apache.org.
AMBARI-22325. Simplify lambdas (adoroszlai)


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: ceeb3829f065b3dfdb1f0d76ba330841f257789f
Parents: e15f057
Author: Attila Doroszlai <ad...@hortonworks.com>
Authored: Mon Nov 13 09:41:16 2017 +0100
Committer: Balazs Bence Sari <be...@apache.org>
Committed: Tue Nov 14 11:31:15 2017 +0100

----------------------------------------------------------------------
 .../controller/DeleteIdentityHandler.java       |  2 +-
 .../server/controller/StackV2Factory.java       |  2 +-
 .../utilities/RemovableIdentities.java          |  4 +--
 .../controller/utilities/UsedIdentities.java    |  2 +-
 .../ambari/server/topology/BlueprintImplV2.java | 35 ++++++++++----------
 .../server/topology/BlueprintV2Factory.java     |  2 +-
 .../ambari/server/topology/HostGroupV2Impl.java |  6 ++--
 .../ambari/server/topology/ServiceGroup.java    |  3 +-
 .../apache/ambari/server/topology/Setting.java  |  2 +-
 9 files changed, 30 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/ceeb3829/ambari-server/src/main/java/org/apache/ambari/server/controller/DeleteIdentityHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/DeleteIdentityHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/DeleteIdentityHandler.java
index f5d51c3..91035f8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/DeleteIdentityHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/DeleteIdentityHandler.java
@@ -234,7 +234,7 @@ class DeleteIdentityHandler {
     }
 
     private Set<String> serviceNames() {
-      return componentFilter().stream().map(component -> component.getServiceName()).collect(toSet());
+      return componentFilter().stream().map(Component::getServiceName).collect(toSet());
     }
 
     private List<Component> componentFilter() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/ceeb3829/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2Factory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2Factory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2Factory.java
index 784b368..0735171 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2Factory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackV2Factory.java
@@ -85,7 +85,7 @@ public class StackV2Factory {
     List<Map.Entry<String, String>> componentServices = stackData.serviceComponents.entrySet().stream().
       flatMap(e -> e.getValue().stream().map( v -> new SimpleImmutableEntry<>(e.getKey(), v))).
       collect(Collectors.toList());
-    componentServices.stream().forEach( componentService -> {
+    componentServices.forEach( componentService -> {
       try {
         ComponentInfo componentInfo = controller.getAmbariMetaInfo().getComponent(stackData.stackName,
           stackData.stackVersion, componentService.getKey(), componentService.getValue());

http://git-wip-us.apache.org/repos/asf/ambari/blob/ceeb3829/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/RemovableIdentities.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/RemovableIdentities.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/RemovableIdentities.java
index cd23e83..ef9518d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/RemovableIdentities.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/RemovableIdentities.java
@@ -101,7 +101,7 @@ public class RemovableIdentities {
   }
 
   private static ServiceExclude excludeService(String excludedServiceName) {
-    return serviceName -> excludedServiceName.equals(serviceName);
+    return excludedServiceName::equals;
   }
 
   private static ComponentExclude excludeComponent(String excludedServiceName, String excludedComponentName, String excludedHostName) {
@@ -116,7 +116,7 @@ public class RemovableIdentities {
 
   private static List<KerberosIdentityDescriptor> componentIdentities(List<String> componentNames, KerberosServiceDescriptor serviceDescriptor) throws AmbariException {
     return componentNames.stream()
-      .map(componentName -> serviceDescriptor.getComponent(componentName))
+      .map(serviceDescriptor::getComponent)
       .filter(Objects::nonNull)
       .flatMap(componentDescriptor -> componentDescriptor.getIdentitiesSkipReferences().stream())
       .collect(toList());

http://git-wip-us.apache.org/repos/asf/ambari/blob/ceeb3829/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/UsedIdentities.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/UsedIdentities.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/UsedIdentities.java
index 2f0974e..2df713f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/UsedIdentities.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/UsedIdentities.java
@@ -86,7 +86,7 @@ public class UsedIdentities {
    * @return true if there is an identity in the used list with the same keytab or principal name than the given identity
    */
   public boolean contains(KerberosIdentityDescriptor identity) {
-    return used.stream().anyMatch(each -> identity.isShared(each));
+    return used.stream().anyMatch(identity::isShared);
   }
 
   public interface ServiceExclude {

http://git-wip-us.apache.org/repos/asf/ambari/blob/ceeb3829/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java
index d889fc2..ad98adc 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java
@@ -30,6 +30,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.function.Function;
 
 import javax.annotation.Nonnull;
 
@@ -68,7 +69,7 @@ public class BlueprintImplV2 implements BlueprintV2 {
 
   public void setStacks(Map<StackId, StackV2> stacks) {
     this.stacks = stacks;
-    getAllServices().stream().forEach(s -> s.setStackFromBlueprint(this));
+    getAllServices().forEach(s -> s.setStackFromBlueprint(this));
   }
 
   @JsonProperty("Blueprints")
@@ -106,14 +107,14 @@ public class BlueprintImplV2 implements BlueprintV2 {
 
   @JsonProperty("service_groups")
   public void setServiceGroups(Collection<ServiceGroup> serviceGroups) {
-    this.serviceGroups = serviceGroups.stream().collect(toMap( sg -> sg.getName(), sg -> sg ));
+    this.serviceGroups = serviceGroups.stream().collect(toMap(ServiceGroup::getName, Function.identity()));
   }
 
   @JsonProperty("host_groups")
   public void setHostGroups(Collection<HostGroupV2Impl> hostGroups) {
     this.hostGroupMap = hostGroups.stream().collect(toMap(
-      hg -> hg.getName(),
-      hg -> hg
+      HostGroupV2Impl::getName,
+      Function.identity()
     ));
   }
 
@@ -153,7 +154,7 @@ public class BlueprintImplV2 implements BlueprintV2 {
   @Override
   @JsonIgnore
   public Collection<String> getStackIds() {
-    return repositoryVersions.stream().map(rv -> rv.getStackId()).collect(toList());
+    return repositoryVersions.stream().map(RepositoryVersion::getStackId).collect(toList());
   }
 
   @Override
@@ -209,7 +210,7 @@ public class BlueprintImplV2 implements BlueprintV2 {
   @Override
   @JsonIgnore
   public Collection<String> getAllServiceTypes() {
-    return getServiceGroups().stream().flatMap(sg -> sg.getServices().stream()).map(s -> s.getType()).collect(toSet());
+    return getServiceGroups().stream().flatMap(sg -> sg.getServices().stream()).map(Service::getType).collect(toSet());
   }
 
   @Override
@@ -256,9 +257,9 @@ public class BlueprintImplV2 implements BlueprintV2 {
   public Configuration getConfiguration() {
     if (null == configuration) {
       configuration = new Configuration(new HashMap<>(), new HashMap<>());
-      getServiceGroups().stream().forEach( sg -> addChildConfiguration(configuration, sg.getConfiguration()) );
-      getHostGroups().values().stream().forEach(
-        hg -> hg.getComponents().stream().forEach(
+      getServiceGroups().forEach( sg -> addChildConfiguration(configuration, sg.getConfiguration()) );
+      getHostGroups().values().forEach(
+        hg -> hg.getComponents().forEach(
           c -> addChildConfiguration(configuration, c.getConfiguration())));
     }
     return configuration;
@@ -285,13 +286,13 @@ public class BlueprintImplV2 implements BlueprintV2 {
   @Override
   @JsonIgnore
   public Collection<String> getAllServiceNames() {
-    return getAllServices().stream().map(s -> s.getName()).collect(toList());
+    return getAllServices().stream().map(Service::getName).collect(toList());
   }
 
   @Nonnull
   @Override
   public Collection<String> getComponentNames(ServiceId serviceId) {
-    return getComponents(serviceId).stream().map(c -> c.getName()).collect(toList());
+    return getComponents(serviceId).stream().map(ComponentV2::getName).collect(toList());
   }
 
   @Override
@@ -355,7 +356,7 @@ public class BlueprintImplV2 implements BlueprintV2 {
       return true;
     }
     final Set<String> serviceNames =
-      getAllServices().stream().map(s -> s.getName()).collect(toSet());
+      getAllServices().stream().map(Service::getName).collect(toSet());
     return getStacks().stream().anyMatch(
       stack -> {
         String service = stack.getServiceForConfigType(configType);
@@ -367,7 +368,7 @@ public class BlueprintImplV2 implements BlueprintV2 {
   public void postDeserialization() {
     // Maintain a ServiceId -> Service map
     this.services = getAllServiceIds().stream().collect(toMap(
-      serviceId -> serviceId,
+      Function.identity(),
       serviceId -> {
         ServiceGroup sg = getServiceGroup(serviceId.getServiceGroup());
         Service service = null != sg ? sg.getServiceByName(serviceId.getName()) : null;
@@ -379,11 +380,11 @@ public class BlueprintImplV2 implements BlueprintV2 {
     ));
 
     // Set Service -> ServiceGroup references and Service -> Service dependencies
-    getAllServices().stream().forEach( s -> {
+    getAllServices().forEach( s -> {
       s.setServiceGroup(serviceGroups.get(s.getServiceGroupId()));
       Map<ServiceId, Service> dependencies = s.getDependentServiceIds().stream().collect(toMap(
-        serviceId -> serviceId,
-        serviceId -> getService(serviceId)
+        Function.identity(),
+        this::getService
       ));
       s.setDependencyMap(dependencies);
     });
@@ -392,7 +393,7 @@ public class BlueprintImplV2 implements BlueprintV2 {
     // Set HostGroup -> Services and Component -> Service references
     for (HostGroupV2Impl hg: hostGroupMap.values()) {
       hg.setServiceMap(hg.getServiceIds().stream().collect(toMap(
-        serviceId -> serviceId,
+        Function.identity(),
         serviceId -> this.services.get(serviceId)
       )));
       for (ComponentV2 comp: hg.getComponents()) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/ceeb3829/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
index 7ad5365..4f22aea 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
@@ -104,7 +104,7 @@ public class BlueprintV2Factory {
     blueprintV2.postDeserialization();
     blueprintV2.setStacks(
       blueprintV2.getStackIds().stream().collect(Collectors.toMap(
-        stackId -> new StackId(stackId),
+        StackId::new,
         stackId -> parseStack(new StackId(stackId))
       ))
     );

http://git-wip-us.apache.org/repos/asf/ambari/blob/ceeb3829/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java
index 8834a37..dd7a316 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java
@@ -128,7 +128,7 @@ public class HostGroupV2Impl implements HostGroupV2, Configurable {
   @Override
   @JsonIgnore
   public Collection<String> getServiceNames() {
-    return serviceMap.values().stream().map(s -> s.getName()).collect(Collectors.toList());
+    return serviceMap.values().stream().map(Service::getName).collect(Collectors.toList());
   }
 
   @JsonIgnore
@@ -159,8 +159,8 @@ public class HostGroupV2Impl implements HostGroupV2, Configurable {
 
   public void setComponents(List<ComponentV2> components) {
     this.components = components;
-    this.containsMasterComponent = components.stream().anyMatch(c -> c.isMasterComponent());
-    this.serviceIds = components.stream().map(c -> c.getServiceId()).collect(Collectors.toSet());
+    this.containsMasterComponent = components.stream().anyMatch(ComponentV2::isMasterComponent);
+    this.serviceIds = components.stream().map(ComponentV2::getServiceId).collect(Collectors.toSet());
   }
 
   @JsonIgnore

http://git-wip-us.apache.org/repos/asf/ambari/blob/ceeb3829/ambari-server/src/main/java/org/apache/ambari/server/topology/ServiceGroup.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/ServiceGroup.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/ServiceGroup.java
index 7f38b2c..a5ba2d4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/ServiceGroup.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/ServiceGroup.java
@@ -23,6 +23,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import com.google.common.collect.ListMultimap;
@@ -76,7 +77,7 @@ public class ServiceGroup {
 
   public void setServices(Collection<Service> services) {
     services.forEach(s -> s.setServiceGroup(this));
-    this.servicesByName = services.stream().collect(Collectors.toMap(Service::getName, s -> s));
+    this.servicesByName = services.stream().collect(Collectors.toMap(Service::getName, Function.identity()));
     this.servicesByType = Multimaps.index(services, Service::getType);
     services.forEach(s -> s.setServiceGroup(this));
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/ceeb3829/ambari-server/src/main/java/org/apache/ambari/server/topology/Setting.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/Setting.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/Setting.java
index 34542e1..496d571 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/Setting.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/Setting.java
@@ -108,7 +108,7 @@ public class Setting {
     List<String> values = getSettingValue(settingCategory).stream().
       flatMap(sv -> sv.entrySet().stream()).
       filter(entry -> Objects.equals(entry.getKey(), propertyName)).
-      map(entry -> entry.getValue()).
+      map(Map.Entry::getValue).
       collect(Collectors.toList());
     Preconditions.checkState(values.size() < 2, "Ambigous settings (%s) for category %s, property %s",
       values.size(), settingCategory, settingCategory);


[15/17] ambari git commit: AMBARI-22325 Yet another fix for v2 blueprint json serialization/deserialization (benyoka)

Posted by be...@apache.org.
AMBARI-22325 Yet another fix for v2 blueprint json serialization/deserialization (benyoka)


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: 1a121106e94306943795522d7578e938e418dd02
Parents: bc08e24
Author: Balazs Bence Sari <be...@apache.org>
Authored: Mon Nov 13 11:20:21 2017 +0100
Committer: Balazs Bence Sari <be...@apache.org>
Committed: Tue Nov 14 11:31:16 2017 +0100

----------------------------------------------------------------------
 .../src/main/java/org/apache/ambari/server/topology/Service.java    | 1 +
 .../ambari/server/topology/validators/BlueprintImplV2Test.java      | 1 +
 2 files changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/1a121106/ambari-server/src/main/java/org/apache/ambari/server/topology/Service.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/Service.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/Service.java
index 7c5ee42..90b4764 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/Service.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/Service.java
@@ -165,6 +165,7 @@ public class Service implements Configurable {
       '}';
   }
 
+  @JsonIgnore
   public String getServiceGroupName() {
     if (serviceGroup != null) {
       return serviceGroup.getName();

http://git-wip-us.apache.org/repos/asf/ambari/blob/1a121106/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/BlueprintImplV2Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/BlueprintImplV2Test.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/BlueprintImplV2Test.java
index 99acfb7..611ada1 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/BlueprintImplV2Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/BlueprintImplV2Test.java
@@ -97,6 +97,7 @@ public class BlueprintImplV2Test {
     String bpSerialized = bpFactory.convertToJson(bp);
     System.out.println(bpSerialized);
     bp = (BlueprintImplV2)bpFactory.convertFromJson(bpSerialized);
+    System.out.println(bp);
   }
 
 


[02/17] ambari git commit: AMBARI-22380 : Add stack name and version to registry API (mradhakrishnan)

Posted by be...@apache.org.
AMBARI-22380 : Add stack name and version to registry API (mradhakrishnan)


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: b558eda2d45724c865914e3f49a2af16abe43f86
Parents: 5301b3f
Author: Madhuvanthi Radhakrishnan <mr...@hortonworks.com>
Authored: Wed Nov 8 09:52:54 2017 -0800
Committer: Madhuvanthi Radhakrishnan <mr...@hortonworks.com>
Committed: Wed Nov 8 09:52:54 2017 -0800

----------------------------------------------------------------------
 .../controller/RegistryMpackVersionResponse.java   | 14 +++++++++++++-
 .../RegistryMpackVersionResourceProvider.java      | 17 ++++++++++++++---
 .../server/registry/RegistryMpackVersion.java      |  7 +++++++
 .../registry/json/JsonRegistryMpackVersion.java    |  8 ++++++++
 4 files changed, 42 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/b558eda2/ambari-server/src/main/java/org/apache/ambari/server/controller/RegistryMpackVersionResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/RegistryMpackVersionResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/RegistryMpackVersionResponse.java
index a0674ee..5929c4c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/RegistryMpackVersionResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/RegistryMpackVersionResponse.java
@@ -33,6 +33,7 @@ public class RegistryMpackVersionResponse {
   private String mpackName;
   private String mpackVersion;
   private String mpackBuildNumber;
+  private String stackId;
   private String mpackUrl;
   private String mpackDocUrl;
   private List<? extends RegistryMpackService> mpackServices;
@@ -48,12 +49,13 @@ public class RegistryMpackVersionResponse {
    * @param mpackDocUrl       mpack documentation url
    * @param mpackServices     list of mpack services
    * @param compatibleMpacks  list of compatible mpacks
+   * @param stackId           stack id of the mpack version
    */
   public RegistryMpackVersionResponse(
     Long registryId, String mpackName, String mpackVersion, String mpackBuildNumber,
     String mpackUrl, String mpackDocUrl,
     List<? extends RegistryMpackService> mpackServices,
-    List<? extends RegistryMpackCompatiblity> compatibleMpacks) {
+    List<? extends RegistryMpackCompatiblity> compatibleMpacks, String stackId) {
     this.registryId = registryId;
     this.mpackName = mpackName;
     this.mpackVersion = mpackVersion;
@@ -62,6 +64,7 @@ public class RegistryMpackVersionResponse {
     this.mpackDocUrl = mpackDocUrl;
     this.mpackServices = mpackServices;
     this.compatibleMpacks = compatibleMpacks;
+    this.stackId = stackId;
   }
 
   public Long getRegistryId() {
@@ -96,6 +99,15 @@ public class RegistryMpackVersionResponse {
     return compatibleMpacks;
   }
 
+
+  public String getStackId() {
+    return stackId;
+  }
+
+  public void setStackId(String stackId) {
+    this.stackId = stackId;
+  }
+
   @Override
   public int hashCode() {
     int result = 1;

http://git-wip-us.apache.org/repos/asf/ambari/blob/b558eda2/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryMpackVersionResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryMpackVersionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryMpackVersionResourceProvider.java
index 3b8a3f5..9020146 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryMpackVersionResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryMpackVersionResourceProvider.java
@@ -65,6 +65,10 @@ public class RegistryMpackVersionResourceProvider extends AbstractControllerReso
   public static final String REGISTRY_MPACK_DOC_URL = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "mpack_doc_url";
   public static final String REGISTRY_MPACK_SERVICES = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "services";
   public static final String REGISTRY_MPACK_COMPATIBLE_MPACKS = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "compatible_mpacks";
+  public static final String REGISTRY_MPACK_STACK_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "stack_name";
+  public static final String REGISTRY_MPACK_STACK_VERSION_PROPERTY_ID =
+          RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "stack_version";
+
 
   private static Set<String> pkPropertyIds = new HashSet<>(
     Arrays.asList(REGISTRY_ID, REGISTRY_MPACK_NAME));
@@ -94,6 +98,9 @@ public class RegistryMpackVersionResourceProvider extends AbstractControllerReso
     PROPERTY_IDS.add(REGISTRY_MPACK_DOC_URL);
     PROPERTY_IDS.add(REGISTRY_MPACK_SERVICES);
     PROPERTY_IDS.add(REGISTRY_MPACK_COMPATIBLE_MPACKS);
+    PROPERTY_IDS.add(REGISTRY_MPACK_STACK_NAME_PROPERTY_ID);
+    PROPERTY_IDS.add(REGISTRY_MPACK_STACK_VERSION_PROPERTY_ID);
+
 
     // keys
     KEY_PROPERTY_IDS.put(Resource.Type.Registry, REGISTRY_ID);
@@ -156,7 +163,9 @@ public class RegistryMpackVersionResourceProvider extends AbstractControllerReso
       setResourceProperty(resource, REGISTRY_MPACK_URL, response.getMpackUrl(), requestedIds);
       setResourceProperty(resource, REGISTRY_MPACK_DOC_URL, response.getMpackDocUrl(), requestedIds);
       setResourceProperty(resource, REGISTRY_MPACK_SERVICES, response.getMpackServices(), requestedIds);
-      setResourceProperty(resource, REGISTRY_MPACK_COMPATIBLE_MPACKS, response.getCompatibleMpacks(), requestedIds);
+      String[] stackid = ((String) response.getStackId()).split("-");
+      setResourceProperty(resource, REGISTRY_MPACK_STACK_NAME_PROPERTY_ID, stackid[0], requestedIds);
+      setResourceProperty(resource, REGISTRY_MPACK_STACK_VERSION_PROPERTY_ID, stackid[1], requestedIds);
       sortedResources.add(resource);
     }
     sortedResources.sort(new Comparator<Resource>() {
@@ -241,7 +250,8 @@ public class RegistryMpackVersionResourceProvider extends AbstractControllerReso
           registryMpackVersion.getMpackUrl(),
           registryMpackVersion.getMpackDocUrl(),
           registryMpackVersion.getMpackServices(),
-          registryMpackVersion.getCompatibleMpacks());
+          registryMpackVersion.getCompatibleMpacks(),
+          registryMpackVersion.getMpackStackId());
         responses.add(response);
       }
     } else {
@@ -255,7 +265,8 @@ public class RegistryMpackVersionResourceProvider extends AbstractControllerReso
           registryMpackVersion.getMpackUrl(),
           registryMpackVersion.getMpackDocUrl(),
           registryMpackVersion.getMpackServices(),
-          registryMpackVersion.getCompatibleMpacks());
+          registryMpackVersion.getCompatibleMpacks(),
+          registryMpackVersion.getMpackStackId());
         responses.add(response);
       }
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b558eda2/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryMpackVersion.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryMpackVersion.java b/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryMpackVersion.java
index 4a4b780..ed7abc2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryMpackVersion.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryMpackVersion.java
@@ -47,6 +47,13 @@ public interface RegistryMpackVersion {
    */
   public String getMpackDocUrl();
 
+
+  /**
+   * Get mpack stack id
+   * @return
+   */
+  public String getMpackStackId();
+
   /**
    * Get list of services in the mpack version
    * @return

http://git-wip-us.apache.org/repos/asf/ambari/blob/b558eda2/ambari-server/src/main/java/org/apache/ambari/server/registry/json/JsonRegistryMpackVersion.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/registry/json/JsonRegistryMpackVersion.java b/ambari-server/src/main/java/org/apache/ambari/server/registry/json/JsonRegistryMpackVersion.java
index 39ebf17..51aa0ca 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/registry/json/JsonRegistryMpackVersion.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/registry/json/JsonRegistryMpackVersion.java
@@ -42,6 +42,9 @@ public class JsonRegistryMpackVersion implements RegistryMpackVersion {
   @SerializedName("docUrl")
   private String docUrl;
 
+  @SerializedName("stack-id")
+  private String stackId;
+
   @SerializedName("services")
   private ArrayList<JsonRegistryMpackService> services;
 
@@ -77,4 +80,9 @@ public class JsonRegistryMpackVersion implements RegistryMpackVersion {
   public List<? extends RegistryMpackCompatiblity> getCompatibleMpacks() {
     return compatibleMpacks;
   }
+
+  @Override
+  public String getMpackStackId() {
+    return stackId;
+  }
 }


[13/17] ambari git commit: AMBARI-22325. Fix impossible equality: ComponentV2 vs ProvisionAction (adoroszlai)

Posted by be...@apache.org.
AMBARI-22325. Fix impossible equality: ComponentV2 vs ProvisionAction (adoroszlai)


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: bc08e246d3bb5bc47d21b7801872dfa94d6b449e
Parents: ceeb382
Author: Attila Doroszlai <ad...@hortonworks.com>
Authored: Mon Nov 13 10:32:43 2017 +0100
Committer: Balazs Bence Sari <be...@apache.org>
Committed: Tue Nov 14 11:31:16 2017 +0100

----------------------------------------------------------------------
 .../ambari/server/topology/HostGroupV2Impl.java | 33 +++++++-------------
 1 file changed, 12 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/bc08e246/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java
index dd7a316..ff82ecf 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java
@@ -17,23 +17,18 @@
  */
 package org.apache.ambari.server.topology;
 
+import static java.util.stream.Collectors.toList;
+
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
-import javax.annotation.Nullable;
-
 import org.apache.ambari.server.controller.internal.ProvisionAction;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
-import com.google.common.base.Predicates;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
 
 public class HostGroupV2Impl implements HostGroupV2, Configurable {
 
@@ -73,22 +68,18 @@ public class HostGroupV2Impl implements HostGroupV2, Configurable {
   @Override
   @JsonIgnore
   public Collection<String> getComponentNames() {
-    return getComponentNames(components);
-  }
-
-  private Collection<String> getComponentNames(List<ComponentV2> components) {
-    return Lists.transform(components,
-      new Function<ComponentV2, String>() {
-        @Override public String apply(@Nullable ComponentV2 input) { return input.getName(); }
-      });
+    return components.stream()
+      .map(ComponentV2::getName)
+      .collect(toList());
   }
 
   @Override
   @JsonIgnore
   public Collection<String> getComponentNames(ProvisionAction provisionAction) {
-    List<ComponentV2> filtered =
-      ImmutableList.copyOf(Collections2.filter(components, Predicates.equalTo(provisionAction)));
-    return getComponentNames(filtered);
+    return components.stream()
+      .filter(c -> c.getProvisionAction().equals(provisionAction))
+      .map(ComponentV2::getName)
+      .collect(toList());
   }
 
   @Override
@@ -98,7 +89,7 @@ public class HostGroupV2Impl implements HostGroupV2, Configurable {
 
   @Override
   public Collection<ComponentV2> getComponentsByServiceId(ServiceId serviceId) {
-    return components.stream().filter(c -> c.getServiceId().equals(serviceId)).collect(Collectors.toList());
+    return components.stream().filter(c -> c.getServiceId().equals(serviceId)).collect(toList());
   }
 
   @Override
@@ -128,13 +119,13 @@ public class HostGroupV2Impl implements HostGroupV2, Configurable {
   @Override
   @JsonIgnore
   public Collection<String> getServiceNames() {
-    return serviceMap.values().stream().map(Service::getName).collect(Collectors.toList());
+    return serviceMap.values().stream().map(Service::getName).collect(toList());
   }
 
   @JsonIgnore
   public void setServiceMap(Map<ServiceId, Service> serviceMap) {
     Preconditions.checkArgument(serviceMap.keySet().equals(this.serviceIds),
-      "Maitained list of service ids doesn't match with received service map: %s vs %s", serviceIds, serviceMap.keySet());
+      "Maintained list of service ids doesn't match with received service map: %s vs %s", serviceIds, serviceMap.keySet());
     this.serviceMap = serviceMap;
   }
 


[10/17] ambari git commit: AMBARI-22325. Log blueprint JSON parse error when loading from DB (adoroszlai)

Posted by be...@apache.org.
AMBARI-22325. Log blueprint JSON parse error when loading from DB (adoroszlai)


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: e15f05760d88e4095f9f0e3cf58a6047c2f6786e
Parents: 57bef16
Author: Attila Doroszlai <ad...@hortonworks.com>
Authored: Mon Nov 13 09:16:44 2017 +0100
Committer: Balazs Bence Sari <be...@apache.org>
Committed: Tue Nov 14 11:31:15 2017 +0100

----------------------------------------------------------------------
 .../ambari/server/controller/internal/ProvisionClusterRequest.java  | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/e15f0576/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java
index f773fc8..48d5016 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java
@@ -325,6 +325,7 @@ public class ProvisionClusterRequest extends BaseClusterRequest {
     try {
       setBlueprint(getBlueprintFactory().getBlueprint(blueprintName));
     } catch (IOException e) {
+      LOG.error("Could not parse JSON stored in DB for blueprint {}", blueprintName, e);
       throw new NoSuchBlueprintException(blueprintName);
     }
 


[04/17] ambari git commit: AMBARI-22366. POST, GET and UPDATE API for cluster settings. (/clusters/{clusterName}/settings).

Posted by be...@apache.org.
AMBARI-22366. POST, GET and UPDATE API for cluster settings. (/clusters/{clusterName}/settings).


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: 4959206893da4060e66b6ece4cfba5136de79157
Parents: b558eda
Author: Swapan Shridhar <ss...@hortonworks.com>
Authored: Fri Nov 10 14:07:40 2017 -0800
Committer: Swapan Shridhar <ss...@hortonworks.com>
Committed: Fri Nov 10 14:07:40 2017 -0800

----------------------------------------------------------------------
 .../server/ClusterSettingNotFoundException.java |  35 ++
 .../resources/ClusterResourceDefinition.java    |   1 +
 .../ClusterSettingResourceDefinition.java       |  45 ++
 .../resources/ResourceInstanceFactoryImpl.java  |   4 +
 .../server/api/services/ClusterService.java     |  13 +
 .../api/services/ClusterSettingService.java     | 276 +++++++++
 .../controller/AmbariManagementController.java  |   8 +
 .../AmbariManagementControllerImpl.java         |   8 +
 .../controller/ClusterSettingRequest.java       |  83 +++
 .../controller/ClusterSettingResponse.java      | 147 +++++
 .../server/controller/ControllerModule.java     |   7 +
 .../controller/ResourceProviderFactory.java     |   4 +-
 .../server/controller/ServiceGroupResponse.java |   2 +-
 .../AbstractControllerResourceProvider.java     |   2 +
 .../ClusterSettingResourceProvider.java         | 554 +++++++++++++++++++
 .../internal/DefaultProviderModule.java         |   2 +
 .../internal/ServiceGroupResourceProvider.java  |   4 +-
 .../ambari/server/controller/spi/Resource.java  |   2 +
 .../server/events/ClusterSettingEvent.java      |  46 ++
 .../server/orm/dao/ClusterSettingDAO.java       | 100 ++++
 .../server/orm/entities/ClusterEntity.java      |  11 +
 .../orm/entities/ClusterSettingEntity.java      | 131 +++++
 .../resources/RootLevelSettingsManager.java     |   2 +-
 .../org/apache/ambari/server/state/Cluster.java |  70 +++
 .../ambari/server/state/ClusterSetting.java     |  56 ++
 .../server/state/ClusterSettingFactory.java     |  33 ++
 .../ambari/server/state/ClusterSettingImpl.java | 201 +++++++
 .../ambari/server/state/ServiceGroupImpl.java   |   4 +-
 .../server/state/cluster/ClusterImpl.java       | 149 ++++-
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  |  10 +
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |   9 +
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |   9 +
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |   9 +
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |   9 +
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |   9 +
 .../src/main/resources/META-INF/persistence.xml |   1 +
 36 files changed, 2044 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/ClusterSettingNotFoundException.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ClusterSettingNotFoundException.java b/ambari-server/src/main/java/org/apache/ambari/server/ClusterSettingNotFoundException.java
new file mode 100644
index 0000000..1720aea
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/ClusterSettingNotFoundException.java
@@ -0,0 +1,35 @@
+/**
+ * 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;
+
+@SuppressWarnings("serial")
+public class ClusterSettingNotFoundException extends ObjectNotFoundException {
+
+    public ClusterSettingNotFoundException(String clusterName, String clusterSettingName) {
+        super("ClusterSetting not found"
+                + ", clusterName=" + clusterName
+                + ", clusterSettingName=" + clusterSettingName);
+    }
+
+    public ClusterSettingNotFoundException(String clusterName, Long clusterSettingId) {
+        super("ClusterSetting not found"
+                + ", clusterName=" + clusterName
+                + ", clusterSettingId=" + clusterSettingId);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java
index e5680dd..d211efd 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java
@@ -63,6 +63,7 @@ public class ClusterResourceDefinition extends BaseResourceDefinition {
     Set<SubResourceDefinition> setChildren = new HashSet<>();
     setChildren.add(new SubResourceDefinition(Resource.Type.ServiceGroup));
     setChildren.add(new SubResourceDefinition(Resource.Type.Host));
+    setChildren.add(new SubResourceDefinition(Resource.Type.ClusterSetting));
     setChildren.add(new SubResourceDefinition(Resource.Type.Configuration));
     setChildren.add(new SubResourceDefinition(Resource.Type.ServiceConfigVersion));
     setChildren.add(new SubResourceDefinition(Resource.Type.Request));

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterSettingResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterSettingResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterSettingResourceDefinition.java
new file mode 100644
index 0000000..151cfe8
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterSettingResourceDefinition.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;
+
+/**
+ * Cluster Setting resource definition.
+ */
+public class ClusterSettingResourceDefinition extends BaseResourceDefinition {
+
+    /**
+     * Constructor.
+     */
+    public ClusterSettingResourceDefinition() {
+        super(Resource.Type.ClusterSetting);
+    }
+
+    @Override
+    public String getPluralName() {
+        return "settings";
+    }
+
+    @Override
+    public String getSingularName() {
+        return "setting";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/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 7ac41a5..2d2e75e 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
@@ -108,6 +108,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
         resourceDefinition = new RootClusterSettingsResourceDefinition();
         break;
 
+      case ClusterSetting:
+        resourceDefinition = new ClusterSettingResourceDefinition();
+        break;
+
       case ServiceGroup:
         resourceDefinition = new ServiceGroupResourceDefinition();
         break;

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
index 92f50f4..31af4e0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
@@ -535,6 +535,19 @@ public class ClusterService extends BaseService {
   }
 
   /**
+   * Gets the cluster setting sub-resource.
+   *
+   * @param request      the request
+   * @param clusterName  the cluster name
+   *
+   * @return the 'cluster setting' service
+   */
+  @Path("{clusterName}/settings")
+  public ClusterSettingService getSettingsHandler(@Context javax.ws.rs.core.Request request, @PathParam("clusterName") String clusterName) {
+    return new ClusterSettingService(clusterName);
+  }
+
+  /**
    * Gets the requests sub-resource.
    *
    * @param request      the request

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterSettingService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterSettingService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterSettingService.java
new file mode 100644
index 0000000..c8f9bd1
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterSettingService.java
@@ -0,0 +1,276 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.services;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.ambari.annotations.ApiIgnore;
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.ClusterSettingResponse;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.http.HttpStatus;
+
+
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+/**
+ * Service responsible for services resource requests.
+ */
+public class ClusterSettingService extends BaseService {
+    private static final String CLUSTER_SETTING_REQUEST_TYPE = "org.apache.ambari.server.controller.ClusterSettingRequestSwagger";
+
+    /**
+     * Parent cluster name.
+     */
+    private String m_clusterName;
+
+    /**
+     * Constructor.
+     *
+     * @param clusterName cluster id
+     */
+    public ClusterSettingService(String clusterName) {
+        m_clusterName = clusterName;
+    }
+
+
+    /**
+     * Handles URL: /clusters/{clusterId}/settings
+     * Get all 'cluster settings' for a cluster.
+     *
+     * @param headers http headers
+     * @param ui      uri info
+     * @return service collection resource representation
+     */
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    @ApiOperation(value = "Get all cluster settings",
+            nickname = "ClusterSettingService#getClusterSettings",
+            notes = "Returns all 'cluster settings'.",
+            response = ClusterSettingResponse.ClusterSettingResponseSwagger.class,
+            responseContainer = RESPONSE_CONTAINER_LIST)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION,
+                    defaultValue = "ClusterSettingInfo/cluster_setting_name, ClusterSettingInfo/cluster_name",
+                    dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY),
+            @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION,
+                    defaultValue = "ClusterSettingInfo/cluster_setting_name.asc, ClusterSettingInfo/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 getClusterSettings(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+        return handleRequest(headers, body, ui, Request.Type.GET,
+                createClusterSettingResource(m_clusterName, null));
+    }
+
+    /**
+     * Handles URL: /clusters/{clusterId}/settings/{clusterSettingName}
+     * Get a specific 'cluster setting' for a cluster.
+     *
+     * @param headers http headers
+     * @param ui      uri info
+     * @return service collection resource representation
+     */
+    @GET
+    @Path("{clusterSettingName}")
+    @Produces(MediaType.TEXT_PLAIN)
+    @ApiOperation(value = "Get the details of a specific 'cluster setting'",
+            nickname = "ClusterSettingService#getClusterSetting",
+            notes = "Returns the details of a specific 'cluster setting'",
+            response = ClusterSettingResponse.ClusterSettingResponseSwagger.class,
+            responseContainer = RESPONSE_CONTAINER_LIST)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "ClusterSettingInfo/*",
+                    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 getClusterSetting(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                      @PathParam("clusterSettingName") String clusterSettingName) {
+        return handleRequest(headers, body, ui, Request.Type.GET,
+                createClusterSettingResource(m_clusterName, clusterSettingName));
+    }
+
+    /**
+     * Handles: PUT /clusters/{clusterName}/settings
+     * Update multiple cluster settings.
+     *
+     * @param body        http body
+     * @param headers     http headers
+     * @param ui          uri info
+     * @return information regarding the updated cluster settings.
+     */
+    @PUT
+    @Produces(MediaType.TEXT_PLAIN)
+    @ApiOperation(value = "Updates multiple cluster settings",
+            nickname = "ClusterSettingService#updateClusterSettings"
+    )
+    @ApiImplicitParams({
+            @ApiImplicitParam(dataType = CLUSTER_SETTING_REQUEST_TYPE, paramType = PARAM_TYPE_BODY)
+    })
+    @ApiResponses({
+            @ApiResponse(code = HttpStatus.SC_OK, 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_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 updateClusterSettings(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+
+        return handleRequest(headers, body, ui, Request.Type.PUT, createClusterSettingResource(m_clusterName, null));
+    }
+
+    /**
+     * Handles: PUT /clusters/{clusterName}/settings/{clusterSettingName}
+     * Updates the specific cluster setting.
+     *
+     * @param body                  http body
+     * @param headers               http headers
+     * @param ui                    uri info
+     * @param clusterSettingName    cluster setting name
+     *
+     * @return information regarding the updated cluster setting.
+     */
+    @PUT
+    @Path("{clusterSettingName}")
+    @Produces(MediaType.TEXT_PLAIN)
+    @ApiOperation(value = "Updates the specific cluster setting",
+            nickname = "ClusterSettingService#updateClusterSetting"
+    )
+    @ApiImplicitParams({
+            @ApiImplicitParam(dataType = CLUSTER_SETTING_REQUEST_TYPE, paramType = PARAM_TYPE_BODY)
+    })
+    @ApiResponses({
+            @ApiResponse(code = HttpStatus.SC_OK, 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_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 updateClusterSettings(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                          @PathParam("clusterSettingName") String clusterSettingName) {
+        return handleRequest(headers, body, ui, Request.Type.PUT, createClusterSettingResource(m_clusterName, clusterSettingName));
+    }
+
+    /**
+     * Handles: DELETE /clusters/{clusterName}/settings/{clusterSettingName}
+     * Delete a specific 'cluster setting'.
+
+     * @param headers               http headers
+     * @param ui                    uri info
+     * @param clusterSettingName    cluster setting name
+     * @return information regarding the deleted 'cluster setting'
+     */
+    @DELETE
+    @Path("{clusterSettingName}")
+    @Produces(MediaType.TEXT_PLAIN)
+    @ApiOperation(value = "Deletes a specific cluster setting",
+            nickname = "ClusterSettingService#deleteClustersetting"
+    )
+    @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 deleteClusterSetting(@Context HttpHeaders headers, @Context UriInfo ui,
+                                       @PathParam("clusterSettingName") String clusterSettingName) {
+
+        return handleRequest(headers, null, ui, Request.Type.DELETE, createClusterSettingResource(m_clusterName, clusterSettingName));
+    }
+
+    /**
+     * Handles URL: /clusters/{clusterId}/settings
+     * The body should contain:
+     * To create multiple settings in a request, provide an array of settings.
+     * eg:
+     *
+     * [
+     *      {
+     *          "ClusterSettingInfo" : {
+     *              "cluster_setting_name": "{setting_name}",
+     *              "cluster_setting_value": "{setting_val}"
+     *          }
+     *      },
+     *      {
+     *          "ClusterSettingInfo" : {
+     *              "cluster_setting_name": "{setting_name}",
+     *              "cluster_setting_value": "{setting_val}"
+     *      }
+     *]
+     *
+     *
+     *
+     * @param headers http headers
+     * @param ui      uri info
+     * @return status code only, 201 if successful
+     */
+    @POST @ApiIgnore // until documented
+    @Produces("text/plain")
+    public Response createConfigurations(String body,@Context HttpHeaders headers, @Context UriInfo ui) {
+        return handleRequest(headers, body, ui, Request.Type.POST, createClusterSettingResource(m_clusterName, null));
+    }
+
+    /**
+     * Create a 'cluster setting' resource instance.
+     *
+     * @param clusterName cluster name
+     *
+     * @return a cluster setting resource instance
+     */
+    ResourceInstance createClusterSettingResource(String clusterName, String clusterSettingName) {
+        Map<Resource.Type,String> mapIds = new HashMap<>();
+        mapIds.put(Resource.Type.Cluster, clusterName);
+        mapIds.put(Resource.Type.ClusterSetting, clusterSettingName);
+
+        return createResource(Resource.Type.ClusterSetting, mapIds);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
index 86ac3c4..b5bc813 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
@@ -51,6 +51,7 @@ import org.apache.ambari.server.security.ldap.LdapBatchDto;
 import org.apache.ambari.server.security.ldap.LdapSyncDto;
 import org.apache.ambari.server.stageplanner.RoleGraphFactory;
 import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.ClusterSettingFactory;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Config;
 import org.apache.ambari.server.state.ConfigHelper;
@@ -582,6 +583,13 @@ public interface AmbariManagementController {
   ServiceGroupFactory getServiceGroupFactory();
 
   /**
+   * Get the 'cluster setting' factory for this management controller.
+   *
+   * @return the 'cluster setting'
+   */
+  ClusterSettingFactory getClusterSettingFactory();
+
+  /**
    * Get the service component factory for this management controller.
    *
    * @return the service component factory

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index dc16f22..80b414578 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -157,6 +157,7 @@ import org.apache.ambari.server.stack.RepoUtil;
 import org.apache.ambari.server.stageplanner.RoleGraph;
 import org.apache.ambari.server.stageplanner.RoleGraphFactory;
 import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.ClusterSettingFactory;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.CommandScriptDefinition;
 import org.apache.ambari.server.state.ComponentInfo;
@@ -270,6 +271,8 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
   @Inject
   private ServiceGroupFactory serviceGroupFactory;
   @Inject
+  private ClusterSettingFactory clusterSettingFactory;
+  @Inject
   private ServiceFactory serviceFactory;
   @Inject
   private ServiceComponentFactory serviceComponentFactory;
@@ -5278,6 +5281,11 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
   }
 
   @Override
+  public ClusterSettingFactory getClusterSettingFactory() {
+    return clusterSettingFactory;
+  }
+
+  @Override
   public ServiceFactory getServiceFactory() { return serviceFactory; }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterSettingRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterSettingRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterSettingRequest.java
new file mode 100644
index 0000000..37fe5bc
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterSettingRequest.java
@@ -0,0 +1,83 @@
+/**
+ * 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;
+
+
+public class ClusterSettingRequest {
+
+    private String clusterName; // REF
+    private String clusterSettingName; // GET/CREATE/DELETE
+    private String clusterSettingValue;
+
+    public ClusterSettingRequest(String clusterName, String clusterSettingName, String clusterSettingValue) {
+        this.clusterName = clusterName;
+        this.clusterSettingName = clusterSettingName;
+        this.clusterSettingValue = clusterSettingValue;
+    }
+
+    /**
+     * @return the clusterName
+     */
+    public String getClusterName() {
+        return clusterName;
+    }
+
+    /**
+     * @param clusterName the clusterName to set
+     */
+    public void setClusterName(String clusterName) {
+        this.clusterName = clusterName;
+    }
+
+    /**
+     * @return the clustesettingName
+     */
+    public String getClusterSettingName() {
+        return clusterSettingName;
+    }
+
+    /**
+     * @param clusterSettingName the cluster setting name to set
+     */
+    public void setClusterSettingName(String clusterSettingName) {
+        this.clusterSettingName = clusterSettingName;
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("clusterName=" + clusterName
+                + ", clusterSettingName=" + clusterSettingName
+                + ", clusterSettingValue=" + clusterSettingValue);
+        return sb.toString();
+    }
+
+    /**
+     * @return the clustesettingName
+     */
+    public String getClusterSettingValue() {
+        return clusterSettingValue;
+    }
+
+    /**
+     * @param clusterSettingValue the cluster setting value to set
+     */
+    public void setClusterSettingValue(String clusterSettingValue) {
+        this.clusterSettingValue = clusterSettingValue;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterSettingResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterSettingResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterSettingResponse.java
new file mode 100644
index 0000000..9d79326
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterSettingResponse.java
@@ -0,0 +1,147 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <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;
+
+import java.util.Objects;
+
+import io.swagger.annotations.ApiModelProperty;
+
+public class ClusterSettingResponse {
+
+    private Long clusterId;
+    private String clusterName;
+    private Long clusterSettingId;
+    private String clusterSettingName;
+    private String clusterSettingValue;
+
+    public ClusterSettingResponse(Long clusterId, String clusterName, Long clusterSettingId,
+                                  String clusterSettingName, String clusterSettingValue) {
+        this.clusterId = clusterId;
+        this.clusterSettingId = clusterSettingId;
+        this.clusterName = clusterName;
+        this.clusterSettingName = clusterSettingName;
+        this.clusterSettingValue = clusterSettingValue;
+    }
+
+    /**
+     * @return the clusterId
+     */
+    public Long getClusterId() {
+        return clusterId;
+    }
+
+    /**
+     * @param clusterId the clusterId to set
+     */
+    public void setClusterId(Long clusterId) {
+        this.clusterId = clusterId;
+    }
+
+
+
+    /**
+     * @return the clusterName
+     */
+    public String getClusterName() {
+        return clusterName;
+    }
+
+    /**
+     * @param clusterName the clusterName to set
+     */
+    public void setClusterName(String clusterName) {
+        this.clusterName = clusterName;
+    }
+
+
+
+    /**
+     * @return the cluster Setting Id
+     */
+    public Long getClusterSettingId() {
+        return clusterSettingId;
+    }
+
+    /**
+     * @param  clusterSettingId the cluster Setting Id
+     */
+    public void setClusterSettingId(Long clusterSettingId) {
+        this.clusterSettingId = clusterSettingId;
+    }
+
+
+
+    /**
+     * @return the cluster setting name
+     */
+    public String getClusterSettingName() {
+        return clusterSettingName;
+    }
+
+    /**
+     * @param  clusterSettingName the cluster setting name
+     */
+    public void setClusterSettingName(String clusterSettingName) {
+        this.clusterSettingName = clusterSettingName;
+    }
+
+
+
+    /**
+     * @return the cluster setting name
+     */
+    public String getClusterSettingValue() {
+        return clusterSettingValue;
+    }
+
+    /**
+     * @param  clusterSettingValue the cluster setting value
+     */
+    public void setClusterSettingValue(String clusterSettingValue) {
+        this.clusterSettingValue = clusterSettingValue;
+    }
+
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ClusterSettingResponse that = (ClusterSettingResponse) o;
+
+        return Objects.equals(clusterId, that.clusterId) &&
+               Objects.equals(clusterSettingId, that.clusterSettingId) &&
+               Objects.equals(clusterName, that.clusterName) &&
+               Objects.equals(clusterSettingName, that.clusterSettingName);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(clusterId, clusterSettingId, clusterName, clusterSettingName);
+    }
+
+    /**
+     * Interface to help correct Swagger documentation generation
+     */
+    public interface ClusterSettingResponseSwagger extends ApiModel {
+        @ApiModelProperty(name = "ClusterSettingInfo")
+        ClusterSettingResponse getClusterSettingResponse();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/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 0303a71..eff1e77 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
@@ -64,6 +64,7 @@ import org.apache.ambari.server.configuration.Configuration.ConnectionPoolType;
 import org.apache.ambari.server.configuration.Configuration.DatabaseType;
 import org.apache.ambari.server.controller.internal.AlertTargetResourceProvider;
 import org.apache.ambari.server.controller.internal.AmbariConfigurationResourceProvider;
+import org.apache.ambari.server.controller.internal.ClusterSettingResourceProvider;
 import org.apache.ambari.server.controller.internal.ClusterStackVersionResourceProvider;
 import org.apache.ambari.server.controller.internal.ComponentResourceProvider;
 import org.apache.ambari.server.controller.internal.CredentialResourceProvider;
@@ -129,6 +130,9 @@ import org.apache.ambari.server.serveraction.users.CsvFilePersisterService;
 import org.apache.ambari.server.stack.StackManagerFactory;
 import org.apache.ambari.server.stageplanner.RoleGraphFactory;
 import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.ClusterSetting;
+import org.apache.ambari.server.state.ClusterSettingFactory;
+import org.apache.ambari.server.state.ClusterSettingImpl;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Config;
 import org.apache.ambari.server.state.ConfigFactory;
@@ -473,6 +477,8 @@ public class ControllerModule extends AbstractModule {
         Service.class, ServiceImpl.class).build(ServiceFactory.class));
     install(new FactoryModuleBuilder().implement(
         ServiceGroup.class, ServiceGroupImpl.class).build(ServiceGroupFactory.class));
+    install(new FactoryModuleBuilder().implement(
+        ClusterSetting.class, ClusterSettingImpl.class).build(ClusterSettingFactory.class));
 
     install(new FactoryModuleBuilder()
         .implement(ResourceProvider.class, Names.named("host"), HostResourceProvider.class)
@@ -481,6 +487,7 @@ public class ControllerModule extends AbstractModule {
         .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("clustersetting"), ClusterSettingResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("component"), ComponentResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("member"), MemberResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("repositoryVersion"), RepositoryVersionResourceProvider.class)

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/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 0fbea9a..a6c69af 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
@@ -41,7 +41,6 @@ public interface ResourceProviderFactory {
   @Named("hostComponent")
   ResourceProvider getHostComponentResourceProvider(Set<String> propertyIds, Map<Type, String> keyPropertyIds,
                                                     AmbariManagementController managementController);
-
   @Named("service")
   ResourceProvider getServiceResourceProvider(AmbariManagementController managementController);
 
@@ -54,6 +53,9 @@ public interface ResourceProviderFactory {
   @Named("servicegroupdependency")
   ResourceProvider getServiceGroupDependencyResourceProvider(AmbariManagementController managementController);
 
+  @Named("clustersetting")
+  ResourceProvider getClusterSettingResourceProvider(AmbariManagementController managementController);
+
   @Named("component")
   ResourceProvider getComponentResourceProvider(AmbariManagementController managementController);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupResponse.java
index 147650c..6b7c32f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupResponse.java
@@ -118,7 +118,7 @@ public class ServiceGroupResponse {
    */
   public interface ServiceGroupResponseSwagger extends ApiModel {
     @ApiModelProperty(name = "ServiceGroupInfo")
-    ServiceResponse getServiceGroupResponse();
+    ServiceGroupResponse getServiceGroupResponse();
   }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/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 0acf78f..5cc2116 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
@@ -154,6 +154,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori
         return new ClusterResourceProvider(managementController);
       case RootClusterSetting:
         return new RootClusterSettingsResourceProvider(managementController);
+      case ClusterSetting:
+        return resourceProviderFactory.getClusterSettingResourceProvider(managementController);
       case Service:
         return resourceProviderFactory.getServiceResourceProvider(managementController);
       case ServiceDependency:

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterSettingResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterSettingResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterSettingResourceProvider.java
new file mode 100644
index 0000000..936826a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterSettingResourceProvider.java
@@ -0,0 +1,554 @@
+/**
+ * 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.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+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.ClusterSettingNotFoundException;
+import org.apache.ambari.server.DuplicateResourceException;
+import org.apache.ambari.server.ObjectNotFoundException;
+import org.apache.ambari.server.ParentObjectNotFoundException;
+import org.apache.ambari.server.PropertyNotFoundException;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.ClusterSettingRequest;
+import org.apache.ambari.server.controller.ClusterSettingResponse;
+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.ClusterSetting;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.Validate;
+
+import com.google.common.collect.Sets;
+import com.google.inject.assistedinject.Assisted;
+import com.google.inject.assistedinject.AssistedInject;
+
+
+/**
+ * Resource provider for Cluster Settings resource.
+ **/
+
+public class ClusterSettingResourceProvider extends AbstractControllerResourceProvider {
+
+
+    // ----- Property ID constants ---------------------------------------------
+
+    public static final String RESPONSE_KEY = "ClusterSettingInfo";
+    public static final String ALL_PROPERTIES = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "*";
+    public static final String CLUSTER_SETTING_CLUSTER_ID_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "cluster_id";
+    public static final String CLUSTER_SETTING_CLUSTER_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "cluster_name";
+    public static final String CLUSTER_SETTING_CLUSTER_SETTING_ID_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "cluster_setting_id";
+    public static final String CLUSTER_SETTING_CLUSTER_SETTING_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "cluster_setting_name";
+    public static final String CLUSTER_SETTING_CLUSTER_SETTING_VALUE_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "cluster_setting_value";
+
+    private static final Set<String> pkPropertyIds =
+            Sets.newHashSet(new String[]{
+                    CLUSTER_SETTING_CLUSTER_NAME_PROPERTY_ID,
+                    CLUSTER_SETTING_CLUSTER_SETTING_NAME_PROPERTY_ID});
+
+    /**
+     * The property ids for an cluster setting resource.
+     */
+    private static final Set<String> PROPERTY_IDS = new HashSet<>();
+
+    /**
+     * The key property ids for an cluster setting resource.
+     */
+    private static final Map<Resource.Type, String> KEY_PROPERTY_IDS = new HashMap<>();
+
+    static {
+        // properties
+        PROPERTY_IDS.add(CLUSTER_SETTING_CLUSTER_ID_PROPERTY_ID);
+        PROPERTY_IDS.add(CLUSTER_SETTING_CLUSTER_NAME_PROPERTY_ID);
+        PROPERTY_IDS.add(CLUSTER_SETTING_CLUSTER_SETTING_ID_PROPERTY_ID);
+        PROPERTY_IDS.add(CLUSTER_SETTING_CLUSTER_SETTING_NAME_PROPERTY_ID);
+        PROPERTY_IDS.add(CLUSTER_SETTING_CLUSTER_SETTING_VALUE_PROPERTY_ID);
+
+        // keys
+        KEY_PROPERTY_IDS.put(Resource.Type.Cluster, CLUSTER_SETTING_CLUSTER_NAME_PROPERTY_ID);
+        KEY_PROPERTY_IDS.put(Resource.Type.ClusterSetting, CLUSTER_SETTING_CLUSTER_SETTING_NAME_PROPERTY_ID);
+    }
+
+    // ----- Constructors ----------------------------------------------------
+
+    /**
+     * Create a  new resource provider for the given management controller.
+     *
+     * @param managementController the management controller
+     */
+    @AssistedInject
+    public ClusterSettingResourceProvider(@Assisted AmbariManagementController managementController) {
+        super(Resource.Type.ClusterSetting, PROPERTY_IDS, KEY_PROPERTY_IDS, managementController);
+    }
+
+    // ----- ResourceProvider ------------------------------------------------
+
+    @Override
+    protected RequestStatus createResourcesAuthorized(Request request)
+            throws SystemException,
+            UnsupportedPropertyException,
+            ResourceAlreadyExistsException,
+            NoSuchParentResourceException {
+
+        final Set<ClusterSettingRequest> requests = new HashSet<>();
+        for (Map<String, Object> propertyMap : request.getProperties()) {
+            requests.add(getRequest(propertyMap));
+        }
+        Set<ClusterSettingResponse> createClusterSettings;
+        createClusterSettings = createResources(new Command<Set<ClusterSettingResponse>>() {
+            @Override
+            public Set<ClusterSettingResponse> invoke() throws AmbariException, AuthorizationException {
+                return createClusterSettings(requests);
+            }
+        });
+        Set<Resource> associatedResources = new HashSet<>();
+        if (createClusterSettings != null) {
+            Iterator<ClusterSettingResponse> itr = createClusterSettings.iterator();
+            while (itr.hasNext()) {
+                ClusterSettingResponse response = itr.next();
+                notifyCreate(Resource.Type.ClusterSetting, request);
+                Resource resource = new ResourceImpl(Resource.Type.ClusterSetting);
+                resource.setProperty(CLUSTER_SETTING_CLUSTER_ID_PROPERTY_ID, response.getClusterId());
+                resource.setProperty(CLUSTER_SETTING_CLUSTER_NAME_PROPERTY_ID, response.getClusterName());
+                resource.setProperty(CLUSTER_SETTING_CLUSTER_SETTING_ID_PROPERTY_ID, response.getClusterSettingId());
+                resource.setProperty(CLUSTER_SETTING_CLUSTER_SETTING_NAME_PROPERTY_ID, response.getClusterSettingName());
+                resource.setProperty(CLUSTER_SETTING_CLUSTER_SETTING_VALUE_PROPERTY_ID, response.getClusterSettingValue());
+
+                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<ClusterSettingRequest> requests = new HashSet<>();
+
+        for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+            requests.add(getRequest(propertyMap));
+        }
+
+        Set<ClusterSettingResponse> responses = getResources(new Command<Set<ClusterSettingResponse>>() {
+            @Override
+            public Set<ClusterSettingResponse> invoke() throws AmbariException {
+                return getClusterSettings(requests);
+            }
+        });
+
+        Set<String> requestedIds = getRequestPropertyIds(request, predicate);
+        Set<Resource> resources = new HashSet<>();
+
+        for (ClusterSettingResponse response : responses) {
+            Resource resource = new ResourceImpl(Resource.Type.ClusterSetting);
+            setResourceProperty(resource, CLUSTER_SETTING_CLUSTER_ID_PROPERTY_ID,
+                    response.getClusterId(), requestedIds);
+            setResourceProperty(resource, CLUSTER_SETTING_CLUSTER_NAME_PROPERTY_ID,
+                    response.getClusterName(), requestedIds);
+            setResourceProperty(resource, CLUSTER_SETTING_CLUSTER_SETTING_ID_PROPERTY_ID,
+                    response.getClusterSettingId(), requestedIds);
+            setResourceProperty(resource, CLUSTER_SETTING_CLUSTER_SETTING_NAME_PROPERTY_ID,
+                    response.getClusterSettingName(), requestedIds);
+            setResourceProperty(resource, CLUSTER_SETTING_CLUSTER_SETTING_VALUE_PROPERTY_ID,
+                    response.getClusterSettingValue(), requestedIds);
+            resources.add(resource);
+        }
+        return resources;
+    }
+
+    @Override
+    protected RequestStatus updateResourcesAuthorized(final Request request, Predicate predicate)
+            throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+        final Set<ClusterSettingRequest> requests = new HashSet<>();
+        for (Map<String, Object> propertyMap : request.getProperties()) {
+            requests.add(getRequest(propertyMap));
+        }
+        Set<ClusterSettingResponse> createClusterSettings;
+        createClusterSettings = modifyResources(new Command<Set<ClusterSettingResponse>>() {
+            @Override
+            public Set<ClusterSettingResponse> invoke() throws AmbariException, AuthorizationException {
+                return updateClusterSettings(requests);
+            }
+        });
+        Set<Resource> associatedResources = new HashSet<>();
+        if (createClusterSettings != null) {
+            Iterator<ClusterSettingResponse> itr = createClusterSettings.iterator();
+            while (itr.hasNext()) {
+                ClusterSettingResponse response = itr.next();
+                notifyUpdate(Resource.Type.ClusterSetting, request, predicate);
+                Resource resource = new ResourceImpl(Resource.Type.ClusterSetting);
+                resource.setProperty(CLUSTER_SETTING_CLUSTER_ID_PROPERTY_ID, response.getClusterId());
+                resource.setProperty(CLUSTER_SETTING_CLUSTER_NAME_PROPERTY_ID, response.getClusterName());
+                resource.setProperty(CLUSTER_SETTING_CLUSTER_SETTING_ID_PROPERTY_ID, response.getClusterSettingId());
+                resource.setProperty(CLUSTER_SETTING_CLUSTER_SETTING_NAME_PROPERTY_ID, response.getClusterSettingName());
+                resource.setProperty(CLUSTER_SETTING_CLUSTER_SETTING_VALUE_PROPERTY_ID, response.getClusterSettingValue());
+
+                associatedResources.add(resource);
+            }
+            return getRequestStatus(null, associatedResources);
+        }
+
+        return getRequestStatus(null);
+    }
+
+    @Override
+    protected RequestStatus deleteResourcesAuthorized(Request request, Predicate predicate)
+            throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+        final Set<ClusterSettingRequest> requests = new HashSet<>();
+
+        for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+            requests.add(getRequest(propertyMap));
+        }
+        DeleteStatusMetaData deleteStatusMetaData;
+        deleteStatusMetaData = modifyResources(new Command<DeleteStatusMetaData>() {
+            @Override
+            public DeleteStatusMetaData invoke() throws AmbariException, AuthorizationException {
+                deleteClusterSettings(requests);
+                return new DeleteStatusMetaData();
+            }
+        });
+
+        notifyDelete(Resource.Type.ClusterSetting, predicate);
+        for(ClusterSettingRequest settingReq : requests) {
+            deleteStatusMetaData.addDeletedKey("cluster_name: "+settingReq.getClusterName() + ", " + "cluster_setting_name: "+settingReq.getClusterSettingName());
+        }
+        return getRequestStatus(null, null, deleteStatusMetaData);
+    }
+
+    // ----- AbstractResourceProvider ----------------------------------------
+
+    @Override
+    protected Set<String> getPKPropertyIds() {
+        return pkPropertyIds;
+    }
+
+    // ----- utility methods -------------------------------------------------
+
+    /**
+     * Get a cluster setting request object from a map of property values.
+     *
+     * @param properties the predicate
+     * @return the service request object
+     */
+    private ClusterSettingRequest getRequest(Map<String, Object> properties) {
+        String clusterName = (String) properties.get(CLUSTER_SETTING_CLUSTER_NAME_PROPERTY_ID);
+        String clusterSettingName = (String) properties.get(CLUSTER_SETTING_CLUSTER_SETTING_NAME_PROPERTY_ID);
+        String clusterSettingValue = (String) properties.get(CLUSTER_SETTING_CLUSTER_SETTING_VALUE_PROPERTY_ID);
+        return  new ClusterSettingRequest(clusterName, clusterSettingName, clusterSettingValue);
+    }
+
+    // Create 'cluster setting' based on the given request.
+    private synchronized Set<ClusterSettingResponse> createClusterSettings(Set<ClusterSettingRequest> 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<ClusterSettingResponse> createdClusterSettings = new HashSet<>();
+        for (ClusterSettingRequest request : requests) {
+            Cluster cluster = clusters.getCluster(request.getClusterName());
+
+            // Already checked that 'cluster setting' does not exist
+            ClusterSetting cs = cluster.addClusterSetting(request.getClusterSettingName(), request.getClusterSettingValue());
+            createdClusterSettings.add(cs.convertToResponse());
+        }
+        return createdClusterSettings;
+    }
+
+    // update 'cluster setting' based on the given request.
+    private synchronized Set<ClusterSettingResponse> updateClusterSettings(Set<ClusterSettingRequest> 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
+        validateUpdateRequests(requests, clusters);
+
+        Set<ClusterSettingResponse> updatedClusterSettings = new HashSet<>();
+        for (ClusterSettingRequest request : requests) {
+            Cluster cluster = clusters.getCluster(request.getClusterName());
+
+            // Already checked that 'cluster setting' exists
+            ClusterSetting cs = cluster.updateClusterSetting(request.getClusterSettingName(), request.getClusterSettingValue());
+            updatedClusterSettings.add(cs.convertToResponse());
+        }
+        return updatedClusterSettings;
+    }
+
+    // Get 'cluster settings' from the given set of requests.
+    private Set<ClusterSettingResponse> getClusterSettings(Set<ClusterSettingRequest> requests)
+            throws AmbariException {
+        Set<ClusterSettingResponse> response = new HashSet<>();
+        for (ClusterSettingRequest request : requests) {
+            try {
+                response.addAll(getClusterSettings(request));
+            } catch (ClusterSettingNotFoundException 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 'cluster settings' from the given request.
+    private Set<ClusterSettingResponse> getClusterSettings(ClusterSettingRequest 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);
+        }
+
+        Set<ClusterSettingResponse> response = new HashSet<>();
+        if (request.getClusterSettingName() != null) {
+            ClusterSetting clusterSetting = cluster.getClusterSetting(request.getClusterSettingName());
+            ClusterSettingResponse clusterSettingResponse = clusterSetting.convertToResponse();
+
+            response.add(clusterSettingResponse);
+            return response;
+        }
+
+        for (ClusterSetting clusterSetting : cluster.getClusterSettings().values()) {
+            ClusterSettingResponse clusterSettingResponse = clusterSetting.convertToResponse();
+            response.add(clusterSettingResponse);
+        }
+        return response;
+    }
+
+
+    // Delete 'cluster setting' based on the given set of requests
+    private void deleteClusterSettings(Set<ClusterSettingRequest> request)
+            throws AmbariException, AuthorizationException {
+
+        Clusters clusters = getManagementController().getClusters();
+
+        Set<ClusterSetting> removable = new HashSet<>();
+
+        for (ClusterSettingRequest clusterSettingRequest : request) {
+            if (null == clusterSettingRequest.getClusterName()
+                    || StringUtils.isEmpty(clusterSettingRequest.getClusterSettingName())) {
+                // FIXME throw correct error
+                throw new AmbariException("invalid arguments");
+            } else {
+
+                // TODO : IS 'CLUSTER_MODIFY_CONFIGS' the correct authorization field to be used ?
+                if (!AuthorizationHelper.isAuthorized(
+                        ResourceType.CLUSTER, getClusterResourceId(clusterSettingRequest.getClusterName()),
+                        RoleAuthorization.CLUSTER_MODIFY_CONFIGS)) {
+                    throw new AuthorizationException("The user is not authorized to delete service groups");
+                }
+
+                ClusterSetting clusterSetting = clusters.getCluster(
+                        clusterSettingRequest.getClusterName()).getClusterSetting(
+                        clusterSettingRequest.getClusterSettingName());
+
+                removable.add(clusterSetting);
+            }
+        }
+
+        for (ClusterSetting clusterSetting : removable) {
+            clusterSetting.getCluster().deleteClusterSetting(clusterSetting.getClusterSettingName());
+        }
+    }
+
+
+    private void validateCreateRequests(Set<ClusterSettingRequest> requests, Clusters clusters)
+            throws AuthorizationException, AmbariException {
+
+        Map<String, Set<String>> clusterSettingNames = new HashMap<>();
+        Set<String> duplicates = new HashSet<>();
+        for (ClusterSettingRequest request : requests) {
+            final String clusterName = request.getClusterName();
+            final String clusterSettingName = request.getClusterSettingName();
+
+            Validate.notNull(clusterName, "Cluster name should be provided when creating a 'cluster setting'");
+            Validate.notEmpty(clusterSettingName, "'Cluster Setting name' should be provided when creating a 'cluster setting'");
+
+            LOG.debug("Received a createClusterSetting request, clusterName= {}, clusterSettingName : {}, " +
+                    "request : {}", clusterName, clusterSettingName, request);
+
+            if (!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER,
+                    getClusterResourceId(clusterName), RoleAuthorization.CLUSTER_MODIFY_CONFIGS)) {
+                throw new AuthorizationException("The user is not authorized to add/create cluster settings");
+            }
+
+            clusterSettingNames.computeIfAbsent(clusterName, k -> new HashSet<>());
+
+            if (clusterSettingNames.get(clusterName).contains(clusterSettingName)) {
+                // throw error later for dup
+                duplicates.add(clusterSettingName);
+                continue;
+            }
+            clusterSettingNames.get(clusterName).add(clusterSettingName);
+
+            Cluster cluster;
+            try {
+                cluster = clusters.getCluster(clusterName);
+            } catch (ClusterNotFoundException e) {
+                throw new ParentObjectNotFoundException("Attempted to add a 'cluster setting' to a cluster which doesn't exist", e);
+            }
+            try {
+                ClusterSetting cs = cluster.getClusterSetting(clusterSettingName);
+                if (cs != null) {
+                    // throw error later for dup
+                    duplicates.add(clusterSettingName);
+                    continue;
+                }
+            } catch (ClusterSettingNotFoundException e) {
+                // Expected
+            }
+        }
+        // ensure only a single cluster update
+        if (clusterSettingNames.size() != 1) {
+            throw new IllegalArgumentException("Invalid arguments, updates allowed" +
+                    "on only one cluster at a time");
+        }
+
+        // Validate dups
+        if (!duplicates.isEmpty()) {
+            String clusterName = requests.iterator().next().getClusterName();
+            String msg = "Attempted to add/create a 'cluster setting' which already exists: " +
+                    ", clusterName=" + clusterName + " clusterSettingName=" + StringUtils.join(duplicates, ",");
+
+            throw new DuplicateResourceException(msg);
+        }
+    }
+
+    private void validateUpdateRequests(Set<ClusterSettingRequest> requests, Clusters clusters)
+            throws AuthorizationException, AmbariException {
+
+        Map<String, Set<String>> clusterSettingNames = new HashMap<>();
+        Set<String> duplicates = new HashSet<>();
+        Set<String> nonExisting = new HashSet<>();
+        for (ClusterSettingRequest request : requests) {
+            final String clusterName = request.getClusterName();
+            final String clusterSettingName = request.getClusterSettingName();
+
+            Validate.notNull(clusterName, "Cluster name should be provided when updating a 'cluster setting'");
+            Validate.notEmpty(clusterSettingName, "'Cluster Setting name' should be provided when creating a 'cluster setting'");
+
+            LOG.debug("Received a updateClusterSetting request, clusterName= {}, clusterSettingName : {}, " +
+                    "request : {}", clusterName, clusterSettingName, request);
+
+            if (!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER,
+                    getClusterResourceId(clusterName), RoleAuthorization.CLUSTER_MODIFY_CONFIGS)) {
+                throw new AuthorizationException("The user is not authorized to update cluster settings");
+            }
+
+            clusterSettingNames.computeIfAbsent(clusterName, k -> new HashSet<>());
+
+            if (clusterSettingNames.get(clusterName).contains(clusterSettingName)) {
+                // throw error later for dup
+                duplicates.add(clusterSettingName);
+                continue;
+            }
+            clusterSettingNames.get(clusterName).add(clusterSettingName);
+
+            Cluster cluster;
+            try {
+                cluster = clusters.getCluster(clusterName);
+            } catch (ClusterNotFoundException e) {
+                throw new ParentObjectNotFoundException("Attempted to update a 'cluster setting' to a cluster which doesn't exist", e);
+            }
+            try {
+                ClusterSetting cs = cluster.getClusterSetting(clusterSettingName);
+                if (cs == null) {
+                    // throw error later for it not being present.
+                    nonExisting.add(clusterSettingName);
+                    continue;
+                }
+            } catch (ClusterSettingNotFoundException e) {
+                // Expected
+            }
+        }
+        // ensure only a single cluster update
+        if (clusterSettingNames.size() != 1) {
+            throw new IllegalArgumentException("Invalid arguments, updates allowed" +
+                    "on only one cluster at a time");
+        }
+
+        // Validate dups
+        if (!duplicates.isEmpty()) {
+            String clusterName = requests.iterator().next().getClusterName();
+            String msg = "Attempted to update a 'cluster setting' which has more than one occurrence: " +
+                    ", clusterName=" + clusterName + " clusterSettingName=" + StringUtils.join(nonExisting, ",");
+
+            throw new DuplicateResourceException(msg);
+        }
+
+        // Validate non existing one(s)
+        if (!nonExisting.isEmpty()) {
+            String clusterName = requests.iterator().next().getClusterName();
+            String msg = "Attempted to update a 'cluster setting' which doesn't exist: " +
+                    ", clusterName=" + clusterName + " clusterSettingName=" + StringUtils.join(nonExisting, ",");
+
+            throw new PropertyNotFoundException(msg);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/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 2f8f65f..674b352 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
@@ -78,6 +78,8 @@ public class DefaultProviderModule extends AbstractProviderModule {
         return new ViewPermissionResourceProvider();
       case ClusterPrivilege:
         return new ClusterPrivilegeResourceProvider();
+      case ClusterSetting:
+        return new ClusterSettingResourceProvider(managementController);
       case LdapSyncEvent:
         return new LdapSyncEventResourceProvider(managementController);
       case UserPrivilege:

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupResourceProvider.java
index 2e935af..baccc10 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupResourceProvider.java
@@ -314,7 +314,7 @@ public class ServiceGroupResourceProvider extends AbstractControllerResourceProv
     return response;
   }
 
-  // Get services from the given request.
+  // Get services groups from the given request.
   private Set<ServiceGroupResponse> getServiceGroups(ServiceGroupRequest request)
     throws AmbariException {
     if (request.getClusterName() == null) {
@@ -349,7 +349,7 @@ public class ServiceGroupResourceProvider extends AbstractControllerResourceProv
   }
 
 
-  // Delete services based on the given set of requests
+  // Delete services groups based on the given set of requests
   protected void deleteServiceGroups(Set<ServiceGroupRequest> request)
     throws AmbariException, AuthorizationException {
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/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 31b7517..64ea97b 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
@@ -76,6 +76,7 @@ public interface Resource {
   enum InternalType {
     Cluster,
     RootClusterSetting,
+    ClusterSetting,
     Service,
     ServiceDependency,
     ServiceGroup,
@@ -210,6 +211,7 @@ public interface Resource {
      */
     public static final Type Cluster = InternalType.Cluster.getType();
     public static final Type RootClusterSetting = InternalType.RootClusterSetting.getType();
+    public static final Type ClusterSetting = InternalType.ClusterSetting.getType();
     public static final Type ServiceGroup = InternalType.ServiceGroup.getType();
     public static final Type ServiceGroupDependency = InternalType.ServiceGroupDependency.getType();
     public static final Type Service = InternalType.Service.getType();

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/events/ClusterSettingEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/ClusterSettingEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/ClusterSettingEvent.java
new file mode 100644
index 0000000..3d32831
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/ClusterSettingEvent.java
@@ -0,0 +1,46 @@
+/**
+ * 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.events;
+
+
+public abstract class ClusterSettingEvent extends ClusterEvent {
+
+    /**
+     * The name of the 'cluster setting'.
+     */
+    protected final String m_clusterSettingName;
+
+    /**
+     * Constructor.
+     *
+     * @param eventType
+     * @param clusterId
+     */
+    public ClusterSettingEvent(AmbariEventType eventType, long clusterId, String clusterSettingName) {
+        super(eventType, clusterId);
+        m_clusterSettingName = clusterSettingName;
+    }
+
+    /**
+     * @return the cluster setting name (never {@code null}).
+     */
+    public String getServiceGroupName() {
+        return m_clusterSettingName;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterSettingDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterSettingDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterSettingDAO.java
new file mode 100644
index 0000000..7fa7adc
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterSettingDAO.java
@@ -0,0 +1,100 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.dao;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.ClusterSettingEntity;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+
+@Singleton
+public class ClusterSettingDAO {
+    @Inject
+    Provider<EntityManager> entityManagerProvider;
+    @Inject
+    DaoUtils daoUtils;
+
+    @RequiresSession
+    public ClusterSettingEntity findByPK(Long clusterSettingId) {
+        TypedQuery<ClusterSettingEntity> query = entityManagerProvider.get()
+                .createNamedQuery("clusterSettingById", ClusterSettingEntity.class);
+        query.setParameter("clusterSettingId", clusterSettingId);
+
+        try {
+            return query.getSingleResult();
+        } catch (NoResultException ignored) {
+            return null;
+        }
+    }
+
+    @RequiresSession
+    public ClusterSettingEntity findByClusterIdAndSettingName(Long clusterId, String clusterSettingName) {
+        TypedQuery<ClusterSettingEntity> query = entityManagerProvider.get()
+                .createNamedQuery("clusterSettingByClusterIdAndSettingName", ClusterSettingEntity.class);
+        query.setParameter("clusterId", clusterId);
+        query.setParameter("clusterSettingName", clusterSettingName);
+
+        try {
+            return query.getSingleResult();
+        } catch (NoResultException ignored) {
+            return null;
+        }
+    }
+
+    @RequiresSession
+    public List<ClusterSettingEntity> findAll() {
+        return daoUtils.selectAll(entityManagerProvider.get(), ClusterSettingEntity.class);
+    }
+
+    @Transactional
+    public void refresh(ClusterSettingEntity clusterSettingEntity) {
+        entityManagerProvider.get().refresh(clusterSettingEntity);
+    }
+
+    @Transactional
+    public void create(ClusterSettingEntity clusterSettingEntity) {
+        entityManagerProvider.get().persist(clusterSettingEntity);
+    }
+
+    @Transactional
+    public ClusterSettingEntity merge(ClusterSettingEntity clusterSettingEntity) {
+        return entityManagerProvider.get().merge(clusterSettingEntity);
+    }
+
+    @Transactional
+    public void remove(ClusterSettingEntity clusterSettingEntity) {
+        entityManagerProvider.get().remove(merge(clusterSettingEntity));
+    }
+
+    @Transactional
+    public void removeByPK(Long clusterId) {
+        ClusterSettingEntity entity = findByPK(clusterId);
+        entityManagerProvider.get().remove(entity);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
index abbf709..793f1a1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
@@ -108,6 +108,9 @@ public class ClusterEntity {
   @OneToMany(mappedBy = "clusterEntity")
   private Collection<ServiceGroupEntity> serviceGroupEntities;
 
+  @OneToMany(mappedBy = "clusterEntity")
+  private Collection<ClusterSettingEntity> clusterSettingEntities;
+
   @OneToOne(mappedBy = "clusterEntity", cascade = CascadeType.REMOVE)
   private ClusterStateEntity clusterStateEntity;
 
@@ -281,6 +284,14 @@ public class ClusterEntity {
     this.serviceGroupEntities = serviceGroupEntities;
   }
 
+  public Collection<ClusterSettingEntity> getClusterSettingEntities() {
+    return clusterSettingEntities;
+  }
+
+  public void setClusterSettingEntities(Collection<ClusterSettingEntity> clusterSettingEntities) {
+    this.clusterSettingEntities = clusterSettingEntities;
+  }
+
   public ClusterStateEntity getClusterStateEntity() {
     return clusterStateEntity;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterSettingEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterSettingEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterSettingEntity.java
new file mode 100644
index 0000000..10a829c
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterSettingEntity.java
@@ -0,0 +1,131 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.entities;
+
+import java.util.Objects;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+
+
+@Table(name = "clustersettings")
+@NamedQueries({
+        @NamedQuery(name = "clusterSettingByClusterIdAndSettingName", query =
+                "SELECT clusterSetting " +
+                        "FROM ClusterSettingEntity clusterSetting " +
+                        "JOIN clusterSetting.clusterEntity cluster " +
+                        "WHERE clusterSetting.clusterSettingName=:clusterSettingName AND cluster.clusterId=:clusterId"),
+        @NamedQuery(name = "clusterSettingById", query =
+                "SELECT clusterSetting " +
+                        "FROM ClusterSettingEntity clusterSetting " +
+                        "WHERE clusterSetting.clusterSettingId=:clusterSettingId"),
+})
+@Entity
+@TableGenerator(name = "cluster_setting_id_generator",
+        table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value"
+        , pkColumnValue = "cluster_setting_id_seq"
+        , initialValue = 1
+)
+public class ClusterSettingEntity {
+
+    @Id
+    @Column(name = "id", nullable = false, insertable = true, updatable = true)
+    @GeneratedValue(strategy = GenerationType.TABLE, generator = "cluster_setting_id_generator")
+    private Long clusterSettingId;
+
+    @Column(name = "cluster_id", nullable = false, insertable = false, updatable = false, length = 10)
+    private Long clusterId;
+
+    @Column(name = "setting_name", nullable = false, insertable = true, updatable = false)
+    private String clusterSettingName;
+
+    @Column(name = "setting_value", nullable = false, insertable = true, updatable = true)
+    private String clusterSettingValue;
+
+    @ManyToOne
+    @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false)
+    private ClusterEntity clusterEntity;
+
+    public Long getClusterId() {
+        return clusterId;
+    }
+
+    public void setClusterId(Long clusterId) {
+        this.clusterId = clusterId;
+    }
+
+    public Long getClusterSettingId() {
+        return clusterSettingId;
+    }
+
+    public void setClusterSettingId(Long clusterSettingId) {
+        this.clusterSettingId = clusterSettingId;
+    }
+
+
+    public String getClusterSettingName() {
+        return clusterSettingName;
+    }
+
+    public void setClusterSettingName(String clusterSettingName) {
+        this.clusterSettingName = clusterSettingName;
+    }
+
+    public String getClusterSettingValue() {
+        return clusterSettingValue;
+    }
+
+    public void setClusterSettingValue(String clusterSettingValue) {
+        this.clusterSettingValue = clusterSettingValue;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ClusterSettingEntity that = (ClusterSettingEntity) o;
+        return Objects.equals(clusterId, that.clusterId) &&
+               Objects.equals(clusterSettingName, that.clusterSettingName);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(clusterId, clusterSettingName);
+    }
+
+    public ClusterEntity getClusterEntity() {
+        return clusterEntity;
+    }
+
+    public void setClusterEntity(ClusterEntity clusterEntity) {
+        this.clusterEntity = clusterEntity;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/49592068/ambari-server/src/main/java/org/apache/ambari/server/resources/RootLevelSettingsManager.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/resources/RootLevelSettingsManager.java b/ambari-server/src/main/java/org/apache/ambari/server/resources/RootLevelSettingsManager.java
index 3b74e69..8bd24f2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/resources/RootLevelSettingsManager.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/resources/RootLevelSettingsManager.java
@@ -65,7 +65,7 @@ public class RootLevelSettingsManager {
     clusterSettingsFileName = settingsFileName;
     clusterSettingsConfigType = settingsTypeName;
     clusterSettingsFile = new File(clusterSettingsPath + File.separator + clusterSettingsFileName);
-    LOG.info("\n\n\n\n SWAP - clusterSettingsPath = "+clusterSettingsPath+" - clusterSettingsFileName = "+clusterSettingsFileName
+    LOG.debug("clusterSettingsPath = "+clusterSettingsPath+" - clusterSettingsFileName = "+clusterSettingsFileName
             +" - clusterSettingsConfigType = "+clusterSettingsFile + "clusterSettingsFile = "+clusterSettingsFile);
     populateClusterSettingsXml();
   }


[05/17] ambari git commit: AMBARI-22355 : Addendum patch for adding service_id to clusterconfig (mradhakrishnan)

Posted by be...@apache.org.
AMBARI-22355 : Addendum patch for adding service_id to clusterconfig (mradhakrishnan)


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: 55e450eea40030d21addbb3aa06bf5d87668ae6e
Parents: 4959206
Author: Madhuvanthi Radhakrishnan <mr...@hortonworks.com>
Authored: Fri Nov 10 15:57:00 2017 -0800
Committer: Madhuvanthi Radhakrishnan <mr...@hortonworks.com>
Committed: Fri Nov 10 15:57:00 2017 -0800

----------------------------------------------------------------------
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  | 44 ++++++++++----------
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  | 44 ++++++++++----------
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql | 43 +++++++++----------
 .../resources/Ambari-DDL-Postgres-CREATE.sql    | 43 +++++++++----------
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql | 43 +++++++++----------
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   | 43 +++++++++----------
 6 files changed, 134 insertions(+), 126 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/55e450ee/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 039d8af..a591bbf 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
@@ -86,27 +86,6 @@ CREATE TABLE clusters (
   CONSTRAINT FK_clusters_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id),
   CONSTRAINT FK_clusters_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource(resource_id));
 
-CREATE TABLE clusterconfig (
-  config_id BIGINT NOT NULL,
-  version_tag VARCHAR(255) NOT NULL,
-  version BIGINT NOT NULL,
-  type_name VARCHAR(255) NOT NULL,
-  cluster_id BIGINT NOT NULL,
-  stack_id BIGINT NOT NULL,
-  selected SMALLINT NOT NULL DEFAULT 0,
-  config_data VARCHAR(3000) NOT NULL,
-  config_attributes VARCHAR(3000),
-  create_timestamp BIGINT NOT NULL,
-  unmapped SMALLINT NOT NULL DEFAULT 0,
-  selected_timestamp BIGINT NOT NULL DEFAULT 0,
-  service_id BIGINT,
-  CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
-  CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
-  CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
-  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
-  CONSTRAINT UQ_config_type_tag UNIQUE (version_tag, type_name, cluster_id),
-  CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
-
 CREATE TABLE configuration_base (
   id BIGINT NOT NULL,
   version_tag VARCHAR(255) NOT NULL,
@@ -176,8 +155,31 @@ CREATE TABLE clusterservices (
   service_group_id BIGINT NOT NULL,
   service_enabled INTEGER NOT NULL,
   CONSTRAINT PK_clusterservices PRIMARY KEY (id, service_group_id, cluster_id),
+  CONSTRAINT UQ_service_id UNIQUE (id),
   CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (service_group_id, cluster_id) REFERENCES servicegroups (id, cluster_id));
 
+CREATE TABLE clusterconfig (
+  config_id BIGINT NOT NULL,
+  version_tag VARCHAR(255) NOT NULL,
+  version BIGINT NOT NULL,
+  type_name VARCHAR(255) NOT NULL,
+  cluster_id BIGINT NOT NULL,
+  stack_id BIGINT NOT NULL,
+  selected SMALLINT NOT NULL DEFAULT 0,
+  config_data VARCHAR(3000) NOT NULL,
+  config_attributes VARCHAR(3000),
+  create_timestamp BIGINT NOT NULL,
+  unmapped SMALLINT NOT NULL DEFAULT 0,
+  selected_timestamp BIGINT NOT NULL DEFAULT 0,
+  service_id BIGINT,
+  CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
+  CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
+  CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
+  CONSTRAINT UQ_config_type_tag UNIQUE (version_tag, type_name, cluster_id),
+  CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
+
+
 CREATE TABLE servicedependencies (
   service_id BIGINT NOT NULL,
   service_group_id BIGINT NOT NULL,

http://git-wip-us.apache.org/repos/asf/ambari/blob/55e450ee/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 e14f0f1..6c2c0f4 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -105,27 +105,6 @@ CREATE TABLE clusters (
   CONSTRAINT FK_clusters_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id),
   CONSTRAINT FK_clusters_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource(resource_id));
 
-CREATE TABLE clusterconfig (
-  config_id BIGINT NOT NULL,
-  version_tag VARCHAR(100) NOT NULL,
-  version BIGINT NOT NULL,
-  type_name VARCHAR(100) NOT NULL,
-  cluster_id BIGINT NOT NULL,
-  stack_id BIGINT NOT NULL,
-  selected SMALLINT NOT NULL DEFAULT 0,
-  config_data LONGTEXT NOT NULL,
-  config_attributes LONGTEXT,
-  create_timestamp BIGINT NOT NULL,
-  unmapped SMALLINT NOT NULL DEFAULT 0,
-  selected_timestamp BIGINT NOT NULL DEFAULT 0,
-  service_id BIGINT,
-  CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
-  CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
-  CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
-  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
-  CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
-  CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
-
 CREATE TABLE configuration_base (
   id BIGINT NOT NULL,
   version_tag VARCHAR(100) NOT NULL,
@@ -195,8 +174,31 @@ CREATE TABLE clusterservices (
   service_group_id BIGINT NOT NULL,
   service_enabled INTEGER NOT NULL,
   CONSTRAINT PK_clusterservices PRIMARY KEY (id, service_group_id, cluster_id),
+  CONSTRAINT UQ_service_id UNIQUE (id),
   CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (service_group_id, cluster_id) REFERENCES servicegroups (id, cluster_id));
 
+
+CREATE TABLE clusterconfig (
+  config_id BIGINT NOT NULL,
+  version_tag VARCHAR(100) NOT NULL,
+  version BIGINT NOT NULL,
+  type_name VARCHAR(100) NOT NULL,
+  cluster_id BIGINT NOT NULL,
+  stack_id BIGINT NOT NULL,
+  selected SMALLINT NOT NULL DEFAULT 0,
+  config_data LONGTEXT NOT NULL,
+  config_attributes LONGTEXT,
+  create_timestamp BIGINT NOT NULL,
+  unmapped SMALLINT NOT NULL DEFAULT 0,
+  selected_timestamp BIGINT NOT NULL DEFAULT 0,
+  service_id BIGINT,
+  CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
+  CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
+  CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
+  CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
+  CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
+
 CREATE TABLE servicedependencies (
   service_id BIGINT NOT NULL,
   service_group_id BIGINT NOT NULL,

http://git-wip-us.apache.org/repos/asf/ambari/blob/55e450ee/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 a5911eb..d697e05 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -86,27 +86,6 @@ CREATE TABLE clusters (
   CONSTRAINT FK_clusters_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id),
   CONSTRAINT FK_clusters_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource(resource_id));
 
-CREATE TABLE clusterconfig (
-  config_id NUMBER(19) NOT NULL,
-  version_tag VARCHAR2(255) NOT NULL,
-  version NUMBER(19) NOT NULL,
-  type_name VARCHAR2(255) NOT NULL,
-  cluster_id NUMBER(19) NOT NULL,
-  stack_id NUMBER(19) NOT NULL,
-  selected NUMBER(1) DEFAULT 0 NOT NULL,
-  config_data CLOB NOT NULL,
-  config_attributes CLOB,
-  create_timestamp NUMBER(19) NOT NULL,
-  unmapped SMALLINT DEFAULT 0 NOT NULL,
-  selected_timestamp NUMBER(19) DEFAULT 0 NOT NULL,
-  service_id BIGINT,
-  CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
-  CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
-  CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
-  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
-  CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
-  CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
-
 CREATE TABLE configuration_base (
   id NUMBER(19) NOT NULL,
   version_tag VARCHAR(255) NOT NULL,
@@ -176,8 +155,30 @@ CREATE TABLE clusterservices (
   service_group_id NUMBER(19) NOT NULL,
   service_enabled NUMBER(10) NOT NULL,
   CONSTRAINT PK_clusterservices PRIMARY KEY (id, service_group_id, cluster_id),
+  CONSTRAINT UQ_service_id UNIQUE (id),
   CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (service_group_id, cluster_id) REFERENCES servicegroups (id, cluster_id));
 
+CREATE TABLE clusterconfig (
+  config_id NUMBER(19) NOT NULL,
+  version_tag VARCHAR2(255) NOT NULL,
+  version NUMBER(19) NOT NULL,
+  type_name VARCHAR2(255) NOT NULL,
+  cluster_id NUMBER(19) NOT NULL,
+  stack_id NUMBER(19) NOT NULL,
+  selected NUMBER(1) DEFAULT 0 NOT NULL,
+  config_data CLOB NOT NULL,
+  config_attributes CLOB,
+  create_timestamp NUMBER(19) NOT NULL,
+  unmapped SMALLINT DEFAULT 0 NOT NULL,
+  selected_timestamp NUMBER(19) DEFAULT 0 NOT NULL,
+  service_id BIGINT,
+  CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
+  CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
+  CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
+  CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
+  CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
+
 CREATE TABLE servicedependencies (
   service_id NUMBER(19) NOT NULL,
   service_group_id NUMBER(19) NOT NULL,

http://git-wip-us.apache.org/repos/asf/ambari/blob/55e450ee/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 c5203e4..f9544a5 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -104,27 +104,6 @@ CREATE TABLE ambari_configuration (
   CONSTRAINT FK_ambari_conf_conf_base FOREIGN KEY (id) REFERENCES configuration_base (id)
 );
 
-CREATE TABLE clusterconfig (
-  config_id BIGINT NOT NULL,
-  version_tag VARCHAR(255) NOT NULL,
-  version BIGINT NOT NULL,
-  type_name VARCHAR(255) NOT NULL,
-  cluster_id BIGINT NOT NULL,
-  stack_id BIGINT NOT NULL,
-  selected SMALLINT NOT NULL DEFAULT 0,
-  config_data TEXT NOT NULL,
-  config_attributes TEXT,
-  create_timestamp BIGINT NOT NULL,
-  unmapped SMALLINT NOT NULL DEFAULT 0,
-  selected_timestamp BIGINT NOT NULL DEFAULT 0,
-  service_id BIGINT,
-  CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
-  CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
-  CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
-  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
-  CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
-  CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
-
 CREATE TABLE hosts (
   host_id BIGINT NOT NULL,
   host_name VARCHAR(255) NOT NULL,
@@ -177,8 +156,30 @@ CREATE TABLE clusterservices (
   service_group_id BIGINT NOT NULL,
   service_enabled INTEGER NOT NULL,
   CONSTRAINT PK_clusterservices PRIMARY KEY (id, service_group_id, cluster_id),
+  CONSTRAINT UQ_service_id UNIQUE (id),
   CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (service_group_id, cluster_id) REFERENCES servicegroups (id, cluster_id));
 
+CREATE TABLE clusterconfig (
+  config_id BIGINT NOT NULL,
+  version_tag VARCHAR(255) NOT NULL,
+  version BIGINT NOT NULL,
+  type_name VARCHAR(255) NOT NULL,
+  cluster_id BIGINT NOT NULL,
+  stack_id BIGINT NOT NULL,
+  selected SMALLINT NOT NULL DEFAULT 0,
+  config_data TEXT NOT NULL,
+  config_attributes TEXT,
+  create_timestamp BIGINT NOT NULL,
+  unmapped SMALLINT NOT NULL DEFAULT 0,
+  selected_timestamp BIGINT NOT NULL DEFAULT 0,
+  service_id BIGINT,
+  CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
+  CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
+  CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
+  CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
+  CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
+
 CREATE TABLE servicedependencies (
   service_id BIGINT NOT NULL,
   service_group_id BIGINT NOT NULL,

http://git-wip-us.apache.org/repos/asf/ambari/blob/55e450ee/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 a9032f3..fb98cbd 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -85,27 +85,6 @@ CREATE TABLE clusters (
   CONSTRAINT FK_clusters_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id),
   CONSTRAINT FK_clusters_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource(resource_id));
 
-CREATE TABLE clusterconfig (
-  config_id NUMERIC(19) NOT NULL,
-  version_tag VARCHAR(255) NOT NULL,
-  version NUMERIC(19) NOT NULL,
-  type_name VARCHAR(255) NOT NULL,
-  cluster_id NUMERIC(19) NOT NULL,
-  stack_id NUMERIC(19) NOT NULL,
-  selected SMALLINT NOT NULL DEFAULT 0,
-  config_data TEXT NOT NULL,
-  config_attributes TEXT,
-  create_timestamp NUMERIC(19) NOT NULL,
-  unmapped SMALLINT NOT NULL DEFAULT 0,
-  selected_timestamp NUMERIC(19) NOT NULL DEFAULT 0,
-  service_id BIGINT,
-  CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
-  CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
-  CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
-  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
-  CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
-  CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
-
 CREATE TABLE configuration_base (
   id NUMERIC(19) NOT NULL,
   version_tag VARCHAR(255) NOT NULL,
@@ -175,8 +154,30 @@ CREATE TABLE clusterservices (
   service_group_id NUMERIC(19) NOT NULL,
   service_enabled INTEGER NOT NULL,
   CONSTRAINT PK_clusterservices PRIMARY KEY (id, service_group_id, cluster_id),
+  CONSTRAINT UQ_service_id UNIQUE (id),
   CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (service_group_id, cluster_id) REFERENCES servicegroups (id, cluster_id));
 
+CREATE TABLE clusterconfig (
+  config_id NUMERIC(19) NOT NULL,
+  version_tag VARCHAR(255) NOT NULL,
+  version NUMERIC(19) NOT NULL,
+  type_name VARCHAR(255) NOT NULL,
+  cluster_id NUMERIC(19) NOT NULL,
+  stack_id NUMERIC(19) NOT NULL,
+  selected SMALLINT NOT NULL DEFAULT 0,
+  config_data TEXT NOT NULL,
+  config_attributes TEXT,
+  create_timestamp NUMERIC(19) NOT NULL,
+  unmapped SMALLINT NOT NULL DEFAULT 0,
+  selected_timestamp NUMERIC(19) NOT NULL DEFAULT 0,
+  service_id BIGINT,
+  CONSTRAINT PK_clusterconfig PRIMARY KEY (config_id),
+  CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
+  CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
+  CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
+  CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
+
 CREATE TABLE servicedependencies (
   service_id NUMERIC(19) NOT NULL,
   service_group_id NUMERIC(19) NOT NULL,

http://git-wip-us.apache.org/repos/asf/ambari/blob/55e450ee/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 d782155..9f93fbb 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -99,27 +99,6 @@ CREATE TABLE clusters (
   CONSTRAINT FK_clusters_desired_stack_id FOREIGN KEY (desired_stack_id) REFERENCES stack(stack_id),
   CONSTRAINT FK_clusters_resource_id FOREIGN KEY (resource_id) REFERENCES adminresource(resource_id));
 
-CREATE TABLE clusterconfig (
-  config_id BIGINT NOT NULL,
-  version_tag VARCHAR(255) NOT NULL,
-  version BIGINT NOT NULL,
-  type_name VARCHAR(255) NOT NULL,
-  cluster_id BIGINT NOT NULL,
-  stack_id BIGINT NOT NULL,
-  selected SMALLINT NOT NULL DEFAULT 0,
-  config_data VARCHAR(MAX) NOT NULL,
-  config_attributes VARCHAR(MAX),
-  create_timestamp BIGINT NOT NULL,
-  unmapped SMALLINT NOT NULL DEFAULT 0,
-  selected_timestamp BIGINT NOT NULL DEFAULT 0,
-  service_id BIGINT,
-  CONSTRAINT PK_clusterconfig PRIMARY KEY CLUSTERED (config_id),
-  CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
-  CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
-  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
-  CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
-  CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
-
 CREATE TABLE configuration_base (
   id BIGINT NOT NULL,
   version_tag VARCHAR(255) NOT NULL,
@@ -189,8 +168,30 @@ CREATE TABLE clusterservices (
   service_group_id BIGINT NOT NULL,
   service_enabled INT NOT NULL,
   CONSTRAINT PK_clusterservices PRIMARY KEY (id, service_group_id, cluster_id),
+  CONSTRAINT UQ_service_id UNIQUE (id),
   CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (service_group_id, cluster_id) REFERENCES servicegroups (id, cluster_id));
 
+CREATE TABLE clusterconfig (
+  config_id BIGINT NOT NULL,
+  version_tag VARCHAR(255) NOT NULL,
+  version BIGINT NOT NULL,
+  type_name VARCHAR(255) NOT NULL,
+  cluster_id BIGINT NOT NULL,
+  stack_id BIGINT NOT NULL,
+  selected SMALLINT NOT NULL DEFAULT 0,
+  config_data VARCHAR(MAX) NOT NULL,
+  config_attributes VARCHAR(MAX),
+  create_timestamp BIGINT NOT NULL,
+  unmapped SMALLINT NOT NULL DEFAULT 0,
+  selected_timestamp BIGINT NOT NULL DEFAULT 0,
+  service_id BIGINT,
+  CONSTRAINT PK_clusterconfig PRIMARY KEY CLUSTERED (config_id),
+  CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id),
+  CONSTRAINT FK_clusterconfig_stack_id FOREIGN KEY (stack_id) REFERENCES stack(stack_id),
+  CONSTRAINT FK_clusterconfig_service_id FOREIGN KEY (service_id) REFERENCES clusterservices(id),
+  CONSTRAINT UQ_config_type_tag UNIQUE (cluster_id, type_name, version_tag),
+  CONSTRAINT UQ_config_type_version UNIQUE (cluster_id, type_name, version));
+
 CREATE TABLE servicedependencies (
   service_id BIGINT NOT NULL,
   service_group_id BIGINT NOT NULL,


[14/17] ambari git commit: AMBARI-22325 Fix dependency injection in BaseClusterRequest (benyoka)

Posted by be...@apache.org.
AMBARI-22325 Fix dependency injection in BaseClusterRequest (benyoka)


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: 26143bceb02f0fb54495dbb7fba9fa34e0b5f0c7
Parents: c9e2f6e
Author: Balazs Bence Sari <be...@apache.org>
Authored: Mon Nov 13 14:55:16 2017 +0100
Committer: Balazs Bence Sari <be...@apache.org>
Committed: Tue Nov 14 11:31:16 2017 +0100

----------------------------------------------------------------------
 .../org/apache/ambari/server/controller/AmbariServer.java   | 2 +-
 .../server/controller/internal/BaseClusterRequest.java      | 9 +++------
 .../apache/ambari/server/topology/BlueprintV2Factory.java   | 1 +
 3 files changed, 5 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/26143bce/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index b28cb11..970fb56 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -934,7 +934,7 @@ public class AmbariServer {
     HostResourceProvider.setTopologyManager(injector.getInstance(TopologyManager.class));
     BlueprintFactory.init(injector.getInstance(BlueprintDAO.class));
     BlueprintV2Factory.init(injector.getInstance(BlueprintV2DAO.class));
-    BaseClusterRequest.init(injector.getInstance(BlueprintV2Factory.class));
+    BaseClusterRequest.init(injector.getInstance(AmbariManagementController.class));
     AmbariContext.init(injector.getInstance(HostRoleCommandFactory.class));
 
     PermissionResourceProvider.init(injector.getInstance(PermissionDAO.class));

http://git-wip-us.apache.org/repos/asf/ambari/blob/26143bce/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BaseClusterRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BaseClusterRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BaseClusterRequest.java
index a38f478..eefb31b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BaseClusterRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BaseClusterRequest.java
@@ -27,6 +27,7 @@ import java.util.Set;
 import org.apache.ambari.server.api.predicate.InvalidQueryException;
 import org.apache.ambari.server.api.predicate.QueryLexer;
 import org.apache.ambari.server.api.predicate.Token;
+import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
 import org.apache.ambari.server.controller.utilities.ClusterControllerHelper;
@@ -92,12 +93,8 @@ public abstract class BaseClusterRequest implements TopologyRequest {
   private static ResourceProvider hostResourceProvider;
 
 
-  /**
-   * inject blueprint factory
-   * @param factory  blueprint factory
-   */
-  public static void init(BlueprintV2Factory factory) {
-    blueprintFactory = factory;
+  public static void init(AmbariManagementController controller) {
+    blueprintFactory = BlueprintV2Factory.create(controller);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/26143bce/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
index 9870dcb..47aed80 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
@@ -82,6 +82,7 @@ public class BlueprintV2Factory {
   protected BlueprintV2Factory() {
 
   }
+
   protected BlueprintV2Factory(StackV2Factory stackFactory) {
     this.stackFactory = stackFactory;
   }


[11/17] ambari git commit: AMBARI-22325 Fixes for v2 blueprint json serialization/deserialization (benyoka)

Posted by be...@apache.org.
AMBARI-22325 Fixes for v2 blueprint json serialization/deserialization (benyoka)


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: 57bef16ce0b9326e93a343e4f167e215ea50169c
Parents: 35d704c
Author: Balazs Bence Sari <be...@apache.org>
Authored: Mon Nov 6 11:18:55 2017 +0100
Committer: Balazs Bence Sari <be...@apache.org>
Committed: Tue Nov 14 11:31:15 2017 +0100

----------------------------------------------------------------------
 .../ambari/server/controller/AmbariServer.java  |   1 +
 .../ambari/server/topology/BlueprintImplV2.java |  24 +++-
 .../server/topology/BlueprintV2Factory.java     |  29 +++-
 .../ambari/server/topology/ComponentV2.java     |   5 +
 .../ambari/server/topology/Configurable.java    |  25 +++-
 .../ambari/server/topology/HostGroupV2Impl.java |   7 +
 .../apache/ambari/server/topology/Service.java  |  15 ++
 .../validators/BlueprintImplV2Test.java         |  32 ++++-
 .../resources/blueprintv2/blueprintv2_2.json    | 139 +++++++++++++++++++
 9 files changed, 261 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/57bef16c/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index 9bd8dd3..b28cb11 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -933,6 +933,7 @@ public class AmbariServer {
             .class), injector.getInstance(Gson.class));
     HostResourceProvider.setTopologyManager(injector.getInstance(TopologyManager.class));
     BlueprintFactory.init(injector.getInstance(BlueprintDAO.class));
+    BlueprintV2Factory.init(injector.getInstance(BlueprintV2DAO.class));
     BaseClusterRequest.init(injector.getInstance(BlueprintV2Factory.class));
     AmbariContext.init(injector.getInstance(HostRoleCommandFactory.class));
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/57bef16c/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java
index d31e9d4..d889fc2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java
@@ -23,6 +23,7 @@ import static java.util.stream.Collectors.toList;
 import static java.util.stream.Collectors.toMap;
 import static java.util.stream.Collectors.toSet;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
@@ -47,7 +48,7 @@ public class BlueprintImplV2 implements BlueprintV2 {
 
   private String name;
   private SecurityConfiguration securityConfiguration;
-  private Collection<RepositoryVersion> repositoryVersions;
+  private Collection<RepositoryVersion> repositoryVersions = new ArrayList<>(0);
   private Map<String, ServiceGroup> serviceGroups;
   private Setting setting;
   private Configuration configuration;
@@ -98,6 +99,11 @@ public class BlueprintImplV2 implements BlueprintV2 {
     this.repositoryVersions = repositoryVersions;
   }
 
+  @JsonProperty("repository_versions")
+  public Collection<RepositoryVersion> getRepositoryVersions() {
+    return this.repositoryVersions;
+  }
+
   @JsonProperty("service_groups")
   public void setServiceGroups(Collection<ServiceGroup> serviceGroups) {
     this.serviceGroups = serviceGroups.stream().collect(toMap( sg -> sg.getName(), sg -> sg ));
@@ -128,17 +134,24 @@ public class BlueprintImplV2 implements BlueprintV2 {
   }
 
   @Override
-  @JsonProperty("host_groups")
+  @JsonIgnore
   public Map<String, ? extends HostGroupV2> getHostGroups() {
     return hostGroupMap;
   }
 
+  @JsonProperty("host_groups")
+  public Collection<? extends HostGroupV2> getHostGroupsForSerialization() {
+    return hostGroupMap.values();
+  }
+
   @Override
+  @JsonIgnore
   public Collection<StackV2> getStacks() {
     return stacks.values();
   }
 
   @Override
+  @JsonIgnore
   public Collection<String> getStackIds() {
     return repositoryVersions.stream().map(rv -> rv.getStackId()).collect(toList());
   }
@@ -258,11 +271,16 @@ public class BlueprintImplV2 implements BlueprintV2 {
   }
 
   @Override
-  @JsonProperty("cluster_settings")
+  @JsonIgnore
   public Setting getSetting() {
     return this.setting;
   }
 
+  @JsonProperty("cluster_settings")
+  public Map<String, Set<HashMap<String, String>>> getSettingForSerialization() {
+    return this.setting.getProperties();
+  }
+
   @Nonnull
   @Override
   @JsonIgnore

http://git-wip-us.apache.org/repos/asf/ambari/blob/57bef16c/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
index 7b228e5..7ad5365 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
@@ -32,7 +32,6 @@ import org.apache.ambari.server.controller.StackV2;
 import org.apache.ambari.server.controller.StackV2Factory;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.orm.dao.BlueprintV2DAO;
-import org.apache.ambari.server.orm.dao.StackDAO;
 import org.apache.ambari.server.orm.entities.BlueprintV2Entity;
 import org.apache.ambari.server.orm.entities.StackEntity;
 import org.apache.ambari.server.stack.NoSuchStackException;
@@ -42,6 +41,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.Version;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
 import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver;
 import com.fasterxml.jackson.databind.module.SimpleModule;
 import com.google.inject.Inject;
@@ -72,8 +72,8 @@ public class BlueprintV2Factory {
 
   protected static final String SETTINGS_PROPERTY_ID = "settings";
 
+  private boolean prettyPrintJson = false;
   private static BlueprintV2DAO blueprintDAO;
-  private static StackDAO stackDao;
   private ConfigurationFactory configFactory = new ConfigurationFactory();
 
   private StackV2Factory stackFactory;
@@ -89,6 +89,10 @@ public class BlueprintV2Factory {
     return new BlueprintV2Factory(new StackV2Factory(controller));
   }
 
+  public static BlueprintV2Factory create(StackV2Factory factory) {
+    return new BlueprintV2Factory(factory);
+  }
+
   public BlueprintV2 getBlueprint(String blueprintName) throws NoSuchStackException, NoSuchBlueprintException, IOException {
     BlueprintV2Entity entity =
       Optional.ofNullable(blueprintDAO.findByName(blueprintName)).orElseThrow(() -> new NoSuchBlueprintException(blueprintName));
@@ -107,6 +111,7 @@ public class BlueprintV2Factory {
     return blueprintV2;
   }
 
+
   public BlueprintV2 convertFromEntity(BlueprintV2Entity blueprintEntity) throws IOException {
     return convertFromJson(blueprintEntity.getContent());
   }
@@ -131,7 +136,7 @@ public class BlueprintV2Factory {
 
   public BlueprintV2Entity convertToEntity(BlueprintV2 blueprint) throws JsonProcessingException {
     BlueprintV2Entity entity = new BlueprintV2Entity();
-    String content = createObjectMapper().writeValueAsString(blueprint);
+    String content = convertToJson(blueprint);
     entity.setContent(content);
     entity.setBlueprintName(blueprint.getName());
     entity.setSecurityType(blueprint.getSecurity().getType());
@@ -139,6 +144,11 @@ public class BlueprintV2Factory {
     return entity;
   }
 
+  public String convertToJson(BlueprintV2 blueprint) throws JsonProcessingException {
+    return createObjectMapper().writeValueAsString(blueprint);
+
+  }
+
   /**
    * Convert a map of properties to a blueprint entity.
    *
@@ -180,7 +190,15 @@ public class BlueprintV2Factory {
     }
   }
 
-  static ObjectMapper createObjectMapper() {
+  public boolean isPrettyPrintJson() {
+    return prettyPrintJson;
+  }
+
+  public void setPrettyPrintJson(boolean prettyPrintJson) {
+    this.prettyPrintJson = prettyPrintJson;
+  }
+
+  ObjectMapper createObjectMapper() {
     ObjectMapper mapper = new ObjectMapper();
     SimpleModule module = new SimpleModule("CustomModel", Version.unknownVersion());
     SimpleAbstractTypeResolver resolver = new SimpleAbstractTypeResolver();
@@ -188,6 +206,9 @@ public class BlueprintV2Factory {
     module.setAbstractTypes(resolver);
     mapper.registerModule(module);
     mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+    if (prettyPrintJson) {
+      mapper.enable(SerializationFeature.INDENT_OUTPUT);
+    }
     return mapper;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/57bef16c/ambari-server/src/main/java/org/apache/ambari/server/topology/ComponentV2.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/ComponentV2.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/ComponentV2.java
index 68744d4..0d26ef6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/ComponentV2.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/ComponentV2.java
@@ -68,6 +68,7 @@ public class ComponentV2 implements Configurable {
     return this.provisionAction;
   }
 
+  @JsonIgnore
   public ServiceId getServiceId() {
     return serviceId;
   }
@@ -77,10 +78,12 @@ public class ComponentV2 implements Configurable {
   }
 
   //TODO
+  @JsonIgnore
   public ServiceGroup getServiceGroup() {
     return null;
   }
 
+  @JsonIgnore
   public Configuration getConfiguration() {
     return configuration;
   }
@@ -100,6 +103,7 @@ public class ComponentV2 implements Configurable {
     this.name = name;
   }
 
+  @JsonProperty("service_group")
   public String getServiceGroupName() {
     return serviceId.getServiceGroup();
   }
@@ -123,6 +127,7 @@ public class ComponentV2 implements Configurable {
     this.provisionAction = provisionAction;
   }
 
+  @JsonIgnore
   public void setConfiguration(Configuration configuration) {
     this.configuration = configuration;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/57bef16c/ambari-server/src/main/java/org/apache/ambari/server/topology/Configurable.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/Configurable.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/Configurable.java
index 74308ab..0f3cf17 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/Configurable.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/Configurable.java
@@ -24,17 +24,32 @@ import java.util.Map;
 import java.util.stream.Collectors;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.collect.Lists;
 
 public interface Configurable {
   void setConfiguration(Configuration configuration);
+  Configuration getConfiguration();
 
   @JsonProperty("configurations")
   default void setConfigs(Collection<Map<String, Map<String, Map<String, String>>>> configs) {
-    Map<String, Map<String, String>> allProps = configs.stream().collect(Collectors.toMap(
-      config -> config.keySet().iterator().next(),
-      config -> config.values().iterator().next().get("properties")
-    ));
-    setConfiguration(new Configuration(allProps, new HashMap<>()));
+    if (null != configs) {
+      Map<String, Map<String, String>> allProps = configs.stream().
+        filter( map -> map != null && !map.isEmpty() && map.values().iterator().next().get("properties ") != null).
+        collect(Collectors.toMap(
+          config -> config.keySet().iterator().next(),
+          config -> config.values().iterator().next().get("properties")
+        ));
+      setConfiguration(new Configuration(allProps, new HashMap<>()));
+    }
+  }
+
+  @JsonProperty("configurations")
+  default Collection<Map<String, Map<String, Map<String, String>>>> getConfigs() {
+    Map<String, Map<String, Map<String, String>>> configAsMap = new HashMap<>();
+    if (null != getConfiguration()) {
+      configAsMap.put("properties", getConfiguration().getProperties());
+    }
+    return Lists.newArrayList(configAsMap);
   }
 
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/57bef16c/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java
index 01f34da..8834a37 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupV2Impl.java
@@ -60,6 +60,7 @@ public class HostGroupV2Impl implements HostGroupV2, Configurable {
   }
 
   @Override
+  @JsonIgnore
   public String getFullyQualifiedName() {
     return blueprintName + ":" + name;
   }
@@ -70,6 +71,7 @@ public class HostGroupV2Impl implements HostGroupV2, Configurable {
   }
 
   @Override
+  @JsonIgnore
   public Collection<String> getComponentNames() {
     return getComponentNames(components);
   }
@@ -82,6 +84,7 @@ public class HostGroupV2Impl implements HostGroupV2, Configurable {
   }
 
   @Override
+  @JsonIgnore
   public Collection<String> getComponentNames(ProvisionAction provisionAction) {
     List<ComponentV2> filtered =
       ImmutableList.copyOf(Collections2.filter(components, Predicates.equalTo(provisionAction)));
@@ -99,11 +102,13 @@ public class HostGroupV2Impl implements HostGroupV2, Configurable {
   }
 
   @Override
+  @JsonIgnore
   public boolean containsMasterComponent() {
     return containsMasterComponent;
   }
 
   @Override
+  @JsonIgnore
   public Collection<ServiceId> getServiceIds() {
     return serviceIds;
   }
@@ -134,6 +139,7 @@ public class HostGroupV2Impl implements HostGroupV2, Configurable {
   }
 
   @Override
+  @JsonIgnore
   public Configuration getConfiguration() {
     return configuration;
   }
@@ -157,6 +163,7 @@ public class HostGroupV2Impl implements HostGroupV2, Configurable {
     this.serviceIds = components.stream().map(c -> c.getServiceId()).collect(Collectors.toSet());
   }
 
+  @JsonIgnore
   public void setConfiguration(Configuration configuration) {
     this.configuration = configuration;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/57bef16c/ambari-server/src/main/java/org/apache/ambari/server/topology/Service.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/Service.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/Service.java
index 317e29f..7c5ee42 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/Service.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/Service.java
@@ -21,6 +21,7 @@ package org.apache.ambari.server.topology;
 
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import org.apache.ambari.server.controller.StackV2;
 
@@ -39,6 +40,7 @@ public class Service implements Configurable {
 
   private String stackId;
 
+  @JsonIgnore
   private Configuration configuration;
 
   private Set<ServiceId> dependencies = ImmutableSet.of();
@@ -61,10 +63,12 @@ public class Service implements Configurable {
     return this.id.getName();
   }
 
+  @JsonIgnore
   public String getServiceGroupId() {
     return this.id.getServiceGroup();
   }
 
+  @JsonIgnore
   public ServiceGroup getServiceGroup() {
     return serviceGroup;
   }
@@ -77,18 +81,28 @@ public class Service implements Configurable {
     return stackId;
   }
 
+  @JsonIgnore
   public StackV2 getStack() {
     return stack;
   }
 
+  @JsonIgnore
   public Set<ServiceId> getDependentServiceIds() {
     return dependencies;
   }
 
+  @JsonProperty("dependencies")
+  public Set<Map<String, String>> getDependenciesForSerialization() {
+    return dependencies.stream().map(
+      serviceId -> ImmutableMap.of("service_name", serviceId.getName(), "service_group", serviceId.getServiceGroup())).
+      collect(Collectors.toSet());
+  }
+
   public Set<Service> getDependencies() {
     return ImmutableSet.copyOf(dependencyMap.values());
   }
 
+  @JsonIgnore
   public Configuration getConfiguration() {
     return configuration;
   }
@@ -137,6 +151,7 @@ public class Service implements Configurable {
     this.dependencyMap = dependencyMap;
   }
 
+  @JsonIgnore
   public ServiceId getId() {
     return id;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/57bef16c/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/BlueprintImplV2Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/BlueprintImplV2Test.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/BlueprintImplV2Test.java
index ad2cdbd..99acfb7 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/BlueprintImplV2Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/BlueprintImplV2Test.java
@@ -17,12 +17,18 @@
  */
 package org.apache.ambari.server.topology.validators;
 
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.ambari.server.controller.StackV2;
+import org.apache.ambari.server.controller.StackV2Factory;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.topology.BlueprintImplV2;
+import org.apache.ambari.server.topology.BlueprintV2Factory;
 import org.apache.ambari.server.topology.HostGroupV2;
 import org.apache.ambari.server.topology.HostGroupV2Impl;
 import org.junit.BeforeClass;
@@ -39,11 +45,14 @@ import com.google.common.io.Resources;
 
 public class BlueprintImplV2Test {
 
-  static String BLUEPRINT_V2_JSON;
+  static String BLUEPRINTV2_JSON;
+  static String BLUEPRINTV2_2_JSON;
+
 
   @BeforeClass
   public static void setUpClass() throws Exception {
-    BLUEPRINT_V2_JSON = Resources.toString(Resources.getResource("blueprintv2/blueprintv2.json"), Charsets.UTF_8);
+    BLUEPRINTV2_JSON = Resources.toString(Resources.getResource("blueprintv2/blueprintv2.json"), Charsets.UTF_8);
+    BLUEPRINTV2_2_JSON = Resources.toString(Resources.getResource("blueprintv2/blueprintv2_2.json"), Charsets.UTF_8);
   }
 
   @Test
@@ -55,7 +64,7 @@ public class BlueprintImplV2Test {
     module.setAbstractTypes(resolver);
     mapper.registerModule(module);
     mapper.enable(SerializationFeature.INDENT_OUTPUT);
-    BlueprintImplV2 bp = mapper.readValue(BLUEPRINT_V2_JSON, BlueprintImplV2.class);
+    BlueprintImplV2 bp = mapper.readValue(BLUEPRINTV2_JSON, BlueprintImplV2.class);
     bp.postDeserialization();
     // -- add stack --
     StackV2 hdpCore = new StackV2("HDPCORE", "3.0.0", "3.0.0.0-1", new HashMap<>(), new HashMap<>(), new HashMap<>(),
@@ -67,7 +76,7 @@ public class BlueprintImplV2Test {
     String bpJson = mapper.writeValueAsString(bp);
     System.out.println(bpJson);
     System.out.println("\n\n====================================================================================\n\n");
-    Map<String, Object> map = mapper.readValue(BLUEPRINT_V2_JSON, HashMap.class);
+    Map<String, Object> map = mapper.readValue(BLUEPRINTV2_JSON, HashMap.class);
     System.out.println(map);
     System.out.println("\n\n====================================================================================\n\n");
     String bpJson2 = mapper.writeValueAsString(map);
@@ -76,4 +85,19 @@ public class BlueprintImplV2Test {
     BlueprintImplV2 bp2 = mapper.readValue(bpJson2, BlueprintImplV2.class);
     System.out.println(bp2);
   }
+
+  @Test
+  public void testSerialization2() throws Exception {
+    StackV2 hdpCore = new StackV2("HDPCORE", "3.0.0", "3.0.0.0-1", new HashMap<>(), new HashMap<>(), new HashMap<>(),
+      new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>());    StackV2Factory stackFactory = mock(StackV2Factory.class);
+    when(stackFactory.create(anyString(), anyString())).thenReturn(hdpCore);
+    BlueprintV2Factory bpFactory = BlueprintV2Factory.create(stackFactory);
+    bpFactory.setPrettyPrintJson(true);
+    BlueprintImplV2 bp = (BlueprintImplV2)bpFactory.convertFromJson(BLUEPRINTV2_2_JSON);
+    String bpSerialized = bpFactory.convertToJson(bp);
+    System.out.println(bpSerialized);
+    bp = (BlueprintImplV2)bpFactory.convertFromJson(bpSerialized);
+  }
+
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/57bef16c/ambari-server/src/test/resources/blueprintv2/blueprintv2_2.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/resources/blueprintv2/blueprintv2_2.json b/ambari-server/src/test/resources/blueprintv2/blueprintv2_2.json
new file mode 100644
index 0000000..494e125
--- /dev/null
+++ b/ambari-server/src/test/resources/blueprintv2/blueprintv2_2.json
@@ -0,0 +1,139 @@
+{
+  "Blueprints": {
+    "blueprint_name": "blueprint-def",
+    "security": {
+      "type": "NONE"
+    }
+  },
+  "cluster_settings": {
+    "deployment_settings": [
+      {"skip_failure":"true"}
+    ],
+    "recovery_settings":[
+      {"recovery_enabled":"true"}
+    ]
+  },
+  "repository_versions": [
+    {
+      "stack_id": "HDP-3.0.0",
+      "repository_version": "3.0.0.0-359"
+    }
+  ],
+  "service_groups": [
+    {
+      "name": "CoreSG",
+      "dependencies": [],
+      "services": [
+        {
+          "type": "ZOOKEEPER",
+          "name": "ZK1",
+          "stack_id": "HDP-3.0.0",
+          "configurations": [
+            {
+              "zoo.cfg" : {
+                "properties" : {
+                  "dataDir" : "/zookeeper1"
+                }
+              }
+            }
+          ]
+        },
+        {
+          "type": "HDFS",
+          "stack_id": "HDP-3.0.0"
+        },
+        {
+          "type": "YARN",
+          "stack_id": "HDP-3.0.0"
+        },
+        {
+          "type": "HBASE",
+          "stack_id": "HDP-3.0.0"
+        }
+      ]
+    }
+  ],
+  "host_groups": [
+    {
+      "cardinality": "1",
+      "name": "host_group_1",
+      "configurations": [],
+      "components": [
+        {
+          "type": "NAMENODE",
+          "service_name": "HDFS",
+          "service_group": "CoreSG",
+          "configurations": [],
+          "provision_action": "INSTALL_AND_START"
+        },
+        {
+          "type": "SECONDARY_NAMENODE",
+          "service_name": "HDFS",
+          "service_group": "CoreSG",
+          "configurations": [],
+          "provision_action": "INSTALL_AND_START"
+        },
+        {
+          "type": "DATANODE",
+          "service_name": "HDFS",
+          "service_group": "CoreSG",
+          "configurations": [],
+          "provision_action": "INSTALL_AND_START"
+        },
+        {
+          "type": "ZOOKEEPER_SERVER",
+          "service_name": "ZK1",
+          "service_group": "CoreSG",
+          "configurations": []
+        },
+        {
+          "type": "RESOURCEMANAGER",
+          "service_name": "YARN",
+          "service_group": "CoreSG",
+          "configurations": []
+        },
+        {
+          "type" : "HDFS_CLIENT",
+          "service_name": "HDFS",
+          "service_group": "CoreSG"
+        },
+        {
+          "name" : "HISTORYSERVER",
+          "service_name": "YARN",
+          "service_group": "CoreSG"
+        },
+        {
+          "name" : "APP_TIMELINE_SERVER",
+          "service_name": "YARN",
+          "service_group": "CoreSG"
+        },
+        {
+          "name" : "MAPREDUCE2_CLIENT",
+          "service_name": "YARN",
+          "service_group": "CoreSG"
+        },
+        {
+          "name" : "RESOURCEMANAGER",
+          "service_name": "YARN",
+          "service_group": "CoreSG"
+        },
+        {
+          "name" : "NODEMANAGER",
+          "service_name": "YARN",
+          "service_group": "CoreSG"
+        },
+        {
+          "name" : "YARN_CLIENT",
+          "service_name": "YARN",
+          "service_group": "CoreSG"
+        },
+        {
+          "type": "HBASE_MASTER",
+          "service_name": "HBASE",
+          "service_group": "CoreSG",
+          "configurations": []
+        }
+      ]
+    }
+  ]
+}


[06/17] ambari git commit: AMBARI-22249. Add service group dependencies. Part 2.(vbrodetskyi)

Posted by be...@apache.org.
AMBARI-22249. Add service group dependencies. Part 2.(vbrodetskyi)


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

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

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


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

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

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

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

http://git-wip-us.apache.org/repos/asf/ambari/blob/6a78e1a1/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupDependencyEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupDependencyEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupDependencyEntity.java
new file mode 100644
index 0000000..ee0beeb
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupDependencyEntity.java
@@ -0,0 +1,111 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.orm.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+@Entity
+@Table(name = "servicegroupdependencies")
+@NamedQueries({
+        @NamedQuery(name = "serviceGroupDependencyByServiceGroupsAndClustersIds", query =
+                "SELECT serviceGroupDependency " +
+                   "FROM ServiceGroupDependencyEntity serviceGroupDependency " +
+                   "WHERE serviceGroupDependency.serviceGroupId=:serviceGroupId AND serviceGroupDependency.serviceGroupClusterId=:serviceGroupClusterId " +
+                   "AND serviceGroupDependency.dependentServiceGroupId=:dependentServiceGroupId " +
+                   "AND serviceGroupDependency.dependentServiceGroupClusterId=:dependentServiceGroupClusterId")
+})
+@TableGenerator(name = "service_group_dependency_id_generator",
+        table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value"
+        , pkColumnValue = "service_group_dependency_id_seq"
+        , initialValue = 1
+)
+public class ServiceGroupDependencyEntity {
+
+  @Id
+  @Column(name = "id", nullable = false, insertable = true, updatable = true)
+  @GeneratedValue(strategy = GenerationType.TABLE, generator = "service_group_dependency_id_generator")
+  private Long serviceGroupDependencyId;
+
+  @Column(name = "service_group_id", nullable = false, insertable = false, updatable = false)
+  private long serviceGroupId;
+
+  @Column(name = "service_group_cluster_id", nullable = false, insertable = false, updatable = false)
+  private long serviceGroupClusterId;
+
+  @Column(name = "dependent_service_group_id", nullable = false, insertable = false, updatable = false)
+  private long dependentServiceGroupId;
+
+  @Column(name = "dependent_service_group_cluster_id", nullable = false, insertable = false, updatable = false)
+  private long dependentServiceGroupClusterId;
+
+  @ManyToOne
+  @JoinColumns({
+          @JoinColumn(name = "service_group_id", referencedColumnName = "id", nullable = false),
+          @JoinColumn(name = "service_group_cluster_id", referencedColumnName = "cluster_id", nullable = false) })
+  private ServiceGroupEntity serviceGroup;
+
+  @ManyToOne
+  @JoinColumns({
+          @JoinColumn(name = "dependent_service_group_id", referencedColumnName = "id", nullable = false),
+          @JoinColumn(name = "dependent_service_group_cluster_id", referencedColumnName = "cluster_id", nullable = false) })
+  private ServiceGroupEntity serviceGroupDependency;
+
+  public ServiceGroupEntity getServiceGroup() {
+    return serviceGroup;
+  }
+
+  public void setServiceGroup(ServiceGroupEntity serviceGroup) {
+    this.serviceGroup = serviceGroup;
+  }
+
+  public ServiceGroupEntity getServiceGroupDependency() {
+    return serviceGroupDependency;
+  }
+
+  public void setServiceGroupDependency(ServiceGroupEntity serviceGroupDependency) {
+    this.serviceGroupDependency = serviceGroupDependency;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (!(o instanceof ServiceGroupDependencyEntity)) return false;
+
+    ServiceGroupDependencyEntity that = (ServiceGroupDependencyEntity) o;
+
+    if (!serviceGroupDependencyId.equals(that.serviceGroupDependencyId)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return serviceGroupDependencyId.hashCode();
+  }
+}

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

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

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

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

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

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

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

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

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

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

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

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


[17/17] ambari git commit: AMBARI-22325 Polish blueprint v2 unit tests (benyoka)

Posted by be...@apache.org.
AMBARI-22325 Polish blueprint v2 unit tests (benyoka)


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: 8a55187406646a48426c01b8f9bde79755ebaef3
Parents: 26143bc
Author: Balazs Bence Sari <be...@apache.org>
Authored: Mon Nov 13 18:34:02 2017 +0100
Committer: Balazs Bence Sari <be...@apache.org>
Committed: Tue Nov 14 11:31:17 2017 +0100

----------------------------------------------------------------------
 .../server/topology/BlueprintV2Factory.java     |   2 +-
 .../validators/BlueprintImplV2Test.java         | 167 +++++++++++++------
 2 files changed, 120 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/8a551874/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
index 47aed80..fa12173 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
@@ -198,7 +198,7 @@ public class BlueprintV2Factory {
     this.prettyPrintJson = prettyPrintJson;
   }
 
-  ObjectMapper createObjectMapper() {
+  public ObjectMapper createObjectMapper() {
     ObjectMapper mapper = new ObjectMapper();
     SimpleModule module = new SimpleModule("CustomModel", Version.unknownVersion());
     SimpleAbstractTypeResolver resolver = new SimpleAbstractTypeResolver();

http://git-wip-us.apache.org/repos/asf/ambari/blob/8a551874/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/BlueprintImplV2Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/BlueprintImplV2Test.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/BlueprintImplV2Test.java
index 611ada1..41d1ca8 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/BlueprintImplV2Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/validators/BlueprintImplV2Test.java
@@ -17,30 +17,28 @@
  */
 package org.apache.ambari.server.topology.validators;
 
-import static org.mockito.Mockito.anyString;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
 import org.apache.ambari.server.controller.StackV2;
 import org.apache.ambari.server.controller.StackV2Factory;
 import org.apache.ambari.server.state.StackId;
-import org.apache.ambari.server.topology.BlueprintImplV2;
+import org.apache.ambari.server.topology.BlueprintV2;
 import org.apache.ambari.server.topology.BlueprintV2Factory;
-import org.apache.ambari.server.topology.HostGroupV2;
-import org.apache.ambari.server.topology.HostGroupV2Impl;
+import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import com.fasterxml.jackson.core.Version;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver;
-import com.fasterxml.jackson.databind.module.SimpleModule;
 import com.google.common.base.Charsets;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.io.Resources;
 
 public class BlueprintImplV2Test {
@@ -48,6 +46,7 @@ public class BlueprintImplV2Test {
   static String BLUEPRINTV2_JSON;
   static String BLUEPRINTV2_2_JSON;
 
+  BlueprintV2Factory blueprintFactory;
 
   @BeforeClass
   public static void setUpClass() throws Exception {
@@ -55,50 +54,122 @@ public class BlueprintImplV2Test {
     BLUEPRINTV2_2_JSON = Resources.toString(Resources.getResource("blueprintv2/blueprintv2_2.json"), Charsets.UTF_8);
   }
 
+  @Before
+  public void setUp() throws Exception {
+    StackV2Factory stackFactory = mock(StackV2Factory.class);
+    when(stackFactory.create(any(StackId.class))).thenAnswer(invocation -> {
+      StackId stackId = invocation.getArgumentAt(0, StackId.class);
+      StackV2 stack = new StackV2(stackId.getStackName(), stackId.getStackVersion(), stackId.getStackVersion() + ".0-1",
+        new HashMap<>(), new HashMap<>(), new HashMap<>(),
+        new HashMap<>(), new HashMap<>(), new HashMap<>(),
+        new HashMap<>(), new HashMap<>(), new HashMap<>());
+      return stack;
+    });
+    blueprintFactory = BlueprintV2Factory.create(stackFactory);
+    blueprintFactory.setPrettyPrintJson(true);
+  }
+
+  @Test
+  public void testSerialization_parseJsonAsBlueprint() throws Exception {
+    BlueprintV2 bp = blueprintFactory.convertFromJson(BLUEPRINTV2_JSON);
+    assertEquals(new StackId("HDPCORE", "3.0.0"),
+      bp.getServiceGroups().iterator().next().getServices().iterator().next().getStack().getStackId());
+    assertEquals(2, bp.getStackIds().size());
+    assertEquals(7, bp.getAllServiceIds().size());
+    assertEquals(2, bp.getServiceGroups().size());
+  }
+
   @Test
-  public void testSerialization() throws Exception {
-    ObjectMapper mapper = new ObjectMapper();
-    SimpleModule module = new SimpleModule("CustomModel", Version.unknownVersion());
-    SimpleAbstractTypeResolver resolver = new SimpleAbstractTypeResolver();
-    resolver.addMapping(HostGroupV2.class, HostGroupV2Impl.class);
-    module.setAbstractTypes(resolver);
-    mapper.registerModule(module);
-    mapper.enable(SerializationFeature.INDENT_OUTPUT);
-    BlueprintImplV2 bp = mapper.readValue(BLUEPRINTV2_JSON, BlueprintImplV2.class);
-    bp.postDeserialization();
-    // -- add stack --
-    StackV2 hdpCore = new StackV2("HDPCORE", "3.0.0", "3.0.0.0-1", new HashMap<>(), new HashMap<>(), new HashMap<>(),
-      new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>());
-    StackV2 analytics = new StackV2("ANALYTICS", "1.0.0", "1.0.0.0-1", new HashMap<>(), new HashMap<>(), new HashMap<>(),
-      new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>());
-    bp.setStacks(ImmutableMap.of(new StackId("HDPCORE", "3.0.0"), hdpCore, new StackId("ANALYTICS", "1.0.0"), analytics));
-    // ---------------
-    String bpJson = mapper.writeValueAsString(bp);
-    System.out.println(bpJson);
-    System.out.println("\n\n====================================================================================\n\n");
-    Map<String, Object> map = mapper.readValue(BLUEPRINTV2_JSON, HashMap.class);
-    System.out.println(map);
-    System.out.println("\n\n====================================================================================\n\n");
-    String bpJson2 = mapper.writeValueAsString(map);
-    System.out.println(bpJson2);
-    System.out.println("\n\n====================================================================================\n\n");
-    BlueprintImplV2 bp2 = mapper.readValue(bpJson2, BlueprintImplV2.class);
-    System.out.println(bp2);
+  public void testSerialization_parseJsonAsMap() throws Exception {
+    ObjectMapper mapper = blueprintFactory.createObjectMapper();
+    Map<String, Object> blueprintAsMap = mapper.readValue(BLUEPRINTV2_JSON, HashMap.class);
+    assertEquals(2, getAsMap(blueprintAsMap, "cluster_settings").size());
+    assertEquals(2, getAsMap(blueprintAsMap, "Blueprints").size());
+    assertEquals("blueprint-def", getByPath(blueprintAsMap,
+      ImmutableList.of("Blueprints", "blueprint_name")));
+    assertEquals(2, getAsList(blueprintAsMap, "service_groups").size());
+    assertEquals("StreamSG", getByPath(blueprintAsMap,
+      ImmutableList.of("service_groups", 1, "name")));
+    assertEquals(2, getAsList(blueprintAsMap, "repository_versions").size());
+    assertEquals(1, getAsList(blueprintAsMap, "host_groups").size());
+    assertEquals("host_group_1", getByPath(blueprintAsMap,
+      ImmutableList.of("host_groups", 0, "name")));
+    System.out.println(blueprintAsMap);
   }
 
   @Test
-  public void testSerialization2() throws Exception {
-    StackV2 hdpCore = new StackV2("HDPCORE", "3.0.0", "3.0.0.0-1", new HashMap<>(), new HashMap<>(), new HashMap<>(),
-      new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>());    StackV2Factory stackFactory = mock(StackV2Factory.class);
-    when(stackFactory.create(anyString(), anyString())).thenReturn(hdpCore);
-    BlueprintV2Factory bpFactory = BlueprintV2Factory.create(stackFactory);
-    bpFactory.setPrettyPrintJson(true);
-    BlueprintImplV2 bp = (BlueprintImplV2)bpFactory.convertFromJson(BLUEPRINTV2_2_JSON);
-    String bpSerialized = bpFactory.convertToJson(bp);
-    System.out.println(bpSerialized);
-    bp = (BlueprintImplV2)bpFactory.convertFromJson(bpSerialized);
-    System.out.println(bp);
+  public void testSerialization_serializeBlueprint() throws Exception {
+    BlueprintV2 bp = blueprintFactory.convertFromJson(BLUEPRINTV2_JSON);
+    String serialized = blueprintFactory.convertToJson(bp);
+    // Test that serialized blueprint can be read again
+    bp = blueprintFactory.convertFromJson(serialized);
+    assertEquals(2, bp.getStackIds().size());
+    assertEquals(7, bp.getAllServiceIds().size());
+    assertEquals(2, bp.getServiceGroups().size());
   }
 
+  @Test
+  public void testSerialization2_parseJsonAsBlueprint() throws Exception {
+    BlueprintV2 bp = blueprintFactory.convertFromJson(BLUEPRINTV2_2_JSON);
+    assertEquals(new StackId("HDP", "3.0.0"),
+      bp.getServiceGroups().iterator().next().getServices().iterator().next().getStack().getStackId());
+    assertEquals(1, bp.getStackIds().size());
+    assertEquals(4, bp.getAllServiceIds().size());
+    assertEquals(1, bp.getServiceGroups().size());
+  }
+
+  @Test
+  public void testSerialization2_parseJsonAsMap() throws Exception {
+    ObjectMapper mapper = blueprintFactory.createObjectMapper();
+    Map<String, Object> blueprintAsMap = mapper.readValue(BLUEPRINTV2_2_JSON, HashMap.class);
+    assertEquals(2, getAsMap(blueprintAsMap, "cluster_settings").size());
+    assertEquals(2, getAsMap(blueprintAsMap, "Blueprints").size());
+    assertEquals("blueprint-def", getByPath(blueprintAsMap,
+      ImmutableList.of("Blueprints", "blueprint_name")));
+    assertEquals(1, getAsList(blueprintAsMap, "service_groups").size());
+    assertEquals("CoreSG", getByPath(blueprintAsMap,
+      ImmutableList.of("service_groups", 0, "name")));
+    assertEquals(1, getAsList(blueprintAsMap, "repository_versions").size());
+    assertEquals(1, getAsList(blueprintAsMap, "host_groups").size());
+    assertEquals("host_group_1", getByPath(blueprintAsMap,
+      ImmutableList.of("host_groups", 0, "name")));
+    System.out.println(blueprintAsMap);
+  }
+
+  @Test
+  public void testSerialization2_serializeBlueprint() throws Exception {
+    BlueprintV2 bp = blueprintFactory.convertFromJson(BLUEPRINTV2_2_JSON);
+    String serialized = blueprintFactory.convertToJson(bp);
+    // Test that serialized blueprint can be read again
+    bp = blueprintFactory.convertFromJson(serialized);
+    assertEquals(1, bp.getStackIds().size());
+    assertEquals(4, bp.getAllServiceIds().size());
+    assertEquals(1, bp.getServiceGroups().size());
+  }
+
+  private static Map<String, Object> getAsMap(Map<String, Object> parentMap, String key) {
+    return (Map<String, Object>)parentMap.get(key);
+  }
+
+  private static List<Object> getAsList(Map<String, Object> parentMap, String key) {
+    return (List<Object>)parentMap.get(key);
+  }
+
+  private static Object getByPath(Map<String, Object> initialMap, List<Object> path) {
+    Object returnValue = initialMap;
+    for(Object key: path) {
+      if (key instanceof String) { // this element is a map
+        returnValue = ((Map<String, Object>)returnValue).get(key);
+        Preconditions.checkNotNull(returnValue, "No value for key: " + key);
+      }
+      else if (key instanceof Integer) { // this element is an arraylist
+        returnValue = ((List<Object>)returnValue).get((Integer)key);
+      }
+      else {
+        throw new IllegalArgumentException("Invalid path element: " + key);
+      }
+    }
+    return returnValue;
+  }
 
 }
\ No newline at end of file