From 81685deb60e65f1b4e7150137bb2b62f87dea04a Mon Sep 17 00:00:00 2001 From: d0ngw Date: Mon, 15 Apr 2013 18:19:44 +0800 Subject: [PATCH] FIX HIVE-4233 diff --git a/src/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java b/src/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java index 357815f..d121328 100644 --- a/src/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java +++ b/src/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java @@ -125,6 +125,7 @@ public class HiveAuthFactory { return; } else if (!principal.isEmpty() && !keyTabFile.isEmpty()) { ShimLoader.getHadoopShims().loginUserFromKeytab(principal, keyTabFile); + HiveKerberosReLoginHelper.scheduleReLogin(); } else { throw new IOException ("HiveServer2 kerberos principal or keytab is not correctly configured"); } diff --git a/src/service/src/java/org/apache/hive/service/auth/HiveKerberosReLoginHelper.java b/src/service/src/java/org/apache/hive/service/auth/HiveKerberosReLoginHelper.java new file mode 100644 index 0000000..a6032e8 --- /dev/null +++ b/src/service/src/java/org/apache/hive/service/auth/HiveKerberosReLoginHelper.java @@ -0,0 +1,91 @@ +package org.apache.hive.service.auth; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.security.UserGroupInformation; + +import javax.security.auth.kerberos.KerberosTicket; +import java.lang.reflect.Method; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * User: agile.java@gmail.com + */ +public class HiveKerberosReLoginHelper { + private static final Log LOG = LogFactory.getLog(HiveKerberosReLoginHelper.class.getName()); + private static final long DEFAULT_REFRESH_TIME_MILLS = 10*60*1000L; + private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor(); + private static boolean scheduled = false; + private static final Runnable RE_LOGIN_COMMAND = new ReLoginCommand(); + + /** + * Schedule the kerberos tgt renew command. + */ + public synchronized static void scheduleReLogin() { + if (scheduled || !UserGroupInformation.isSecurityEnabled()) { + return; + } + scheduleCommand(); + scheduled = true; + } + + private static void scheduleCommand() { + long refreshDelayTime = 0; + try { + UserGroupInformation loginUser = UserGroupInformation.getLoginUser(); + if (loginUser == null) { + LOG.warn("Can't find the login user"); + return; + } + KerberosTicket tgt = (KerberosTicket) call(loginUser, "getTGT", null, null); + if (tgt == null) { + LOG.warn("Can't find the tgt"); + return; + } + Long nextRefreshTime = (Long) call(loginUser, "getRefreshTime", new Class[]{KerberosTicket.class}, new Object[]{tgt}); + if (nextRefreshTime != null) { + refreshDelayTime = nextRefreshTime - System.currentTimeMillis(); + } + if (refreshDelayTime <= 0) { + refreshDelayTime = DEFAULT_REFRESH_TIME_MILLS; + } + } catch (Exception e) { + LOG.error("Schedule re-login error.", e); + } finally { + LOG.info("Schedule re-login command after " + refreshDelayTime + " ms"); + EXECUTOR.schedule(RE_LOGIN_COMMAND, refreshDelayTime, TimeUnit.MILLISECONDS); + } + } + + private synchronized static void reLogin() throws Exception { + LOG.info("Begin re-login"); + UserGroupInformation loginUser = UserGroupInformation.getLoginUser(); + if (loginUser == null) { + LOG.warn("Can't find login user."); + return; + } + loginUser.reloginFromKeytab(); + LOG.info("Finish re-login"); + } + + private static Object call(Object target, String methodName, Class[] parameterType, Object[] args) throws Exception { + Method method = target.getClass().getDeclaredMethod(methodName, parameterType); + method.setAccessible(true); + return method.invoke(target, args); + } + + private static class ReLoginCommand implements Runnable { + @Override + public void run() { + try { + reLogin(); + } catch (Exception e) { + LOG.error("Re-login fail.", e); + } finally { + scheduleCommand(); + } + } + } +} -- 1.7.12.4 (Apple Git-37)