SENTRY-1316: Implement Sentry leadership election (Colin Patrick McCabe, Reviewed by Sravya Tirukkovalur, Hao Hao)
Change-Id: Ib7dc6470694a2f06def90039f321c28cd72952ae Project: http://git-wip-us.apache.org/repos/asf/sentry/repo Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/5630fc5c Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/5630fc5c Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/5630fc5c Branch: refs/heads/sentry-ha-redesign Commit: 5630fc5cecfa7720c372f84ebb0bdc059ebc2c2e Parents: 24b686e Author: hahao <[email protected]> Authored: Thu Jun 23 12:22:15 2016 -0700 Committer: hahao <[email protected]> Committed: Thu Jun 23 12:22:15 2016 -0700 ---------------------------------------------------------------------- .../hdfs/SentryHDFSServiceClientFactory.java | 14 +- .../hdfs/ha/HdfsHAClientInvocationHandler.java | 142 ------------ .../sentry/hdfs/MetastorePluginWithHA.java | 99 --------- .../org/apache/sentry/hdfs/UpdateForwarder.java | 10 +- .../sentry/hdfs/UpdateForwarderWithHA.java | 130 ----------- .../apache/sentry/hdfs/TestPluginCacheSync.java | 151 ------------- .../db/service/persistent/ServiceManager.java | 97 -------- .../thrift/HAClientInvocationHandler.java | 139 ------------ .../sentry/service/thrift/LeaderStatus.java | 134 ++++++++++++ .../service/thrift/LeaderStatusAdaptor.java | 170 ++++++++++++++ .../sentry/service/thrift/SentryService.java | 25 ++- .../thrift/SentryServiceClientFactory.java | 8 +- .../thrift/SentryServiceClientPoolFactory.java | 13 +- .../sentry/service/thrift/ServiceConstants.java | 8 +- .../persistent/TestSentryServiceDiscovery.java | 123 ----------- .../TestSentryServerForHaWithoutKerberos.java | 219 ------------------- ...estSentryServerForPoolHAWithoutKerberos.java | 36 --- .../TestSentryServiceForHAWithKerberos.java | 75 ------- .../TestSentryServiceForPoolHAWithKerberos.java | 36 --- .../sentry/service/thrift/TestLeaderStatus.java | 219 +++++++++++++++++++ .../sentry/tests/e2e/ha/TestHaEnd2End.java | 171 --------------- .../AbstractTestWithStaticConfiguration.java | 2 +- 22 files changed, 555 insertions(+), 1466 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/SentryHDFSServiceClientFactory.java ---------------------------------------------------------------------- diff --git a/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/SentryHDFSServiceClientFactory.java b/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/SentryHDFSServiceClientFactory.java index 6c9c8bb..2a18b15 100644 --- a/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/SentryHDFSServiceClientFactory.java +++ b/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/SentryHDFSServiceClientFactory.java @@ -17,11 +17,7 @@ */ package org.apache.sentry.hdfs; -import java.lang.reflect.Proxy; - import org.apache.hadoop.conf.Configuration; -import org.apache.sentry.hdfs.ha.HdfsHAClientInvocationHandler; -import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig; /** * Client factory to create normal client or proxy with HA invocation handler @@ -34,15 +30,7 @@ public class SentryHDFSServiceClientFactory { public static SentryHDFSServiceClient create(Configuration conf) throws Exception { - boolean haEnabled = conf.getBoolean(ServerConfig.SENTRY_HA_ENABLED, false); - if (haEnabled) { - return (SentryHDFSServiceClient) Proxy.newProxyInstance( - SentryHDFSServiceClientDefaultImpl.class.getClassLoader(), - SentryHDFSServiceClientDefaultImpl.class.getInterfaces(), - new HdfsHAClientInvocationHandler(conf)); - } else { - return new SentryHDFSServiceClientDefaultImpl(conf); - } + return new SentryHDFSServiceClientDefaultImpl(conf); } } http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/ha/HdfsHAClientInvocationHandler.java ---------------------------------------------------------------------- diff --git a/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/ha/HdfsHAClientInvocationHandler.java b/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/ha/HdfsHAClientInvocationHandler.java deleted file mode 100644 index 6138b8c..0000000 --- a/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/ha/HdfsHAClientInvocationHandler.java +++ /dev/null @@ -1,142 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sentry.hdfs.ha; - -import java.io.IOException; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.InetSocketAddress; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.security.SecurityUtil; -import org.apache.curator.x.discovery.ServiceInstance; -import org.apache.sentry.hdfs.SentryHDFSServiceClientDefaultImpl; -import org.apache.sentry.hdfs.SentryHdfsServiceException; -import org.apache.sentry.hdfs.ServiceConstants; -import org.apache.sentry.provider.db.service.persistent.HAContext; -import org.apache.sentry.provider.db.service.persistent.ServiceManager; -import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Preconditions; - -public class HdfsHAClientInvocationHandler implements InvocationHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(HdfsHAClientInvocationHandler.class); - - private final Configuration conf; - private ServiceManager manager; - private ServiceInstance<Void> currentServiceInstance; - private SentryHDFSServiceClientDefaultImpl client = null; - - private static final String THRIFT_EXCEPTION_MESSAGE = "Thrift exception occured "; - public static final String SENTRY_HA_ERROR_MESSAGE = "No Sentry server available. " - + "Please ensure that at least one Sentry server is online"; - - public HdfsHAClientInvocationHandler(Configuration conf) throws Exception { - this.conf = conf; - checkClientConf(); - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws - SentryHdfsServiceException { - Object result = null; - try { - if (!method.isAccessible()) { - method.setAccessible(true); - } - // The client is initialized in the first call instead of constructor. - // This way we can propagate the connection exception to caller cleanly - if (client == null) { - renewSentryClient(); - } - result = method.invoke(client, args); - } catch (IllegalAccessException e) { - throw new SentryHdfsServiceException(e.getMessage(), e.getCause()); - } catch (InvocationTargetException e) { - if (!(e.getTargetException() instanceof SentryHdfsServiceException)) { - throw new SentryHdfsServiceException("Error in Sentry HDFS client", - e.getTargetException()); - } else { - LOGGER.warn(THRIFT_EXCEPTION_MESSAGE + ": Error in connect current" + - " service, will retry other service.", e); - if (client != null) { - client.close(); - client = null; - } - throw (SentryHdfsServiceException) e.getTargetException(); - } - } catch (IOException e1) { - // close() doesn't throw exception we supress that in case of connection - // loss. Changing SentryPolicyServiceClient#close() to throw an - // exception would be a backward incompatible change for Sentry clients. - if ("close".equals(method.getName())) { - return null; - } - throw new SentryHdfsServiceException( - "Error connecting to sentry service " + e1.getMessage(), e1); - } - return result; - } - - // Retrieve the new connection endpoint from ZK and connect to new server - private void renewSentryClient() throws IOException { - try { - manager = new ServiceManager(HAContext.getHAContext(conf)); - } catch (Exception e1) { - throw new IOException("Failed to extract Sentry node info from zookeeper", e1); - } - - try { - while (true) { - currentServiceInstance = manager.getServiceInstance(); - if (currentServiceInstance == null) { - throw new IOException(SENTRY_HA_ERROR_MESSAGE); - } - InetSocketAddress serverAddress = - ServiceManager.convertServiceInstance(currentServiceInstance); - conf.set(ServiceConstants.ClientConfig.SERVER_RPC_ADDRESS, serverAddress.getHostName()); - conf.setInt(ServiceConstants.ClientConfig.SERVER_RPC_PORT, serverAddress.getPort()); - try { - client = new SentryHDFSServiceClientDefaultImpl(conf); - LOGGER.info("Sentry Client using server " + serverAddress.getHostName() + - ":" + serverAddress.getPort()); - break; - } catch (IOException e) { - manager.reportError(currentServiceInstance); - LOGGER.info("Transport exception while opening transport:", e, e.getMessage()); - } - } - } finally { - manager.close(); - } - } - - private void checkClientConf() { - if (conf.getBoolean(ServerConfig.SENTRY_HA_ZOOKEEPER_SECURITY, - ServerConfig.SENTRY_HA_ZOOKEEPER_SECURITY_DEFAULT)) { - String serverPrincipal = Preconditions.checkNotNull(conf.get(ServerConfig.PRINCIPAL), - ServerConfig.PRINCIPAL + " is required"); - Preconditions.checkArgument(serverPrincipal.contains(SecurityUtil.HOSTNAME_PATTERN), - ServerConfig.PRINCIPAL + " : " + serverPrincipal + " should contain " + SecurityUtil.HOSTNAME_PATTERN); - } - } -} http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/MetastorePluginWithHA.java ---------------------------------------------------------------------- diff --git a/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/MetastorePluginWithHA.java b/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/MetastorePluginWithHA.java deleted file mode 100644 index 6476a01..0000000 --- a/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/MetastorePluginWithHA.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sentry.hdfs; - -import org.apache.curator.framework.CuratorFramework; -import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; -import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener; -import org.apache.hadoop.conf.Configuration; -import org.apache.sentry.hdfs.ServiceConstants.ServerConfig; -import org.apache.sentry.provider.db.SentryPolicyStorePlugin.SentryPluginException; -import org.apache.sentry.binding.metastore.MetastoreAuthzBindingBase; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MetastorePluginWithHA extends MetastorePlugin { - private static final Logger LOGGER = LoggerFactory - .getLogger(MetastorePluginWithHA.class); - public static class SentryMetastoreHACacheListener implements PathChildrenCacheListener { - private MetastorePluginWithHA metastorePlugin; - - public SentryMetastoreHACacheListener(MetastorePluginWithHA metastorePlugin) { - this.metastorePlugin = metastorePlugin; - } - - @Override - public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) - throws Exception { - switch ( event.getType() ) { - case CHILD_ADDED: - PathsUpdate newUpdate = new PathsUpdate(); - PluginCacheSyncUtil.setUpdateFromChildEvent(event, newUpdate); - metastorePlugin.processCacheNotification(newUpdate); - break; - case INITIALIZED: - case CHILD_UPDATED: - case CHILD_REMOVED: - break; - case CONNECTION_RECONNECTED: - MetastoreAuthzBindingBase.setSentryCacheOutOfSync(false); - break; - case CONNECTION_SUSPENDED: - case CONNECTION_LOST: - MetastoreAuthzBindingBase.setSentryCacheOutOfSync(true); - break; - default: - break; - } - } - } - - private String zkPath; - private PluginCacheSyncUtil pluginCacheSync; - - public MetastorePluginWithHA(Configuration conf, Configuration sentryConfig) throws Exception { - super(conf, sentryConfig); - zkPath = sentryConfig.get(ServerConfig.SENTRY_METASTORE_HA_ZOOKEEPER_NAMESPACE, - ServerConfig.SENTRY_METASTORE_HA_ZOOKEEPER_NAMESPACE_DEFAULT); - - pluginCacheSync = new PluginCacheSyncUtil(zkPath, sentryConfig, - new SentryMetastoreHACacheListener(this)); - // start seq# from the last global seq - seqNum.set(pluginCacheSync.getUpdateCounter()); - MetastorePlugin.lastSentSeqNum = seqNum.get(); - } - - @Override - protected void processUpdate(PathsUpdate update) { - try { - // push to ZK in order to keep the metastore local cache in sync - pluginCacheSync.handleCacheUpdate(update); - - // notify Sentry. Note that Sentry service already has a cache - // sync mechanism to replicate this update to all other Sentry servers - notifySentry(update); - } catch (SentryPluginException e) { - LOGGER.error("Error pushing update to cache", e); - } - } - - // apply the update to local cache - private void processCacheNotification(PathsUpdate update) { - super.applyLocal(update); - } -} http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/UpdateForwarder.java ---------------------------------------------------------------------- diff --git a/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/UpdateForwarder.java b/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/UpdateForwarder.java index 7387281..ea1c8f6 100644 --- a/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/UpdateForwarder.java +++ b/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/UpdateForwarder.java @@ -31,7 +31,6 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.hadoop.conf.Configuration; import org.apache.sentry.provider.db.SentryPolicyStorePlugin.SentryPluginException; -import org.apache.sentry.provider.db.service.persistent.HAContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -98,13 +97,8 @@ public class UpdateForwarder<K extends Updateable.Update> implements public static <K extends Updateable.Update> UpdateForwarder<K> create(Configuration conf, Updateable<K> updateable, K update, ExternalImageRetriever<K> imageRetreiver, int maxUpdateLogSize, int initUpdateRetryDelay) throws SentryPluginException { - if (HAContext.isHaEnabled(conf)) { - return new UpdateForwarderWithHA<K>(conf, updateable, update, imageRetreiver, - maxUpdateLogSize, initUpdateRetryDelay); - } else { - return new UpdateForwarder<K>(conf, updateable, imageRetreiver, - maxUpdateLogSize, initUpdateRetryDelay); - } + return new UpdateForwarder<K>(conf, updateable, imageRetreiver, + maxUpdateLogSize, initUpdateRetryDelay); } private void spawnInitialUpdater(final Updateable<K> updateable, http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/UpdateForwarderWithHA.java ---------------------------------------------------------------------- diff --git a/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/UpdateForwarderWithHA.java b/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/UpdateForwarderWithHA.java deleted file mode 100644 index 574627c..0000000 --- a/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/UpdateForwarderWithHA.java +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sentry.hdfs; - -import java.io.IOException; -import java.util.LinkedList; - -import org.apache.curator.framework.CuratorFramework; -import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; -import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener; -import org.apache.hadoop.conf.Configuration; -import org.apache.sentry.hdfs.ServiceConstants.ServerConfig; -import org.apache.sentry.provider.db.SentryPolicyStorePlugin.SentryPluginException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class UpdateForwarderWithHA<K extends Updateable.Update> extends -UpdateForwarder<K> implements Updateable<K> { - private static final Logger LOGGER = LoggerFactory.getLogger(UpdateForwarderWithHA.class); - private static final String UPDATABLE_TYPE_NAME = "ha_update_forwarder"; - - public static class SentryHAPathChildrenCacheListener<K extends Updateable.Update> - implements PathChildrenCacheListener { - private final LinkedList<K> updateLog; - private final K baseUpdate; - private final UpdateForwarderWithHA<K> updateForwarder; - - public SentryHAPathChildrenCacheListener(LinkedList<K> updateLog, - K baseUpdate, UpdateForwarderWithHA<K> updateForwarder) { - this.updateLog = updateLog; - this.baseUpdate = baseUpdate; - this.updateForwarder = updateForwarder; - } - - @Override - public synchronized void childEvent(CuratorFramework client, - PathChildrenCacheEvent event) throws Exception { - switch ( event.getType() ) { - case CHILD_ADDED: - K newUpdate = (K) baseUpdate.getClass().newInstance(); - PluginCacheSyncUtil.setUpdateFromChildEvent(event, newUpdate); - updateForwarder.postNotificationToLog(newUpdate); - break; - case INITIALIZED: - case CHILD_UPDATED: - case CHILD_REMOVED: - break; - case CONNECTION_RECONNECTED: - // resume the node - SentryPlugin.instance.setOutOfSync(false); - break; - case CONNECTION_SUSPENDED: - case CONNECTION_LOST: - // suspend the node - SentryPlugin.instance.setOutOfSync(true); - break; - default: - break; - } - } - } - - private final String zkPath; - private final PluginCacheSyncUtil pluginCacheSync; - - public UpdateForwarderWithHA(Configuration conf, Updateable<K> updateable, K baseUpdate, - ExternalImageRetriever<K> imageRetreiver, int updateLogSize) throws SentryPluginException { - this(conf, updateable, baseUpdate, imageRetreiver, updateLogSize, INIT_UPDATE_RETRY_DELAY); - } - - public UpdateForwarderWithHA(Configuration conf, Updateable<K> updateable, K baseUpdate, - ExternalImageRetriever<K> imageRetreiver, int updateLogSize, - int initUpdateRetryDelay) throws SentryPluginException { - super(conf, updateable, imageRetreiver, updateLogSize, initUpdateRetryDelay); - zkPath = conf.get(ServerConfig.SENTRY_HDFS_HA_ZOOKEEPER_NAMESPACE, - ServerConfig.SENTRY_HDFS_HA_ZOOKEEPER_NAMESPACE_DEFAULT) + "/" + - updateable.getUpdateableTypeName(); - pluginCacheSync = new PluginCacheSyncUtil(zkPath, conf, - new SentryHAPathChildrenCacheListener<K>(getUpdateLog(), baseUpdate, - this)); - } - - @Override - public String getUpdateableTypeName() { - return UPDATABLE_TYPE_NAME; - } - - @Override - public void handleUpdateNotification(final K update) throws SentryPluginException { - pluginCacheSync.handleCacheUpdate(update); - } - - private void postNotificationToLog(K update) throws SentryPluginException { - super.handleUpdateNotification(update); - } - - @Override - public void close() throws IOException { - pluginCacheSync.close(); - } - - @Override - public boolean areAllUpdatesCommited() { - try { - if (lastCommittedSeqNum.get() == INIT_SEQ_NUM) { - return false; - } - return lastCommittedSeqNum.get() == pluginCacheSync.getUpdateCounter(); - } catch (Exception e) { - LOGGER.error("Error loading the update counter for ZK", e); - return true; - } - } - -} http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-hdfs/sentry-hdfs-service/src/test/java/org/apache/sentry/hdfs/TestPluginCacheSync.java ---------------------------------------------------------------------- diff --git a/sentry-hdfs/sentry-hdfs-service/src/test/java/org/apache/sentry/hdfs/TestPluginCacheSync.java b/sentry-hdfs/sentry-hdfs-service/src/test/java/org/apache/sentry/hdfs/TestPluginCacheSync.java deleted file mode 100644 index 132a4a3..0000000 --- a/sentry-hdfs/sentry-hdfs-service/src/test/java/org/apache/sentry/hdfs/TestPluginCacheSync.java +++ /dev/null @@ -1,151 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sentry.hdfs; - -import static org.junit.Assert.*; - -import java.util.List; - -import org.apache.curator.framework.CuratorFramework; -import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; -import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener; -import org.apache.curator.test.TestingServer; -import org.apache.hadoop.conf.Configuration; -import org.apache.sentry.hdfs.TestUpdateForwarder.DummyUpdate; -import org.apache.sentry.provider.db.service.persistent.HAContext; -import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -public class TestPluginCacheSync { - // Test PathChildrenCacheListener to track the Update event received from ZK - public static class TestCacheListener implements PathChildrenCacheListener { - private DummyUpdate dummyUpdate; - private boolean recievedEvent = false; - - @Override - public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) - throws Exception { - switch (event.getType()) { - case CHILD_ADDED: - DummyUpdate newUpdate = new DummyUpdate(); - PluginCacheSyncUtil.setUpdateFromChildEvent(event, newUpdate); - dummyUpdate = newUpdate; - recievedEvent = true; - break; - default: - break; - } - } - - public DummyUpdate getDummyUpdate() { - return dummyUpdate; - } - - public boolean isRecievedEvent() { - return recievedEvent; - } - - public void setRecievedEvent(boolean recievedEvent) { - this.recievedEvent = recievedEvent; - } - } - - private static final String TEST_ZPATH = "/test"; - private static TestingServer testServer; - private static Configuration conf; - - private PluginCacheSyncUtil pluginCache; - - @BeforeClass - public static void preSetup() throws Exception { - testServer = new TestingServer(); - testServer.start(); - conf = new Configuration(); - conf.set(ServerConfig.SENTRY_HA_ZOOKEEPER_QUORUM, - testServer.getConnectString()); - } - - @After - public void destroy() throws Exception { - pluginCache.close(); - } - - @AfterClass - public static void shutDown() throws Exception { - testServer.stop(); - } - - /** - * Post a dummy update to PluginCacheSync. Verify that the update is received - * by cache via ZK sync - * @throws Exception - */ - @Test - public void testCachePost() throws Exception { - TestCacheListener cacheListener = new TestCacheListener(); - pluginCache = new PluginCacheSyncUtil(TEST_ZPATH, conf, - cacheListener); - - // post an update - DummyUpdate dummyUpdate = new DummyUpdate(); - dummyUpdate.setState("foo"); - pluginCache.handleCacheUpdate(dummyUpdate); - - // wait for update to sync up - int timeLeft = 5000; - while (!cacheListener.isRecievedEvent() && (timeLeft > 0)) { - Thread.sleep(200); - timeLeft -= 200; - } - cacheListener.setRecievedEvent(false); - DummyUpdate newUpdate = cacheListener.getDummyUpdate(); - assertEquals(dummyUpdate.getState(), newUpdate.getState()); - } - - @Test - public void pluginCacheGC() throws Exception { - pluginCache = new PluginCacheSyncUtil(TEST_ZPATH, conf, - new TestCacheListener()); - - // post updates - for (int updCount = 1; updCount <= PluginCacheSyncUtil.CACHE_GC_SIZE_THRESHOLD_HWM + 2; updCount++) { - DummyUpdate dummyUpdate = new DummyUpdate(); - dummyUpdate.setSeqNum(updCount); - dummyUpdate.setState("foo"); - pluginCache.handleCacheUpdate(dummyUpdate); - } - - // force gc - pluginCache.gcPluginCache(conf); - - // count remaining znodes - HAContext haContext = HAContext.getHAContext(conf); - List<String> znodeList = haContext.getCuratorFramework().getChildren() - .forPath(TEST_ZPATH + "/cache"); - assertFalse(znodeList.isEmpty()); - assertFalse(znodeList.contains(String - .valueOf(PluginCacheSyncUtil.GC_COUNTER_INIT_VALUE))); - assertFalse(znodeList.contains(String - .valueOf(PluginCacheSyncUtil.GC_COUNTER_INIT_VALUE + 1))); - assertTrue(znodeList.contains(String - .valueOf(PluginCacheSyncUtil.CACHE_GC_SIZE_THRESHOLD_HWM))); - } -} http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/ServiceManager.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/ServiceManager.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/ServiceManager.java deleted file mode 100644 index 9f921d4..0000000 --- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/ServiceManager.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.sentry.provider.db.service.persistent; - -import java.io.IOException; -import java.net.InetSocketAddress; - -import org.apache.curator.x.discovery.ServiceDiscovery; -import org.apache.curator.x.discovery.ServiceDiscoveryBuilder; -import org.apache.curator.x.discovery.ServiceInstance; -import org.apache.curator.x.discovery.ServiceProvider; -import org.apache.curator.x.discovery.details.InstanceSerializer; -import org.apache.hadoop.net.NetUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/*** - * ServerManager handles registration of the Sentry service for Curator service - * discovery. Each server registers with ZK and add its host:port details which - * is used by the clients to discover available servers - */ -public class ServiceManager { - private static final Logger LOGGER = LoggerFactory - .getLogger(ServiceManager.class); - private HAContext haContext; - private ServiceProvider<Void> serviceProvider; - private ServiceDiscovery<Void> serviceDiscovery; - - public ServiceManager(HAContext haContext) throws IOException { - this.haContext = haContext; - init(); - } - - private void init() throws IOException { - try { - haContext.startCuratorFramework(); - InstanceSerializer<Void> instanceSerializer = new FixedJsonInstanceSerializer<Void>(Void.class); - serviceDiscovery = ServiceDiscoveryBuilder.<Void>builder(Void.class) - .basePath(HAContext.SENTRY_SERVICE_REGISTER_NAMESPACE) - .serializer(instanceSerializer) - .client(haContext.getCuratorFramework()) - .build(); - serviceDiscovery.start(); - serviceProvider = serviceDiscovery - .serviceProviderBuilder() - .serviceName(HAContext.SENTRY_SERVICE_REGISTER_NAMESPACE) - .build(); - serviceProvider.start(); - } catch (Exception e) { - throw new IOException(e); - } - } - - public ServiceInstance<Void> getServiceInstance() throws IOException { - ServiceInstance<Void> service; - try { - service = serviceProvider.getInstance(); - return service; - } catch (Exception e) { - throw new IOException(e); - } - } - - public void reportError(ServiceInstance<Void> instance) { - serviceProvider.noteError(instance); - } - - public static InetSocketAddress convertServiceInstance(ServiceInstance<?> service) { - return NetUtils.createSocketAddr(service.getAddress(),service.getPort()); - } - - public void close() { - try { - serviceProvider.close(); - serviceDiscovery.close(); - LOGGER.debug("Closed ZK resources"); - } catch (IOException e) { - LOGGER.warn("Error closing the service manager", e); - } - } -} http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/HAClientInvocationHandler.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/HAClientInvocationHandler.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/HAClientInvocationHandler.java deleted file mode 100644 index d97a07e..0000000 --- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/HAClientInvocationHandler.java +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sentry.service.thrift; - -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.InetSocketAddress; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.security.SecurityUtil; -import org.apache.curator.x.discovery.ServiceInstance; -import org.apache.sentry.core.common.exception.SentryUserException; -import org.apache.sentry.provider.db.service.persistent.HAContext; -import org.apache.sentry.provider.db.service.persistent.ServiceManager; -import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient; -import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClientDefaultImpl; -import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Preconditions; - -public class HAClientInvocationHandler extends SentryClientInvocationHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(HAClientInvocationHandler.class); - - private final Configuration conf; - private ServiceManager manager; - private ServiceInstance<Void> currentServiceInstance; - private SentryPolicyServiceClient client = null; - - private static final String THRIFT_EXCEPTION_MESSAGE = "Thrift exception occured "; - public static final String SENTRY_HA_ERROR_MESSAGE = "No Sentry server available. Please ensure that at least one Sentry server is online"; - - public HAClientInvocationHandler(Configuration conf) throws Exception { - this.conf = conf; - checkClientConf(); - } - - @Override - public Object invokeImpl(Object proxy, Method method, Object[] args) throws - SentryUserException { - Object result = null; - try { - if (!method.isAccessible()) { - method.setAccessible(true); - } - // The client is initialized in the first call instead of constructor. - // This way we can propagate the connection exception to caller cleanly - if (client == null) { - renewSentryClient(); - } - result = method.invoke(client, args); - } catch (IllegalAccessException e) { - throw new SentryUserException(e.getMessage(), e.getCause()); - } catch (InvocationTargetException e) { - if (e.getTargetException() instanceof SentryUserException) { - throw (SentryUserException)e.getTargetException(); - } else { - LOGGER.warn(THRIFT_EXCEPTION_MESSAGE + ": Error in connect current" + - " service, will retry other service.", e); - if (client != null) { - client.close(); - client = null; - } - } - } catch (IOException e1) { - throw new SentryUserException("Error connecting to sentry service " - + e1.getMessage(), e1); - } - return result; - } - - // Retrieve the new connection endpoint from ZK and connect to new server - private void renewSentryClient() throws IOException { - try { - manager = new ServiceManager(HAContext.getHAContext(conf)); - } catch (Exception e1) { - throw new IOException("Failed to extract Sentry node info from zookeeper", e1); - } - - try { - while (true) { - currentServiceInstance = manager.getServiceInstance(); - if (currentServiceInstance == null) { - throw new IOException(SENTRY_HA_ERROR_MESSAGE); - } - InetSocketAddress serverAddress = - ServiceManager.convertServiceInstance(currentServiceInstance); - conf.set(ServiceConstants.ClientConfig.SERVER_RPC_ADDRESS, serverAddress.getHostName()); - conf.setInt(ServiceConstants.ClientConfig.SERVER_RPC_PORT, serverAddress.getPort()); - try { - client = new SentryPolicyServiceClientDefaultImpl(conf); - LOGGER.info("Sentry Client using server " + serverAddress.getHostName() + - ":" + serverAddress.getPort()); - break; - } catch (IOException e) { - manager.reportError(currentServiceInstance); - LOGGER.info("Transport exception while opening transport:", e, e.getMessage()); - } - } - } finally { - manager.close(); - } - } - - private void checkClientConf() { - if (conf.getBoolean(ServerConfig.SENTRY_HA_ZOOKEEPER_SECURITY, - ServerConfig.SENTRY_HA_ZOOKEEPER_SECURITY_DEFAULT)) { - String serverPrincipal = Preconditions.checkNotNull(conf.get(ServerConfig.PRINCIPAL), - ServerConfig.PRINCIPAL + " is required"); - Preconditions.checkArgument(serverPrincipal.contains(SecurityUtil.HOSTNAME_PATTERN), - ServerConfig.PRINCIPAL + " : " + serverPrincipal + " should contain " + SecurityUtil.HOSTNAME_PATTERN); - } - } - - @Override - public void close() { - if (client != null) { - client.close(); - } - } -} http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/LeaderStatus.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/LeaderStatus.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/LeaderStatus.java new file mode 100644 index 0000000..e846766 --- /dev/null +++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/LeaderStatus.java @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sentry.service.thrift; + +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; + +import java.io.Closeable; +import java.io.IOException; +import java.security.SecureRandom; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.apache.sentry.service.thrift.ServiceConstants.ServerConfig.SENTRY_HA_ENABLED; +import static org.apache.sentry.service.thrift.ServiceConstants.ServerConfig.SENTRY_HA_ENABLED_DEFAULT; + +/** + * Determines the leadership status of the Sentry daemon. + * It handles both highly-available and non-highly-available configurations. + */ +final class LeaderStatus implements Closeable { + private static final Log LOG = LogFactory.getLog(LeaderStatus.class); + + /** + * Callback functions which are invoked when the leader status changes. + */ + interface Listener { + /** + * Attempt to become the leader. + * + * @throws Exception On error. If an exception is thrown, we will + * relinquish leadership. + */ + void becomeActive() throws Exception; + + /** + * Become the standby. All exceptions thrown from this function will + * be ignored. + */ + void becomeStandby(); + } + + /** + * The listener to invoke when our leadership status changes. + */ + private final Listener listener; + + /** + * The unique ID of this potential leader. + */ + private final String incarnationId; + + /** + * The LeaderStatusThread, or null if HA is disabled. + */ + private final LeaderStatusAdaptor leaderStatusAdaptor; + + /** + * True if this object has been closed.<p/> + * + * This is an AtomicBoolean so that multiple calls to close only result in one + * close action. + */ + private final AtomicBoolean closed = new AtomicBoolean(false); + + /** + * Generate a 128-bit random ID. + */ + static String generateIncarnationId() { + SecureRandom srand = new SecureRandom(); + byte[] buf = new byte[32]; + srand.nextBytes(buf); + return "sentry_" + Hex.encodeHexString(buf); + } + + LeaderStatus(Listener listener, Configuration conf) throws Exception { + this.listener = listener; + this.incarnationId = generateIncarnationId(); + boolean isHa = conf. + getBoolean(SENTRY_HA_ENABLED, SENTRY_HA_ENABLED_DEFAULT); + if (isHa) { + this.leaderStatusAdaptor = new LeaderStatusAdaptor(incarnationId, conf, listener); + } else { + LOG.info("LeaderStatus(incarnationId=" + incarnationId + + "): HA is disabled."); + this.leaderStatusAdaptor = null; + } + } + + public String getIncarnationId() { + return incarnationId; + } + + public void start() throws Exception { + if (this.leaderStatusAdaptor != null) { + this.leaderStatusAdaptor.start(); + } else { + this.listener.becomeActive(); + } + } + + @Override + public void close() throws IOException { + if (closed.compareAndSet(false, true)) { + if (leaderStatusAdaptor != null) { + // Shut down in the HA case. + leaderStatusAdaptor.close(); + } else { + // Shut down in the non-HA case. + try { + listener.becomeStandby(); + } catch (Throwable t) { + LOG.error("becomeStandby: " + incarnationId + + " threw an unexpected exception", t); + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/LeaderStatusAdaptor.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/LeaderStatusAdaptor.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/LeaderStatusAdaptor.java new file mode 100644 index 0000000..80a6571 --- /dev/null +++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/LeaderStatusAdaptor.java @@ -0,0 +1,170 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sentry.service.thrift; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.framework.recipes.leader.LeaderSelector; +import org.apache.curator.framework.recipes.leader.LeaderSelectorListenerAdapter; +import org.apache.curator.retry.ExponentialBackoffRetry; +import org.apache.hadoop.conf.Configuration; + +import java.io.Closeable; +import java.io.IOException; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +import static org.apache.sentry.service.thrift.ServiceConstants.ServerConfig.SENTRY_HA_ZOOKEEPER_QUORUM; +import static org.apache.sentry.service.thrift.ServiceConstants.ServerConfig.SENTRY_HA_ZOOKEEPER_QUORUM_DEFAULT; +import static org.apache.sentry.service.thrift.ServiceConstants.ServerConfig.SENTRY_HA_ZOOKEEPER_NAMESPACE; +import static org.apache.sentry.service.thrift.ServiceConstants.ServerConfig.SENTRY_HA_ZOOKEEPER_NAMESPACE_DEFAULT; + +/** + * Determines the leadership status of the Sentry daemon. + */ +final class LeaderStatusAdaptor + extends LeaderSelectorListenerAdapter implements Closeable { + private static final Log LOG = + LogFactory.getLog(LeaderStatusAdaptor.class); + + private final String LEADER_SELECTOR_SUFFIX = "leader"; + + /** + * The ZooKeeper path prefix to use. + */ + private final String zkNamespace; + + /** + * The Curator framework object. + */ + private final CuratorFramework framework; + + /** + * The listener which we should notify about HA state changes. + */ + private final LeaderStatus.Listener listener; + + /** + * The Curator LeaderSelector object. + */ + private final LeaderSelector leaderSelector; + + /** + * The lock which protects isActive. + */ + private final ReentrantLock lock = new ReentrantLock(); + + /** + * A condition variable which the takeLeadership function will wait on. + */ + private final Condition cond = lock.newCondition(); + + /** + * The number of times this incarnation has become the leader. + */ + private long becomeLeaderCount = 0; + + /** + * True only if this incarnation is currently active. + */ + private boolean isActive = false; + + LeaderStatusAdaptor(String incarnationId, Configuration conf, + LeaderStatus.Listener listener) { + this.zkNamespace = conf.get(SENTRY_HA_ZOOKEEPER_NAMESPACE, + SENTRY_HA_ZOOKEEPER_NAMESPACE_DEFAULT); + String zkServers = conf.get(SENTRY_HA_ZOOKEEPER_QUORUM, + SENTRY_HA_ZOOKEEPER_QUORUM_DEFAULT); + if ((zkServers == null) || (zkServers.trim().isEmpty())) { + throw new RuntimeException("You must configure some ZooKeeper " + + "servers via " + SENTRY_HA_ZOOKEEPER_QUORUM + " when enabling HA"); + } + this.framework = CuratorFrameworkFactory.newClient(zkServers, + new ExponentialBackoffRetry(1000, 3)); + this.framework.start(); + this.listener = listener; + this.leaderSelector = new LeaderSelector(this.framework, + this.zkNamespace + "/" + LEADER_SELECTOR_SUFFIX, this); + this.leaderSelector.setId(incarnationId); + this.leaderSelector.autoRequeue(); + LOG.info("Created LeaderStatusAdaptor(zkNamespace=" + zkNamespace + + ", incarnationId=" + incarnationId + + ", zkServers='" + zkServers + "')"); + } + + public void start() { + this.leaderSelector.start(); + } + + @Override + public void close() throws IOException { + leaderSelector.close(); + } + + /** + * @return true if this client is the current leader. + */ + public boolean isActive() { + lock.lock(); + try { + return isActive; + } finally { + lock.unlock(); + } + } + + /** + * Deactivate the current client, if it is active. + */ + public void deactivate() { + lock.lock(); + try { + if (isActive) { + isActive = false; + cond.signal(); + } + } finally { + lock.unlock(); + } + } + + @Override + public void takeLeadership(CuratorFramework client) throws Exception { + lock.lock(); + try { + isActive = true; + becomeLeaderCount++; + LOG.info("SentryLeaderSelectorClient: becoming active. " + + "becomeLeaderCount=" + becomeLeaderCount); + listener.becomeActive(); + while (isActive) { + cond.await(); + } + } finally { + isActive = false; + LOG.info("SentryLeaderSelectorClient: becoming standby"); + try { + listener.becomeStandby(); + } catch (Throwable t) { + LOG.error("becomeStandby threw unexpected exception", t); + } + lock.unlock(); + } + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryService.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryService.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryService.java index 6883bf4..809af06 100644 --- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryService.java +++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryService.java @@ -95,8 +95,9 @@ public class SentryService implements Callable { private SentryWebServer sentryWebServer; private long maxMessageSize; private final boolean isHA; - private boolean isActive; + private volatile boolean isActive = false; SentryMetrics sentryMetrics; + private final LeaderStatus leaderStatus; public SentryService(Configuration conf) { this.conf = conf; @@ -143,8 +144,6 @@ public class SentryService implements Callable { } isHA = conf.getBoolean(ServerConfig.SENTRY_HA_ENABLED, ServerConfig.SENTRY_HA_ENABLED_DEFAULT); - //setting isActive to true for now, until we have Sentry HA implemented - isActive = true; serviceExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() { private int count = 0; @@ -154,6 +153,25 @@ public class SentryService implements Callable { + (count++)); } }); + try { + leaderStatus = new LeaderStatus( + new LeaderStatus.Listener() { + @Override + public void becomeActive() throws Exception { + LOGGER.info("Activating " + leaderStatus.getIncarnationId()); + isActive = true; + } + + @Override + public void becomeStandby() { + LOGGER.info("Deactivating " + leaderStatus.getIncarnationId()); + isActive = false; + } + }, conf); + leaderStatus.start(); // TODO: move this into call? + } catch (Exception e) { + throw new RuntimeException(e); + } webServerPort = conf.getInt(ServerConfig.SENTRY_WEB_PORT, ServerConfig.SENTRY_WEB_PORT_DEFAULT); status = Status.NOT_STARTED; } @@ -289,6 +307,7 @@ public class SentryService implements Callable { public synchronized void stop() throws Exception{ MultiException exception = null; LOGGER.info("Attempting to stop..."); + leaderStatus.close(); if (isRunning()) { LOGGER.info("Attempting to stop sentry thrift service..."); try { http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceClientFactory.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceClientFactory.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceClientFactory.java index 48ee66a..56d774b 100644 --- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceClientFactory.java +++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceClientFactory.java @@ -32,21 +32,15 @@ public final class SentryServiceClientFactory { } public static SentryPolicyServiceClient create(Configuration conf) throws Exception { - boolean haEnabled = conf.getBoolean(ClientConfig.SERVER_HA_ENABLED, false); boolean pooled = conf.getBoolean(ClientConfig.SENTRY_POOL_ENABLED, false); if (pooled) { return (SentryPolicyServiceClient) Proxy .newProxyInstance(SentryPolicyServiceClientDefaultImpl.class.getClassLoader(), SentryPolicyServiceClientDefaultImpl.class.getInterfaces(), new PoolClientInvocationHandler(conf)); - } else if (haEnabled) { - return (SentryPolicyServiceClient) Proxy - .newProxyInstance(SentryPolicyServiceClientDefaultImpl.class.getClassLoader(), - SentryPolicyServiceClientDefaultImpl.class.getInterfaces(), - new HAClientInvocationHandler(conf)); } else { return new SentryPolicyServiceClientDefaultImpl(conf); } } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceClientPoolFactory.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceClientPoolFactory.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceClientPoolFactory.java index 3a38b24..afea78a 100644 --- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceClientPoolFactory.java +++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceClientPoolFactory.java @@ -18,15 +18,12 @@ package org.apache.sentry.service.thrift; -import java.lang.reflect.Proxy; - import org.apache.commons.pool2.BasePooledObjectFactory; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.apache.hadoop.conf.Configuration; import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient; import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClientDefaultImpl; -import org.apache.sentry.service.thrift.ServiceConstants.ClientConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,15 +45,7 @@ public class SentryServiceClientPoolFactory extends BasePooledObjectFactory<Sent @Override public SentryPolicyServiceClient create() throws Exception { LOGGER.debug("Creating Sentry Service Client..."); - boolean haEnabled = conf.getBoolean(ClientConfig.SERVER_HA_ENABLED, false); - if (haEnabled) { - return (SentryPolicyServiceClient) Proxy - .newProxyInstance(SentryPolicyServiceClientDefaultImpl.class.getClassLoader(), - SentryPolicyServiceClientDefaultImpl.class.getInterfaces(), - new HAClientInvocationHandler(conf)); - } else { - return new SentryPolicyServiceClientDefaultImpl(conf); - } + return new SentryPolicyServiceClientDefaultImpl(conf); } @Override http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/ServiceConstants.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/ServiceConstants.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/ServiceConstants.java index 32a4044..0ab8192 100644 --- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/ServiceConstants.java +++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/ServiceConstants.java @@ -115,13 +115,13 @@ public class ServiceConstants { public static final String SENTRY_HA_ZOOKEEPER_SECURITY = SENTRY_HA_ZK_PROPERTY_PREFIX + "security"; public static final boolean SENTRY_HA_ZOOKEEPER_SECURITY_DEFAULT = false; public static final String SENTRY_HA_ZOOKEEPER_QUORUM = SENTRY_HA_ZK_PROPERTY_PREFIX + "quorum"; - public static final String SENTRY_HA_ZOOKEEPER_QUORUM_DEFAULT = "localhost:2181"; + public static final String SENTRY_HA_ZOOKEEPER_QUORUM_DEFAULT = ""; public static final String SENTRY_HA_ZOOKEEPER_RETRIES_MAX_COUNT = SENTRY_HA_ZK_PROPERTY_PREFIX + "session.retries.max.count"; public static final int SENTRY_HA_ZOOKEEPER_RETRIES_MAX_COUNT_DEFAULT = 3; public static final String SENTRY_HA_ZOOKEEPER_SLEEP_BETWEEN_RETRIES_MS = SENTRY_HA_ZK_PROPERTY_PREFIX + "session.sleep.between.retries.ms"; public static final int SENTRY_HA_ZOOKEEPER_SLEEP_BETWEEN_RETRIES_MS_DEFAULT = 100; public static final String SENTRY_HA_ZOOKEEPER_NAMESPACE = SENTRY_HA_ZK_PROPERTY_PREFIX + "namespace"; - public static final String SENTRY_HA_ZOOKEEPER_NAMESPACE_DEFAULT = "sentry"; + public static final String SENTRY_HA_ZOOKEEPER_NAMESPACE_DEFAULT = "/sentry"; // principal and keytab for client to be able to connect to secure ZK. Needed for Sentry HA with secure ZK public static final String SERVER_HA_ZOOKEEPER_CLIENT_PRINCIPAL = "sentry.zookeeper.client.principal"; public static final String SERVER_HA_ZOOKEEPER_CLIENT_KEYTAB = "sentry.zookeeper.client.keytab"; @@ -200,8 +200,8 @@ public class ServiceConstants { public static final int SERVER_RPC_CONN_TIMEOUT_DEFAULT = 200000; // HA configuration - public static final String SERVER_HA_ENABLED = "sentry.ha.enabled"; - public static final boolean SERVER_HA_ENABLED_DEFAULT = ServerConfig.SENTRY_HA_ENABLED_DEFAULT; + public static final String SENTRY_HA_ENABLED = "sentry.ha.enabled"; + public static final boolean SENTRY_HA_ENABLED_DEFAULT = ServerConfig.SENTRY_HA_ENABLED_DEFAULT; public static final String SENTRY_HA_ZOOKEEPER_QUORUM = ServerConfig.SENTRY_HA_ZOOKEEPER_QUORUM; public static final String SERVER_HA_ZOOKEEPER_QUORUM_DEFAULT = ServerConfig.SENTRY_HA_ZOOKEEPER_QUORUM_DEFAULT; public static final String SENTRY_HA_ZOOKEEPER_NAMESPACE = ServerConfig.SENTRY_HA_ZOOKEEPER_NAMESPACE; http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryServiceDiscovery.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryServiceDiscovery.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryServiceDiscovery.java deleted file mode 100644 index 7cbcc11..0000000 --- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryServiceDiscovery.java +++ /dev/null @@ -1,123 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.sentry.provider.db.service.persistent; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import org.apache.hadoop.conf.Configuration; - -import org.apache.curator.test.TestingServer; -import org.apache.curator.x.discovery.ServiceInstance; -import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import static org.junit.Assert.assertEquals; - -public class TestSentryServiceDiscovery { - - private HAContext haContext; - private TestingServer server; - - @Before - public void setup() throws Exception { - server = new TestingServer(); - // HA conf - Configuration conf = new Configuration(false); - conf.set(ServerConfig.SENTRY_HA_ENABLED, "true"); - conf.set(ServerConfig.SENTRY_HA_ZOOKEEPER_NAMESPACE, "sentry-test"); - conf.set(ServerConfig.SENTRY_HA_ZOOKEEPER_QUORUM, server.getConnectString()); - haContext = HAContext.getHAContext(conf); - } - - @After - public void teardown() { - HAContext.clearServerContext(); - if (server != null) { - try { - server.stop(); - } catch (IOException e) { - } - } - } - - @Test - public void testRegisterOneService() throws Exception { - final String hostname = "localhost1"; - final Integer port = 123; - ServiceRegister register = new ServiceRegister(haContext); - register.regService(hostname, port); - ServiceManager manager = new ServiceManager(haContext); - ServiceInstance<Void> instance = manager.getServiceInstance(); - assertEquals("'hostname' doesn't match.", hostname, instance.getAddress()); - assertEquals("'port' doesn't match.", port, instance.getPort()); - } - - @Test - public void testRegisterMultiService() throws Exception { - - final String hostname1 = "localhost1"; - final Integer port1 = 123; - final String hostname2 = "localhost2"; - final Integer port2 = 456; - final String hostname3 = "localhost3"; - final Integer port3 = 789; - - Map<String, Integer> servicesMap = new HashMap<String, Integer>(); - servicesMap.put(hostname1, port1); - servicesMap.put(hostname2, port2); - servicesMap.put(hostname3, port3); - - ServiceRegister register1 = new ServiceRegister(haContext); - register1.regService(hostname1, port1); - ServiceRegister register2 = new ServiceRegister(haContext); - register2.regService(hostname2, port2); - ServiceRegister register3 = new ServiceRegister(haContext); - register3.regService(hostname3, port3); - - ServiceManager manager = new ServiceManager(haContext); - ServiceInstance<Void> instance = manager.getServiceInstance(); - assertEquals("'instance' doesn't match.", instance.getPort(), servicesMap.get(instance.getAddress())); - instance = manager.getServiceInstance(); - assertEquals("'instance' doesn't match.", instance.getPort(), servicesMap.get(instance.getAddress())); - instance = manager.getServiceInstance(); - assertEquals("'instance' doesn't match.", instance.getPort(), servicesMap.get(instance.getAddress())); - } - - @Test - public void testReportError() throws Exception { - final String hostname1 = "localhost1"; - final Integer port1 = 123; - - ServiceRegister register1 = new ServiceRegister(haContext); - register1.regService(hostname1, port1); - - ServiceManager manager = new ServiceManager(haContext); - ServiceInstance<Void> instance = manager.getServiceInstance(); - manager.reportError(instance); - // report twice, manager will not return temporarily - instance = manager.getServiceInstance(); - manager.reportError(instance); - instance = manager.getServiceInstance(); - assertEquals("'instance' should be null.", null, instance); - } - -} http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServerForHaWithoutKerberos.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServerForHaWithoutKerberos.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServerForHaWithoutKerberos.java deleted file mode 100644 index 6c78942..0000000 --- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServerForHaWithoutKerberos.java +++ /dev/null @@ -1,219 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless createRequired by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.sentry.provider.db.service.thrift; -import static org.junit.Assert.assertEquals; - -import java.util.HashSet; -import java.util.Set; - -import org.apache.sentry.core.common.ActiveRoleSet; -import org.apache.sentry.core.model.db.AccessConstants; -import org.apache.sentry.core.model.db.Database; -import org.apache.sentry.core.model.db.Server; -import org.apache.sentry.core.model.db.Table; -import org.apache.sentry.service.thrift.SentryServiceIntegrationBase; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; - -public class TestSentryServerForHaWithoutKerberos extends SentryServiceIntegrationBase { - - @BeforeClass - public static void setup() throws Exception { - kerberos = false; - haEnabled = true; - beforeSetup(); - setupConf(); - startSentryService(); - afterSetup(); - } - - @Test - public void testCreateRole() throws Exception { - String requestorUserName = ADMIN_USER; - Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); - setLocalGroupMapping(requestorUserName, requestorUserGroupNames); - writePolicyFile(); - String roleName = "admin_r"; - client.dropRoleIfExists(requestorUserName, roleName); - client.createRole(requestorUserName, roleName); - client.dropRole(requestorUserName, roleName); - } - - @Test - public void testQueryPushDown() throws Exception { - String requestorUserName = ADMIN_USER; - Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); - setLocalGroupMapping(requestorUserName, requestorUserGroupNames); - writePolicyFile(); - - String roleName1 = "admin_r1"; - String roleName2 = "admin_r2"; - - String group1 = "g1"; - String group2 = "g2"; - - client.dropRoleIfExists(requestorUserName, roleName1); - client.createRole(requestorUserName, roleName1); - client.grantRoleToGroup(requestorUserName, group1, roleName1); - - client.grantTablePrivilege(requestorUserName, roleName1, "server", "db1", "table1", "ALL"); - client.grantTablePrivilege(requestorUserName, roleName1, "server", "db1", "table2", "ALL"); - client.grantTablePrivilege(requestorUserName, roleName1, "server", "db2", "table3", "ALL"); - client.grantTablePrivilege(requestorUserName, roleName1, "server", "db2", "table4", "ALL"); - - - client.dropRoleIfExists(requestorUserName, roleName2); - client.createRole(requestorUserName, roleName2); - client.grantRoleToGroup(requestorUserName, group1, roleName2); - client.grantRoleToGroup(requestorUserName, group2, roleName2); - - client.grantTablePrivilege(requestorUserName, roleName2, "server", "db1", "table1", "ALL"); - client.grantTablePrivilege(requestorUserName, roleName2, "server", "db1", "table2", "ALL"); - client.grantTablePrivilege(requestorUserName, roleName2, "server", "db2", "table3", "ALL"); - client.grantTablePrivilege(requestorUserName, roleName2, "server", "db2", "table4", "ALL"); - client.grantTablePrivilege(requestorUserName, roleName2, "server", "db3", "table5", "ALL"); - - Set<TSentryPrivilege> listPrivilegesByRoleName = client.listPrivilegesByRoleName(requestorUserName, roleName2, Lists.newArrayList(new Server("server"), new Database("db1"))); - assertEquals("Privilege not assigned to role2 !!", 2, listPrivilegesByRoleName.size()); - - listPrivilegesByRoleName = client.listPrivilegesByRoleName(requestorUserName, roleName2, Lists.newArrayList(new Server("server"), new Database("db2"), new Table("table1"))); - assertEquals("Privilege not assigned to role2 !!", 0, listPrivilegesByRoleName.size()); - - listPrivilegesByRoleName = client.listPrivilegesByRoleName(requestorUserName, roleName2, Lists.newArrayList(new Server("server"), new Database("db1"), new Table("table1"))); - assertEquals("Privilege not assigned to role2 !!", 1, listPrivilegesByRoleName.size()); - - listPrivilegesByRoleName = client.listPrivilegesByRoleName(requestorUserName, roleName2, Lists.newArrayList(new Server("server"), new Database("db3"))); - assertEquals("Privilege not assigned to role2 !!", 1, listPrivilegesByRoleName.size()); - - Set<String> listPrivilegesForProvider = client.listPrivilegesForProvider(Sets.newHashSet(group1, group2), null, ActiveRoleSet.ALL, new Server("server"), new Database("db2")); - assertEquals("Privilege not correctly assigned to roles !!", - Sets.newHashSet("server=server->db=db2->table=table4->action=all", "server=server->db=db2->table=table3->action=all"), - listPrivilegesForProvider); - - listPrivilegesForProvider = client.listPrivilegesForProvider(Sets.newHashSet(group1, group2), null, ActiveRoleSet.ALL, new Server("server"), new Database("db3")); - assertEquals("Privilege not correctly assigned to roles !!", Sets.newHashSet("server=server->db=db3->table=table5->action=all"), listPrivilegesForProvider); - - listPrivilegesForProvider = client.listPrivilegesForProvider(Sets.newHashSet(group1, group2), null, new ActiveRoleSet(Sets.newHashSet(roleName1)), new Server("server"), new Database("db3")); - assertEquals("Privilege not correctly assigned to roles !!", Sets.newHashSet("server=+"), listPrivilegesForProvider); - - listPrivilegesForProvider = client.listPrivilegesForProvider(Sets.newHashSet(group1, group2), null, new ActiveRoleSet(Sets.newHashSet(roleName1)), new Server("server1")); - assertEquals("Privilege not correctly assigned to roles !!", new HashSet<String>(), listPrivilegesForProvider); - } - - - - /** - * Create role, add privileges and grant it to a group drop the role and - * verify the privileges are no longer visible recreate the role with same - * name and verify the privileges again. - * @throws Exception - */ - @Test - public void testDropRole() throws Exception { - String requestorUserName = ADMIN_USER; - Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); - setLocalGroupMapping(requestorUserName, requestorUserGroupNames); - writePolicyFile(); - String roleName = "admin_r"; - - // create role and add privileges - client.dropRoleIfExists(requestorUserName, roleName); - client.createRole(requestorUserName, roleName); - client.grantRoleToGroup(requestorUserName, ADMIN_GROUP, roleName); - client.grantDatabasePrivilege(requestorUserName, roleName, "server1", "db2", AccessConstants.ALL); - client.grantTablePrivilege(requestorUserName, roleName, "server1", "db3", "tab3", "ALL"); - assertEquals(2, client.listPrivilegesForProvider(requestorUserGroupNames, null, - ActiveRoleSet.ALL).size()); - - // drop role and verify privileges - client.dropRole(requestorUserName, roleName); - assertEquals(0, client.listPrivilegesForProvider(requestorUserGroupNames, null, - ActiveRoleSet.ALL).size()); - - // recreate the role - client.createRole(requestorUserName, roleName); - client.grantRoleToGroup(requestorUserName, ADMIN_GROUP, roleName); - assertEquals(0, client.listPrivilegesForProvider(requestorUserGroupNames, null, - ActiveRoleSet.ALL).size()); - - // grant different privileges and verify - client.grantDatabasePrivilege(requestorUserName, roleName, "server1", "db2", AccessConstants.ALL); - assertEquals(1, client.listPrivilegesForProvider(requestorUserGroupNames, null, - ActiveRoleSet.ALL).size()); - client.dropRole(requestorUserName, roleName); - assertEquals(0, client.listPrivilegesForProvider(requestorUserGroupNames, null, - ActiveRoleSet.ALL).size()); - assertEquals(0, client.listPrivilegesForProvider(requestorUserGroupNames, null, - ActiveRoleSet.ALL).size()); - } - - @Test - public void testDropRoleOnUser() throws Exception { - String requestorUserName = ADMIN_USER; - Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); - Set<String> requestorUserNames = Sets.newHashSet(ADMIN_USER); - setLocalGroupMapping(requestorUserName, requestorUserGroupNames); - writePolicyFile(); - String roleName = "admin_r"; - - // create role and add privileges - client.dropRoleIfExists(requestorUserName, roleName); - client.createRole(requestorUserName, roleName); - client.grantRoleToUser(requestorUserName, ADMIN_USER, roleName); - client.grantDatabasePrivilege(requestorUserName, roleName, "server1", "db2", AccessConstants.ALL); - client.grantTablePrivilege(requestorUserName, roleName, "server1", "db3", "tab3", "ALL"); - assertEquals(2, client.listPrivilegesForProvider(requestorUserGroupNames, requestorUserNames, - ActiveRoleSet.ALL).size()); - - // drop role and verify privileges - client.dropRole(requestorUserName, roleName); - assertEquals(0, client.listPrivilegesForProvider(requestorUserGroupNames, requestorUserNames, - ActiveRoleSet.ALL).size()); - - // recreate the role - client.createRole(requestorUserName, roleName); - client.grantRoleToGroup(requestorUserName, ADMIN_GROUP, roleName); - assertEquals(0, client.listPrivilegesForProvider(requestorUserGroupNames, requestorUserNames, - ActiveRoleSet.ALL).size()); - - // grant different privileges and verify - client.grantDatabasePrivilege(requestorUserName, roleName, "server1", "db2", AccessConstants.ALL); - assertEquals(1, client.listPrivilegesForProvider(requestorUserGroupNames, requestorUserNames, - ActiveRoleSet.ALL).size()); - client.dropRole(requestorUserName, roleName); - assertEquals(0, client.listPrivilegesForProvider(requestorUserGroupNames, requestorUserNames, - ActiveRoleSet.ALL).size()); - assertEquals(0, client.listPrivilegesForProvider(requestorUserGroupNames, requestorUserNames, - ActiveRoleSet.ALL).size()); - } - - /** - * Test that we are correctly substituting "_HOST" if/when needed. - * - * @throws Exception - */ - @Test - public void testHostSubstitution() throws Exception { - // We just need to ensure that we are able to correct connect to the server - connectToSentryService(); - } -} http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServerForPoolHAWithoutKerberos.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServerForPoolHAWithoutKerberos.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServerForPoolHAWithoutKerberos.java deleted file mode 100644 index 9ba7d23..0000000 --- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServerForPoolHAWithoutKerberos.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless createRequired by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.sentry.provider.db.service.thrift; - -import org.junit.BeforeClass; - -public class TestSentryServerForPoolHAWithoutKerberos extends TestSentryServerForHaWithoutKerberos { - - @BeforeClass - public static void setup() throws Exception { - kerberos = false; - haEnabled = true; - pooled = true; - beforeSetup(); - setupConf(); - startSentryService(); - afterSetup(); - } - -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceForHAWithKerberos.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceForHAWithKerberos.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceForHAWithKerberos.java deleted file mode 100644 index 813b30b..0000000 --- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceForHAWithKerberos.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.sentry.provider.db.service.thrift; - - -import java.io.File; -import java.util.Set; - -import org.apache.sentry.provider.file.PolicyFile; -import org.apache.sentry.service.thrift.SentryServiceIntegrationBase; -import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.google.common.collect.Sets; - -/** - * Test various kerberos related stuff on the SentryService side - */ -public class TestSentryServiceForHAWithKerberos extends SentryServiceIntegrationBase { - - @BeforeClass - public static void setup() throws Exception { - kerberos = true; - haEnabled = true; - SERVER_KERBEROS_NAME = "sentry/_HOST@" + REALM; - beforeSetup(); - setupConf(); - startSentryService(); - afterSetup(); - } - - @Override - @Before - public void before() throws Exception { - policyFilePath = new File(dbDir, "local_policy_file.ini"); - conf.set(ServerConfig.SENTRY_STORE_GROUP_MAPPING_RESOURCE, - policyFilePath.getPath()); - policyFile = new PolicyFile(); - connectToSentryService(); - } - - @Test - public void testCreateRole() throws Exception { - runTestAsSubject(new TestOperation(){ - @Override - public void runTestAsSubject() throws Exception { - String requestorUserName = ADMIN_USER; - Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP); - setLocalGroupMapping(requestorUserName, requestorUserGroupNames); - writePolicyFile(); - String roleName = "admin_r"; - client.dropRoleIfExists(requestorUserName, roleName); - client.createRole(requestorUserName, roleName); - client.dropRole(requestorUserName, roleName); - } - }); - } -} http://git-wip-us.apache.org/repos/asf/sentry/blob/5630fc5c/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceForPoolHAWithKerberos.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceForPoolHAWithKerberos.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceForPoolHAWithKerberos.java deleted file mode 100644 index acb906f..0000000 --- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceForPoolHAWithKerberos.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless createRequired by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.sentry.provider.db.service.thrift; - -import org.junit.BeforeClass; - -public class TestSentryServiceForPoolHAWithKerberos extends TestSentryServiceWithKerberos { - - @BeforeClass - public static void setup() throws Exception { - kerberos = true; - haEnabled = true; - pooled = true; - beforeSetup(); - setupConf(); - startSentryService(); - afterSetup(); - } - -} \ No newline at end of file
