Pārlūkot izejas kodu

AMBARI-17454. Add manual task for regenerating keytabs for Ranger upgrade (ncole)

Nate Cole 9 gadi atpakaļ
vecāks
revīzija
f403a36ff5
17 mainītis faili ar 363 papildinājumiem un 77 dzēšanām
  1. 26 15
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
  2. 0 2
      ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KDCType.java
  3. 112 0
      ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/KerberosKeytabsAction.java
  4. 0 6
      ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ManualTask.java
  5. 7 0
      ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServerSideActionTask.java
  6. 0 6
      ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/nonrolling-upgrade-2.2.xml
  7. 0 6
      ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/nonrolling-upgrade-2.3.xml
  8. 0 6
      ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/nonrolling-upgrade-2.4.xml
  9. 0 6
      ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.3.xml
  10. 0 6
      ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.4.xml
  11. 0 6
      ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.5.xml
  12. 7 0
      ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.5.xml
  13. 0 6
      ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/nonrolling-upgrade-2.4.xml
  14. 0 6
      ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/nonrolling-upgrade-2.5.xml
  15. 7 0
      ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.5.xml
  16. 0 6
      ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/nonrolling-upgrade-2.5.xml
  17. 204 0
      ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/KerberosKeytabsActionTest.java

+ 26 - 15
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java

@@ -919,6 +919,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
                 continue;
               }
               UpgradeItemEntity itemEntity = new UpgradeItemEntity();
+
               itemEntity.setText(wrapper.getText());
               itemEntity.setTasks(wrapper.getTasksJson());
               itemEntity.setHosts(wrapper.getHostsJson());
@@ -1539,28 +1540,38 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
 
     String itemDetail = entity.getText();
     String stageText = StringUtils.abbreviate(entity.getText(), 255);
