diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterAndRegionObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterAndRegionObserver.java index 428840c..c99b1ea 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterAndRegionObserver.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterAndRegionObserver.java @@ -31,6 +31,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.backup.BackupType; import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.classification.InterfaceStability; import org.apache.hadoop.hbase.client.Admin; @@ -39,6 +40,7 @@ import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription; import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.Quotas; +import org.apache.hadoop.hbase.util.Pair; @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC) @InterfaceStability.Evolving @@ -435,6 +437,17 @@ public class BaseMasterAndRegionObserver extends BaseRegionObserver } @Override + public void preBackupTables(final ObserverContext ctx, + final BackupType type, final List tablesList) throws IOException { + } + + @Override + public void postBackupTables(final ObserverContext ctx, + final BackupType type, final List tablesList, final Pair pair) + throws IOException { + } + + @Override public void preBalance(ObserverContext ctx) 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 7da63bf..43abbba 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 @@ -31,6 +31,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.backup.BackupType; import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.classification.InterfaceStability; import org.apache.hadoop.hbase.client.Admin; @@ -39,6 +40,7 @@ import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription; import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.Quotas; +import org.apache.hadoop.hbase.util.Pair; @InterfaceAudience.LimitedPrivate({HBaseInterfaceAudience.COPROC, HBaseInterfaceAudience.CONFIG}) @InterfaceStability.Evolving @@ -438,6 +440,17 @@ public class BaseMasterObserver implements MasterObserver { } @Override + public void preBackupTables(final ObserverContext ctx, + final BackupType type, final List tablesList) throws IOException { + } + + @Override + public void postBackupTables(final ObserverContext ctx, + final BackupType type, final List tablesList, final Pair pair) + throws IOException { + } + + @Override public boolean preSetSplitOrMergeEnabled(final ObserverContext ctx, final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException { return false; 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 230f4ce..c7b3e48 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 @@ -31,6 +31,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.backup.BackupType; import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.classification.InterfaceStability; import org.apache.hadoop.hbase.client.Admin; @@ -39,6 +40,7 @@ import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription; import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.Quotas; +import org.apache.hadoop.hbase.util.Pair; /** * Defines coprocessor hooks for interacting with operations on the @@ -798,6 +800,26 @@ public interface MasterObserver extends Coprocessor { throws IOException; /** + * Called prior to backing up tables + * @param ctx the coprocessor instance's environment + * @param type the type of backup + * @param tablesList list of tables to backup + */ + void preBackupTables(final ObserverContext ctx, + final BackupType type, final List tablesList) throws IOException; + + /** + * Called after backing up tables + * @param ctx the coprocessor instance's environment + * @param type the type of backup + * @param tablesList list of tables to backup + * @param pair the pair of procedure Id and backup Id + */ + void postBackupTables(final ObserverContext ctx, + final BackupType type, final List tablesList, final Pair pair) + 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 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 53582cd..bb62652 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 @@ -34,6 +34,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.backup.BackupType; import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; @@ -45,6 +46,7 @@ import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription; import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.Quotas; +import org.apache.hadoop.hbase.util.Pair; /** * Provides the coprocessor framework and environment for master oriented @@ -772,6 +774,28 @@ public class MasterCoprocessorHost }); } + public boolean preBackupTables(final BackupType type, final List tablesList) + throws IOException { + return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + @Override + public void call(MasterObserver oserver, ObserverContext ctx) + throws IOException { + oserver.preBackupTables(ctx, type, tablesList); + } + }); + } + + public void postBackupTables(final BackupType type, final List tablesList, + final Pair pair) throws IOException { + execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + @Override + public void call(MasterObserver oserver, ObserverContext ctx) + throws IOException { + oserver.postBackupTables(ctx, type, tablesList, pair); + } + }); + } + public boolean preSetSplitOrMergeEnabled(final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException { return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { 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 930bfd6..143bc07 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 @@ -1062,9 +1062,22 @@ public class MasterRpcServices extends RSRpcServices for (HBaseProtos.TableName table : request.getTablesList()) { tablesList.add(ProtobufUtil.toTableName(table)); } - Pair pair = master.backupTables( - BackupType.valueOf(request.getType().name()), tablesList, request.getTargetRootDir(), - (int)request.getWorkers(), request.getBandwidth()); + BackupType type = BackupType.valueOf(request.getType().name()); + boolean bypass = false; + if (master.cpHost != null) { + bypass = master.cpHost.preBackupTables(type, tablesList); + } + Pair pair; + if (!bypass) { + pair = master.backupTables( + type, tablesList, request.getTargetRootDir(), + (int)request.getWorkers(), request.getBandwidth()); + } else { + pair = new Pair<>(-1L, ""); + } + if (master.cpHost != null) { + master.cpHost.postBackupTables(type, tablesList, pair); + } return response.setProcId(pair.getFirst()).setBackupId(pair.getSecond()).build(); } 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 f81ab8c..a8119e0 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 @@ -57,6 +57,7 @@ import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.Tag; import org.apache.hadoop.hbase.TagRewriteCell; import org.apache.hadoop.hbase.TagUtil; +import org.apache.hadoop.hbase.backup.BackupType; import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.Append; @@ -1259,6 +1260,18 @@ public class AccessController extends BaseMasterAndRegionObserver } @Override + public void preBackupTables(final ObserverContext ctx, + final BackupType type, final List tablesList) throws IOException { + requirePermission("backupTables", Action.ADMIN); + } + + @Override + public void postBackupTables(final ObserverContext ctx, + final BackupType type, final List tablesList, final Pair pair) + throws IOException { + } + + @Override public boolean preSetSplitOrMergeEnabled(final ObserverContext ctx, final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException { requirePermission("setSplitOrMergeEnabled", 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 6e2f8ed..64b6e2b 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 @@ -50,6 +50,7 @@ import org.apache.hadoop.hbase.Tag; import org.apache.hadoop.hbase.TagRewriteCell; import org.apache.hadoop.hbase.TagType; import org.apache.hadoop.hbase.TagUtil; +import org.apache.hadoop.hbase.backup.BackupType; import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.Append; @@ -103,6 +104,7 @@ import org.apache.hadoop.hbase.security.AccessDeniedException; import org.apache.hadoop.hbase.security.Superusers; import org.apache.hadoop.hbase.security.User; import org.apache.hadoop.hbase.security.access.AccessController; +import org.apache.hadoop.hbase.security.access.Permission.Action; import org.apache.hadoop.hbase.util.ByteStringer; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Pair; @@ -309,6 +311,17 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements } @Override + public void preBackupTables(final ObserverContext ctx, + final BackupType type, final List tablesList) throws IOException { + } + + @Override + public void postBackupTables(final ObserverContext ctx, + final BackupType type, final List tablesList, final Pair pair) + throws IOException { + } + + @Override public boolean preSetSplitOrMergeEnabled(final ObserverContext ctx, final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException { return false; 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 5b0d202..d7c7fb9 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 @@ -44,6 +44,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.backup.BackupType; import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client.ConnectionFactory; @@ -64,9 +65,11 @@ import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescripto import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableNamesRequest; import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.Quotas; import org.apache.hadoop.hbase.regionserver.HRegionServer; +import org.apache.hadoop.hbase.security.access.Permission.Action; import org.apache.hadoop.hbase.testclassification.CoprocessorTests; import org.apache.hadoop.hbase.testclassification.MediumTests; import org.apache.hadoop.hbase.util.Bytes; +import org.apache.hadoop.hbase.util.Pair; import org.apache.hadoop.hbase.util.Threads; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -345,6 +348,17 @@ public class TestMasterObserver { } @Override + public void preBackupTables(final ObserverContext ctx, + final BackupType type, final List tablesList) throws IOException { + } + + @Override + public void postBackupTables(final ObserverContext ctx, + final BackupType type, final List tablesList, final Pair pair) + throws IOException { + } + + @Override public boolean preSetSplitOrMergeEnabled(final ObserverContext ctx, final boolean newValue, final Admin.MasterSwitchType switchType) throws IOException { return false; 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 7317abb..a772141 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 @@ -57,6 +57,7 @@ import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.TableNotFoundException; import org.apache.hadoop.hbase.Tag; import org.apache.hadoop.hbase.ArrayBackedTag; +import org.apache.hadoop.hbase.backup.BackupType; import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.Append; import org.apache.hadoop.hbase.client.Connection; @@ -723,6 +724,22 @@ public class TestAccessController extends SecureTestUtil { } @Test (timeout=180000) + public void testbackupTables() throws Exception { + AccessTestAction action = new AccessTestAction() { + @Override + public Object run() throws Exception { + ACCESS_CONTROLLER.preBackupTables(ObserverContext.createAndPrepare(CP_ENV, null), + BackupType.FULL, null); + 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