AMBARI-18755. Deployment failing at creating principal (aonishuk)

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

Branch: refs/heads/branch-feature-AMBARI-18634
Commit: 99f695616683b466f94ce42bce105834ac2a3ead
Parents: bfc3368
Author: Andrew Onishuk <aonis...@hortonworks.com>
Authored: Wed Nov 9 14:25:38 2016 +0200
Committer: Andrew Onishuk <aonis...@hortonworks.com>
Committed: Wed Nov 9 14:25:38 2016 +0200

----------------------------------------------------------------------
 ambari-server/docs/configuration/index.md       |  1 +
 .../server/configuration/Configuration.java     | 20 ++++++-
 .../kerberos/MITKerberosOperationHandler.java   | 28 +++++++++-
 .../MITKerberosOperationHandlerTest.java        | 57 ++++++++++----------
 4 files changed, 75 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/99f69561/ambari-server/docs/configuration/index.md
----------------------------------------------------------------------
diff --git a/ambari-server/docs/configuration/index.md 
b/ambari-server/docs/configuration/index.md
index 52b4744..ae6019c 100644
--- a/ambari-server/docs/configuration/index.md
+++ b/ambari-server/docs/configuration/index.md
@@ -133,6 +133,7 @@ The following are the properties which can be used to 
configure Ambari.
 | kdcserver.connection.check.timeout | The timeout, in milliseconds, to wait 
when communicating with a Kerberos Key Distribution Center. |`10000` | 
 | kerberos.check.jaas.configuration | Determines whether Kerberos-enabled 
Ambari deployments should use JAAS to validate login credentials. |`false` | 
 | kerberos.keytab.cache.dir | The location on the Ambari Server where Kerberos 
keytabs are cached. 
|`/home/crashtua/dev/ambari-work/var/lib/ambari-server/data/cache` | 
+| kerberos.operation.retries | The number of times failed kerberos operations 
should be retried to execute. |`3` | 
 | ldap.sync.username.collision.behavior | Determines how to handle username 
collision while updating from LDAP.<br/><br/>The following are examples of 
valid values:<ul><li>`skip`<li>`convert`</ul> |`convert` | 
 | metadata.path | The location on the Ambari Server where the stack resources 
exist.<br/><br/>The following are examples of valid 
values:<ul><li>`/var/lib/ambari-server/resources/stacks`</ul> | | 
 | metrics.retrieval-service.cache.timeout | The amount of time, in minutes, 
that JMX and REST metrics retrieved directly can remain in the cache. |`30` | 