+
     switch (task.getType()) {
+      case SERVER_ACTION:
       case MANUAL: {
-        ManualTask mt = (ManualTask) task;
-        JsonArray messageArray = new JsonArray();
-        for(String message: mt.messages){
-          JsonObject messageObj = new JsonObject();
-          messageObj.addProperty("message", message);
-          messageArray.add(messageObj);
-        }
-        itemDetail = messageArray.toString();
-        if (null != mt.summary) {
-          stageText = mt.summary;
+        ServerSideActionTask serverTask = (ServerSideActionTask) task;
+
+        if (null != serverTask.summary) {
+          stageText = serverTask.summary;
         }
 
-        entity.setText(itemDetail);
+        if (task.getType() == Task.Type.MANUAL) {
+          ManualTask mt = (ManualTask) task;
 
-        if (null != mt.structuredOut) {
-          commandParams.put(COMMAND_PARAM_STRUCT_OUT, mt.structuredOut);
+          if (StringUtils.isNotBlank(mt.structuredOut)) {
+            commandParams.put(COMMAND_PARAM_STRUCT_OUT, mt.structuredOut);
+          }
         }
 
-        //To be used later on by the Stage...
-        itemDetail = StringUtils.join(mt.messages, " ");
+        if (!serverTask.messages.isEmpty()) {
+          JsonArray messageArray = new JsonArray();
+          for (String message : serverTask.messages) {
+            JsonObject messageObj = new JsonObject();
+            messageObj.addProperty("message", message);
+            messageArray.add(messageObj);
+          }
+          itemDetail = messageArray.toString();
+
+          entity.setText(itemDetail);
+
+          //To be used later on by the Stage...
+          itemDetail = StringUtils.join(serverTask.messages, " ");
+        }
         break;
       }
       case CONFIGURE: {

+ 0 - 2
ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KDCType.java

@@ -18,8 +18,6 @@
 
 package org.apache.ambari.server.serveraction.kerberos;
 
-import com.sun.istack.NotNull;
-
 /**
  * Enumerates the supported KDC types
  */

+ 112 - 0
ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/KerberosKeytabsAction.java

@@ -0,0 +1,112 @@
+/**
+ * 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.upgrades;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+
+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.serveraction.AbstractServerAction;
+import org.apache.ambari.server.serveraction.kerberos.KDCType;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.Config;
+
+import com.google.inject.Inject;
+
+/**
+ * This class is made to emulate a manual action.  It runs in RU when Ranger Admin
+ * is installed to the cluster and moving to a version that requires a new keytab.
+ *
+ * There are checks for:
+ * <ul>
+ *  <li>Kerberos is enabled for the cluster</li>
+ *  <li>If the KDC type is set (KDCType is not {@link KDCType#NONE}, implying manual)</li>
+ * </ul>
+ */
+public class KerberosKeytabsAction extends AbstractServerAction {
+
+  private static final String KERBEROS_ENV = "kerberos-env";
+  private static final String KDC_TYPE_KEY = "kdc_type";
+
+
+  /**
+   * Used for retrieving the cluster (and eventually the desired configuration).
+   */
+  @Inject
+  private Clusters m_clusters;
+
+  @Inject
+  private KerberosHelper m_kerberosHelper;
+
+  @Override
+  public CommandReport execute(ConcurrentMap<String, Object> requestSharedDataContext)
+      throws AmbariException, InterruptedException {
+
+
+    String clusterName = getExecutionCommand().getClusterName();
+    Cluster cluster = m_clusters.getCluster(clusterName);
+
+    StringBuilder stdout = new StringBuilder();
+
+    stdout.append(String.format("Checking %s is secured by Kerberos... %s",
+        clusterName, m_kerberosHelper.isClusterKerberosEnabled(cluster))).append(System.lineSeparator());
+
+    if (!m_kerberosHelper.isClusterKerberosEnabled(cluster)) {
+      stdout.append(String.format("Cluster %s is not secured by Kerberos.  No action required.",
+          clusterName));
+
+      return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", stdout.toString(), "");
+    }
+
+    stdout.append(String.format("Loading %s for cluster %s", KERBEROS_ENV, clusterName)).append(System.lineSeparator());
+
+    Config kerberosEnv = cluster.getDesiredConfigByType(KERBEROS_ENV);
+    if (kerberosEnv == null) {
+      stdout.append(String.format("Configuration %s was not found.  No action required.", KERBEROS_ENV));
+
+      return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", stdout.toString(), "");
+    }
+
+    Map<String, String> kerbProperties = kerberosEnv.getProperties();
+
+    KDCType kdcType = KDCType.NONE;
+
+    if (null != kerbProperties && kerbProperties.containsKey(KDC_TYPE_KEY)) {
+      kdcType = KDCType.translate(kerbProperties.get(KDC_TYPE_KEY));
+    }
+
+    stdout.append(String.format("Checking KDC type... %s", kdcType)).append(System.lineSeparator());
+
+    if (KDCType.NONE == kdcType) {
+      stdout.append(String.format("KDC Type is %s, keytabs are managed manually.  No action required.", kdcType));
+
+      return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", stdout.toString(), "");
+    }
+
+    stdout.append(String.format("Ambari is managing Kerberos keytabs.  Regenerate " +
+        "keytabs after upgrade is complete."));
+
+    // !!! make this holding, as the user must manually acknowlege.
+    return createCommandReport(0, HostRoleStatus.HOLDING, "{}", stdout.toString(), "");
+  }
+
+}

+ 0 - 6
ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ManualTask.java

@@ -17,11 +17,8 @@
  */
 package org.apache.ambari.server.state.stack.upgrade;
 
-import java.util.List;
-
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
@@ -46,9 +43,6 @@ public class ManualTask extends ServerSideActionTask {
   @XmlTransient
   public String structuredOut = null;
 
-  @XmlElement(name="message")
-  public List<String> messages;
-
   @Override
   public Task.Type getType() {
     return type;

+ 7 - 0
ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ServerSideActionTask.java

@@ -17,7 +17,11 @@
  */
 package org.apache.ambari.server.state.stack.upgrade;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
 
 /**
  *
@@ -33,6 +37,9 @@ public abstract class ServerSideActionTask extends Task {
     return implClass;
   }
 
+  @XmlElement(name="message")
+  public List<String> messages = new ArrayList<>();
+
   @Override
   public String getActionVerb() {
     return actionVerb;

+ 0 - 6
ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/nonrolling-upgrade-2.2.xml

@@ -205,12 +205,6 @@
         </task>
       </execute-stage>
 
-      <execute-stage service="KNOX" component="KNOX_GATEWAY" title="Restore Knox Data">
-        <task xsi:type="manual">
-          <message>Before continuing, please restore the Knox data. E.g., "cp -RL ~/knox_backup/* /var/lib/knox/data/" on the following host(s): {{hosts.all}}.</message>
-        </task>
-      </execute-stage>
-
       <execute-stage service="RANGER" component="RANGER_ADMIN" title="Restore Ranger Database">
         <task xsi:type="manual">
           <message>Before continuing, please restore the Ranger Admin database and Ranger Audit database on the following host(s): {{hosts.all}}.</message>

+ 0 - 6
ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/nonrolling-upgrade-2.3.xml

@@ -215,12 +215,6 @@
         </task>
       </execute-stage>
 
-      <execute-stage service="KNOX" component="KNOX_GATEWAY" title="Restore Knox Data">
-        <task xsi:type="manual">
-          <message>Before continuing, please restore the Knox data. E.g., "cp -RL ~/knox_backup/* /var/lib/knox/data/" on the following host(s): {{hosts.all}}.</message>
-        </task>
-      </execute-stage>
-
       <execute-stage service="RANGER" component="RANGER_ADMIN" title="Restore Ranger Database">
         <task xsi:type="manual">
           <message>Before continuing, please restore the Ranger Admin database and Ranger Audit database on the following host(s): {{hosts.all}}.</message>

+ 0 - 6
ambari-server/src/main/resources/stacks/HDP/2.2/upgrades/nonrolling-upgrade-2.4.xml

@@ -239,12 +239,6 @@
         </task>
       </execute-stage>
 
-      <execute-stage service="KNOX" component="KNOX_GATEWAY" title="Restore Knox Data">
-        <task xsi:type="manual">
-          <message>Before continuing, please restore the Knox data. E.g., "cp -RL ~/knox_backup/* /usr/hdp/$(old_version)/knox/data/" on the following host(s): {{hosts.all}}.</message>
-        </task>
-      </execute-stage>
-
       <execute-stage service="RANGER" component="RANGER_ADMIN" title="Restore Ranger Database">
         <task xsi:type="manual">
           <message>Before continuing, please restore the Ranger Admin database and Ranger Audit database on the following host(s): {{hosts.all}}.</message>

+ 0 - 6
ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.3.xml

@@ -227,12 +227,6 @@
         </task>
       </execute-stage>
 
-      <execute-stage service="KNOX" component="KNOX_GATEWAY" title="Restore Knox Data">
-        <task xsi:type="manual">
-          <message>Before continuing, please restore the Knox data. E.g., "cp -RL ~/knox_backup/* /usr/hdp/$(old_version)/knox/data/" on the following host(s): {{hosts.all}}.</message>
-        </task>
-      </execute-stage>
-
       <execute-stage service="RANGER" component="RANGER_ADMIN" title="Restore Ranger Database">
         <task xsi:type="manual">
           <message>Before continuing, please restore the Ranger Admin database and Ranger Audit database on the following host(s): {{hosts.all}}.</message>

+ 0 - 6
ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.4.xml

@@ -232,12 +232,6 @@
         </task>
       </execute-stage>
 
-      <execute-stage service="KNOX" component="KNOX_GATEWAY" title="Restore Knox Data">
-        <task xsi:type="manual">
-          <message>Before continuing, please restore the Knox data. E.g., "cp -RL ~/knox_backup/* /usr/hdp/$(old_version)/knox/data/" on the following host(s): {{hosts.all}}.</message>
-        </task>
-      </execute-stage>
-
       <execute-stage service="RANGER" component="RANGER_ADMIN" title="Restore Ranger Database">
         <task xsi:type="manual">
           <message>Before continuing, please restore the Ranger Admin database and Ranger Audit database on the following host(s): {{hosts.all}}.</message>

+ 0 - 6
ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/nonrolling-upgrade-2.5.xml

@@ -241,12 +241,6 @@
         </task>
       </execute-stage>
 
-      <execute-stage service="KNOX" component="KNOX_GATEWAY" title="Restore Knox Data">
-        <task xsi:type="manual">
-          <message>Before continuing, please restore the Knox data. E.g., "cp -RL ~/knox_backup/* /usr/hdp/$(old_version)/knox/data/" on the following host(s): {{hosts.all}}.</message>
-        </task>
-      </execute-stage>
-
       <execute-stage service="RANGER" component="RANGER_ADMIN" title="Restore Ranger Database">
         <task xsi:type="manual">
           <message>Before continuing, please restore the Ranger Admin database and Ranger Audit database on the following host(s): {{hosts.all}}.</message>

+ 7 - 0
ambari-server/src/main/resources/stacks/HDP/2.3/upgrades/upgrade-2.5.xml

@@ -500,6 +500,13 @@
 
           <task xsi:type="server_action" summary="Calculating Ranger Properties" class="org.apache.ambari.server.serveraction.upgrades.RangerKerberosConfigCalculation"/>
 
+          <task xsi:type="server_action" class="org.apache.ambari.server.serveraction.upgrades.KerberosKeytabsAction">
+            <summary>Ranger Kerberos Keytab Check</summary>
+            <message>Please follow below steps to complete upgrade in kerberos environment</message>
+            <message>-- If keytabs are managed by Ambari, Perform Regenerate Keytabs for missing components to get Ranger keytabs and restart ranger components.</message>
+            <message>-- If keytabs are managed manually, create the required ranger keytabs in the locations specified in ranger config and restart ranger components.</message>
+          </task>
+
           <task xsi:type="execute" hosts="all">
             <script>scripts/ranger_admin.py</script>
             <function>set_pre_start</function>

+ 0 - 6
ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/nonrolling-upgrade-2.4.xml

@@ -228,12 +228,6 @@
         </task>
       </execute-stage>
 
-      <execute-stage service="KNOX" component="KNOX_GATEWAY" title="Restore Knox Data">
-        <task xsi:type="manual">
-          <message>Before continuing, please restore the Knox data. E.g., "cp -RL ~/knox_backup/* /usr/hdp/$(old_version)/knox/data/" on the following host(s): {{hosts.all}}.</message>
-        </task>
-      </execute-stage>
-
       <execute-stage service="RANGER" component="RANGER_ADMIN" title="Restore Ranger Database">
         <task xsi:type="manual">
           <message>Before continuing, please restore the Ranger Admin database and Ranger Audit database on the following host(s): {{hosts.all}}.</message>

+ 0 - 6
ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/nonrolling-upgrade-2.5.xml

@@ -236,12 +236,6 @@
         </task>
       </execute-stage>
 
-      <execute-stage service="KNOX" component="KNOX_GATEWAY" title="Restore Knox Data">
-        <task xsi:type="manual">
-          <message>Before continuing, please restore the Knox data. E.g., "cp -RL ~/knox_backup/* /usr/hdp/$(old_version)/knox/data/" on the following host(s): {{hosts.all}}.</message>
-        </task>
-      </execute-stage>
-
       <execute-stage service="RANGER" component="RANGER_ADMIN" title="Restore Ranger Database">
         <task xsi:type="manual">
           <message>Before continuing, please restore the Ranger Admin database and Ranger Audit database on the following host(s): {{hosts.all}}.</message>

+ 7 - 0
ambari-server/src/main/resources/stacks/HDP/2.4/upgrades/upgrade-2.5.xml

@@ -495,6 +495,13 @@
 
           <task xsi:type="server_action" summary="Calculating Ranger Properties" class="org.apache.ambari.server.serveraction.upgrades.RangerKerberosConfigCalculation"/>
 
+          <task xsi:type="server_action" class="org.apache.ambari.server.serveraction.upgrades.KerberosKeytabsAction">
+            <summary>Ranger Kerberos Keytab Check</summary>
+            <message>Please follow below steps to complete upgrade in kerberos environment</message>
+            <message>-- If keytabs are managed by Ambari, Perform Regenerate Keytabs for missing components to get Ranger keytabs and restart ranger components.</message>
+            <message>-- If keytabs are managed manually, create the required ranger keytabs in the locations specified in ranger config and restart ranger components.</message>
+          </task>
+
           <task xsi:type="execute" hosts="all">
             <script>scripts/ranger_admin.py</script>
             <function>set_pre_start</function>

+ 0 - 6
ambari-server/src/main/resources/stacks/HDP/2.5/upgrades/nonrolling-upgrade-2.5.xml

@@ -234,12 +234,6 @@
         </task>
       </execute-stage>
 
-      <execute-stage service="KNOX" component="KNOX_GATEWAY" title="Restore Knox Data">
-        <task xsi:type="manual">
-          <message>Before continuing, please restore the Knox data. E.g., "cp -RL ~/knox_backup/* /usr/hdp/$(old_version)/knox/data/" on the following host(s): {{hosts.all}}.</message>
-        </task>
-      </execute-stage>
-
       <execute-stage service="RANGER" component="RANGER_ADMIN" title="Restore Ranger Database">
         <task xsi:type="manual">
           <message>Before continuing, please restore the Ranger Admin database and Ranger Audit database on the following host(s): {{hosts.all}}.</message>

+ 204 - 0
ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/KerberosKeytabsActionTest.java

@@ -0,0 +1,204 @@
+/**
+ * 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.upgrades;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.ambari.server.actionmanager.ExecutionCommandWrapper;
+import org.apache.ambari.server.actionmanager.HostRoleCommand;
+import org.apache.ambari.server.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.agent.CommandReport;
+import org.apache.ambari.server.agent.ExecutionCommand;
+import org.apache.ambari.server.audit.AuditLogger;
+import org.apache.ambari.server.controller.KerberosHelper;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.Config;
+import org.apache.ambari.server.state.ConfigImpl;
+import org.apache.ambari.server.state.SecurityType;
+import org.apache.commons.lang.StringUtils;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests upgrade-related server side actions
+*/
+
+public class KerberosKeytabsActionTest {
+
+  private Injector m_injector;
+  private Clusters m_clusters;
+  private KerberosHelper m_kerberosHelper;
+  private Config m_kerberosConfig;
+
+  @Before
+  public void setup() throws Exception {
+
+    m_clusters = EasyMock.createMock(Clusters.class);
+    m_kerberosHelper = EasyMock.createMock(KerberosHelper.class);
+
+    m_kerberosConfig = new ConfigImpl("kerberos-env") {
+      Map<String, String> mockProperties = new HashMap<String, String>() {{
+        put("kerberos-env", "");
+      }};
+
+      @Override
+      public Map<String, String> getProperties() {
+        return mockProperties;
+      }
+
+      @Override
+      public void setProperties(Map<String, String> properties) {
+        mockProperties.putAll(properties);
+      }
+
+      @Override
+      public void persist(boolean newConfig) {
+        // no-op
+      }
+    };
+
+    Cluster cluster = EasyMock.createMock(Cluster.class);
+
+    expect(cluster.getDesiredConfigByType("kerberos-env")).andReturn(m_kerberosConfig).atLeastOnce();
+    expect(cluster.getSecurityType()).andReturn(SecurityType.KERBEROS).anyTimes();
+    expect(m_clusters.getCluster((String) anyObject())).andReturn(cluster).anyTimes();
+
+    replay(m_clusters, cluster);
+
+    m_injector = Guice.createInjector(new AbstractModule() {
+
+      @Override
+      protected void configure() {
+        bind(Clusters.class).toInstance(m_clusters);
+        bind(KerberosHelper.class).toInstance(m_kerberosHelper);
+        bind(AuditLogger.class).toInstance(EasyMock.createNiceMock(AuditLogger.class));
+      }
+    });
+  }
+
+  @Test
+  public void testAction_NotKerberized() throws Exception {
+    reset(m_kerberosHelper);
+    expect(m_kerberosHelper.isClusterKerberosEnabled(EasyMock.anyObject(Cluster.class))).andReturn(Boolean.FALSE).atLeastOnce();
+    replay(m_kerberosHelper);
+
+    Map<String, String> commandParams = new HashMap<String, String>();
+    commandParams.put("clusterName", "c1");
+
+    ExecutionCommand executionCommand = new ExecutionCommand();
+    executionCommand.setCommandParams(commandParams);
+    executionCommand.setClusterName("c1");
+
+    HostRoleCommand hrc = EasyMock.createMock(HostRoleCommand.class);
+    expect(hrc.getRequestId()).andReturn(1L).anyTimes();
+    expect(hrc.getStageId()).andReturn(2L).anyTimes();
+    expect(hrc.getExecutionCommandWrapper()).andReturn(new ExecutionCommandWrapper(executionCommand)).anyTimes();
+    replay(hrc);
+
+    KerberosKeytabsAction action = m_injector.getInstance(KerberosKeytabsAction.class);
+
+    action.setExecutionCommand(executionCommand);
+    action.setHostRoleCommand(hrc);
+
+    CommandReport report = action.execute(null);
+    assertNotNull(report);
+
+    Assert.assertEquals(HostRoleStatus.COMPLETED.name(), report.getStatus());
+    Assert.assertTrue(StringUtils.contains(report.getStdOut(), "Cluster c1 is not secured by Kerberos"));
+    Assert.assertTrue(StringUtils.contains(report.getStdOut(), "No action required."));
+  }
+
+  @Test
+  public void testAction_NoKdcType() throws Exception {
+    reset(m_kerberosHelper);
+    expect(m_kerberosHelper.isClusterKerberosEnabled(EasyMock.anyObject(Cluster.class))).andReturn(Boolean.TRUE).atLeastOnce();
+    replay(m_kerberosHelper);
+
+    Map<String, String> commandParams = new HashMap<String, String>();
+    commandParams.put("clusterName", "c1");
+
+    ExecutionCommand executionCommand = new ExecutionCommand();
+    executionCommand.setCommandParams(commandParams);
+    executionCommand.setClusterName("c1");
+
+    HostRoleCommand hrc = EasyMock.createMock(HostRoleCommand.class);
+    expect(hrc.getRequestId()).andReturn(1L).anyTimes();
+    expect(hrc.getStageId()).andReturn(2L).anyTimes();
+    expect(hrc.getExecutionCommandWrapper()).andReturn(new ExecutionCommandWrapper(executionCommand)).anyTimes();
+    replay(hrc);
+
+    KerberosKeytabsAction action = m_injector.getInstance(KerberosKeytabsAction.class);
+
+    action.setExecutionCommand(executionCommand);
+    action.setHostRoleCommand(hrc);
+
+    CommandReport report = action.execute(null);
+    assertNotNull(report);
+
+    Assert.assertEquals(HostRoleStatus.COMPLETED.name(), report.getStatus());
+    Assert.assertTrue(StringUtils.contains(report.getStdOut(), "KDC Type is NONE"));
+    Assert.assertTrue(StringUtils.contains(report.getStdOut(), "No action required."));
+  }
+
+  @Test
+  public void testAction_Kerberized() throws Exception {
+    reset(m_kerberosHelper);
+    expect(m_kerberosHelper.isClusterKerberosEnabled(EasyMock.anyObject(Cluster.class))).andReturn(Boolean.TRUE).atLeastOnce();
+    replay(m_kerberosHelper);
+    m_kerberosConfig.getProperties().put("kdc_type", "mit-kdc");
+
+    Map<String, String> commandParams = new HashMap<String, String>();
+    commandParams.put("clusterName", "c1");
+
+    ExecutionCommand executionCommand = new ExecutionCommand();
+    executionCommand.setCommandParams(commandParams);
+    executionCommand.setClusterName("c1");
+
+    HostRoleCommand hrc = EasyMock.createMock(HostRoleCommand.class);
+    expect(hrc.getRequestId()).andReturn(1L).anyTimes();
+    expect(hrc.getStageId()).andReturn(2L).anyTimes();
+    expect(hrc.getExecutionCommandWrapper()).andReturn(new ExecutionCommandWrapper(executionCommand)).anyTimes();
+    replay(hrc);
+
+    KerberosKeytabsAction action = m_injector.getInstance(KerberosKeytabsAction.class);
+
+    action.setExecutionCommand(executionCommand);
+    action.setHostRoleCommand(hrc);
+
+    CommandReport report = action.execute(null);
+    assertNotNull(report);
+
+    Assert.assertEquals(HostRoleStatus.HOLDING.name(), report.getStatus());
+    Assert.assertTrue(StringUtils.contains(report.getStdOut(), "Checking KDC type... MIT_KDC"));
+    Assert.assertTrue(StringUtils.contains(report.getStdOut(), "Regenerate keytabs after upgrade is complete."));
+  }
+}