diff --git a/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java b/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java index e51dcc2..22bad72 100644 --- a/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java +++ b/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java @@ -43,6 +43,7 @@ import org.apache.hadoop.hbase.NamespaceDescriptor; import org.apache.hadoop.hbase.ProcedureInfo; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.constraint.ConstraintException; import org.apache.hadoop.hbase.coprocessor.CoprocessorService; import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment; @@ -825,6 +826,17 @@ public class RSGroupAdminEndpoint extends RSGroupAdminService } @Override + public boolean preSetSplitOrMergeEnabled(final ObserverContext ctx, + final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException { + return false; + } + + @Override + public void postSetSplitOrMergeEnabled(final ObserverContext ctx, + final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException { + } + + @Override public void preSetUserQuota(ObserverContext ctx, String userName, Quotas quotas) throws IOException { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java index 0adb179..18c6a0a 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java @@ -36,6 +36,7 @@ import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.classification.InterfaceStability; +import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.master.RegionPlan; import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; @@ -440,6 +441,17 @@ public class BaseMasterObserver implements MasterObserver { } @Override + public boolean preSetSplitOrMergeEnabled(final ObserverContext ctx, + final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException { + return false; + } + + @Override + public void postSetSplitOrMergeEnabled(final ObserverContext ctx, + final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException { + } + + @Override public void preBalance(ObserverContext ctx) throws IOException { } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java index 82b6ffe..81f97aa 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java @@ -36,6 +36,7 @@ import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.classification.InterfaceStability; +import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.master.RegionPlan; import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; @@ -800,6 +801,24 @@ public interface MasterObserver extends Coprocessor { throws IOException; /** + * Called prior to setting split / merge switch + * @param ctx the coprocessor instance's environment + * @param newValue the new value submitted in the call + * @param switchType type of switch + */ + boolean preSetSplitOrMergeEnabled(final ObserverContext ctx, + final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException; + + /** + * Called after setting split / merge switch + * @param ctx the coprocessor instance's environment + * @param newValue the new value submitted in the call + * @param switchType type of switch + */ + void postSetSplitOrMergeEnabled(final ObserverContext ctx, + final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException; + + /** * Called prior to modifying the flag used to enable/disable region balancing. * @param ctx the coprocessor instance's environment * @param newValue the new flag value submitted in the call diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java index b16c232..313b1ad 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java @@ -38,6 +38,7 @@ import org.apache.hadoop.hbase.ProcedureInfo; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.classification.InterfaceAudience; +import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; import org.apache.hadoop.hbase.coprocessor.CoprocessorService; import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment; @@ -777,6 +778,28 @@ public class MasterCoprocessorHost }); } + public boolean preSetSplitOrMergeEnabled(final boolean newValue, + final Admin.MasterSwitchType switchType) throws IOException { + return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + @Override + public void call(MasterObserver oserver, ObserverContext ctx) + throws IOException { + oserver.preSetSplitOrMergeEnabled(ctx, newValue, switchType); + } + }); + } + + public void postSetSplitOrMergeEnabled(final boolean newValue, + final Admin.MasterSwitchType switchType) throws IOException { + execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + @Override + public void call(MasterObserver oserver, ObserverContext ctx) + throws IOException { + oserver.postSetSplitOrMergeEnabled(ctx, newValue, switchType); + } + }); + } + public boolean preBalanceSwitch(final boolean b) throws IOException { return execOperationWithResult(b, coprocessors.isEmpty() ? null : new CoprocessorOperationWithResult() { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java index 753ecb6..6a60c2c 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java @@ -1524,8 +1524,17 @@ public class MasterRpcServices extends RSRpcServices for (MasterSwitchType masterSwitchType : request.getSwitchTypesList()) { Admin.MasterSwitchType switchType = convert(masterSwitchType); boolean oldValue = master.isSplitOrMergeEnabled(switchType); - master.getSplitOrMergeTracker().setSplitOrMergeEnabled(newValue, switchType); response.addPrevValue(oldValue); + boolean bypass = false; + if (master.cpHost != null) { + bypass = master.cpHost.preSetSplitOrMergeEnabled(newValue, switchType); + } + if (!bypass) { + master.getSplitOrMergeTracker().setSplitOrMergeEnabled(newValue, switchType); + } + if (master.cpHost != null) { + master.cpHost.postSetSplitOrMergeEnabled(newValue, switchType); + } } } catch (IOException e) { throw new ServiceException(e); 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 0a88a86..3b36ada 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 @@ -60,6 +60,7 @@ import org.apache.hadoop.hbase.Tag; import org.apache.hadoop.hbase.TagRewriteCell; import org.apache.hadoop.hbase.TagUtil; import org.apache.hadoop.hbase.classification.InterfaceAudience; +import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.Append; import org.apache.hadoop.hbase.client.Delete; import org.apache.hadoop.hbase.client.Durability; @@ -1260,6 +1261,18 @@ public class AccessController extends BaseMasterAndRegionObserver } @Override + public boolean preSetSplitOrMergeEnabled(final ObserverContext ctx, + final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException { + requirePermission("setSplitOrMergeEnabled", Action.ADMIN); + return false; + } + + @Override + public void postSetSplitOrMergeEnabled(final ObserverContext ctx, + final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException { + } + + @Override public void preBalance(ObserverContext c) throws IOException { requirePermission("balance", Action.ADMIN); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java index 347f3da..6e2f8ed 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java @@ -51,6 +51,7 @@ import org.apache.hadoop.hbase.TagRewriteCell; import org.apache.hadoop.hbase.TagType; import org.apache.hadoop.hbase.TagUtil; import org.apache.hadoop.hbase.classification.InterfaceAudience; +import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.Append; import org.apache.hadoop.hbase.client.Delete; import org.apache.hadoop.hbase.client.Get; @@ -308,6 +309,17 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements } @Override + public boolean preSetSplitOrMergeEnabled(final ObserverContext ctx, + final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException { + return false; + } + + @Override + public void postSetSplitOrMergeEnabled(final ObserverContext ctx, + final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException { + } + + @Override public void preBatchMutate(ObserverContext c, MiniBatchOperationInProgress miniBatchOp) throws IOException { if (c.getEnvironment().getRegion().getRegionInfo().getTable().isSystemTable()) { diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java index 3810f1e..65fc0c3 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java @@ -347,6 +347,17 @@ public class TestMasterObserver { } @Override + public boolean preSetSplitOrMergeEnabled(final ObserverContext ctx, + final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException { + return false; + } + + @Override + public void postSetSplitOrMergeEnabled(final ObserverContext ctx, + final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException { + } + + @Override public void preModifyTable(ObserverContext env, TableName tableName, HTableDescriptor htd) throws IOException { if (bypass) { 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 66ea050..7b1454d 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 @@ -705,6 +705,22 @@ public class TestAccessController extends SecureTestUtil { } @Test (timeout=180000) + public void testSetSplitOrMergeEnabled() throws Exception { + AccessTestAction action = new AccessTestAction() { + @Override + public Object run() throws Exception { + ACCESS_CONTROLLER.preSetSplitOrMergeEnabled(ObserverContext.createAndPrepare(CP_ENV, null), + true, Admin.MasterSwitchType.MERGE); + return null; + } + }; + + verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); + verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, + USER_GROUP_WRITE, USER_GROUP_CREATE); + } + + @Test (timeout=180000) public void testBalance() throws Exception { AccessTestAction action = new AccessTestAction() { @Override