You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sm...@apache.org on 2017/02/25 02:23:37 UTC

ambari git commit: AMBARI-20136. Services should be able to specify that credential store is always enabled (smohanty)

Repository: ambari
Updated Branches:
  refs/heads/branch-2.5 7cffc49cb -> 503d95f80


AMBARI-20136. Services should be able to specify that credential store is always enabled (smohanty)


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

Branch: refs/heads/branch-2.5
Commit: 503d95f80b681647a1737a04c293b846d12836e7
Parents: 7cffc49
Author: Sumit Mohanty <sm...@hortonworks.com>
Authored: Fri Feb 24 18:23:26 2017 -0800
Committer: Sumit Mohanty <sm...@hortonworks.com>
Committed: Fri Feb 24 18:23:26 2017 -0800

----------------------------------------------------------------------
 .../server/controller/ServiceRequest.java       |  19 ++-
 .../server/controller/StackServiceResponse.java |  24 +++
 .../internal/ServiceResourceProvider.java       |  40 +++--
 .../internal/StackServiceResourceProvider.java  |  18 ++-
 .../server/state/CredentialStoreInfo.java       | 158 +++++++++++--------
 .../org/apache/ambari/server/state/Service.java |   7 +
 .../apache/ambari/server/state/ServiceImpl.java |  14 +-
 .../apache/ambari/server/state/ServiceInfo.java |  29 ++++
 .../src/main/resources/properties.json          |   1 +
 .../stacks/HDP/2.3/services/RANGER/metainfo.xml |   4 -
 .../stacks/HDP/2.4/services/RANGER/metainfo.xml |   4 -
 .../stacks/HDP/2.5/services/RANGER/metainfo.xml |   4 -
 .../stacks/HDP/2.6/services/RANGER/metainfo.xml |   4 -
 .../AmbariManagementControllerTest.java         |  83 ++++++++++
 .../ambari/server/stack/ServiceModuleTest.java  |   7 +-
 .../ambari/server/state/ServiceInfoTest.java    |   4 +
 .../stacks/HDP/2.2.0/services/HDFS/metainfo.xml |   6 +-
 .../HDP/2.2.0/services/STORM/metainfo.xml       |   6 +
 .../HDP/2.2.0/services/ZOOKEEPER/metainfo.xml   |   6 +-
 19 files changed, 333 insertions(+), 105 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
