commit 5f4986f46cf3acce21574c33744a3485d49e3628 Author: Chris Drome Date: Tue Oct 31 00:23:28 2017 +0000 HIVE-17853: RetryingMetaStoreClient loses UGI impersonation-context when reconnecting after timeout diff --git metastore/src/java/org/apache/hadoop/hive/metastore/RetryingMetaStoreClient.java metastore/src/java/org/apache/hadoop/hive/metastore/RetryingMetaStoreClient.java index d3e5f7e..9a6d808 100644 --- metastore/src/java/org/apache/hadoop/hive/metastore/RetryingMetaStoreClient.java +++ metastore/src/java/org/apache/hadoop/hive/metastore/RetryingMetaStoreClient.java @@ -25,6 +25,8 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -57,6 +59,7 @@ private static final Logger LOG = LoggerFactory.getLogger(RetryingMetaStoreClient.class.getName()); private final IMetaStoreClient base; + private final UserGroupInformation ugi; private final int retryLimit; private final long retryDelaySeconds; private final ConcurrentHashMap metaCallTimeMap; @@ -69,6 +72,12 @@ protected RetryingMetaStoreClient(HiveConf hiveConf, Class[] constructorArgTy Object[] constructorArgs, ConcurrentHashMap metaCallTimeMap, Class msClientClass) throws MetaException { + this.ugi = getUGI(); + + if (this.ugi == null) { + LOG.warn("RetryingMetaStoreClient unable to determine current user UGI."); + } + this.retryLimit = hiveConf.getIntVar(HiveConf.ConfVars.METASTORETHRIFTFAILURERETRIES); this.retryDelaySeconds = hiveConf.getTimeVar( HiveConf.ConfVars.METASTORE_CLIENT_CONNECT_RETRY_DELAY, TimeUnit.SECONDS); @@ -80,8 +89,13 @@ protected RetryingMetaStoreClient(HiveConf hiveConf, Class[] constructorArgTy localMetaStore = (msUri == null) || msUri.trim().isEmpty(); reloginExpiringKeytabUser(); + this.base = (IMetaStoreClient) MetaStoreUtils.newInstance( msClientClass, constructorArgTypes, constructorArgs); + + LOG.info("RetryingMetaStoreClient proxy=" + msClientClass + " ugi=" + this.ugi + + " retries=" + this.retryLimit + " delay=" + this.retryDelaySeconds + + " lifetime=" + this.connectionLifeTimeInMillis); } public static IMetaStoreClient getProxy( @@ -160,8 +174,32 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl if (allowReconnect) { if (retriesMade > 0 || hasConnectionLifeTimeReached(method)) { - base.reconnect(); - lastConnectionTime = System.currentTimeMillis(); + if (this.ugi != null) { + // Perform reconnect with the proper user context + try { + LOG.info("RetryingMetaStoreClient trying reconnect as " + this.ugi); + + this.ugi.doAs( + new PrivilegedExceptionAction () { + @Override + public Object run() throws MetaException { + base.reconnect(); + return null; + } + }); + } catch (UndeclaredThrowableException e) { + Throwable te = e.getCause(); + if (te instanceof PrivilegedActionException) { + throw te.getCause(); + } else { + throw te; + } + } + lastConnectionTime = System.currentTimeMillis(); + } else { + LOG.warn("RetryingMetaStoreClient unable to reconnect. No UGI information."); + throw new MetaException("UGI information unavailable. Will not attempt a reconnect."); + } } } @@ -222,6 +260,22 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl return ret; } + /** + * Returns the UGI for the current user. + * @return the UGI for the current user. + */ + private UserGroupInformation getUGI() { + UserGroupInformation ugi = null; + + try { + ugi = UserGroupInformation.getCurrentUser(); + } catch (IOException e) { + // Swallow the exception and let the call determine what to do. + } + + return ugi; + } + private void addMethodTime(Method method, long timeTaken) { String methodStr = getMethodString(method); while (true) {