diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/RetryingMetaStoreClient.java b/metastore/src/java/org/apache/hadoop/hive/metastore/RetryingMetaStoreClient.java index 76b1989..0b853d2 100644 --- a/metastore/src/java/org/apache/hadoop/hive/metastore/RetryingMetaStoreClient.java +++ b/metastore/src/java/org/apache/hadoop/hive/metastore/RetryingMetaStoreClient.java @@ -18,6 +18,7 @@ package org.apache.hadoop.hive.metastore; +import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -28,26 +29,36 @@ import org.apache.commons.logging.LogFactory; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.metastore.api.MetaException; +import org.apache.hadoop.hive.shims.ShimLoader; import org.apache.thrift.TApplicationException; import org.apache.thrift.TException; import org.apache.thrift.protocol.TProtocolException; import org.apache.thrift.transport.TTransportException; +/** + * RetryingMetaStoreClient. Creates a proxy for a 'real' IMetaStoreClient + * subclass and retries calls to it on failure. + * If the login user is authenticated using keytab, it relogins user before + * each call. + * + */ public class RetryingMetaStoreClient implements InvocationHandler { private static final Log LOG = LogFactory.getLog(RetryingMetaStoreClient.class.getName()); private final IMetaStoreClient base; - private final HiveConf hiveConf; private final int retryLimit; private final int retryDelaySeconds; + + protected RetryingMetaStoreClient(HiveConf hiveConf, HiveMetaHookLoader hookLoader, Class msClientClass) throws MetaException { - this.hiveConf = hiveConf; this.retryLimit = hiveConf.getIntVar(HiveConf.ConfVars.METASTORETHRIFTFAILURERETRIES); this.retryDelaySeconds = hiveConf.getIntVar(HiveConf.ConfVars.METASTORE_CLIENT_CONNECT_RETRY_DELAY); + + reloginKeytabUser(); this.base = (IMetaStoreClient) MetaStoreUtils.newInstance(msClientClass, new Class[] { HiveConf.class, HiveMetaHookLoader.class}, new Object[] {hiveConf, hookLoader}); } @@ -71,6 +82,7 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl TException caughtException = null; while (true) { try { + reloginKeytabUser(); ret = method.invoke(base, args); break; } catch (UndeclaredThrowableException e) { @@ -95,8 +107,25 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl LOG.warn("MetaStoreClient lost connection. Attempting to reconnect.", caughtException); Thread.sleep(retryDelaySeconds * 1000); + reloginKeytabUser(); base.reconnect(); } return ret; } + + /** + * Relogin if login user is logged in using keytab + * Relogin is actually done by ugi code only if sufficient time has passed + * @throws MetaException + */ + private void reloginKeytabUser() throws MetaException { + try { + ShimLoader.getHadoopShims().reLoginUserFromKeytab(); + } catch (IOException e) { + String msg = "Error doing relogin using keytab " + e.getMessage(); + LOG.error(msg, e); + throw new MetaException(msg); + } + } + } diff --git a/shims/src/0.20/java/org/apache/hadoop/hive/shims/Hadoop20Shims.java b/shims/src/0.20/java/org/apache/hadoop/hive/shims/Hadoop20Shims.java index c9baa7f..8dd85f9 100644 --- a/shims/src/0.20/java/org/apache/hadoop/hive/shims/Hadoop20Shims.java +++ b/shims/src/0.20/java/org/apache/hadoop/hive/shims/Hadoop20Shims.java @@ -600,7 +600,14 @@ public UserGroupInformation createRemoteUser(String userName, List group @Override public void loginUserFromKeytab(String principal, String keytabFile) throws IOException { - throw new UnsupportedOperationException("Kerberos login is not supported in current hadoop version"); + throw new UnsupportedOperationException("Kerberos login is not supported" + + " in current hadoop version"); + } + + @Override + public void reLoginUserFromKeytab() throws IOException{ + throw new UnsupportedOperationException("Kerberos login is not supported" + + " in current hadoop version"); } @Override diff --git a/shims/src/common-secure/java/org/apache/hadoop/hive/shims/HadoopShimsSecure.java b/shims/src/common-secure/java/org/apache/hadoop/hive/shims/HadoopShimsSecure.java index 9edcafd..a4ad04b 100644 --- a/shims/src/common-secure/java/org/apache/hadoop/hive/shims/HadoopShimsSecure.java +++ b/shims/src/common-secure/java/org/apache/hadoop/hive/shims/HadoopShimsSecure.java @@ -556,6 +556,16 @@ public void loginUserFromKeytab(String principal, String keytabFile) throws IOEx } @Override + public void reLoginUserFromKeytab() throws IOException{ + UserGroupInformation ugi = UserGroupInformation.getLoginUser(); + //checkTGT calls ugi.relogin only after checking if it is close to tgt expiry + //hadoop relogin is actually done only every x minutes (x=10 in hadoop 1.x) + if(ugi.isFromKeytab()){ + ugi.checkTGTAndReloginFromKeytab(); + } + } + + @Override abstract public JobTrackerState getJobTrackerState(ClusterStatus clusterStatus) throws Exception; @Override diff --git a/shims/src/common/java/org/apache/hadoop/hive/shims/HadoopShims.java b/shims/src/common/java/org/apache/hadoop/hive/shims/HadoopShims.java index b0f5077..1ac2185 100644 --- a/shims/src/common/java/org/apache/hadoop/hive/shims/HadoopShims.java +++ b/shims/src/common/java/org/apache/hadoop/hive/shims/HadoopShims.java @@ -321,13 +321,19 @@ void setTokenStr(UserGroupInformation ugi, String tokenStr, String tokenService) public String getJobLauncherHttpAddress(Configuration conf); - /** - * Perform kerberos login using the given principal and keytab - * @throws IOException - */ + /** + * Perform kerberos login using the given principal and keytab + * @throws IOException + */ public void loginUserFromKeytab(String principal, String keytabFile) throws IOException; /** + * Perform kerberos re-login using the given principal and keytab, to renew the credentials + * @throws IOException + */ + public void reLoginUserFromKeytab() throws IOException; + + /** * Move the directory/file to trash. In case of the symlinks or mount points, the file is * moved to the trashbin in the actual volume of the path p being deleted * @param fs