diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionServerObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionServerObserver.java index 4f51d5b..9a31751 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionServerObserver.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseRegionServerObserver.java @@ -68,4 +68,12 @@ public class BaseRegionServerObserver implements RegionServerObserver { public void postRollBackMerge(ObserverContext ctx, HRegion regionA, HRegion regionB) throws IOException { } + @Override + public void preRollWALWriter(ObserverContext ctx) + throws IOException { } + + @Override + public void postRollWALWriter(ObserverContext ctx) + throws IOException { } + } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerObserver.java index df1018e..ed290ec 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerObserver.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/RegionServerObserver.java @@ -105,4 +105,19 @@ public interface RegionServerObserver extends Coprocessor { void postRollBackMerge(final ObserverContext ctx, final HRegion regionA, final HRegion regionB) throws IOException; + /** + * This will be called before rolling a region server WAL. + * @param ctx An instance of RegionServerCoprocessorEnvironment + * @throws IOException Signals that an I/O exception has occurred. + */ + void preRollWALWriter(final ObserverContext ctx) + throws IOException; + + /** + * This will be called after rolling a region server WAL. + * @param ctx An instance of RegionServerCoprocessorEnvironment + * @throws IOException Signals that an I/O exception has occurred. + */ + void postRollWALWriter(final ObserverContext ctx) + throws IOException; } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java index 2e7b022..a899bab 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java @@ -1409,6 +1409,7 @@ public class RSRpcServices implements HBaseRPCErrorHandler, try { checkOpen(); requestCount.increment(); + regionServer.getRegionServerCoprocessorHost().preRollWALWriter(); HLog wal = regionServer.getWAL(); byte[][] regionsToFlush = wal.rollWriter(true); RollWALWriterResponse.Builder builder = RollWALWriterResponse.newBuilder(); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerCoprocessorHost.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerCoprocessorHost.java index b37ed6f..51a1068 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerCoprocessorHost.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerCoprocessorHost.java @@ -218,6 +218,50 @@ public class RegionServerCoprocessorHost extends } } + public void preRollWALWriter() throws IOException { + ObserverContext ctx = null; + for (RegionServerEnvironment env : coprocessors) { + if (env.getInstance() instanceof RegionServerObserver) { + ctx = ObserverContext.createAndPrepare(env, ctx); + Thread currentThread = Thread.currentThread(); + ClassLoader cl = currentThread.getContextClassLoader(); + try { + currentThread.setContextClassLoader(env.getClassLoader()); + ((RegionServerObserver) env.getInstance()).preRollWALWriter(ctx); + } catch (Throwable e) { + handleCoprocessorThrowable(env, e); + } finally { + currentThread.setContextClassLoader(cl); + } + if (ctx.shouldComplete()) { + break; + } + } + } + } + + public void postRollWALWriter() throws IOException { + ObserverContext ctx = null; + for (RegionServerEnvironment env : coprocessors) { + if (env.getInstance() instanceof RegionServerObserver) { + ctx = ObserverContext.createAndPrepare(env, ctx); + Thread currentThread = Thread.currentThread(); + ClassLoader cl = currentThread.getContextClassLoader(); + try { + currentThread.setContextClassLoader(env.getClassLoader()); + ((RegionServerObserver) env.getInstance()).postRollWALWriter(ctx); + } catch (Throwable e) { + handleCoprocessorThrowable(env, e); + } finally { + currentThread.setContextClassLoader(cl); + } + if (ctx.shouldComplete()) { + break; + } + } + } + } + /** * Coprocessor environment extension providing access to region server * related services. diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java index b772223..0bb7f85 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java @@ -787,13 +787,19 @@ public class AccessController extends BaseRegionObserver if (env instanceof MasterCoprocessorEnvironment) { // if running on HMaster MasterCoprocessorEnvironment mEnv = (MasterCoprocessorEnvironment) env; + LOG.info("AccessController runing on master: " + + mEnv.getMasterServices().getServerName().getServerName()); zk = mEnv.getMasterServices().getZooKeeper(); - } else if (env instanceof RegionServerCoprocessorEnvironment) { + } else if (env instanceof RegionServerCoprocessorEnvironment) { RegionServerCoprocessorEnvironment rsEnv = (RegionServerCoprocessorEnvironment) env; + LOG.info("AccessController runing on region server: " + + rsEnv.getRegionServerServices().getServerName().getServerName()); zk = rsEnv.getRegionServerServices().getZooKeeper(); } else if (env instanceof RegionCoprocessorEnvironment) { // if running at region regionEnv = (RegionCoprocessorEnvironment) env; + LOG.info("AccessControler runing at region: " + + regionEnv.getRegion().getRegionNameAsString()); conf.addStringMap(regionEnv.getRegion().getTableDesc().getConfiguration()); zk = regionEnv.getRegionServerServices().getZooKeeper(); compatibleEarlyTermination = conf.getBoolean(AccessControlConstants.CF_ATTRIBUTE_EARLY_OUT, @@ -2157,4 +2163,15 @@ public class AccessController extends BaseRegionObserver @Override public void postRollBackMerge(ObserverContext ctx, HRegion regionA, HRegion regionB) throws IOException { } + + @Override + public void preRollWALWriter(ObserverContext ctx) + throws IOException { + requirePermission("preRollLogWriter", Permission.Action.ADMIN); + } + + @Override + public void postRollWALWriter(ObserverContext ctx) + throws IOException { + } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java index 6e79124..363da06 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java @@ -1787,6 +1787,20 @@ public class TestAccessController extends SecureTestUtil { } @Test + public void testRollWALWriter() throws Exception { + AccessTestAction action = new AccessTestAction() { + @Override + public Object run() throws Exception { + ACCESS_CONTROLLER.preRollWALWriter(ObserverContext.createAndPrepare(RSCP_ENV, null)); + return null; + } + }; + + verifyAllowed(action, SUPERUSER, USER_ADMIN); + verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE); + } + + @Test public void testOpenRegion() throws Exception { AccessTestAction action = new AccessTestAction() { @Override diff --git a/src/main/docbkx/security.xml b/src/main/docbkx/security.xml index 4797522..37756cf 100644 --- a/src/main/docbkx/security.xml +++ b/src/main/docbkx/security.xml @@ -727,6 +727,10 @@ Access control mechanisms are mature and fairly standardized in the relational d org.apache.hadoop.hbase.security.access.AccessController + hbase.coprocessor.regionserver.classes + org.apache.hadoop.hbase.security.access.AccessController + + hbase.coprocessor.region.classes org.apache.hadoop.hbase.security.token.TokenProvider, org.apache.hadoop.hbase.security.access.AccessController