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

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

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