index ec45a85..a8e6315 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
@@ -26,6 +26,7 @@ public class ServiceRequest {
   private String desiredState; // CREATE/UPDATE
   private String maintenanceState; // UPDATE
   private String credentialStoreEnabled; // CREATE/UPDATE/GET
+  private String credentialStoreSupported; //GET
 
   public ServiceRequest(String clusterName, String serviceName,
                         String desiredState) {
@@ -107,6 +108,14 @@ public class ServiceRequest {
     return credentialStoreEnabled;
   }
 
+
+  /**
+   * @return credential store supported
+   */
+  public String getCredentialStoreSupported() {
+    return credentialStoreSupported;
+  }
+
   /**
    * @param credentialStoreEnabled the new credential store enabled
    */
@@ -114,12 +123,20 @@ public class ServiceRequest {
     this.credentialStoreEnabled = credentialStoreEnabled;
   }
 
+  /**
+   * @param credentialStoreSupported the new credential store supported
+   */
+  public void setCredentialStoreSupported(String credentialStoreSupported) {
+    this.credentialStoreSupported = credentialStoreSupported;
+  }
+
   public String toString() {
     StringBuilder sb = new StringBuilder();
     sb.append("clusterName=" + clusterName
         + ", serviceName=" + serviceName
         + ", desiredState=" + desiredState
-        + ", credentialStoreEnabled=" + credentialStoreEnabled);
+        + ", credentialStoreEnabled=" + credentialStoreEnabled
+        + ", credentialStoreSupported=" + credentialStoreSupported);
     return sb.toString();
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java
index a6dd31f..6c696e7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java
@@ -70,6 +70,12 @@ public class StackServiceResponse {
   private boolean credentialStoreEnabled;
 
   /**
+   * Indicates if the stack definition says this service requires
+   * credential store use. If not specified, this will be false.
+   */
+  private boolean credentialStoreRequired;
+
+  /**
    * Constructor.
    *
    * @param service
@@ -281,4 +287,22 @@ public class StackServiceResponse {
   public void setCredentialStoreEnabled(boolean credentialStoreEnabled) {
     this.credentialStoreEnabled = credentialStoreEnabled;
   }
+
+  /**
+   * Get whether credential store use is required
+   *
+   * @return true or false
+   */
+  public boolean isCredentialStoreRequired() {
+    return credentialStoreRequired;
+  }
+
+  /**
+   * Set credential store required value.
+   *
+   * @param credentialStoreRequired
+   */
+  public void setCredentialStoreRequired(boolean credentialStoreRequired) {
+    this.credentialStoreRequired = credentialStoreRequired;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
index a1c53a7..0cc1745 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
@@ -339,6 +339,11 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
       svcRequest.setMaintenanceState(o.toString());
     }
 
+    o = properties.get(SERVICE_CREDENTIAL_STORE_SUPPORTED_PROPERTY_ID);
+    if (null != o) {
+      svcRequest.setMaintenanceState(o.toString());
+    }
+
     return svcRequest;
   }
 
@@ -368,22 +373,30 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
       AmbariMetaInfo ambariMetaInfo = getManagementController().getAmbariMetaInfo();
       ServiceInfo serviceInfo = ambariMetaInfo.getService(stackId.getStackName(),
           stackId.getStackVersion(), request.getServiceName());
-      LOG.info("Service: {}, credential_store_supported from stack definition:{}", request.getServiceName(),
-          serviceInfo.isCredentialStoreSupported());
 
+      boolean credentialStoreSupported = serviceInfo.isCredentialStoreSupported();
+      boolean credentialStoreRequired = serviceInfo.isCredentialStoreRequired();
+
+      LOG.info("Service: {}, credential_store_supported = {} and credential_store_required = {} from stack definition",
+               request.getServiceName(), credentialStoreSupported, credentialStoreRequired);
       /**
        * If request does not have credential_store_enabled field,
        * then get the default from the stack definition.
        */
       if (StringUtils.isNotEmpty(request.getCredentialStoreEnabled())) {
         boolean credentialStoreEnabled = Boolean.parseBoolean(request.getCredentialStoreEnabled());
-        s.setCredentialStoreEnabled(credentialStoreEnabled);
-        LOG.info("Service: {}, credential_store_enabled from request: {}", request.getServiceName(),
-            credentialStoreEnabled);
+        boolean enableCredStore = credentialStoreSupported && (credentialStoreRequired || credentialStoreEnabled);
+        s.setCredentialStoreEnabled(enableCredStore);
+        LOG.info("Service: {}, credential_store_enabled = {} from request and resulting" +
+                 " credential store enabled status is = {}",
+                 request.getServiceName(), credentialStoreEnabled, enableCredStore);
       } else {
-        s.setCredentialStoreEnabled(serviceInfo.isCredentialStoreEnabled());
-        LOG.info("Service: {}, credential_store_enabled from stack definition:{}", s.getName(),
-            serviceInfo.isCredentialStoreEnabled());
+        boolean enableCredStore = credentialStoreSupported &&
+                                  (credentialStoreRequired || serviceInfo.isCredentialStoreEnabled());
+        s.setCredentialStoreEnabled(enableCredStore);
+        LOG.info("Service: {}, credential_store_enabled = {} from stack definition and resulting" +
+                 " credential store enabled status is = {}",
+                 s.getName(), serviceInfo.isCredentialStoreEnabled(), enableCredStore);
       }
 
       // Initialize service widgets
@@ -498,7 +511,7 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
       reqOpLvl = Resource.Type.Cluster;
     }
 
-    Clusters       clusters        = controller.getClusters();
+    Clusters clusters = controller.getClusters();
 
     // We don't expect batch requests for different clusters, that's why
     // nothing bad should happen if value is overwritten few times
@@ -581,11 +594,20 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
           throw new IllegalArgumentException("Invalid arguments, cannot enable credential store " +
               "as it is not supported by the service. Service=" + s.getName());
         }
