Back to home page

OSCL-LXR

 
 

    


0001 /**
0002  * Licensed to the Apache Software Foundation (ASF) under one
0003  * or more contributor license agreements.  See the NOTICE file
0004  * distributed with this work for additional information
0005  * regarding copyright ownership.  The ASF licenses this file
0006  * to you under the Apache License, Version 2.0 (the
0007  * "License"); you may not use this file except in compliance
0008  * with the License.  You may obtain a copy of the License at
0009  *
0010  *     http://www.apache.org/licenses/LICENSE-2.0
0011  *
0012  * Unless required by applicable law or agreed to in writing, software
0013  * distributed under the License is distributed on an "AS IS" BASIS,
0014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0015  * See the License for the specific language governing permissions and
0016  * limitations under the License.
0017  */
0018 
0019 package org.apache.hive.service.cli;
0020 
0021 import java.io.IOException;
0022 import java.util.List;
0023 import java.util.Map;
0024 import java.util.concurrent.CancellationException;
0025 import java.util.concurrent.ExecutionException;
0026 import java.util.concurrent.TimeUnit;
0027 import java.util.concurrent.TimeoutException;
0028 
0029 import javax.security.auth.login.LoginException;
0030 
0031 import org.apache.commons.logging.Log;
0032 import org.apache.commons.logging.LogFactory;
0033 import org.apache.hadoop.hive.conf.HiveConf;
0034 import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
0035 import org.apache.hadoop.hive.metastore.HiveMetaStoreClient;
0036 import org.apache.hadoop.hive.metastore.IMetaStoreClient;
0037 import org.apache.hadoop.hive.metastore.api.MetaException;
0038 import org.apache.hadoop.hive.ql.exec.FunctionRegistry;
0039 import org.apache.hadoop.hive.ql.metadata.Hive;
0040 import org.apache.hadoop.hive.ql.metadata.HiveException;
0041 import org.apache.hadoop.hive.ql.session.SessionState;
0042 import org.apache.hadoop.hive.shims.Utils;
0043 import org.apache.hadoop.security.UserGroupInformation;
0044 import org.apache.hive.service.CompositeService;
0045 import org.apache.hive.service.ServiceException;
0046 import org.apache.hive.service.auth.HiveAuthFactory;
0047 import org.apache.hive.service.cli.operation.Operation;
0048 import org.apache.hive.service.cli.session.SessionManager;
0049 import org.apache.hive.service.cli.thrift.TProtocolVersion;
0050 import org.apache.hive.service.server.HiveServer2;
0051 
0052 /**
0053  * CLIService.
0054  *
0055  */
0056 public class CLIService extends CompositeService implements ICLIService {
0057 
0058   public static final TProtocolVersion SERVER_VERSION;
0059 
0060   static {
0061     TProtocolVersion[] protocols = TProtocolVersion.values();
0062     SERVER_VERSION = protocols[protocols.length - 1];
0063   }
0064 
0065   private final Log LOG = LogFactory.getLog(CLIService.class.getName());
0066 
0067   private HiveConf hiveConf;
0068   private SessionManager sessionManager;
0069   private UserGroupInformation serviceUGI;
0070   private UserGroupInformation httpUGI;
0071   // The HiveServer2 instance running this service
0072   private final HiveServer2 hiveServer2;
0073 
0074   public CLIService(HiveServer2 hiveServer2) {
0075     super(CLIService.class.getSimpleName());
0076     this.hiveServer2 = hiveServer2;
0077   }
0078 
0079   @Override
0080   public synchronized void init(HiveConf hiveConf) {
0081     this.hiveConf = hiveConf;
0082     sessionManager = new SessionManager(hiveServer2);
0083     addService(sessionManager);
0084     //  If the hadoop cluster is secure, do a kerberos login for the service from the keytab
0085     if (UserGroupInformation.isSecurityEnabled()) {
0086       try {
0087         HiveAuthFactory.loginFromKeytab(hiveConf);
0088         this.serviceUGI = Utils.getUGI();
0089       } catch (IOException e) {
0090         throw new ServiceException("Unable to login to kerberos with given principal/keytab", e);
0091       } catch (LoginException e) {
0092         throw new ServiceException("Unable to login to kerberos with given principal/keytab", e);
0093       }
0094 
0095       // Also try creating a UGI object for the SPNego principal
0096       String principal = hiveConf.getVar(ConfVars.HIVE_SERVER2_SPNEGO_PRINCIPAL);
0097       String keyTabFile = hiveConf.getVar(ConfVars.HIVE_SERVER2_SPNEGO_KEYTAB);
0098       if (principal.isEmpty() || keyTabFile.isEmpty()) {
0099         LOG.info("SPNego httpUGI not created, spNegoPrincipal: " + principal +
0100             ", ketabFile: " + keyTabFile);
0101       } else {
0102         try {
0103           this.httpUGI = HiveAuthFactory.loginFromSpnegoKeytabAndReturnUGI(hiveConf);
0104           LOG.info("SPNego httpUGI successfully created.");
0105         } catch (IOException e) {
0106           LOG.warn("SPNego httpUGI creation failed: ", e);
0107         }
0108       }
0109     }
0110     // creates connection to HMS and thus *must* occur after kerberos login above
0111     try {
0112       applyAuthorizationConfigPolicy(hiveConf);
0113     } catch (Exception e) {
0114       throw new RuntimeException("Error applying authorization policy on hive configuration: "
0115           + e.getMessage(), e);
0116     }
0117     setupBlockedUdfs();
0118     super.init(hiveConf);
0119   }
0120 
0121   private void applyAuthorizationConfigPolicy(HiveConf newHiveConf) throws HiveException,
0122       MetaException {
0123     // authorization setup using SessionState should be revisited eventually, as
0124     // authorization and authentication are not session specific settings
0125     SessionState ss = new SessionState(newHiveConf);
0126     ss.setIsHiveServerQuery(true);
0127     SessionState.start(ss);
0128     ss.applyAuthorizationPolicy();
0129   }
0130 
0131   private void setupBlockedUdfs() {
0132     FunctionRegistry.setupPermissionsForBuiltinUDFs(
0133         hiveConf.getVar(ConfVars.HIVE_SERVER2_BUILTIN_UDF_WHITELIST),
0134         hiveConf.getVar(ConfVars.HIVE_SERVER2_BUILTIN_UDF_BLACKLIST));
0135   }
0136 
0137   public UserGroupInformation getServiceUGI() {
0138     return this.serviceUGI;
0139   }
0140 
0141   public UserGroupInformation getHttpUGI() {
0142     return this.httpUGI;
0143   }
0144 
0145   @Override
0146   public synchronized void start() {
0147     super.start();
0148     // Initialize and test a connection to the metastore
0149     IMetaStoreClient metastoreClient = null;
0150     try {
0151       metastoreClient = new HiveMetaStoreClient(hiveConf);
0152       metastoreClient.getDatabases("default");
0153     } catch (Exception e) {
0154       throw new ServiceException("Unable to connect to MetaStore!", e);
0155     }
0156     finally {
0157       if (metastoreClient != null) {
0158         metastoreClient.close();
0159       }
0160     }
0161   }
0162 
0163   @Override
0164   public synchronized void stop() {
0165     super.stop();
0166   }
0167 
0168   /**
0169    * @deprecated  Use {@link #openSession(TProtocolVersion, String, String, String, Map)}
0170    */
0171   @Deprecated
0172   public SessionHandle openSession(TProtocolVersion protocol, String username, String password,
0173       Map<String, String> configuration) throws HiveSQLException {
0174     SessionHandle sessionHandle = sessionManager.openSession(protocol, username, password, null, configuration, false, null);
0175     LOG.debug(sessionHandle + ": openSession()");
0176     return sessionHandle;
0177   }
0178 
0179   /**
0180    * @deprecated  Use {@link #openSessionWithImpersonation(TProtocolVersion, String, String, String, Map, String)}
0181    */
0182   @Deprecated
0183   public SessionHandle openSessionWithImpersonation(TProtocolVersion protocol, String username,
0184       String password, Map<String, String> configuration, String delegationToken)
0185           throws HiveSQLException {
0186     SessionHandle sessionHandle = sessionManager.openSession(protocol, username, password, null, configuration,
0187         true, delegationToken);
0188     LOG.debug(sessionHandle + ": openSessionWithImpersonation()");
0189     return sessionHandle;
0190   }
0191 
0192   public SessionHandle openSession(TProtocolVersion protocol, String username, String password, String ipAddress,
0193       Map<String, String> configuration) throws HiveSQLException {
0194     SessionHandle sessionHandle = sessionManager.openSession(protocol, username, password, ipAddress, configuration, false, null);
0195     LOG.debug(sessionHandle + ": openSession()");
0196     return sessionHandle;
0197   }
0198 
0199   public SessionHandle openSessionWithImpersonation(TProtocolVersion protocol, String username,
0200       String password, String ipAddress, Map<String, String> configuration, String delegationToken)
0201           throws HiveSQLException {
0202     SessionHandle sessionHandle = sessionManager.openSession(protocol, username, password, ipAddress, configuration,
0203         true, delegationToken);
0204     LOG.debug(sessionHandle + ": openSession()");
0205     return sessionHandle;
0206   }
0207 
0208   /* (non-Javadoc)
0209    * @see org.apache.hive.service.cli.ICLIService#openSession(java.lang.String, java.lang.String, java.util.Map)
0210    */
0211   @Override
0212   public SessionHandle openSession(String username, String password, Map<String, String> configuration)
0213       throws HiveSQLException {
0214     SessionHandle sessionHandle = sessionManager.openSession(SERVER_VERSION, username, password, null, configuration, false, null);
0215     LOG.debug(sessionHandle + ": openSession()");
0216     return sessionHandle;
0217   }
0218 
0219   /* (non-Javadoc)
0220    * @see org.apache.hive.service.cli.ICLIService#openSession(java.lang.String, java.lang.String, java.util.Map)
0221    */
0222   @Override
0223   public SessionHandle openSessionWithImpersonation(String username, String password, Map<String, String> configuration,
0224       String delegationToken) throws HiveSQLException {
0225     SessionHandle sessionHandle = sessionManager.openSession(SERVER_VERSION, username, password, null, configuration,
0226         true, delegationToken);
0227     LOG.debug(sessionHandle + ": openSession()");
0228     return sessionHandle;
0229   }
0230 
0231   /* (non-Javadoc)
0232    * @see org.apache.hive.service.cli.ICLIService#closeSession(org.apache.hive.service.cli.SessionHandle)
0233    */
0234   @Override
0235   public void closeSession(SessionHandle sessionHandle)
0236       throws HiveSQLException {
0237     sessionManager.closeSession(sessionHandle);
0238     LOG.debug(sessionHandle + ": closeSession()");
0239   }
0240 
0241   /* (non-Javadoc)
0242    * @see org.apache.hive.service.cli.ICLIService#getInfo(org.apache.hive.service.cli.SessionHandle, java.util.List)
0243    */
0244   @Override
0245   public GetInfoValue getInfo(SessionHandle sessionHandle, GetInfoType getInfoType)
0246       throws HiveSQLException {
0247     GetInfoValue infoValue = sessionManager.getSession(sessionHandle)
0248         .getInfo(getInfoType);
0249     LOG.debug(sessionHandle + ": getInfo()");
0250     return infoValue;
0251   }
0252 
0253   /* (non-Javadoc)
0254    * @see org.apache.hive.service.cli.ICLIService#executeStatement(org.apache.hive.service.cli.SessionHandle,
0255    *  java.lang.String, java.util.Map)
0256    */
0257   @Override
0258   public OperationHandle executeStatement(SessionHandle sessionHandle, String statement,
0259       Map<String, String> confOverlay)
0260           throws HiveSQLException {
0261     OperationHandle opHandle = sessionManager.getSession(sessionHandle)
0262         .executeStatement(statement, confOverlay);
0263     LOG.debug(sessionHandle + ": executeStatement()");
0264     return opHandle;
0265   }
0266 
0267   /* (non-Javadoc)
0268    * @see org.apache.hive.service.cli.ICLIService#executeStatementAsync(org.apache.hive.service.cli.SessionHandle,
0269    *  java.lang.String, java.util.Map)
0270    */
0271   @Override
0272   public OperationHandle executeStatementAsync(SessionHandle sessionHandle, String statement,
0273       Map<String, String> confOverlay) throws HiveSQLException {
0274     OperationHandle opHandle = sessionManager.getSession(sessionHandle)
0275         .executeStatementAsync(statement, confOverlay);
0276     LOG.debug(sessionHandle + ": executeStatementAsync()");
0277     return opHandle;
0278   }
0279 
0280 
0281   /* (non-Javadoc)
0282    * @see org.apache.hive.service.cli.ICLIService#getTypeInfo(org.apache.hive.service.cli.SessionHandle)
0283    */
0284   @Override
0285   public OperationHandle getTypeInfo(SessionHandle sessionHandle)
0286       throws HiveSQLException {
0287     OperationHandle opHandle = sessionManager.getSession(sessionHandle)
0288         .getTypeInfo();
0289     LOG.debug(sessionHandle + ": getTypeInfo()");
0290     return opHandle;
0291   }
0292 
0293   /* (non-Javadoc)
0294    * @see org.apache.hive.service.cli.ICLIService#getCatalogs(org.apache.hive.service.cli.SessionHandle)
0295    */
0296   @Override
0297   public OperationHandle getCatalogs(SessionHandle sessionHandle)
0298       throws HiveSQLException {
0299     OperationHandle opHandle = sessionManager.getSession(sessionHandle)
0300         .getCatalogs();
0301     LOG.debug(sessionHandle + ": getCatalogs()");
0302     return opHandle;
0303   }
0304 
0305   /* (non-Javadoc)
0306    * @see org.apache.hive.service.cli.ICLIService#getSchemas(org.apache.hive.service.cli.SessionHandle, java.lang.String, java.lang.String)
0307    */
0308   @Override
0309   public OperationHandle getSchemas(SessionHandle sessionHandle,
0310       String catalogName, String schemaName)
0311           throws HiveSQLException {
0312     OperationHandle opHandle = sessionManager.getSession(sessionHandle)
0313         .getSchemas(catalogName, schemaName);
0314     LOG.debug(sessionHandle + ": getSchemas()");
0315     return opHandle;
0316   }
0317 
0318   /* (non-Javadoc)
0319    * @see org.apache.hive.service.cli.ICLIService#getTables(org.apache.hive.service.cli.SessionHandle, java.lang.String, java.lang.String, java.lang.String, java.util.List)
0320    */
0321   @Override
0322   public OperationHandle getTables(SessionHandle sessionHandle,
0323       String catalogName, String schemaName, String tableName, List<String> tableTypes)
0324           throws HiveSQLException {
0325     OperationHandle opHandle = sessionManager.getSession(sessionHandle)
0326         .getTables(catalogName, schemaName, tableName, tableTypes);
0327     LOG.debug(sessionHandle + ": getTables()");
0328     return opHandle;
0329   }
0330 
0331   /* (non-Javadoc)
0332    * @see org.apache.hive.service.cli.ICLIService#getTableTypes(org.apache.hive.service.cli.SessionHandle)
0333    */
0334   @Override
0335   public OperationHandle getTableTypes(SessionHandle sessionHandle)
0336       throws HiveSQLException {
0337     OperationHandle opHandle = sessionManager.getSession(sessionHandle)
0338         .getTableTypes();
0339     LOG.debug(sessionHandle + ": getTableTypes()");
0340     return opHandle;
0341   }
0342 
0343   /* (non-Javadoc)
0344    * @see org.apache.hive.service.cli.ICLIService#getColumns(org.apache.hive.service.cli.SessionHandle)
0345    */
0346   @Override
0347   public OperationHandle getColumns(SessionHandle sessionHandle,
0348       String catalogName, String schemaName, String tableName, String columnName)
0349           throws HiveSQLException {
0350     OperationHandle opHandle = sessionManager.getSession(sessionHandle)
0351         .getColumns(catalogName, schemaName, tableName, columnName);
0352     LOG.debug(sessionHandle + ": getColumns()");
0353     return opHandle;
0354   }
0355 
0356   /* (non-Javadoc)
0357    * @see org.apache.hive.service.cli.ICLIService#getFunctions(org.apache.hive.service.cli.SessionHandle)
0358    */
0359   @Override
0360   public OperationHandle getFunctions(SessionHandle sessionHandle,
0361       String catalogName, String schemaName, String functionName)
0362           throws HiveSQLException {
0363     OperationHandle opHandle = sessionManager.getSession(sessionHandle)
0364         .getFunctions(catalogName, schemaName, functionName);
0365     LOG.debug(sessionHandle + ": getFunctions()");
0366     return opHandle;
0367   }
0368 
0369   /* (non-Javadoc)
0370    * @see org.apache.hive.service.cli.ICLIService#getOperationStatus(org.apache.hive.service.cli.OperationHandle)
0371    */
0372   @Override
0373   public OperationStatus getOperationStatus(OperationHandle opHandle)
0374       throws HiveSQLException {
0375     Operation operation = sessionManager.getOperationManager().getOperation(opHandle);
0376     /**
0377      * If this is a background operation run asynchronously,
0378      * we block for a configured duration, before we return
0379      * (duration: HIVE_SERVER2_LONG_POLLING_TIMEOUT).
0380      * However, if the background operation is complete, we return immediately.
0381      */
0382     if (operation.shouldRunAsync()) {
0383       HiveConf conf = operation.getParentSession().getHiveConf();
0384       long timeout = HiveConf.getTimeVar(conf,
0385           HiveConf.ConfVars.HIVE_SERVER2_LONG_POLLING_TIMEOUT, TimeUnit.MILLISECONDS);
0386       try {
0387         operation.getBackgroundHandle().get(timeout, TimeUnit.MILLISECONDS);
0388       } catch (TimeoutException e) {
0389         // No Op, return to the caller since long polling timeout has expired
0390         LOG.trace(opHandle + ": Long polling timed out");
0391       } catch (CancellationException e) {
0392         // The background operation thread was cancelled
0393         LOG.trace(opHandle + ": The background operation was cancelled", e);
0394       } catch (ExecutionException e) {
0395         // The background operation thread was aborted
0396         LOG.warn(opHandle + ": The background operation was aborted", e);
0397       } catch (InterruptedException e) {
0398         // No op, this thread was interrupted
0399         // In this case, the call might return sooner than long polling timeout
0400       }
0401     }
0402     OperationStatus opStatus = operation.getStatus();
0403     LOG.debug(opHandle + ": getOperationStatus()");
0404     return opStatus;
0405   }
0406 
0407   /* (non-Javadoc)
0408    * @see org.apache.hive.service.cli.ICLIService#cancelOperation(org.apache.hive.service.cli.OperationHandle)
0409    */
0410   @Override
0411   public void cancelOperation(OperationHandle opHandle)
0412       throws HiveSQLException {
0413     sessionManager.getOperationManager().getOperation(opHandle)
0414     .getParentSession().cancelOperation(opHandle);
0415     LOG.debug(opHandle + ": cancelOperation()");
0416   }
0417 
0418   /* (non-Javadoc)
0419    * @see org.apache.hive.service.cli.ICLIService#closeOperation(org.apache.hive.service.cli.OperationHandle)
0420    */
0421   @Override
0422   public void closeOperation(OperationHandle opHandle)
0423       throws HiveSQLException {
0424     sessionManager.getOperationManager().getOperation(opHandle)
0425     .getParentSession().closeOperation(opHandle);
0426     LOG.debug(opHandle + ": closeOperation");
0427   }
0428 
0429   /* (non-Javadoc)
0430    * @see org.apache.hive.service.cli.ICLIService#getResultSetMetadata(org.apache.hive.service.cli.OperationHandle)
0431    */
0432   @Override
0433   public TableSchema getResultSetMetadata(OperationHandle opHandle)
0434       throws HiveSQLException {
0435     TableSchema tableSchema = sessionManager.getOperationManager()
0436         .getOperation(opHandle).getParentSession().getResultSetMetadata(opHandle);
0437     LOG.debug(opHandle + ": getResultSetMetadata()");
0438     return tableSchema;
0439   }
0440 
0441   /* (non-Javadoc)
0442    * @see org.apache.hive.service.cli.ICLIService#fetchResults(org.apache.hive.service.cli.OperationHandle)
0443    */
0444   @Override
0445   public RowSet fetchResults(OperationHandle opHandle)
0446       throws HiveSQLException {
0447     return fetchResults(opHandle, Operation.DEFAULT_FETCH_ORIENTATION,
0448         Operation.DEFAULT_FETCH_MAX_ROWS, FetchType.QUERY_OUTPUT);
0449   }
0450 
0451   @Override
0452   public RowSet fetchResults(OperationHandle opHandle, FetchOrientation orientation,
0453                              long maxRows, FetchType fetchType) throws HiveSQLException {
0454     RowSet rowSet = sessionManager.getOperationManager().getOperation(opHandle)
0455         .getParentSession().fetchResults(opHandle, orientation, maxRows, fetchType);
0456     LOG.debug(opHandle + ": fetchResults()");
0457     return rowSet;
0458   }
0459 
0460   // obtain delegation token for the give user from metastore
0461   public synchronized String getDelegationTokenFromMetaStore(String owner)
0462       throws HiveSQLException, UnsupportedOperationException, LoginException, IOException {
0463     if (!hiveConf.getBoolVar(HiveConf.ConfVars.METASTORE_USE_THRIFT_SASL) ||
0464         !hiveConf.getBoolVar(HiveConf.ConfVars.HIVE_SERVER2_ENABLE_DOAS)) {
0465       throw new UnsupportedOperationException(
0466           "delegation token is can only be obtained for a secure remote metastore");
0467     }
0468 
0469     try {
0470       Hive.closeCurrent();
0471       return Hive.get(hiveConf).getDelegationToken(owner, owner);
0472     } catch (HiveException e) {
0473       if (e.getCause() instanceof UnsupportedOperationException) {
0474         throw (UnsupportedOperationException)e.getCause();
0475       } else {
0476         throw new HiveSQLException("Error connect metastore to setup impersonation", e);
0477       }
0478     }
0479   }
0480 
0481   @Override
0482   public String getDelegationToken(SessionHandle sessionHandle, HiveAuthFactory authFactory,
0483       String owner, String renewer) throws HiveSQLException {
0484     String delegationToken = sessionManager.getSession(sessionHandle)
0485         .getDelegationToken(authFactory, owner, renewer);
0486     LOG.info(sessionHandle  + ": getDelegationToken()");
0487     return delegationToken;
0488   }
0489 
0490   @Override
0491   public void cancelDelegationToken(SessionHandle sessionHandle, HiveAuthFactory authFactory,
0492       String tokenStr) throws HiveSQLException {
0493     sessionManager.getSession(sessionHandle).cancelDelegationToken(authFactory, tokenStr);
0494     LOG.info(sessionHandle  + ": cancelDelegationToken()");
0495   }
0496 
0497   @Override
0498   public void renewDelegationToken(SessionHandle sessionHandle, HiveAuthFactory authFactory,
0499       String tokenStr) throws HiveSQLException {
0500     sessionManager.getSession(sessionHandle).renewDelegationToken(authFactory, tokenStr);
0501     LOG.info(sessionHandle  + ": renewDelegationToken()");
0502   }
0503 
0504   public SessionManager getSessionManager() {
0505     return sessionManager;
0506   }
0507 }