http://git-wip-us.apache.org/repos/asf/ambari/blob/e3acc7f0/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerAction.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerAction.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerAction.java
new file mode 100644
index 0000000..b3b6b48
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/AbstractPrepareKerberosServerAction.java
@@ -0,0 +1,192 @@
+/*
+ * 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.serveraction.kerberos;
+
+import com.google.common.reflect.TypeToken;
+import com.google.inject.Inject;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.agent.CommandReport;
+import org.apache.ambari.server.controller.KerberosHelper;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.ServiceComponentHost;
+import org.apache.ambari.server.state.kerberos.KerberosComponentDescriptor;
+import org.apache.ambari.server.state.kerberos.KerberosDescriptor;
+import org.apache.ambari.server.state.kerberos.KerberosIdentityDescriptor;
+import org.apache.ambari.server.state.kerberos.KerberosServiceDescriptor;
+import org.apache.ambari.server.utils.StageUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class AbstractPrepareKerberosServerAction extends 
KerberosServerAction {
+  private final static Logger LOG = 
LoggerFactory.getLogger(AbstractPrepareKerberosServerAction.class);
+
+  /**
+   * KerberosHelper
+   */
+  @Inject
+  private KerberosHelper kerberosHelper;
+
+  @Inject
+  private KerberosIdentityDataFileWriterFactory 
kerberosIdentityDataFileWriterFactory;
+
+  @Override
+  protected CommandReport processIdentity(Map<String, String> identityRecord, 
String evaluatedPrincipal, KerberosOperationHandler operationHandler, 
Map<String, String> kerberosConfiguration, Map<String, Object> 
requestSharedDataContext) throws AmbariException {
+    throw new UnsupportedOperationException();
+  }
+
+  protected void processIdentities(Cluster cluster, KerberosDescriptor 
kerberosDescriptor, List<ServiceComponentHost> schToProcess,
+                                   Collection<String> identityFilter, String 
dataDirectory,
+                                   Map<String, Map<String, String>> 
kerberosConfigurations) throws AmbariException {
+
+    actionLog.writeStdOut("Processing Kerberos Identities");
+
+    if (!schToProcess.isEmpty()) {
+      if(dataDirectory == null) {
+        String message = "The data directory has not been set.  Generated data 
can not be stored.";
+        LOG.error(message);
+        throw new AmbariException(message);
+      }
+
+      // Create the file used to store details about principals and keytabs to 
create
+      File identityDataFile = new File(dataDirectory, 
KerberosIdentityDataFileWriter.DATA_FILE_NAME);
+
+      // Group ServiceComponentHosts with their relevant hosts so we can 
create the relevant host-based
+      // configurations once per host, rather than for every 
ServiceComponentHost we encounter
+      Map<String, List<ServiceComponentHost>> hostServiceComponentHosts = new 
HashMap<String, List<ServiceComponentHost>>();
+      for (ServiceComponentHost sch : schToProcess) {
+        String hostName = sch.getHostName();
+        List<ServiceComponentHost> serviceComponentHosts = 
hostServiceComponentHosts.get(hostName);
+
+        if (serviceComponentHosts == null) {
+          serviceComponentHosts = new ArrayList<ServiceComponentHost>();
+          hostServiceComponentHosts.put(hostName, serviceComponentHosts);
+        }
+
+        serviceComponentHosts.add(sch);
+      }
+
+      Map<String, String> kerberosDescriptorProperties = 
kerberosDescriptor.getProperties();
+      KerberosIdentityDataFileWriter kerberosIdentityDataFileWriter = null;
+
+      try {
+        for (Map.Entry<String, List<ServiceComponentHost>> entry : 
hostServiceComponentHosts.entrySet()) {
+          String hostName = entry.getKey();
+          List<ServiceComponentHost> serviceComponentHosts = entry.getValue();
+
+          // Calculate the current host-specific configurations. These will be 
used to replace
+          // variables within the Kerberos descriptor data
+          Map<String, Map<String, String>> configurations = 
kerberosHelper.calculateConfigurations(cluster, hostName, 
kerberosDescriptorProperties);
+
+          try {
+            // Iterate over the components installed on the current host to 
get the service and
+            // component-level Kerberos descriptors in order to determine 
which principals,
+            // keytab files, and configurations need to be created or updated.
+            for (ServiceComponentHost sch : serviceComponentHosts) {
+              String serviceName = sch.getServiceName();
+              String componentName = sch.getServiceComponentName();
+
+              KerberosServiceDescriptor serviceDescriptor = 
kerberosDescriptor.getService(serviceName);
+
+              if (serviceDescriptor != null) {
+                List<KerberosIdentityDescriptor> serviceIdentities = 
serviceDescriptor.getIdentities(true);
+
+                // Lazily create the KerberosIdentityDataFileWriter instance...
+                if (kerberosIdentityDataFileWriter == null) {
+                  actionLog.writeStdOut(String.format("Writing Kerberos 
identity data metadata file to %s", identityDataFile.getAbsolutePath()));
+                  kerberosIdentityDataFileWriter = 
kerberosIdentityDataFileWriterFactory.createKerberosIdentityDataFileWriter(identityDataFile);
+                }
+
+                // Add service-level principals (and keytabs)
+                kerberosHelper.addIdentities(kerberosIdentityDataFileWriter, 
serviceIdentities,
+                    identityFilter, hostName, serviceName, componentName, 
kerberosConfigurations, configurations);
+
+                KerberosComponentDescriptor componentDescriptor = 
serviceDescriptor.getComponent(componentName);
+
+                if (componentDescriptor != null) {
+                  List<KerberosIdentityDescriptor> componentIdentities = 
componentDescriptor.getIdentities(true);
+
+                  // Calculate the set of configurations to update and replace 
any variables
+                  // using the previously calculated Map of configurations for 
the host.
+                  kerberosHelper.mergeConfigurations(kerberosConfigurations,
+                      componentDescriptor.getConfigurations(true), 
configurations);
+
+                  // Add component-level principals (and keytabs)
+                  kerberosHelper.addIdentities(kerberosIdentityDataFileWriter, 
componentIdentities,
+                      identityFilter, hostName, serviceName, componentName, 
kerberosConfigurations, configurations);
+                }
+              }
+            }
+          } catch (IOException e) {
+            String message = String.format("Failed to write index file - %s", 
identityDataFile.getAbsolutePath());
+            LOG.error(message, e);
+            actionLog.writeStdOut(message);
+            actionLog.writeStdErr(message + "\n" + e.getLocalizedMessage());
+            throw new AmbariException(message, e);
+          }
+        }
+      }
+      finally {
+        if (kerberosIdentityDataFileWriter != null) {
+          // Make sure the data file is closed
+          try {
+            kerberosIdentityDataFileWriter.close();
+          } catch (IOException e) {
+            String message = "Failed to close the index file writer";
+            LOG.warn(message, e);
+            actionLog.writeStdOut(message);
+            actionLog.writeStdErr(message + "\n" + e.getLocalizedMessage());
+          }
+        }
+      }
+    }
+  }
+
+  protected Map<String, ? extends Collection<String>> 
getServiceComponentFilter() {
+    String serializedValue = 
getCommandParameterValue(SERVICE_COMPONENT_FILTER);
+
+    if(serializedValue != null) {
+      Type type = new TypeToken<Map<String, ? extends Collection<String>>>() 
{}.getType();
+      return StageUtils.getGson().fromJson(serializedValue, type);
+    }
+    else {
+      return null;
+    }
+  }
+
+  protected Collection<String> getIdentityFilter() {
+    String serializedValue = getCommandParameterValue(IDENTITY_FILTER);
+
+    if(serializedValue != null) {
+      Type type = new TypeToken<Collection<String>>() {}.getType();
+      return StageUtils.getGson().fromJson(serializedValue, type);
+    }
+    else {
+      return null;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/e3acc7f0/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreateKeytabFilesServerAction.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreateKeytabFilesServerAction.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreateKeytabFilesServerAction.java
index 34780d6..c7123a4 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreateKeytabFilesServerAction.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreateKeytabFilesServerAction.java
@@ -150,13 +150,19 @@ public class CreateKeytabFilesServerAction extends 
KerberosServerAction {
 
     if (identityRecord != null) {
       String message;
+      String dataDirectory = getDataDirectoryPath();
 
       if (operationHandler == null) {
         message = String.format("Failed to create keytab file for %s, missing 
KerberosOperationHandler", evaluatedPrincipal);
         actionLog.writeStdErr(message);
         LOG.error(message);
         commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", 
actionLog.getStdOut(), actionLog.getStdErr());
-      } else {
+      } else if (dataDirectory == null) {
+        message = "The data directory has not been set. Generated keytab files 
can not be stored.";
+        LOG.error(message);
+        commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", 
actionLog.getStdOut(), actionLog.getStdErr());
+      }
+      else {
         Map<String, String> principalPasswordMap = 
getPrincipalPasswordMap(requestSharedDataContext);
         Map<String, Integer> principalKeyNumberMap = 
getPrincipalKeyNumberMap(requestSharedDataContext);
 
@@ -178,7 +184,7 @@ public class CreateKeytabFilesServerAction extends 
KerberosServerAction {
 
             // Determine where to store the keytab file.  It should go into a 
host-specific
             // directory under the previously determined data directory.
-            File hostDirectory = new File(getDataDirectoryPath(), hostName);
+            File hostDirectory = new File(dataDirectory, hostName);
 
             // Ensure the host directory exists...
             if (!hostDirectory.exists() && hostDirectory.mkdirs()) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/e3acc7f0/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
index 55018de..57e5527 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
@@ -70,6 +70,15 @@ public abstract class KerberosServerAction extends 
AbstractServerAction {
   public static final String DEFAULT_REALM = "default_realm";
 
   /**
+   * A (command parameter) property name used to hold the (serialized) 
service/component filter map.
+   */
+  public static final String SERVICE_COMPONENT_FILTER = 
"service_component_filter";
+
+  /**
+   * A (command parameter) property name used to hold the (serialized) 
identity filter list.
+   */
+  public static final String IDENTITY_FILTER = "identity_filter";
+  /**
    * A (command parameter) property name used to hold the relevant KDC type 
value.  See
    * {@link org.apache.ambari.server.serveraction.kerberos.KDCType} for valid 
values
    */

http://git-wip-us.apache.org/repos/asf/ambari/blob/e3acc7f0/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java
new file mode 100644
index 0000000..68fcca0
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java
@@ -0,0 +1,250 @@
+/*
+ * 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.serveraction.kerberos;
+
+import com.google.inject.Inject;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.agent.CommandReport;
+import org.apache.ambari.server.controller.KerberosHelper;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.ConfigHelper;
+import org.apache.ambari.server.state.PropertyInfo;
+import org.apache.ambari.server.state.SecurityState;
+import org.apache.ambari.server.state.ServiceComponentHost;
+import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.kerberos.KerberosDescriptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * PrepareEnableKerberosServerAction is a ServerAction implementation that 
prepares metadata needed
+ * to enable Kerberos on the cluster.
+ */
+public class PrepareDisableKerberosServerAction extends 
AbstractPrepareKerberosServerAction {
+  private final static Logger LOG = 
LoggerFactory.getLogger(PrepareDisableKerberosServerAction.class);
+
+  /**
+   * KerberosHelper
+   */
+  @Inject
+  private KerberosHelper kerberosHelper;
+
+  @Inject
+  private ConfigHelper configHelper;
+
+  @Inject
+  private KerberosConfigDataFileWriterFactory 
kerberosConfigDataFileWriterFactory;
+
+
+  /**
+   * Called to execute this action.  Upon invocation, calls
+   * {@link KerberosServerAction#processIdentities(Map)}
+   * to iterate through the Kerberos identity metadata and call
+   * {@link PrepareDisableKerberosServerAction#processIdentities(Map)}
+   * for each identity to process.
+   *
+   * @param requestSharedDataContext a Map to be used a shared data among all 
ServerActions related
+   *                                 to a given request
+   * @return a CommandReport indicating the result of this action
+   * @throws AmbariException
+   * @throws InterruptedException
+   */
+  @Override
+  public CommandReport execute(ConcurrentMap<String, Object> 
requestSharedDataContext) throws
+      AmbariException, InterruptedException {
+
+    Cluster cluster = getCluster();
+
+    if (cluster == null) {
+      throw new AmbariException("Missing cluster object");
+    }
+
+    KerberosDescriptor kerberosDescriptor = 
kerberosHelper.getKerberosDescriptor(cluster);
+    Collection<String> identityFilter = getIdentityFilter();
+    List<ServiceComponentHost> schToProcess = 
kerberosHelper.getServiceComponentHostsToProcess(cluster,
+        kerberosDescriptor,
+        getServiceComponentFilter(),
+        identityFilter,
+        new KerberosHelper.Command<Boolean, ServiceComponentHost>() {
+          @Override
+          public Boolean invoke(ServiceComponentHost sch) throws 
AmbariException {
+            return (sch.getDesiredSecurityState() == SecurityState.UNSECURED) 
&&  (sch.getSecurityState() != SecurityState.UNSECURED);
+          }
+        });
+
+    Map<String, Map<String, String>> kerberosConfigurations = new 
HashMap<String, Map<String, String>>();
+    Map<String, String> commandParameters = getCommandParameters();
+    String dataDirectory = getCommandParameterValue(commandParameters, 
DATA_DIRECTORY);
+
+    int schCount = schToProcess.size();
+    if (schCount == 0) {
+      actionLog.writeStdOut("There are no components to process");
+    } else if (schCount == 1) {
+      actionLog.writeStdOut(String.format("Processing %d component", 
schCount));
+    } else {
+      actionLog.writeStdOut(String.format("Processing %d components", 
schCount));
+    }
+
+    processIdentities(cluster, kerberosDescriptor, schToProcess, 
identityFilter, dataDirectory, kerberosConfigurations);
+
+    actionLog.writeStdOut("Determining configuration changes");
+    // Ensure the cluster-env/security_enabled flag is set properly
+    Map<String, String> clusterEnvProperties = 
kerberosConfigurations.get(KerberosHelper.SECURITY_ENABLED_CONFIG_TYPE);
+    if (clusterEnvProperties == null) {
+      clusterEnvProperties = new HashMap<String, String>();
+      kerberosConfigurations.put(KerberosHelper.SECURITY_ENABLED_CONFIG_TYPE, 
clusterEnvProperties);
+    }
+    clusterEnvProperties.put(KerberosHelper.SECURITY_ENABLED_PROPERTY_NAME, 
"false");
+
+    // If there are configurations to set, create a (temporary) data file to 
store the configuration
+    // updates and fill it will the relevant configurations.
+    if (!kerberosConfigurations.isEmpty()) {
+      if(dataDirectory == null) {
+        String message = "The data directory has not been set.  Generated data 
can not be stored.";
+        LOG.error(message);
+        throw new AmbariException(message);
+      }
+
+      Map<String, Collection<String>> configurationsToRemove = new 
HashMap<String, Collection<String>>();
+      File configFile = new File(dataDirectory, 
KerberosConfigDataFileWriter.DATA_FILE_NAME);
+      KerberosConfigDataFileWriter kerberosConfDataFileWriter = null;
+
+      // Fill the configurationsToRemove map with all Kerberos-related 
configurations.  Values
+      // needed to be kept will have new values from the stack definition and 
thus pruned from
+      // this map.
+      for (Map.Entry<String, Map<String, String>> entry : 
kerberosConfigurations.entrySet()) {
+        configurationsToRemove.put(entry.getKey(), new 
HashSet<String>(entry.getValue().keySet()));
+      }
+
+      // Remove cluster-env from the set of configurations to remove since it 
has no default set
+      // or properties and the logic below will remove all from this set - 
which is not desirable.
+      configurationsToRemove.remove("cluster-env");
+
+      if (!schToProcess.isEmpty()) {
+        Set<String> visitedServices = new HashSet<String>();
+
+        for (ServiceComponentHost sch : schToProcess) {
+          String serviceName = sch.getServiceName();
+
+          if (!visitedServices.contains(serviceName)) {
+            StackId stackVersion = sch.getStackVersion();
+
+            visitedServices.add(serviceName);
+
+            if (stackVersion != null) {
+              Set<PropertyInfo> serviceProperties = 
configHelper.getServiceProperties(stackVersion, serviceName, true);
+
+              if (serviceProperties != null) {
+                for (PropertyInfo propertyInfo : serviceProperties) {
+                  String filename = propertyInfo.getFilename();
+
+                  if (filename != null) {
+                    String type = ConfigHelper.fileNameToConfigType(filename);
+                    String propertyName = propertyInfo.getName();
+
+                    Map<String, String> kerberosConfiguration = 
kerberosConfigurations.get(type);
+                    if ((kerberosConfiguration != null) && 
(kerberosConfiguration.containsKey(propertyName))) {
+                      kerberosConfiguration.put(propertyName, 
propertyInfo.getValue());
+                    }
+
+                    // Remove the relevant from the set of properties (for the 
given type) to remove
+                    Collection<String> propertiesToRemove = 
configurationsToRemove.get(type);
+                    if (propertiesToRemove != null) {
+                      propertiesToRemove.remove(propertyName);
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+
+      actionLog.writeStdOut(String.format("Writing configuration changes 
metadata file to %s", configFile.getAbsolutePath()));
+      try {
+        kerberosConfDataFileWriter = 
kerberosConfigDataFileWriterFactory.createKerberosConfigDataFileWriter(configFile);
+
+        for (Map.Entry<String, Map<String, String>> entry : 
kerberosConfigurations.entrySet()) {
+          String type = entry.getKey();
+          Map<String, String> properties = entry.getValue();
+          Collection<String> propertiesToRemove = 
configurationsToRemove.get(type);
+
+          if (properties != null) {
+            for (Map.Entry<String, String> configTypeEntry : 
properties.entrySet()) {
+              String propertyName = configTypeEntry.getKey();
+
+              // Ignore properties that should be removed
+              if ((propertiesToRemove == null) || 
!propertiesToRemove.contains(propertyName)) {
+                String value = configTypeEntry.getValue();
+                String operation = (value == null)
+                    ? KerberosConfigDataFileWriter.OPERATION_TYPE_REMOVE
+                    : KerberosConfigDataFileWriter.OPERATION_TYPE_SET;
+
+                kerberosConfDataFileWriter.addRecord(type, propertyName, 
value, operation);
+              }
+            }
+          }
+        }
+
+        // Declare which properties to remove from the configurations
+        for (Map.Entry<String, Collection<String>> entry : 
configurationsToRemove.entrySet()) {
+          String type = entry.getKey();
+          Collection<String> properties = entry.getValue();
+
+          if (properties != null) {
+            for (String propertyName : properties) {
+              kerberosConfDataFileWriter.addRecord(type, propertyName, null, 
KerberosConfigDataFileWriter.OPERATION_TYPE_REMOVE);
+            }
+          }
+        }
+      } catch (IOException e) {
+        String message = String.format("Failed to write kerberos 
configurations file - %s", configFile.getAbsolutePath());
+        LOG.error(message, e);
+        actionLog.writeStdOut(message);
+        actionLog.writeStdErr(message + "\n" + e.getLocalizedMessage());
+        throw new AmbariException(message, e);
+      } finally {
+        if (kerberosConfDataFileWriter != null) {
+          try {
+            kerberosConfDataFileWriter.close();
+          } catch (IOException e) {
+            String message = "Failed to close the kerberos configurations file 
writer";
+            LOG.warn(message, e);
+            actionLog.writeStdOut(message);
+            actionLog.writeStdErr(message + "\n" + e.getLocalizedMessage());
+          }
+        }
+      }
+    }
+
+    return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", 
actionLog.getStdOut(), actionLog.getStdErr());
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/e3acc7f0/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java
new file mode 100644
index 0000000..2295eeb
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareEnableKerberosServerAction.java
@@ -0,0 +1,183 @@
+/*
+ * 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.serveraction.kerberos;
+
+import com.google.inject.Inject;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.agent.CommandReport;
+import org.apache.ambari.server.controller.KerberosHelper;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.SecurityState;
+import org.apache.ambari.server.state.ServiceComponentHost;
+import org.apache.ambari.server.state.kerberos.KerberosDescriptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * PrepareEnableKerberosServerAction is a ServerAction implementation that 
prepares metadata needed
+ * to enable Kerberos on the cluster.
+ */
+public class PrepareEnableKerberosServerAction extends 
AbstractPrepareKerberosServerAction {
+  private final static Logger LOG = 
LoggerFactory.getLogger(PrepareEnableKerberosServerAction.class);
+
+  /**
+   * KerberosHelper
+   */
+  @Inject
+  private KerberosHelper kerberosHelper;
+
+  @Inject
+  private KerberosConfigDataFileWriterFactory 
kerberosConfigDataFileWriterFactory;
+
+
+  /**
+   * Called to execute this action.  Upon invocation, calls
+   * {@link KerberosServerAction#processIdentities(Map)}
+   * to iterate through the Kerberos identity metadata and call
+   * {@link PrepareEnableKerberosServerAction#processIdentities(Map)}
+   * for each identity to process.
+   *
+   * @param requestSharedDataContext a Map to be used a shared data among all 
ServerActions related
+   *                                 to a given request
+   * @return a CommandReport indicating the result of this action
+   * @throws AmbariException
+   * @throws InterruptedException
+   */
+  @Override
+  public CommandReport execute(ConcurrentMap<String, Object> 
requestSharedDataContext) throws
+      AmbariException, InterruptedException {
+
+    Cluster cluster = getCluster();
+
+    if (cluster == null) {
+      throw new AmbariException("Missing cluster object");
+    }
+
+    KerberosDescriptor kerberosDescriptor = 
kerberosHelper.getKerberosDescriptor(cluster);
+    Collection<String> identityFilter = getIdentityFilter();
+    List<ServiceComponentHost> schToProcess = 
kerberosHelper.getServiceComponentHostsToProcess(cluster,
+        kerberosDescriptor,
+        getServiceComponentFilter(),
+        identityFilter,
+        new KerberosHelper.Command<Boolean, ServiceComponentHost>() {
+          @Override
+          public Boolean invoke(ServiceComponentHost sch) throws 
AmbariException {
+            return (sch.getDesiredSecurityState() == 
SecurityState.SECURED_KERBEROS) && (sch.getSecurityState() != 
SecurityState.SECURED_KERBEROS);
+          }
+        });
+
+    Map<String, String> commandParameters = getCommandParameters();
+    String dataDirectory = getCommandParameterValue(commandParameters, 
DATA_DIRECTORY);
+    Map<String, Map<String, String>> kerberosConfigurations = new 
HashMap<String, Map<String, String>>();
+
+    int schCount = schToProcess.size();
+    if (schCount == 0) {
+      actionLog.writeStdOut("There are no components to process");
+    } else if (schCount == 1) {
+      actionLog.writeStdOut(String.format("Processing %d component", 
schCount));
+    } else {
+      actionLog.writeStdOut(String.format("Processing %d components", 
schCount));
+    }
+
+    processIdentities(cluster, kerberosDescriptor, schToProcess, 
identityFilter, dataDirectory, kerberosConfigurations);
+
+    if (!schToProcess.isEmpty()) {
+      actionLog.writeStdOut("Creating auth-to-local rules");
+      kerberosHelper.setAuthToLocalRules(kerberosDescriptor, cluster, 
getDefaultRealm(commandParameters),
+          kerberosHelper.calculateConfigurations(cluster, null, 
kerberosDescriptor.getProperties()),
+          kerberosConfigurations);
+    }
+
+
+    actionLog.writeStdOut("Determining configuration changes");
+    // Ensure the cluster-env/security_enabled flag is set properly
+    Map<String, String> clusterEnvProperties = 
kerberosConfigurations.get(KerberosHelper.SECURITY_ENABLED_CONFIG_TYPE);
+    if (clusterEnvProperties == null) {
+      clusterEnvProperties = new HashMap<String, String>();
+      kerberosConfigurations.put(KerberosHelper.SECURITY_ENABLED_CONFIG_TYPE, 
clusterEnvProperties);
+    }
+    clusterEnvProperties.put(KerberosHelper.SECURITY_ENABLED_PROPERTY_NAME, 
"true");
+
+    // If there are configurations to set, create a (temporary) data file to 
store the configuration
+    // updates and fill it will the relevant configurations.
+    if (!kerberosConfigurations.isEmpty()) {
+      if(dataDirectory == null) {
+        String message = "The data directory has not been set.  Generated data 
can not be stored.";
+        LOG.error(message);
+        throw new AmbariException(message);
+      }
+
+      File configFile = new File(dataDirectory, 
KerberosConfigDataFileWriter.DATA_FILE_NAME);
+      KerberosConfigDataFileWriter kerberosConfDataFileWriter = null;
+
+      actionLog.writeStdOut(String.format("Writing configuration changes 
metadata file to %s", configFile.getAbsolutePath()));
+      try {
+        kerberosConfDataFileWriter = 
kerberosConfigDataFileWriterFactory.createKerberosConfigDataFileWriter(configFile);
+
+        for (Map.Entry<String, Map<String, String>> entry : 
kerberosConfigurations.entrySet()) {
+          String type = entry.getKey();
+          Map<String, String> properties = entry.getValue();
+
+          if (properties != null) {
+            for (Map.Entry<String, String> configTypeEntry : 
properties.entrySet()) {
+              kerberosConfDataFileWriter.addRecord(type,
+                  configTypeEntry.getKey(),
+                  configTypeEntry.getValue(),
+                  KerberosConfigDataFileWriter.OPERATION_TYPE_SET);
+            }
+          }
+        }
+      } catch (IOException e) {
+        String message = String.format("Failed to write kerberos 
configurations file - %s", configFile.getAbsolutePath());
+        LOG.error(message, e);
+        actionLog.writeStdOut(message);
+        actionLog.writeStdErr(message + "\n" + e.getLocalizedMessage());
+        throw new AmbariException(message, e);
+      } finally {
+        if (kerberosConfDataFileWriter != null) {
+          try {
+            kerberosConfDataFileWriter.close();
+          } catch (IOException e) {
+            String message = "Failed to close the kerberos configurations file 
writer";
+            LOG.warn(message, e);
+            actionLog.writeStdOut(message);
+            actionLog.writeStdErr(message + "\n" + e.getLocalizedMessage());
+          }
+        }
+      }
+    }
+
+    return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", 
actionLog.getStdOut(), actionLog.getStdErr());
+  }
+
+  @Override
+  protected CommandReport processIdentity(Map<String, String> identityRecord, 
String evaluatedPrincipal, KerberosOperationHandler operationHandler, 
Map<String, String> kerberosConfiguration, Map<String, Object> 
requestSharedDataContext) throws AmbariException {
+    throw new UnsupportedOperationException();
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/e3acc7f0/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java
new file mode 100644
index 0000000..e39d868
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareKerberosIdentitiesServerAction.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     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.serveraction.kerberos;
+
+import com.google.inject.Inject;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.agent.CommandReport;
+import org.apache.ambari.server.controller.KerberosHelper;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.ServiceComponentHost;
+import org.apache.ambari.server.state.kerberos.KerberosDescriptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * PrepareKerberosIdentitiesServerAction is a ServerAction implementation that 
prepares metadata needed
+ * to process Kerberos identities (principals and keytabs files).
+ */
+public class PrepareKerberosIdentitiesServerAction extends 
AbstractPrepareKerberosServerAction {
+  private final static Logger LOG = 
LoggerFactory.getLogger(PrepareKerberosIdentitiesServerAction.class);
+
+  /**
+   * KerberosHelper
+   */
+  @Inject
+  private KerberosHelper kerberosHelper;
+
+  /**
+   * Called to execute this action.  Upon invocation, calls
+   * {@link KerberosServerAction#processIdentities(Map)}
+   * to iterate through the Kerberos identity metadata and call
+   * {@link PrepareKerberosIdentitiesServerAction#processIdentities(Map)}
+   * for each identity to process.
+   *
+   * @param requestSharedDataContext a Map to be used a shared data among all 
ServerActions related
+   *                                 to a given request
+   * @return a CommandReport indicating the result of this action
+   * @throws AmbariException
+   * @throws InterruptedException
+   */
+  @Override
+  public CommandReport execute(ConcurrentMap<String, Object> 
requestSharedDataContext) throws
+      AmbariException, InterruptedException {
+
+    Cluster cluster = getCluster();
+
+    if (cluster == null) {
+      throw new AmbariException("Missing cluster object");
+    }
+
+    KerberosDescriptor kerberosDescriptor = 
kerberosHelper.getKerberosDescriptor(cluster);
+    Collection<String> identityFilter = getIdentityFilter();
+    List<ServiceComponentHost> schToProcess = 
kerberosHelper.getServiceComponentHostsToProcess(cluster,
+        kerberosDescriptor,
+        getServiceComponentFilter(),
+        identityFilter,
+        new KerberosHelper.Command<Boolean, ServiceComponentHost>() {
+          @Override
+          public Boolean invoke(ServiceComponentHost sch) throws 
AmbariException {
+            return true;
+          }
+        });
+
+    Map<String, String> commandParameters = getCommandParameters();
+    String dataDirectory = getCommandParameterValue(commandParameters, 
DATA_DIRECTORY);
+    Map<String, Map<String, String>> kerberosConfigurations = new 
HashMap<String, Map<String, String>>();
+
+    int schCount = schToProcess.size();
+    if (schCount == 0) {
+      actionLog.writeStdOut("There are no components to process");
+    } else if (schCount == 1) {
+      actionLog.writeStdOut(String.format("Processing %d component", 
schCount));
+    } else {
+      actionLog.writeStdOut(String.format("Processing %d components", 
schCount));
+    }
+
+    processIdentities(cluster, kerberosDescriptor, schToProcess, 
identityFilter, dataDirectory, kerberosConfigurations);
+
+
+    return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", 
actionLog.getStdOut(), actionLog.getStdErr());
+  }
+
+  @Override
+  protected CommandReport processIdentity(Map<String, String> identityRecord, 
String evaluatedPrincipal, KerberosOperationHandler operationHandler, 
Map<String, String> kerberosConfiguration, Map<String, Object> 
requestSharedDataContext) throws AmbariException {
+    throw new UnsupportedOperationException();
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/e3acc7f0/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java 
b/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
index 10204ea..2e2cc29 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
@@ -81,6 +81,17 @@ public interface Cluster {
   List<ServiceComponentHost> getServiceComponentHosts(String hostname);
 
   /**
+   * Get all ServiceComponentHosts for a given service and optional component
+   *
+   * If the component name is <code>null</code>, all components for the 
requested service will be returned.
+   *
+   * @param serviceName the name a the desired service
+   * @param componentName the name a the desired component - null indicates 
all components for the service
+   * @return a list of found ServiceComponentHost instances
+   */
+  List<ServiceComponentHost> getServiceComponentHosts(String serviceName, 
String componentName);
+
+  /**
    * Get all hosts associated with this cluster.
    *
    * @return collection of hosts that are associated with this cluster

http://git-wip-us.apache.org/repos/asf/ambari/blob/e3acc7f0/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
index 186963f..8fa4034 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
@@ -797,6 +797,30 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
+  public List<ServiceComponentHost> getServiceComponentHosts(String 
serviceName, String componentName) {
+    ArrayList<ServiceComponentHost> foundItems = new 
ArrayList<ServiceComponentHost>();
+
+    loadServiceHostComponents();
+    clusterGlobalLock.readLock().lock();
+    try {
+      Map<String, Map<String, ServiceComponentHost>> foundByService = 
serviceComponentHosts.get(serviceName);
+      if (foundByService != null) {
+        if (componentName == null) {
+          for(Map<String, ServiceComponentHost> foundByComponent 
:foundByService.values()) {
+            foundItems.addAll(foundByComponent.values());
+          }
+        } else if (foundByService.containsKey(componentName)) {
+          foundItems.addAll(foundByService.get(componentName).values());
+        }
+      }
+    } finally {
+      clusterGlobalLock.readLock().unlock();
+    }
+
+    return foundItems;
+  }
+
+  @Override
   public void addService(Service service)
     throws AmbariException {
     loadServices();

Reply via email to