+        if (s.isCredentialStoreRequired() && !credentialStoreEnabled) {
+          throw new IllegalArgumentException("Invalid arguments, cannot disable credential store " +
+                                             "as it is required by the service. Service=" + s.getName());
+        }
         serviceCredentialStoreEnabledMap.put(s, credentialStoreEnabled);
         LOG.info("Service: {}, credential_store_enabled from request: {}", request.getServiceName(),
             credentialStoreEnabled);
       }
 
+      if (StringUtils.isNotEmpty(request.getCredentialStoreSupported())) {
+        throw new IllegalArgumentException("Invalid arguments, cannot update credential_store_supported " +
+                                           "as it is set only via service definition. Service=" + s.getName());
+      }
+
       if (newState == null) {
         if (LOG.isDebugEnabled()) {
           LOG.debug("Nothing to do for new updateService request"

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackServiceResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackServiceResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackServiceResourceProvider.java
index 504da49..a2a77c6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackServiceResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackServiceResourceProvider.java
@@ -86,13 +86,16 @@ public class StackServiceResourceProvider extends ReadOnlyResourceProvider {
       "StackServices", "custom_commands");
 
   private static final String SERVICE_PROPERTIES_PROPERTY_ID = PropertyHelper.getPropertyId(
-    "StackServices", "properties");
+      "StackServices", "properties");
 
   private static final String CREDENTIAL_STORE_SUPPORTED = PropertyHelper.getPropertyId(
-          "StackServices", "credential_store_supported");
+      "StackServices", "credential_store_supported");
+
+  private static final String CREDENTIAL_STORE_REQUIRED = PropertyHelper.getPropertyId(
+      "StackServices", "credential_store_required");
 
   private static final String CREDENTIAL_STORE_ENABLED = PropertyHelper.getPropertyId(
-          "StackServices", "credential_store_enabled");
+      "StackServices", "credential_store_enabled");
 
   private static Set<String> pkPropertyIds = new HashSet<String>(
       Arrays.asList(new String[]{STACK_NAME_PROPERTY_ID,
@@ -191,13 +194,16 @@ public class StackServiceResourceProvider extends ReadOnlyResourceProvider {
         response.getCustomCommands(), requestedIds);
 
     setResourceProperty(resource, SERVICE_PROPERTIES_PROPERTY_ID,
-      response.getServiceProperties(), requestedIds);
+        response.getServiceProperties(), requestedIds);
 
     setResourceProperty(resource, CREDENTIAL_STORE_SUPPORTED,
-      response.isCredentialStoreSupported(), requestedIds);
+        response.isCredentialStoreSupported(), requestedIds);
+
+    setResourceProperty(resource, CREDENTIAL_STORE_REQUIRED,
+        response.isCredentialStoreRequired(), requestedIds);
 
     setResourceProperty(resource, CREDENTIAL_STORE_ENABLED,
-      response.isCredentialStoreEnabled(), requestedIds);
+        response.isCredentialStoreEnabled(), requestedIds);
 
     return resource;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/main/java/org/apache/ambari/server/state/CredentialStoreInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/CredentialStoreInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/CredentialStoreInfo.java
