Repository: sentry Updated Branches: refs/heads/sentry-ha-redesign 2ce6bb275 -> 39c473c1f
SENTRY-1415: Provide a hook to stop the active sentry sevice. (Rahul Sharma, reviewed by Anne Yu). Project: http://git-wip-us.apache.org/repos/asf/sentry/repo Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/39c473c1 Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/39c473c1 Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/39c473c1 Branch: refs/heads/sentry-ha-redesign Commit: 39c473c1f47ae73a131bc3ab607d4400a4aabe54 Parents: 2ce6bb2 Author: Anne Yu <[email protected]> Authored: Thu Jul 28 15:11:59 2016 -0700 Committer: Anne Yu <[email protected]> Committed: Thu Jul 28 15:13:23 2016 -0700 ---------------------------------------------------------------------- .../apache/sentry/service/thrift/Activator.java | 9 +++ .../sentry/service/thrift/LeaderStatus.java | 20 +++++ .../sentry/service/thrift/SentryService.java | 35 +++++++++ .../db/service/thrift/TestActivator.java | 53 +++++++++++++ .../sentry/tests/e2e/ha/TestFailover.java | 81 ++++++++++++++++++++ 5 files changed, 198 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/sentry/blob/39c473c1/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/Activator.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/Activator.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/Activator.java index 730dbb1..a261d8d 100644 --- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/Activator.java +++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/Activator.java @@ -22,6 +22,7 @@ import java.io.Closeable; import java.io.IOException; import java.util.Properties; +import com.google.common.annotations.VisibleForTesting; import org.apache.hadoop.conf.Configuration; import org.apache.sentry.core.common.exception.SentryStandbyException; import org.apache.sentry.provider.db.service.persistent.Fencer; @@ -83,6 +84,14 @@ public class Activator implements Closeable { this.pmf.close(); } + /** + * Deactivates this activator. + */ + @VisibleForTesting + public void deactivate() throws IOException { + leaderStatus.becomeStandby(); + } + private class TransitionHandler implements LeaderStatus.Listener { @Override public void becomeActive() throws Exception { http://git-wip-us.apache.org/repos/asf/sentry/blob/39c473c1/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 index e32e1db..02ff7ff 100644 --- 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 @@ -16,6 +16,7 @@ */ package org.apache.sentry.service.thrift; +import com.google.common.annotations.VisibleForTesting; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; @@ -137,6 +138,25 @@ final class LeaderStatus implements Closeable { } } + /** + * Called by tests to force deactivate(standby) a daemon, + * so that another daemon becomes active. + * @throws IOException + */ + @VisibleForTesting + public void becomeStandby() throws IOException { + if (leaderStatusAdaptor != null) { + leaderStatusAdaptor.deactivate(); + } else { + try { + listener.becomeStandby(); + } catch (Throwable t) { + LOG.error("becomeStandby: " + incarnationId + + " threw an unexpected exception", t); + } + } + } + @Override public void close() throws IOException { if (closed.compareAndSet(false, true)) { http://git-wip-us.apache.org/repos/asf/sentry/blob/39c473c1/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 51dde0e..e93e5b4 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 @@ -38,6 +38,7 @@ import java.util.concurrent.ThreadFactory; import javax.security.auth.Subject; import com.codahale.metrics.Gauge; +import com.google.common.annotations.VisibleForTesting; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.GnuParser; @@ -324,6 +325,37 @@ public class SentryService implements Callable { LOGGER.info("Stopped..."); } + /** + * If the current daemon is active, make it standby. + */ + @VisibleForTesting + public synchronized void becomeStandby() throws Exception{ + try { + if(act.isActive()) { + LOGGER.info("Server with incarnation id: " + act.getIncarnationId() + + " becoming standby"); + act.deactivate(); + } + } catch (Exception e) { + LOGGER.error("Error while deactivating the active sentry daemon", e); + } + } + + /** + * If the current daemon is active, shutdown the server. + */ + @VisibleForTesting + public synchronized void shutdownActive() throws Exception{ + try { + if(act.isActive()) { + LOGGER.info("Stopping active server with incarnation id: " + act.getIncarnationId()); + stop(); + } + } catch (Exception e) { + LOGGER.error("Error while stopping the active sentry daemon", e); + } + } + // wait for the service thread to finish execution public synchronized void waitOnFuture() throws ExecutionException, InterruptedException { LOGGER.info("Waiting on future.get()"); @@ -442,6 +474,9 @@ public class SentryService implements Callable { return thriftServer.getEventHandler(); } + @VisibleForTesting + public Activator getActivator() {return act;} + public Gauge<Boolean> getIsActiveGauge() { return new Gauge<Boolean>() { @Override http://git-wip-us.apache.org/repos/asf/sentry/blob/39c473c1/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestActivator.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestActivator.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestActivator.java new file mode 100644 index 0000000..60cfc73 --- /dev/null +++ b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestActivator.java @@ -0,0 +1,53 @@ +/** + * 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 org.apache.sentry.service.thrift.SentryServiceIntegrationBase; +import org.junit.*; + +public class TestActivator extends SentryServiceIntegrationBase { + + @BeforeClass + public static void setup() throws Exception { + kerberos = false; + beforeSetup(); + setupConf(); + startSentryService(); + afterSetup(); + } + + @Override + @Before + public void before() throws Exception { + + } + + @Test + public void testStopActive() throws Exception { + Assert.assertEquals(Boolean.TRUE,server.getActivator().isActive()); + //stop the current service. + server.becomeStandby(); + Assert.assertEquals(Boolean.FALSE,server.getActivator().isActive()); + } + + @Override + @After + public void after() { + + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/39c473c1/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/ha/TestFailover.java ---------------------------------------------------------------------- diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/ha/TestFailover.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/ha/TestFailover.java new file mode 100644 index 0000000..57d579c --- /dev/null +++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/ha/TestFailover.java @@ -0,0 +1,81 @@ +/** + * 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.tests.e2e.ha; + +import org.apache.sentry.tests.e2e.hive.AbstractTestWithStaticConfiguration; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + + +/** + * End2End tests with Sentry service HA enabled. + */ +public class TestFailover extends AbstractTestWithStaticConfiguration { + + @BeforeClass + public static void setupTestStaticConfiguration() throws Exception { + useSentryService = true; + enableSentryHA = true; + clearDbPerTest = false; + AbstractTestWithStaticConfiguration.setupTestStaticConfiguration(); + } + + + /** + * Test service failover. Run Sentry operations with shutting down one or more + * of the services. + * @throws Exception + */ + @Test + public void testFailover() throws Exception { + int active = 0; + int passive = 1; + int maxTries = 10; + //get the active service + if (getSentrySrv().get(1).getActivator().isActive()) { + active = 1; + passive = 0; + } + + Assert.assertEquals(Boolean.TRUE,getSentrySrv().get(active).getActivator().isActive()); + Assert.assertEquals(Boolean.FALSE,getSentrySrv().get(passive).getActivator().isActive()); + + //stop the active service + getSentrySrv().get(active).becomeStandby(); + + for(int i = 0; i < maxTries ; i++) { + if(!getSentrySrv().get(active).getActivator().isActive()) { + break; + } + Thread.sleep(100); + } + //assert the active is now standby + Assert.assertEquals(Boolean.FALSE,getSentrySrv().get(active).getActivator().isActive()); + //wait for the passive to become active + for(int i = 0; i < maxTries ; i++) { + if(getSentrySrv().get(passive).getActivator().isActive()) { + break; + } + Thread.sleep(100); + } + //assert that the previously passive service is now active + Assert.assertEquals(Boolean.TRUE,getSentrySrv().get(passive).getActivator().isActive()); + } + +}
