You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zeppelin.apache.org by pr...@apache.org on 2017/02/15 08:40:30 UTC

zeppelin git commit: [ZEPPELIN-2063] Hive Jdbc interpreter does not relogin if kerberos ticket expired when hive.server2.transport.mode is http

Repository: zeppelin
Updated Branches:
  refs/heads/master 632947856 -> 090a40a9f


[ZEPPELIN-2063] Hive Jdbc interpreter does not relogin if kerberos ticket expired when hive.server2.transport.mode is http

### What is this PR for?
Hadoop Client will re-login once the ticket expired in case of RPC and so when hive.server2.transport.mode is binary, Hive Jdbc interpreter does a relogin and works fine. But when Rest API is used i.e when hive.server2.transport.mode is http, it is not doing a re-login and so fails with GSS exception.

### What type of PR is it?
[Bug Fix]

### What is the Jira issue?
* [ZEPPELIN-2063](https://issues.apache.org/jira/browse/ZEPPELIN-2063)

### How should this be tested?
Run hive in http mode i.e. hive.server2.transport.mode is http. Run any query say `show tables` now wait for key to expire (usually its 24hrs), now try to run the same paragraph again without restarting zeppelin-server or jdbc interpreter. It should not fail with `GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)
` exception

### Screenshots (if appropriate)
N/A

### Questions:
* Does the licenses files need update? N/A
* Is there breaking changes for older versions? N/A
* Does this needs documentation? N/A

Author: Prabhjyot Singh <pr...@gmail.com>

Closes #1979 from prabhjyotsingh/ZEPPELIN-2063 and squashes the following commits:

4199fd8 [Prabhjyot Singh] Catch all GSS initiate failed instead of GSS
0617ebd [Prabhjyot Singh] - reduce error log sent to user in interpreter exception  - log error, if any while closeDBPool
b417c37 [Prabhjyot Singh] try to re login from keytab before failing.


Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo
Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/090a40a9
Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/090a40a9
Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/090a40a9

Branch: refs/heads/master
Commit: 090a40a9fc944c58734cee3a294074b117a694f0
Parents: 6329478
Author: Prabhjyot Singh <pr...@gmail.com>
Authored: Fri Feb 10 12:44:44 2017 +0530
Committer: Prabhjyot Singh <pr...@gmail.com>
Committed: Wed Feb 15 14:10:24 2017 +0530

----------------------------------------------------------------------
 .../apache/zeppelin/jdbc/JDBCInterpreter.java   | 54 ++++++++++++++++----
 .../zeppelin/jdbc/JDBCUserConfigurations.java   | 16 ++++++
 2 files changed, 59 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zeppelin/blob/090a40a9/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java b/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
index 988ed68..c43e392 100644
--- a/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
+++ b/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
@@ -17,6 +17,7 @@ package org.apache.zeppelin.jdbc;
 import static org.apache.commons.lang.StringUtils.containsIgnoreCase;
 import static org.apache.commons.lang.StringUtils.isEmpty;
 import static org.apache.commons.lang.StringUtils.isNotEmpty;
+import static org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod.KERBEROS;
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
 import java.io.IOException;
@@ -36,6 +37,7 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
+import com.google.common.base.Throwables;
 import org.apache.commons.dbcp2.ConnectionFactory;
 import org.apache.commons.dbcp2.DriverManagerConnectionFactory;
 import org.apache.commons.dbcp2.PoolableConnectionFactory;
@@ -46,6 +48,7 @@ import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.security.alias.CredentialProvider;
 import org.apache.hadoop.security.alias.CredentialProviderFactory;
+import org.apache.thrift.transport.TTransportException;
 import org.apache.zeppelin.interpreter.*;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
 import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
@@ -565,6 +568,7 @@ public class JDBCInterpreter extends Interpreter {
           getJDBCConfiguration(user).saveStatement(paragraphId, statement);
 
           boolean isResultSetAvailable = statement.execute(sqlToExecute);
+          getJDBCConfiguration(user).setConnectionInDBDriverPoolSuccessful(propertyKey);
           if (isResultSetAvailable) {
             resultSet = statement.getResultSet();
 
@@ -608,21 +612,49 @@ public class JDBCInterpreter extends Interpreter {
       }
       getJDBCConfiguration(user).removeStatement(paragraphId);
     } catch (Exception e) {
-      logger.error("Cannot run " + sql, e);
-      ByteArrayOutputStream baos = new ByteArrayOutputStream();
-      PrintStream ps = new PrintStream(baos);
-      e.printStackTrace(ps);
-      String errorMsg = new String(baos.toByteArray(), StandardCharsets.UTF_8);
+      if (e.getCause() instanceof TTransportException &&
+          Throwables.getStackTraceAsString(e).contains("GSS") &&
+          getJDBCConfiguration(user).isConnectionInDBDriverPoolSuccessful(propertyKey)) {
+        return reLoginFromKeytab(propertyKey, sql, interpreterContext, interpreterResult);
+      } else {
+        logger.error("Cannot run " + sql, e);
+        String errorMsg = Throwables.getStackTraceAsString(e);
+        try {
+          closeDBPool(user, propertyKey);
+        } catch (SQLException e1) {
+          logger.error("Cannot close DBPool for user, propertyKey: " + user + propertyKey, e1);
+        }
+        interpreterResult.add(errorMsg);
+        return new InterpreterResult(Code.ERROR, interpreterResult.message());
+      }
+    }
+    return interpreterResult;
+  }
 
+  private InterpreterResult reLoginFromKeytab(String propertyKey, String sql,
+     InterpreterContext interpreterContext, InterpreterResult interpreterResult) {
+    String user = interpreterContext.getAuthenticationInfo().getUser();
+    try {
+      closeDBPool(user, propertyKey);
+    } catch (SQLException e) {
+      logger.error("Error, could not close DB pool in reLoginFromKeytab ", e);
+    }
+    UserGroupInformation.AuthenticationMethod authType =
+        JDBCSecurityImpl.getAuthtype(property);
+    if (authType.equals(KERBEROS)) {
       try {
-        closeDBPool(user, propertyKey);
-      } catch (SQLException e1) {
-        e1.printStackTrace();
+        if (UserGroupInformation.isLoginKeytabBased()) {
+          UserGroupInformation.getLoginUser().reloginFromKeytab();
+        } else if (UserGroupInformation.isLoginTicketBased()) {
+          UserGroupInformation.getLoginUser().reloginFromTicketCache();
+        }
+      } catch (IOException e) {
+        logger.error("Cannot reloginFromKeytab " + sql, e);
+        interpreterResult.add(e.getMessage());
+        return new InterpreterResult(Code.ERROR, interpreterResult.message());
       }
-      interpreterResult.add(errorMsg);
-      return new InterpreterResult(Code.ERROR, interpreterResult.message());
     }
-    return interpreterResult;
+    return executeSql(propertyKey, sql, interpreterContext);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/090a40a9/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCUserConfigurations.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCUserConfigurations.java b/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCUserConfigurations.java
index e23145b..d00e1e9 100644
--- a/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCUserConfigurations.java
+++ b/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCUserConfigurations.java
@@ -31,11 +31,13 @@ public class JDBCUserConfigurations {
   private final Map<String, Statement> paragraphIdStatementMap;
   private final Map<String, PoolingDriver> poolingDriverMap;
   private final HashMap<String, Properties> propertiesMap;
+  private HashMap<String, Boolean> isSuccessful;
 
   public JDBCUserConfigurations() {
     paragraphIdStatementMap = new HashMap<>();
     poolingDriverMap = new HashMap<>();
     propertiesMap = new HashMap<>();
+    isSuccessful = new HashMap<>();
   }
 
   public void initStatementMap() throws SQLException {
@@ -53,6 +55,7 @@ public class JDBCUserConfigurations {
       it.remove();
     }
     poolingDriverMap.clear();
+    isSuccessful.clear();
   }
 
   public void setPropertyMap(String key, Properties properties) {
@@ -88,8 +91,10 @@ public class JDBCUserConfigurations {
 
   public void saveDBDriverPool(String key, PoolingDriver driver) throws SQLException {
     poolingDriverMap.put(key, driver);
+    isSuccessful.put(key, false);
   }
   public PoolingDriver removeDBDriverPool(String key) throws SQLException {
+    isSuccessful.remove(key);
     return poolingDriverMap.remove(key);
   }
 
@@ -97,4 +102,15 @@ public class JDBCUserConfigurations {
     return poolingDriverMap.containsKey(key);
   }
 
+  public void setConnectionInDBDriverPoolSuccessful(String key) {
+    isSuccessful.put(key, true);
+  }
+
+  public boolean isConnectionInDBDriverPoolSuccessful(String key) {
+    if (isSuccessful.containsKey(key)) {
+      return isSuccessful.get(key);
+    }
+    return false;
+  }
+
 }