http://git-wip-us.apache.org/repos/asf/ambari/blob/99f69561/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
index 3103b6d..f9557a5 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
@@ -116,6 +116,10 @@ import com.google.inject.Singleton;
  */
 @Singleton
 public class Configuration {
+  /**
+   * JVM property with optional path to Makrdown template file.
+   */
+  private static final String AMBARI_CONFIGURATION_MD_TEMPLATE_PROPERTY = 
"ambari.configuration.md.template";
 
   /**
    * The file to generate the complete Markdown documentation.
@@ -1386,6 +1390,11 @@ public class Configuration {
    * Kerberos authentication-specific properties (end)
    * 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 */
 
+
+  @Markdown(description = "The number of times failed kerberos operations 
should be retried to execute.")
+  public static final ConfigurationProperty<Integer> 
KERBEROS_OPERATION_RETRIES = new ConfigurationProperty<>(
+      "kerberos.operation.retries", 3);
+
   /**
    * The type of connection pool to use with JDBC connections to the database.
    */
@@ -5267,7 +5276,12 @@ public class Configuration {
     // replace the tokens in the markdown template and write out the final MD 
file
     InputStream inputStream = null;
     try {
-      inputStream = 
Configuration.class.getResourceAsStream(MARKDOWN_TEMPLATE_FILE);
+      if 
(System.getProperties().containsKey(AMBARI_CONFIGURATION_MD_TEMPLATE_PROPERTY)) 
{
+        // for using from IDEA or other tools without whole compilation
+        inputStream = new 
FileInputStream(System.getProperties().getProperty(AMBARI_CONFIGURATION_MD_TEMPLATE_PROPERTY));
+      } else {
+        inputStream = 
Configuration.class.getResourceAsStream(MARKDOWN_TEMPLATE_FILE);
+      }
       String template = IOUtils.toString(inputStream);
       String markdown = template.replace(MARKDOWN_CONFIGURATION_TABLE_KEY, 
allPropertiesBuffer.toString());
       markdown = markdown.replace(MARKDOWN_BASELINE_VALUES_KEY, 
baselineBuffer.toString());
@@ -5624,4 +5638,8 @@ public class Configuration {
 
     return kerberosAuthProperties;
   }
+
+  public int getKerberosOperationRetries(){
+    return Integer.valueOf(getProperty(KERBEROS_OPERATION_RETRIES));
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/99f69561/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java
index 7e915fc..a21d330 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java
@@ -18,6 +18,8 @@
 
 package org.apache.ambari.server.serveraction.kerberos;
 
+import com.google.inject.Inject;
+import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.security.credential.PrincipalKeyCredential;
 import org.apache.ambari.server.utils.ShellCommandUtil;
 import org.apache.commons.lang.ArrayUtils;
@@ -44,6 +46,9 @@ import java.util.regex.Pattern;
  */
 public class MITKerberosOperationHandler extends KerberosOperationHandler {
 
+  @Inject
+  private Configuration configuration;
+
   /**
    * A regular expression pattern to use to parse the key number from the text 
captured from the
    * get_principal kadmin command
@@ -388,7 +393,7 @@ public class MITKerberosOperationHandler extends 
KerberosOperationHandler {
       throw new KerberosOperationException("Missing kadmin query");
     }
 
-    ShellCommandUtil.Result result;
+    ShellCommandUtil.Result result = null;
     PrincipalKeyCredential administratorCredential = 
getAdministratorCredential();
     String defaultRealm = getDefaultRealm();
 
@@ -451,7 +456,26 @@ public class MITKerberosOperationHandler extends 
KerberosOperationHandler {
       LOG.debug(String.format("Executing: %s", command));
     }
 
-    result = executeCommand(command.toArray(new String[command.size()]), null, 
interactiveHandler);
+    int retryCount = configuration.getKerberosOperationRetries();
+    int tries = 0;
+
+    while (tries <= retryCount) {
+      try {
+        result = executeCommand(command.toArray(new String[command.size()]), 
null, interactiveHandler);
+      } catch (KerberosOperationException exception) {
+        if (tries == retryCount) {
+          throw exception;
+        }
+      } finally {
+        if (result != null && result.isSuccessful()) {
+          break; // break on successful result
+        }
+        tries++;
+        String message = String.format("Retrying to execute 
kadmin:\n\tCommand: %s", command);
+        LOG.warn(message);
+      }
+    }
+
 
     if (!result.isSuccessful()) {
       String message = String.format("Failed to execute kadmin:\n\tCommand: 
%s\n\tExitCode: %s\n\tSTDOUT: %s\n\tSTDERR: %s",

http://git-wip-us.apache.org/repos/asf/ambari/blob/99f69561/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandlerTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandlerTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandlerTest.java
index 6fd30ee..4c40a5d 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandlerTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandlerTest.java
@@ -32,6 +32,7 @@ import org.apache.ambari.server.utils.ShellCommandUtil;
 import org.easymock.Capture;
 import org.easymock.EasyMock;
 import org.easymock.IAnswer;
+import org.easymock.IMockBuilder;
 import org.junit.BeforeClass;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -122,10 +123,11 @@ public class MITKerberosOperationHandlerTest extends 
KerberosOperationHandlerTes
 
   @Test(expected = KerberosPrincipalDoesNotExistException.class)
   public void testSetPrincipalPasswordPrincipalDoesNotExist() throws Exception 
{
+
     MITKerberosOperationHandler handler = 
createMockBuilder(MITKerberosOperationHandler.class)
         .addMockedMethod(methodExecuteCommand)
         .createNiceMock();
-
+    injector.injectMembers(handler);
     expect(handler.executeCommand(anyObject(String[].class), 
anyObject(Map.class), 
anyObject(MITKerberosOperationHandler.InteractivePasswordHandler.class)))
         .andAnswer(new IAnswer<ShellCommandUtil.Result>() {
           @Override
@@ -187,9 +189,7 @@ public class MITKerberosOperationHandlerTest extends 
KerberosOperationHandlerTes
 
   @Test(expected = KerberosPrincipalAlreadyExistsException.class)
   public void testCreatePrincipalPrincipalAlreadyNotExists() throws Exception {
-    MITKerberosOperationHandler handler = 
createMockBuilder(MITKerberosOperationHandler.class)
-        .addMockedMethod(methodExecuteCommand)
-        .createNiceMock();
+    MITKerberosOperationHandler handler = createMock();
 
     expect(handler.executeCommand(anyObject(String[].class), 
anyObject(Map.class), 
anyObject(MITKerberosOperationHandler.InteractivePasswordHandler.class)))
         .andAnswer(new IAnswer<ShellCommandUtil.Result>() {
@@ -254,9 +254,7 @@ public class MITKerberosOperationHandlerTest extends 
KerberosOperationHandlerTes
 
   @Test(expected = KerberosAdminAuthenticationException.class)
   public void testTestAdministratorCredentialsIncorrectAdminPassword() throws 
Exception {
-    MITKerberosOperationHandler handler = 
createMockBuilder(MITKerberosOperationHandler.class)
-        .addMockedMethod(methodExecuteCommand)
-        .createNiceMock();
+    MITKerberosOperationHandler handler = createMock();
 
     expect(handler.executeCommand(anyObject(String[].class), 
anyObject(Map.class), 
anyObject(MITKerberosOperationHandler.InteractivePasswordHandler.class)))
         .andAnswer(new IAnswer<ShellCommandUtil.Result>() {
@@ -287,9 +285,7 @@ public class MITKerberosOperationHandlerTest extends 
KerberosOperationHandlerTes
 
   @Test(expected = KerberosAdminAuthenticationException.class)
   public void testTestAdministratorCredentialsIncorrectAdminPrincipal() throws 
Exception {
-    MITKerberosOperationHandler handler = 
createMockBuilder(MITKerberosOperationHandler.class)
-        .addMockedMethod(methodExecuteCommand)
-        .createNiceMock();
+    MITKerberosOperationHandler handler = createMock();
 
     expect(handler.executeCommand(anyObject(String[].class), 
anyObject(Map.class), 
anyObject(MITKerberosOperationHandler.InteractivePasswordHandler.class)))
         .andAnswer(new IAnswer<ShellCommandUtil.Result>() {
@@ -320,9 +316,7 @@ public class MITKerberosOperationHandlerTest extends 
KerberosOperationHandlerTes
 
   @Test(expected = KerberosRealmException.class)
   public void testTestAdministratorCredentialsInvalidRealm() throws Exception {
-    MITKerberosOperationHandler handler = 
createMockBuilder(MITKerberosOperationHandler.class)
-        .addMockedMethod(methodExecuteCommand)
-        .createNiceMock();
+    MITKerberosOperationHandler handler = createMock();
 
     expect(handler.executeCommand(anyObject(String[].class), 
anyObject(Map.class), 
anyObject(MITKerberosOperationHandler.InteractivePasswordHandler.class)))
         .andAnswer(new IAnswer<ShellCommandUtil.Result>() {
@@ -353,9 +347,7 @@ public class MITKerberosOperationHandlerTest extends 
KerberosOperationHandlerTes
 
   @Test(expected = KerberosRealmException.class)
   public void testTestAdministratorCredentialsInvalidRealm2() throws Exception 
{
-    MITKerberosOperationHandler handler = 
createMockBuilder(MITKerberosOperationHandler.class)
-        .addMockedMethod(methodExecuteCommand)
-        .createNiceMock();
+    MITKerberosOperationHandler handler = createMock();
 
     expect(handler.executeCommand(anyObject(String[].class), 
anyObject(Map.class), 
anyObject(MITKerberosOperationHandler.InteractivePasswordHandler.class)))
         .andAnswer(new IAnswer<ShellCommandUtil.Result>() {
@@ -386,9 +378,7 @@ public class MITKerberosOperationHandlerTest extends 
KerberosOperationHandlerTes
 
   @Test(expected = KerberosKDCConnectionException.class)
   public void testTestAdministratorCredentialsKDCConnectionException() throws 
Exception {
-    MITKerberosOperationHandler handler = 
createMockBuilder(MITKerberosOperationHandler.class)
-        .addMockedMethod(methodExecuteCommand)
-        .createNiceMock();
+    MITKerberosOperationHandler handler = createMock();
 
     expect(handler.executeCommand(anyObject(String[].class), 
anyObject(Map.class), 
anyObject(MITKerberosOperationHandler.InteractivePasswordHandler.class)))
         .andAnswer(new IAnswer<ShellCommandUtil.Result>() {
@@ -419,9 +409,7 @@ public class MITKerberosOperationHandlerTest extends 
KerberosOperationHandlerTes
 
   @Test(expected = KerberosKDCConnectionException.class)
   public void testTestAdministratorCredentialsKDCConnectionException2() throws 
Exception {
-    MITKerberosOperationHandler handler = 
createMockBuilder(MITKerberosOperationHandler.class)
-        .addMockedMethod(methodExecuteCommand)
-        .createNiceMock();
+    MITKerberosOperationHandler handler = createMock();
 
     expect(handler.executeCommand(anyObject(String[].class), 
anyObject(Map.class), 
anyObject(MITKerberosOperationHandler.InteractivePasswordHandler.class)))
         .andAnswer(new IAnswer<ShellCommandUtil.Result>() {
@@ -452,9 +440,7 @@ public class MITKerberosOperationHandlerTest extends 
KerberosOperationHandlerTes
 
   @Test
   public void testTestAdministratorCredentialsNotFound() throws Exception {
-    MITKerberosOperationHandler handler = 
createMockBuilder(MITKerberosOperationHandler.class)
-        .addMockedMethod(methodExecuteCommand)
-        .createNiceMock();
+    MITKerberosOperationHandler handler = createMock();
 
     expect(handler.executeCommand(anyObject(String[].class), 
anyObject(Map.class), 
anyObject(MITKerberosOperationHandler.InteractivePasswordHandler.class)))
         .andAnswer(new IAnswer<ShellCommandUtil.Result>() {
@@ -485,9 +471,7 @@ public class MITKerberosOperationHandlerTest extends 
KerberosOperationHandlerTes
 
   @Test
   public void testTestAdministratorCredentialsSuccess() throws Exception {
-    MITKerberosOperationHandler handler = 
createMockBuilder(MITKerberosOperationHandler.class)
-        .addMockedMethod(methodExecuteCommand)
-        .createNiceMock();
+    MITKerberosOperationHandler handler = createMock();
 
     expect(handler.executeCommand(anyObject(String[].class), 
anyObject(Map.class), 
anyObject(MITKerberosOperationHandler.InteractivePasswordHandler.class)))
         .andAnswer(new IAnswer<ShellCommandUtil.Result>() {
@@ -562,4 +546,21 @@ public class MITKerberosOperationHandlerTest extends 
KerberosOperationHandlerTes
     handler.testAdministratorCredentials();
     handler.close();
   }
+
+  private MITKerberosOperationHandler createMock(){
+    return createMock(false);
+  }
+
+  private MITKerberosOperationHandler createMock(boolean strict) {
+    IMockBuilder<MITKerberosOperationHandler> mockBuilder = 
createMockBuilder(MITKerberosOperationHandler.class)
+        .addMockedMethod(methodExecuteCommand);
+    MITKerberosOperationHandler result;
+    if(strict){
+      result = mockBuilder.createStrictMock();
+    } else {
+      result = mockBuilder.createNiceMock();
+    }
+    injector.injectMembers(result);
+    return result;
+  }
 }
\ No newline at end of file

Reply via email to