index 43f6690..c3f6efb 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/CredentialStoreInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/CredentialStoreInfo.java
@@ -27,81 +27,103 @@ import javax.xml.bind.annotation.XmlElement;
  */
 @XmlAccessorType(XmlAccessType.FIELD)
 public class CredentialStoreInfo {
-    /**
-     * Use Boolean data-type internally, so that we can validate
-     * the XML.
-     */
+  /**
+   * Use Boolean data-type internally, so that we can validate the XML.
+   */
 
-    @XmlElement(name="supported")
-    private Boolean supported = null;
+  @XmlElement(name = "supported")
+  private Boolean supported = null;
 
-    @XmlElement(name="enabled")
-    private Boolean enabled = null;
+  @XmlElement(name = "required")
+  private Boolean required = null;
 
-    /**
-     * Default constructor
-     */
-    public CredentialStoreInfo() {
-    }
+  @XmlElement(name = "enabled")
+  private Boolean enabled = null;
 
-    /**
-     * Constructor taking in values for supported and enabled
-     *
-     * @param supported
-     * @param enabled
-     */
-    public CredentialStoreInfo(Boolean supported, Boolean enabled) {
-        this.supported = supported;
-        this.enabled = enabled;
-    }
+  /**
+   * Default constructor
+   */
+  public CredentialStoreInfo() {
+  }
 
-    /**
-     * Gets a value indicating if the service supports
-     * credential store. If null, this was not specified.
-     * @return
-     */
-    public Boolean isSupported() {
-        return supported;
-    }
+  /**
+   * Constructor taking in values for supported and enabled
+   *
+   * @param supported
+   * @param enabled
+   * @param required
+   */
+  public CredentialStoreInfo(Boolean supported, Boolean enabled, Boolean required) {
+    this.supported = supported;
+    this.enabled = enabled;
+    this.required = required;
+  }
 
-    /**
-     * Set whether a service supports credential store.
-     *
-     * @param supported
-     */
-    public void setSupported(Boolean supported) {
-        this.supported = supported;
-    }
+  /**
+   * Gets a value indicating if the service supports credential store. If null, this was not specified.
+   *
+   * @return
+   */
+  public Boolean isSupported() {
+    return supported;
+  }
 
-    /**
-     * Gets a value indicating whether the service is
-     * enabled for credential store use.
-     *
-     * @return - true, false, null if not specified.
-     */
-    public Boolean isEnabled() {
-        return enabled;
-    }
+  /**
+   * Set whether a service supports credential store.
+   *
+   * @param supported
+   */
+  public void setSupported(Boolean supported) {
+    this.supported = supported;
+  }
 
-    /**
-     * Set whether the service is enabled for credential
-     * store use.
-     *
-     * @param enabled - true, false, null.
-     */
-    public void setEnabled(Boolean enabled) {
-        this.enabled = enabled;
-    }
+  /**
+   * Gets a value indicating whether the service is enabled for credential store use.
+   *
+   * @return - true, false, null if not specified.
+   */
+  public Boolean isEnabled() {
+    return enabled;
+  }
 
-    /**
-     * String representation of this object
-     * @return
-     */
-    @Override
-    public String toString() {
-        return "CredentialStoreInfo{" +
-                "supported=" + supported +
-                ", enabled=" + enabled +
-                '}';
-    }
+  /**
+   * Set whether the service is enabled for credential store use.
+   *
+   * @param enabled - true, false, null.
+   */
+  public void setEnabled(Boolean enabled) {
+    this.enabled = enabled;
+  }
+
+  /**
+   * Gets a value indicating whether the service requires credential store.
+   *
+   * @return - true, false, null if not specified.
+   */
+  public Boolean isRequired() {
+    return required;
+  }
+
+  /**
+   * Set whether the service requires credential store
+   *
+   * @param required - true, false, null.
+   */
+  public void setRequired(Boolean required) {
+    this.required = required;
+  }
+
+  /**
+   * String representation of this object
+   *
+   * @return
+   */
+  @Override
+  public String toString() {
+    return "CredentialStoreInfo{" +
+           "supported=" + supported +
+           ", required=" + required +
+           ", enabled=" + enabled +
+           '}';
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/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 0f425a4..70efeb5 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
@@ -110,6 +110,13 @@ public interface Service {
   boolean isCredentialStoreSupported();
 
   /**
+   * Get a true or false value specifying
+   * whether credential store is required by this service.
+   * @return true or false
+   */
+  boolean isCredentialStoreRequired();
+
+  /**
    * Get a true or false value specifying whether
    * credential store use is enabled for this service.
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/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 713c189..7d807c6 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
@@ -71,6 +71,7 @@ public class ServiceImpl implements Service {
   private final ConcurrentMap<String, ServiceComponent> components = new ConcurrentHashMap<>();
   private final boolean isClientOnlyService;
   private final boolean isCredentialStoreSupported;
+  private final boolean isCredentialStoreRequired;
 
   @Inject
   private ServiceConfigDAO serviceConfigDAO;
@@ -132,6 +133,7 @@ public class ServiceImpl implements Service {
     isClientOnlyService = sInfo.isClientOnlyService();
 
     isCredentialStoreSupported = sInfo.isCredentialStoreSupported();
+    isCredentialStoreRequired = sInfo.isCredentialStoreRequired();
 
     persist(serviceEntity);
   }
@@ -178,6 +180,7 @@ public class ServiceImpl implements Service {
         stackId.getStackVersion(), getName());
     isClientOnlyService = sInfo.isClientOnlyService();
     isCredentialStoreSupported = sInfo.isCredentialStoreSupported();
+    isCredentialStoreRequired = sInfo.isCredentialStoreRequired();
   }
 
   @Override
@@ -334,7 +337,16 @@ public class ServiceImpl implements Service {
     return isCredentialStoreSupported;
   }
 
-
+  /**
+   * Get a true or false value specifying whether
+   * credential store is required by this service.
+   *
+   * @return true or false
+   */
+  @Override
+  public boolean isCredentialStoreRequired() {
+    return isCredentialStoreRequired;
+  }
 
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
index a38af29..8fe0a52 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
@@ -30,6 +30,8 @@ import org.apache.ambari.server.state.stack.MetricDefinition;
 import org.apache.ambari.server.state.stack.StackRoleCommandOrder;
 import org.codehaus.jackson.annotate.JsonIgnore;
 import org.codehaus.jackson.map.annotate.JsonFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.xml.bind.Unmarshaller;
 import javax.xml.bind.annotation.XmlAccessType;
@@ -476,6 +478,33 @@ public String getVersion() {
   }
 
   /**
+   * Indicates if this service is requires credential store.
+   * False if it was not specified.
+   *
+   * @return true or false
+   */
+  public boolean isCredentialStoreRequired() {
+    if (credentialStoreInfo != null) {
+      if (credentialStoreInfo.isRequired() != null) {
+        return credentialStoreInfo.isRequired();
+      }
+    }
+
+    return false;
+  }
+
+  /**
+   * Set a value indicating if this service requires credential store.
+   * @param credentialStoreRequired
+   */
+  public void setCredentialStoreRequired(boolean credentialStoreRequired) {
+    if (credentialStoreInfo == null) {
+      credentialStoreInfo = new CredentialStoreInfo();
+    }
+    credentialStoreInfo.setRequired(credentialStoreRequired);
+  }
+
+  /**
    * Indicates if this service is enabled for credential store use.
    * False if it was not specified.
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/main/resources/properties.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/properties.json b/ambari-server/src/main/resources/properties.json
index 698b6c5..33854c5 100644
--- a/ambari-server/src/main/resources/properties.json
+++ b/ambari-server/src/main/resources/properties.json
@@ -222,6 +222,7 @@
         "StackServices/required_services",
         "StackServices/credential_store_supported",
         "StackServices/credential_store_enabled",
+        "StackServices/credential_store_required",
         "StackServices/properties",
         "_"
     ],

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/metainfo.xml
index f2002e1..a98dcc8 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/metainfo.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/metainfo.xml
@@ -27,10 +27,6 @@
       <comment>Comprehensive security for Hadoop</comment>
       <extends>common-services/RANGER/0.5.0</extends>
       <version>0.5.0.2.3</version>
-      <credential-store>
-        <supported>true</supported>
-        <enabled>false</enabled>
-      </credential-store>
     </service>
   </services>
 </metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/main/resources/stacks/HDP/2.4/services/RANGER/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.4/services/RANGER/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.4/services/RANGER/metainfo.xml
index 97bc19f..cbfafc2 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.4/services/RANGER/metainfo.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.4/services/RANGER/metainfo.xml
@@ -24,10 +24,6 @@
     <service>
       <name>RANGER</name>
       <version>0.5.0.2.4</version>
-      <credential-store>
-        <supported>true</supported>
-        <enabled>false</enabled>
-      </credential-store>
     </service>
   </services>
 </metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/main/resources/stacks/HDP/2.5/services/RANGER/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.5/services/RANGER/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.5/services/RANGER/metainfo.xml
index 7afbfb7..fe97a41 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.5/services/RANGER/metainfo.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.5/services/RANGER/metainfo.xml
@@ -25,10 +25,6 @@
       <name>RANGER</name>
       <extends>common-services/RANGER/0.6.0</extends>
       <version>0.6.0.2.5</version>
-      <credential-store>
-        <supported>true</supported>
-	<enabled>false</enabled>
-      </credential-store>
     </service>
   </services>
 </metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/main/resources/stacks/HDP/2.6/services/RANGER/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.6/services/RANGER/metainfo.xml b/ambari-server/src/main/resources/stacks/HDP/2.6/services/RANGER/metainfo.xml
index cc25d44..01d1cbf 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.6/services/RANGER/metainfo.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.6/services/RANGER/metainfo.xml
@@ -25,10 +25,6 @@
       <name>RANGER</name>
       <extends>common-services/RANGER/0.7.0</extends>
       <version>0.7.0.2.6</version>
-      <credential-store>
-        <supported>true</supported>
-        <enabled>false</enabled>
-      </credential-store>
     </service>
   </services>
 </metainfo>

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
index 8859d7f..06b521e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
@@ -10380,6 +10380,89 @@ public class AmbariManagementControllerTest {
   }
 
   @Test
+  public void testCredentialStoreRelatedAPICallsToUpdateSettings() throws Exception {
+    String cluster1 = getUniqueName();
+    createCluster(cluster1);
+    clusters.getCluster(cluster1).setDesiredStackVersion(
+        new StackId("HDP-2.2.0"));
+
+    String service1Name = "HDFS";
+    String service2Name = "STORM";
+    String service3Name = "ZOOKEEPER";
+    createService(cluster1, service1Name, null);
+    createService(cluster1, service2Name, null);
+    createService(cluster1, service3Name, null);
+    String component1Name = "NAMENODE";
+    String component2Name = "DRPC_SERVER";
+    String component3Name = "ZOOKEEPER_SERVER";
+    createServiceComponent(cluster1, service1Name, component1Name, State.INIT);
+    createServiceComponent(cluster1, service2Name, component2Name, State.INIT);
+    createServiceComponent(cluster1, service3Name, component3Name, State.INIT);
+    String host1 = getUniqueName();
+    addHostToCluster(host1, cluster1);
+    createServiceComponentHost(cluster1, service1Name, component1Name, host1, null);
+    createServiceComponentHost(cluster1, service2Name, component2Name, host1, null);
+    createServiceComponentHost(cluster1, service3Name, component3Name, host1, null);
+
+    Map<String, String> requestProperties = new HashMap<String, String>();
+    requestProperties.put("context", "Called from a test");
+
+    Cluster cluster = clusters.getCluster(cluster1);
+    Service service1 = cluster.getService(service1Name);
+
+    MaintenanceStateHelper
+        maintenanceStateHelper =
+        MaintenanceStateHelperTest.getMaintenanceStateHelperInstance(clusters);
+
+    // test updating a service
+    ServiceRequest sr = new ServiceRequest(cluster1, service1Name, null);
+    sr.setCredentialStoreEnabled("true");
+
+    ServiceResourceProviderTest.updateServices(controller,
+                                               Collections.singleton(sr), requestProperties, false, false,
+                                               maintenanceStateHelper);
+    Assert.assertTrue(service1.isCredentialStoreEnabled());
+    Assert.assertTrue(service1.isCredentialStoreSupported());
+    Assert.assertFalse(service1.isCredentialStoreRequired());
+
+    ServiceRequest sr2 = new ServiceRequest(cluster1, service2Name, null);
+    sr2.setCredentialStoreEnabled("true");
+    try {
+      ServiceResourceProviderTest.updateServices(controller,
+                                                 Collections.singleton(sr2), requestProperties, false, false,
+                                                 maintenanceStateHelper);
+      Assert.assertTrue("Expected exception not thrown - service does not support cred store", true);
+    }catch(IllegalArgumentException iaex) {
+      Assert.assertTrue(iaex.getMessage(), iaex.getMessage().contains(
+          "Invalid arguments, cannot enable credential store as it is not supported by the service. Service=STORM"));
+    }
+
+    ServiceRequest sr3 = new ServiceRequest(cluster1, service3Name, null);
+    sr3.setCredentialStoreEnabled("false");
+    try {
+      ServiceResourceProviderTest.updateServices(controller,
+                                                 Collections.singleton(sr3), requestProperties, false, false,
+                                                 maintenanceStateHelper);
+      Assert.assertTrue("Expected exception not thrown - service does not support disabling of cred store", true);
+    }catch(IllegalArgumentException iaex) {
+      Assert.assertTrue(iaex.getMessage(), iaex.getMessage().contains(
+          "Invalid arguments, cannot disable credential store as it is required by the service. Service=ZOOKEEPER"));
+    }
+
+    ServiceRequest sr4 = new ServiceRequest(cluster1, service3Name, null);
+    sr4.setCredentialStoreSupported("true");
+    try {
+      ServiceResourceProviderTest.updateServices(controller,
+                                                 Collections.singleton(sr4), requestProperties, false, false,
+                                                 maintenanceStateHelper);
+      Assert.assertTrue("Expected exception not thrown - service does not support updating cred store support", true);
+    }catch(IllegalArgumentException iaex) {
+      Assert.assertTrue(iaex.getMessage(), iaex.getMessage().contains(
+          "Invalid arguments, cannot update credential_store_supported as it is set only via service definition. Service=ZOOKEEPER"));
+    }
+  }
+
+  @Test
   public void testPassiveSkipServices() throws Exception {
     String cluster1 = getUniqueName();
     createCluster(cluster1);

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
index 3b963a8..a6ca8a3 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
@@ -978,8 +978,8 @@ public class ServiceModuleTest {
    */
   @Test
   public void testResolve_CredentialStoreInfo() throws Exception {
-    CredentialStoreInfo credentialStoreInfoChild = new CredentialStoreInfo(true /* supported */, false /* enabled */);
-    CredentialStoreInfo credentialStoreInfoParent = new CredentialStoreInfo(true /* supported */, true /* enabled */);
+    CredentialStoreInfo credentialStoreInfoChild = new CredentialStoreInfo(true /* supported */, false /* enabled */, true /*required*/);
+    CredentialStoreInfo credentialStoreInfoParent = new CredentialStoreInfo(true /* supported */, true /* enabled */, false /*required*/);
     ServiceInfo childInfo = new ServiceInfo();
     ServiceInfo parentInfo = new ServiceInfo();
     ServiceModule service;
@@ -990,6 +990,7 @@ public class ServiceModuleTest {
     service = resolveService(childInfo, parentInfo);
     assertEquals(credentialStoreInfoChild.isSupported(), service.getModuleInfo().isCredentialStoreSupported());
     assertEquals(credentialStoreInfoChild.isEnabled(), service.getModuleInfo().isCredentialStoreEnabled());
+    assertEquals(credentialStoreInfoChild.isRequired(), service.getModuleInfo().isCredentialStoreRequired());
 
     // specified in parent only, parent wins
     childInfo.setCredentialStoreInfo(null);
@@ -997,6 +998,7 @@ public class ServiceModuleTest {
     service = resolveService(childInfo, parentInfo);
     assertEquals(credentialStoreInfoParent.isSupported(), service.getModuleInfo().isCredentialStoreSupported());
     assertEquals(credentialStoreInfoParent.isEnabled(), service.getModuleInfo().isCredentialStoreEnabled());
+    assertEquals(credentialStoreInfoParent.isRequired(), service.getModuleInfo().isCredentialStoreRequired());
 
     // specified in both, child wins
     childInfo.setCredentialStoreInfo(credentialStoreInfoChild);
@@ -1004,6 +1006,7 @@ public class ServiceModuleTest {
     service = resolveService(childInfo, parentInfo);
     assertEquals(credentialStoreInfoChild.isSupported(), service.getModuleInfo().isCredentialStoreSupported());
     assertEquals(credentialStoreInfoChild.isEnabled(), service.getModuleInfo().isCredentialStoreEnabled());
+    assertEquals(credentialStoreInfoChild.isRequired(), service.getModuleInfo().isCredentialStoreRequired());
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceInfoTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceInfoTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceInfoTest.java
index 3034459..d841400 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceInfoTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceInfoTest.java
@@ -158,6 +158,7 @@ public class ServiceInfoTest {
             "      <credential-store>\n" +
             "          <supported>true</supported>\n" +
             "          <enabled>true</enabled>\n" +
+            "          <required>true</required>\n" +
             "      </credential-store>\n" +
             "    </service>\n" +
             "  </services>\n" +
@@ -166,6 +167,7 @@ public class ServiceInfoTest {
     ServiceInfo service = serviceInfoMap.get("RANGER");
     assertTrue(service.isCredentialStoreSupported());
     assertTrue(service.isCredentialStoreEnabled());
+    assertTrue(service.isCredentialStoreRequired());
 
     /*
      * <credential-store> supported but not enabled.
@@ -178,6 +180,7 @@ public class ServiceInfoTest {
             "      <credential-store>\n" +
             "          <supported>true</supported>\n" +
             "          <enabled>false</enabled>\n" +
+            "          <required>false</required>\n" +
             "      </credential-store>\n" +
             "    </service>\n" +
             "  </services>\n" +
@@ -186,6 +189,7 @@ public class ServiceInfoTest {
     service = serviceInfoMap.get("HIVE");
     assertTrue(service.isCredentialStoreSupported());
     assertFalse(service.isCredentialStoreEnabled());
+    assertFalse(service.isCredentialStoreRequired());
 
     /*
      * <credential-store> is missing

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/HDFS/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/HDFS/metainfo.xml b/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/HDFS/metainfo.xml
index 281c77e..f6aa61d 100644
--- a/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/HDFS/metainfo.xml
+++ b/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/HDFS/metainfo.xml
@@ -22,7 +22,11 @@
       <name>HDFS</name>
       <comment>Apache Hadoop Distributed File System</comment>
       <version>2.1.0.2.0.6.0</version>
-
+      <credential-store>
+        <supported>true</supported>
+        <enabled>true</enabled>
+        <required>false</required>
+      </credential-store>
       <components>
         <component>
           <name>NAMENODE</name>

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/STORM/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/STORM/metainfo.xml b/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/STORM/metainfo.xml
index 6075ba3..400eb13 100644
--- a/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/STORM/metainfo.xml
+++ b/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/STORM/metainfo.xml
@@ -23,6 +23,12 @@
       <name>STORM</name>
       <comment>Apache Hadoop Stream processing framework</comment>
       <version>0.9.0.1</version>
+      <credential-store>
+        <supported>false</supported>
+        <enabled>false</enabled>
+        <required>false</required>
+      </credential-store>
+
       <components>
 
         <component>

http://git-wip-us.apache.org/repos/asf/ambari/blob/503d95f8/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/ZOOKEEPER/metainfo.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/ZOOKEEPER/metainfo.xml b/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/ZOOKEEPER/metainfo.xml
index ed0a132..5577684 100644
--- a/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/ZOOKEEPER/metainfo.xml
+++ b/ambari-server/src/test/resources/stacks/HDP/2.2.0/services/ZOOKEEPER/metainfo.xml
@@ -23,7 +23,11 @@
       <displayName>ZooKeeper</displayName>
       <comment>Centralized service which provides highly reliable distributed coordination</comment>
       <version>3.4.5.2.0</version>
-
+      <credential-store>
+        <supported>true</supported>
+        <enabled>false</enabled>
+        <required>true</required>
+      </credential-store>
       <components>
         <component>
           <name>ZOOKEEPER_SERVER</name>