You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by zg...@apache.org on 2017/05/18 09:51:12 UTC

[8/8] hbase git commit: HBASE-11013: Clone Snapshots on Secure Cluster Should provide option to apply Retained User Permissions

HBASE-11013: Clone Snapshots on Secure Cluster Should provide option to apply Retained User Permissions

Signed-off-by: Guanghao Zhang <zg...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/37dd8ff7
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/37dd8ff7
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/37dd8ff7

Branch: refs/heads/master
Commit: 37dd8ff722fa762d9ef86488dea90e5470672e67
Parents: 32d2062
Author: huzheng <op...@gmail.com>
Authored: Mon May 8 21:01:47 2017 +0800
Committer: Guanghao Zhang <zg...@apache.org>
Committed: Thu May 18 17:39:50 2017 +0800

----------------------------------------------------------------------
 .../org/apache/hadoop/hbase/client/Admin.java   |    30 +
 .../hadoop/hbase/client/AsyncHBaseAdmin.java    |     5 +-
 .../apache/hadoop/hbase/client/HBaseAdmin.java  |    55 +-
 .../access/ShadedAccessControlUtil.java         |   277 +
 .../hbase/security/access/TablePermission.java  |     4 +
 .../hbase/shaded/protobuf/ProtobufUtil.java     |    20 +-
 .../ClientSnapshotDescriptionUtils.java         |     5 +-
 .../protobuf/generated/AccessControlProtos.java | 11171 +++++++++++++++++
 .../shaded/protobuf/generated/AdminProtos.java  |     2 -
 .../shaded/protobuf/generated/HBaseProtos.java  |  1393 +-
 .../generated/MasterProcedureProtos.java        |   516 +-
 .../shaded/protobuf/generated/MasterProtos.java |  1191 +-
 .../protobuf/generated/SnapshotProtos.java      |  1585 ++-
 .../src/main/protobuf/AccessControl.proto       |   130 +
 .../src/main/protobuf/HBase.proto               |    17 +-
 .../src/main/protobuf/Master.proto              |     2 +
 .../src/main/protobuf/MasterProcedure.proto     |     3 +
 .../src/main/protobuf/Snapshot.proto            |    19 +
 .../hbase/rsgroup/RSGroupAdminEndpoint.java     |     4 +-
 .../hadoop/hbase/backup/util/RestoreTool.java   |     4 +-
 .../hbase/coprocessor/MasterObserver.java       |     2 +-
 .../mapreduce/TableSnapshotInputFormatImpl.java |     2 +-
 .../org/apache/hadoop/hbase/master/HMaster.java |     7 +-
 .../hbase/master/MasterCoprocessorHost.java     |     2 +-
 .../hadoop/hbase/master/MasterRpcServices.java  |     6 +-
 .../hadoop/hbase/master/SnapshotSentinel.java   |     2 +-
 .../procedure/CloneSnapshotProcedure.java       |    24 +-
 .../procedure/RestoreSnapshotProcedure.java     |    25 +-
 .../snapshot/DisabledTableSnapshotHandler.java  |     2 +-
 .../snapshot/EnabledTableSnapshotHandler.java   |     2 +-
 .../master/snapshot/MasterSnapshotVerifier.java |     2 +-
 .../hbase/master/snapshot/SnapshotManager.java  |    46 +-
 .../master/snapshot/TakeSnapshotHandler.java    |     2 +-
 .../hadoop/hbase/regionserver/HRegion.java      |     2 +-
 .../snapshot/FlushSnapshotSubprocedure.java     |     2 +-
 .../snapshot/RegionServerSnapshotManager.java   |     2 +-
 .../security/access/AccessControlLists.java     |     2 +-
 .../hbase/security/access/AccessController.java |     2 +-
 .../hadoop/hbase/snapshot/ExportSnapshot.java   |     2 +-
 .../hbase/snapshot/RestoreSnapshotHelper.java   |    29 +-
 .../snapshot/SnapshotDescriptionUtils.java      |    44 +-
 .../hadoop/hbase/snapshot/SnapshotInfo.java     |    21 +-
 .../hadoop/hbase/snapshot/SnapshotManifest.java |     2 +-
 .../hbase/snapshot/SnapshotManifestV1.java      |     2 +-
 .../hbase/snapshot/SnapshotManifestV2.java      |     4 +-
 .../hbase/snapshot/SnapshotReferenceUtil.java   |     2 +-
 .../hbase-webapps/master/snapshotsStats.jsp     |     5 +-
 .../hbase/client/TestSnapshotWithAcl.java       |   240 +
 .../hbase/coprocessor/TestMasterObserver.java   |     2 +-
 .../master/cleaner/TestSnapshotFromMaster.java  |     2 +-
 .../procedure/TestCloneSnapshotProcedure.java   |    13 +-
 .../procedure/TestRestoreSnapshotProcedure.java |     3 +-
 .../hbase/security/access/SecureTestUtil.java   |     2 +-
 .../security/access/TestAccessController.java   |     3 +-
 .../access/TestWithDisabledAuthorization.java   |     2 +-
 .../hbase/snapshot/SnapshotTestingUtils.java    |    34 +-
 .../hbase/snapshot/TestExportSnapshot.java      |     2 +-
 .../snapshot/TestFlushSnapshotFromClient.java   |     5 +-
 .../snapshot/TestRestoreSnapshotHelper.java     |     2 +-
 .../snapshot/TestSnapshotClientRetries.java     |     2 +-
 .../snapshot/TestSnapshotDescriptionUtils.java  |     4 +-
 .../hbase/snapshot/TestSnapshotManifest.java    |     2 +-
 hbase-shell/src/main/ruby/hbase/admin.rb        |    10 +-
 hbase-shell/src/main/ruby/hbase_constants.rb    |     1 +
 .../main/ruby/shell/commands/clone_snapshot.rb  |    11 +-
 .../ruby/shell/commands/restore_snapshot.rb     |    10 +-
 .../hbase/client/TestReplicationShell.java      |     1 -
 67 files changed, 14677 insertions(+), 2352 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/37dd8ff7/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java
index 6e7c566..9300372 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java
@@ -1521,6 +1521,23 @@ public interface Admin extends Abortable, Closeable {
       throws IOException, RestoreSnapshotException;
 
   /**
+   * Restore the specified snapshot on the original table. (The table must be disabled) If
+   * 'takeFailSafeSnapshot' is set to true, a snapshot of the current table is taken before
+   * executing the restore operation. In case of restore failure, the failsafe snapshot will be
+   * restored. If the restore completes without problem the failsafe snapshot is deleted. The
+   * failsafe snapshot name is configurable by using the property
+   * "hbase.snapshot.restore.failsafe.name".
+   * @param snapshotName name of the snapshot to restore
+   * @param takeFailSafeSnapshot true if the failsafe snapshot should be taken
+   * @param restoreAcl true to restore acl of snapshot
+   * @throws IOException if a remote or network exception occurs
+   * @throws RestoreSnapshotException if snapshot failed to be restored
+   * @throws IllegalArgumentException if the restore request is formatted incorrectly
+   */
+  void restoreSnapshot(final String snapshotName, final boolean takeFailSafeSnapshot,
+      final boolean restoreAcl) throws IOException, RestoreSnapshotException;
+
+  /**
    * Create a new table by cloning the snapshot content.
    *
    * @param snapshotName name of the snapshot to be cloned
@@ -1535,6 +1552,19 @@ public interface Admin extends Abortable, Closeable {
 
   /**
    * Create a new table by cloning the snapshot content.
+   * @param snapshotName name of the snapshot to be cloned
+   * @param tableName name of the table where the snapshot will be restored
+   * @param restoreAcl true to clone acl into newly created table
+   * @throws IOException if a remote or network exception occurs
+   * @throws TableExistsException if table to be created already exists
+   * @throws RestoreSnapshotException if snapshot failed to be cloned
+   * @throws IllegalArgumentException if the specified table has not a valid name
+   */
+  void cloneSnapshot(final String snapshotName, final TableName tableName, final boolean restoreAcl)
+      throws IOException, TableExistsException, RestoreSnapshotException;
+
+  /**
+   * Create a new table by cloning the snapshot content.
    *
    * @param snapshotName name of the snapshot to be cloned
    * @param tableName name of the table where the snapshot will be restored

http://git-wip-us.apache.org/repos/asf/hbase/blob/37dd8ff7/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java
index baad871..5e64fa3 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java
@@ -178,6 +178,7 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.Remov
 import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.RemoveReplicationPeerResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.UpdateReplicationPeerConfigRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.UpdateReplicationPeerConfigResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos;
 import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
 import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException;
 import org.apache.hadoop.hbase.snapshot.SnapshotCreationException;
@@ -1706,7 +1707,7 @@ public class AsyncHBaseAdmin implements AsyncAdmin {
 
   @Override
   public CompletableFuture<Void> snapshot(SnapshotDescription snapshotDesc) {
-    HBaseProtos.SnapshotDescription snapshot =
+    SnapshotProtos.SnapshotDescription snapshot =
         ProtobufUtil.createHBaseProtosSnapshotDesc(snapshotDesc);
     try {
       ClientSnapshotDescriptionUtils.assertSnapshotRequestIsValid(snapshot);
@@ -1916,7 +1917,7 @@ public class AsyncHBaseAdmin implements AsyncAdmin {
 
   private CompletableFuture<Void> internalRestoreSnapshot(String snapshotName,
       TableName tableName) {
-    HBaseProtos.SnapshotDescription snapshot = HBaseProtos.SnapshotDescription.newBuilder()
+    SnapshotProtos.SnapshotDescription snapshot = SnapshotProtos.SnapshotDescription.newBuilder()
         .setName(snapshotName).setTable(tableName.getNameAsString()).build();
     try {
       ClientSnapshotDescriptionUtils.assertSnapshotRequestIsValid(snapshot);

http://git-wip-us.apache.org/repos/asf/hbase/blob/37dd8ff7/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
index ca5f0d2..d9bd75e 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
@@ -107,7 +107,6 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.CoprocessorServiceRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.CoprocessorServiceResponse;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
-import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.NameStringPair;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.ProcedureDescription;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.TableSchema;
@@ -186,6 +185,7 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.UnassignRe
 import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.GetReplicationPeerConfigResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos;
 import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
 import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException;
 import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException;
@@ -2420,7 +2420,7 @@ public class HBaseAdmin implements Admin {
   public void snapshot(SnapshotDescription snapshotDesc)
       throws IOException, SnapshotCreationException, IllegalArgumentException {
     // actually take the snapshot
-    HBaseProtos.SnapshotDescription snapshot =
+    SnapshotProtos.SnapshotDescription snapshot =
       ProtobufUtil.createHBaseProtosSnapshotDesc(snapshotDesc);
     SnapshotResponse response = asyncSnapshot(snapshot);
     final IsSnapshotDoneRequest request =
@@ -2466,7 +2466,7 @@ public class HBaseAdmin implements Admin {
     asyncSnapshot(ProtobufUtil.createHBaseProtosSnapshotDesc(snapshotDesc));
   }
 
-  private SnapshotResponse asyncSnapshot(HBaseProtos.SnapshotDescription snapshot)
+  private SnapshotResponse asyncSnapshot(SnapshotProtos.SnapshotDescription snapshot)
       throws IOException {
     ClientSnapshotDescriptionUtils.assertSnapshotRequestIsValid(snapshot);
     final SnapshotRequest request = SnapshotRequest.newBuilder().setSnapshot(snapshot)
@@ -2484,7 +2484,7 @@ public class HBaseAdmin implements Admin {
   @Override
   public boolean isSnapshotFinished(final SnapshotDescription snapshotDesc)
       throws IOException, HBaseSnapshotException, UnknownSnapshotException {
-    final HBaseProtos.SnapshotDescription snapshot =
+    final SnapshotProtos.SnapshotDescription snapshot =
         ProtobufUtil.createHBaseProtosSnapshotDesc(snapshotDesc);
     return executeCallable(new MasterCallable<IsSnapshotDoneResponse>(getConnection(),
         getRpcControllerFactory()) {
@@ -2542,13 +2542,19 @@ public class HBaseAdmin implements Admin {
   }
 
   @Override
-  public void restoreSnapshot(final String snapshotName, final boolean takeFailSafeSnapshot)
+  public void restoreSnapshot(String snapshotName, boolean takeFailSafeSnapshot)
       throws IOException, RestoreSnapshotException {
+    restoreSnapshot(snapshotName, takeFailSafeSnapshot, false);
+  }
+
+  @Override
+  public void restoreSnapshot(final String snapshotName, final boolean takeFailSafeSnapshot,
+      final boolean restoreAcl) throws IOException, RestoreSnapshotException {
     TableName tableName = getTableNameBeforeRestoreSnapshot(snapshotName);
 
     // The table does not exists, switch to clone.
     if (!tableExists(tableName)) {
-      cloneSnapshot(snapshotName, tableName);
+      cloneSnapshot(snapshotName, tableName, restoreAcl);
       return;
     }
 
@@ -2573,7 +2579,7 @@ public class HBaseAdmin implements Admin {
     try {
       // Restore snapshot
       get(
-        internalRestoreSnapshotAsync(snapshotName, tableName),
+        internalRestoreSnapshotAsync(snapshotName, tableName, restoreAcl),
         syncWaitTimeout,
         TimeUnit.MILLISECONDS);
     } catch (IOException e) {
@@ -2582,7 +2588,7 @@ public class HBaseAdmin implements Admin {
       if (takeFailSafeSnapshot) {
         try {
           get(
-            internalRestoreSnapshotAsync(failSafeSnapshotSnapshotName, tableName),
+            internalRestoreSnapshotAsync(failSafeSnapshotSnapshotName, tableName, restoreAcl),
             syncWaitTimeout,
             TimeUnit.MILLISECONDS);
           String msg = "Restore snapshot=" + snapshotName +
@@ -2625,7 +2631,7 @@ public class HBaseAdmin implements Admin {
       throw new TableNotDisabledException(tableName);
     }
 
-    return internalRestoreSnapshotAsync(snapshotName, tableName);
+    return internalRestoreSnapshotAsync(snapshotName, tableName, false);
   }
 
   @Override
@@ -2635,24 +2641,30 @@ public class HBaseAdmin implements Admin {
   }
 
   @Override
-  public void cloneSnapshot(final String snapshotName, final TableName tableName)
+  public void cloneSnapshot(String snapshotName, TableName tableName, boolean restoreAcl)
       throws IOException, TableExistsException, RestoreSnapshotException {
     if (tableExists(tableName)) {
       throw new TableExistsException(tableName);
     }
     get(
-      internalRestoreSnapshotAsync(snapshotName, tableName),
+      internalRestoreSnapshotAsync(snapshotName, tableName, restoreAcl),
       Integer.MAX_VALUE,
       TimeUnit.MILLISECONDS);
   }
 
   @Override
+  public void cloneSnapshot(final String snapshotName, final TableName tableName)
+      throws IOException, TableExistsException, RestoreSnapshotException {
+    cloneSnapshot(snapshotName, tableName, false);
+  }
+
+  @Override
   public Future<Void> cloneSnapshotAsync(final String snapshotName, final TableName tableName)
       throws IOException, TableExistsException {
     if (tableExists(tableName)) {
       throw new TableExistsException(tableName);
     }
-    return internalRestoreSnapshotAsync(snapshotName, tableName);
+    return internalRestoreSnapshotAsync(snapshotName, tableName, false);
   }
 
   @Override
@@ -2740,10 +2752,10 @@ public class HBaseAdmin implements Admin {
    * @throws RestoreSnapshotException if snapshot failed to be restored
    * @throws IllegalArgumentException if the restore request is formatted incorrectly
    */
-  private Future<Void> internalRestoreSnapshotAsync(
-      final String snapshotName,
-      final TableName tableName) throws IOException, RestoreSnapshotException {
-    final HBaseProtos.SnapshotDescription snapshot = HBaseProtos.SnapshotDescription.newBuilder()
+  private Future<Void> internalRestoreSnapshotAsync(final String snapshotName,
+      final TableName tableName, final boolean restoreAcl)
+      throws IOException, RestoreSnapshotException {
+    final SnapshotProtos.SnapshotDescription snapshot = SnapshotProtos.SnapshotDescription.newBuilder()
         .setName(snapshotName).setTable(tableName.getNameAsString()).build();
 
     // actually restore the snapshot
@@ -2757,6 +2769,7 @@ public class HBaseAdmin implements Admin {
             .setSnapshot(snapshot)
             .setNonceGroup(ng.getNonceGroup())
             .setNonce(ng.newNonce())
+            .setRestoreACL(restoreAcl)
             .build();
         return master.restoreSnapshot(getRpcController(), request);
       }
@@ -2768,7 +2781,7 @@ public class HBaseAdmin implements Admin {
   private static class RestoreSnapshotFuture extends TableFuture<Void> {
     public RestoreSnapshotFuture(
         final HBaseAdmin admin,
-        final HBaseProtos.SnapshotDescription snapshot,
+        final SnapshotProtos.SnapshotDescription snapshot,
         final TableName tableName,
         final RestoreSnapshotResponse response) {
       super(admin, tableName,
@@ -2798,12 +2811,12 @@ public class HBaseAdmin implements Admin {
         getRpcControllerFactory()) {
       @Override
       protected List<SnapshotDescription> rpcCall() throws Exception {
-        List<HBaseProtos.SnapshotDescription> snapshotsList = master
+        List<SnapshotProtos.SnapshotDescription> snapshotsList = master
             .getCompletedSnapshots(getRpcController(),
                 GetCompletedSnapshotsRequest.newBuilder().build())
             .getSnapshotsList();
         List<SnapshotDescription> result = new ArrayList<>(snapshotsList.size());
-        for (HBaseProtos.SnapshotDescription snapshot : snapshotsList) {
+        for (SnapshotProtos.SnapshotDescription snapshot : snapshotsList) {
           result.add(ProtobufUtil.createSnapshotDesc(snapshot));
         }
         return result;
@@ -2866,7 +2879,7 @@ public class HBaseAdmin implements Admin {
       protected Void rpcCall() throws Exception {
         master.deleteSnapshot(getRpcController(),
           DeleteSnapshotRequest.newBuilder().setSnapshot(
-                HBaseProtos.SnapshotDescription.newBuilder().setName(snapshotName).build())
+                SnapshotProtos.SnapshotDescription.newBuilder().setName(snapshotName).build())
               .build()
         );
         return null;
@@ -4122,7 +4135,7 @@ public class HBaseAdmin implements Admin {
   /**
    * Decide whether the table need replicate to the peer cluster according to the peer config
    * @param table name of the table
-   * @param peerConfig config for the peer
+   * @param peer config for the peer
    * @return true if the table need replicate to the peer cluster
    */
   private boolean needToReplicate(TableName table, ReplicationPeerDescription peer) {

http://git-wip-us.apache.org/repos/asf/hbase/blob/37dd8ff7/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/ShadedAccessControlUtil.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/ShadedAccessControlUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/ShadedAccessControlUtil.java
new file mode 100644
index 0000000..03798ad
--- /dev/null
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/ShadedAccessControlUtil.java
@@ -0,0 +1,277 @@
+/*
+ * 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.hadoop.hbase.security.access;
+
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ListMultimap;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
+import org.apache.hadoop.hbase.security.access.Permission.Action;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
+import org.apache.hadoop.hbase.shaded.com.google.protobuf.ByteString;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Convert protobuf objects in AccessControl.proto under hbase-protocol-shaded to user-oriented
+ * objects and vice versa. <br>
+ *
+ * In HBASE-15638, we create a hbase-protocol-shaded module for upgrading protobuf version to 3.x,
+ * but there are still some coprocessor endpoints(such as AccessControl, Authentication,
+ * MulitRowMutation) which depend on hbase-protocol module for CPEP compatibility. In fact, we use
+ * PB objects in AccessControl.proto under hbase-protocol for access control logic and use shaded
+ * AccessControl.proto only for serializing/deserializing permissions of .snapshotinfo.
+ */
+@InterfaceAudience.Private
+public class ShadedAccessControlUtil {
+
+  /**
+   * Convert a client user permission to a user permission shaded proto.
+   */
+  public static
+      org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action
+      toPermissionAction(Permission.Action action) {
+    switch (action) {
+    case READ:
+      return org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action.READ;
+    case WRITE:
+      return org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action.WRITE;
+    case EXEC:
+      return org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action.EXEC;
+    case CREATE:
+      return org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action.CREATE;
+    case ADMIN:
+      return org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action.ADMIN;
+    }
+    throw new IllegalArgumentException("Unknown action value " + action.name());
+  }
+
+  /**
+   * Convert a Permission.Action shaded proto to a client Permission.Action object.
+   */
+  public static Permission.Action toPermissionAction(
+      org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action action) {
+    switch (action) {
+    case READ:
+      return Permission.Action.READ;
+    case WRITE:
+      return Permission.Action.WRITE;
+    case EXEC:
+      return Permission.Action.EXEC;
+    case CREATE:
+      return Permission.Action.CREATE;
+    case ADMIN:
+      return Permission.Action.ADMIN;
+    }
+    throw new IllegalArgumentException("Unknown action value " + action.name());
+  }
+
+  /**
+   * Converts a list of Permission.Action shaded proto to a list of client Permission.Action
+   * objects.
+   * @param protoActions the list of shaded protobuf Actions
+   * @return the converted list of Actions
+   */
+  public static List<Permission.Action> toPermissionActions(
+      List<org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action> protoActions) {
+    List<Permission.Action> actions = new ArrayList<>(protoActions.size());
+    for (org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action a : protoActions) {
+      actions.add(toPermissionAction(a));
+    }
+    return actions;
+  }
+
+  public static org.apache.hadoop.hbase.TableName toTableName(HBaseProtos.TableName tableNamePB) {
+    return org.apache.hadoop.hbase.TableName.valueOf(
+      tableNamePB.getNamespace().asReadOnlyByteBuffer(),
+      tableNamePB.getQualifier().asReadOnlyByteBuffer());
+  }
+
+  public static HBaseProtos.TableName toProtoTableName(TableName tableName) {
+    return HBaseProtos.TableName.newBuilder()
+        .setNamespace(ByteString.copyFrom(tableName.getNamespace()))
+        .setQualifier(ByteString.copyFrom(tableName.getQualifier())).build();
+  }
+
+  /**
+   * Converts a Permission shaded proto to a client TablePermission object.
+   * @param proto the protobuf Permission
+   * @return the converted TablePermission
+   */
+  public static TablePermission toTablePermission(AccessControlProtos.Permission proto) {
+
+    if (proto.getType() == AccessControlProtos.Permission.Type.Global) {
+      AccessControlProtos.GlobalPermission perm = proto.getGlobalPermission();
+      List<Action> actions = toPermissionActions(perm.getActionList());
+
+      return new TablePermission(null, null, null,
+          actions.toArray(new Permission.Action[actions.size()]));
+    }
+    if (proto.getType() == AccessControlProtos.Permission.Type.Namespace) {
+      AccessControlProtos.NamespacePermission perm = proto.getNamespacePermission();
+      List<Permission.Action> actions = toPermissionActions(perm.getActionList());
+
+      if (!proto.hasNamespacePermission()) {
+        throw new IllegalStateException("Namespace must not be empty in NamespacePermission");
+      }
+      String namespace = perm.getNamespaceName().toStringUtf8();
+      return new TablePermission(namespace, actions.toArray(new Permission.Action[actions.size()]));
+    }
+    if (proto.getType() == AccessControlProtos.Permission.Type.Table) {
+      AccessControlProtos.TablePermission perm = proto.getTablePermission();
+      List<Permission.Action> actions = toPermissionActions(perm.getActionList());
+
+      byte[] qualifier = null;
+      byte[] family = null;
+      TableName table = null;
+
+      if (!perm.hasTableName()) {
+        throw new IllegalStateException("TableName cannot be empty");
+      }
+      table = toTableName(perm.getTableName());
+
+      if (perm.hasFamily()) family = perm.getFamily().toByteArray();
+      if (perm.hasQualifier()) qualifier = perm.getQualifier().toByteArray();
+
+      return new TablePermission(table, family, qualifier,
+          actions.toArray(new Permission.Action[actions.size()]));
+    }
+    throw new IllegalStateException("Unrecognize Perm Type: " + proto.getType());
+  }
+
+  /**
+   * Convert a client Permission to a Permission shaded proto
+   * @param perm the client Permission
+   * @return the protobuf Permission
+   */
+  public static org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission
+      toPermission(Permission perm) {
+    org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Builder ret =
+        org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission
+            .newBuilder();
+    if (perm instanceof TablePermission) {
+      TablePermission tablePerm = (TablePermission) perm;
+      if (tablePerm.hasNamespace()) {
+        ret.setType(
+          org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Type.Namespace);
+
+        org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.NamespacePermission.Builder builder =
+            org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.NamespacePermission
+                .newBuilder();
+        builder.setNamespaceName(org.apache.hadoop.hbase.shaded.com.google.protobuf.ByteString
+            .copyFromUtf8(tablePerm.getNamespace()));
+        Permission.Action[] actions = perm.getActions();
+        if (actions != null) {
+          for (Permission.Action a : actions) {
+            builder.addAction(toPermissionAction(a));
+          }
+        }
+        ret.setNamespacePermission(builder);
+        return ret.build();
+      } else if (tablePerm.hasTable()) {
+        ret.setType(
+          org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Type.Table);
+
+        org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.TablePermission.Builder builder =
+            org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.TablePermission
+                .newBuilder();
+        builder.setTableName(toProtoTableName(tablePerm.getTableName()));
+        if (tablePerm.hasFamily()) {
+          builder.setFamily(ByteString.copyFrom(tablePerm.getFamily()));
+        }
+        if (tablePerm.hasQualifier()) {
+          builder.setQualifier(ByteString.copyFrom(tablePerm.getQualifier()));
+        }
+        Permission.Action actions[] = perm.getActions();
+        if (actions != null) {
+          for (Permission.Action a : actions) {
+            builder.addAction(toPermissionAction(a));
+          }
+        }
+        ret.setTablePermission(builder);
+        return ret.build();
+      }
+    }
+
+    ret.setType(
+      org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Type.Global);
+
+    org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GlobalPermission.Builder builder =
+        org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GlobalPermission
+            .newBuilder();
+    Permission.Action actions[] = perm.getActions();
+    if (actions != null) {
+      for (Permission.Action a : actions) {
+        builder.addAction(toPermissionAction(a));
+      }
+    }
+    ret.setGlobalPermission(builder);
+    return ret.build();
+  }
+
+  /**
+   * Convert a shaded protobuf UserTablePermissions to a ListMultimap&lt;String, TablePermission&gt;
+   * where key is username.
+   * @param proto the protobuf UserPermission
+   * @return the converted UserPermission
+   */
+  public static ListMultimap<String, TablePermission> toUserTablePermissions(
+      org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.UsersAndPermissions proto) {
+    ListMultimap<String, TablePermission> perms = ArrayListMultimap.create();
+    org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.UsersAndPermissions.UserPermissions userPerm;
+    for (int i = 0; i < proto.getUserPermissionsCount(); i++) {
+      userPerm = proto.getUserPermissions(i);
+      for (int j = 0; j < userPerm.getPermissionsCount(); j++) {
+        TablePermission tablePerm = toTablePermission(userPerm.getPermissions(j));
+        perms.put(userPerm.getUser().toStringUtf8(), tablePerm);
+      }
+    }
+    return perms;
+  }
+
+  /**
+   * Convert a ListMultimap&lt;String, TablePermission&gt; where key is username to a shaded
+   * protobuf UserPermission
+   * @param perm the list of user and table permissions
+   * @return the protobuf UserTablePermissions
+   */
+  public static
+      org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.UsersAndPermissions
+      toUserTablePermissions(ListMultimap<String, TablePermission> perm) {
+    org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.UsersAndPermissions.Builder builder =
+        org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.UsersAndPermissions
+            .newBuilder();
+    for (Map.Entry<String, Collection<TablePermission>> entry : perm.asMap().entrySet()) {
+      org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.UsersAndPermissions.UserPermissions.Builder userPermBuilder =
+          org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.UsersAndPermissions.UserPermissions
+              .newBuilder();
+      userPermBuilder.setUser(ByteString.copyFromUtf8(entry.getKey()));
+      for (TablePermission tablePerm : entry.getValue()) {
+        userPermBuilder.addPermissions(toPermission(tablePerm));
+      }
+      builder.addUserPermissions(userPermBuilder.build());
+    }
+    return builder.build();
+  }
+}

http://git-wip-us.apache.org/repos/asf/hbase/blob/37dd8ff7/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/TablePermission.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/TablePermission.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/TablePermission.java
index 4804b30..8e88a8c 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/TablePermission.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/TablePermission.java
@@ -155,6 +155,10 @@ public class TablePermission extends Permission {
     return table;
   }
 
+  public void setTableName(TableName table) {
+    this.table = table;
+  }
+
   public boolean hasFamily() {
     return family != null;
   }

http://git-wip-us.apache.org/repos/asf/hbase/blob/37dd8ff7/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java
index 2e62deb..f8ea0a5 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java
@@ -35,7 +35,6 @@ import java.util.NavigableSet;
 import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
 
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.Path;
@@ -164,6 +163,7 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos.Procedu
 import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerReportRequest;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.BulkLoadDescriptor;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.CompactionDescriptor;
@@ -2954,9 +2954,9 @@ public final class ProtobufUtil {
    * @param type the SnapshotDescription type
    * @return the protobuf SnapshotDescription type
    */
-  public static HBaseProtos.SnapshotDescription.Type
+  public static SnapshotProtos.SnapshotDescription.Type
       createProtosSnapShotDescType(SnapshotType type) {
-    return HBaseProtos.SnapshotDescription.Type.valueOf(type.name());
+    return SnapshotProtos.SnapshotDescription.Type.valueOf(type.name());
   }
 
   /**
@@ -2965,9 +2965,9 @@ public final class ProtobufUtil {
    * @param snapshotDesc string representing the snapshot description type
    * @return the protobuf SnapshotDescription type
    */
-  public static HBaseProtos.SnapshotDescription.Type
+  public static SnapshotProtos.SnapshotDescription.Type
       createProtosSnapShotDescType(String snapshotDesc) {
-    return HBaseProtos.SnapshotDescription.Type.valueOf(snapshotDesc.toUpperCase(Locale.ROOT));
+    return SnapshotProtos.SnapshotDescription.Type.valueOf(snapshotDesc.toUpperCase(Locale.ROOT));
   }
 
   /**
@@ -2976,7 +2976,7 @@ public final class ProtobufUtil {
    * @param type the snapshot description type
    * @return the protobuf SnapshotDescription type
    */
-  public static SnapshotType createSnapshotType(HBaseProtos.SnapshotDescription.Type type) {
+  public static SnapshotType createSnapshotType(SnapshotProtos.SnapshotDescription.Type type) {
     return SnapshotType.valueOf(type.toString());
   }
 
@@ -2986,9 +2986,9 @@ public final class ProtobufUtil {
    * @param snapshotDesc the POJO SnapshotDescription
    * @return the protobuf SnapshotDescription
    */
-  public static HBaseProtos.SnapshotDescription
+  public static SnapshotProtos.SnapshotDescription
       createHBaseProtosSnapshotDesc(SnapshotDescription snapshotDesc) {
-    HBaseProtos.SnapshotDescription.Builder builder = HBaseProtos.SnapshotDescription.newBuilder();
+    SnapshotProtos.SnapshotDescription.Builder builder = SnapshotProtos.SnapshotDescription.newBuilder();
     if (snapshotDesc.getTableName() != null) {
       builder.setTable(snapshotDesc.getTableNameAsString());
     }
@@ -3005,7 +3005,7 @@ public final class ProtobufUtil {
       builder.setVersion(snapshotDesc.getVersion());
     }
     builder.setType(ProtobufUtil.createProtosSnapShotDescType(snapshotDesc.getType()));
-    HBaseProtos.SnapshotDescription snapshot = builder.build();
+    SnapshotProtos.SnapshotDescription snapshot = builder.build();
     return snapshot;
   }
 
@@ -3017,7 +3017,7 @@ public final class ProtobufUtil {
    * @return the POJO SnapshotDescription
    */
   public static SnapshotDescription
-      createSnapshotDesc(HBaseProtos.SnapshotDescription snapshotDesc) {
+      createSnapshotDesc(SnapshotProtos.SnapshotDescription snapshotDesc) {
     return new SnapshotDescription(snapshotDesc.getName(),
         snapshotDesc.hasTable() ? TableName.valueOf(snapshotDesc.getTable()) : null,
         createSnapshotType(snapshotDesc.getType()), snapshotDesc.getOwner(),

http://git-wip-us.apache.org/repos/asf/hbase/blob/37dd8ff7/hbase-client/src/main/java/org/apache/hadoop/hbase/snapshot/ClientSnapshotDescriptionUtils.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/snapshot/ClientSnapshotDescriptionUtils.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/snapshot/ClientSnapshotDescriptionUtils.java
index 88b6bec..3e83f3e 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/snapshot/ClientSnapshotDescriptionUtils.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/snapshot/ClientSnapshotDescriptionUtils.java
@@ -22,6 +22,7 @@ package org.apache.hadoop.hbase.snapshot;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos;
 import org.apache.hadoop.hbase.util.Bytes;
 
 /**
@@ -36,7 +37,7 @@ public class ClientSnapshotDescriptionUtils {
    * @throws IllegalArgumentException if the name of the snapshot or the name of the table to
    *           snapshot are not valid names.
    */
-  public static void assertSnapshotRequestIsValid(HBaseProtos.SnapshotDescription snapshot)
+  public static void assertSnapshotRequestIsValid(SnapshotProtos.SnapshotDescription snapshot)
       throws IllegalArgumentException {
     // make sure the snapshot name is valid
     TableName.isLegalTableQualifierName(Bytes.toBytes(snapshot.getName()), true);
@@ -57,7 +58,7 @@ public class ClientSnapshotDescriptionUtils {
    * @param ssd
    * @return Single line string with a summary of the snapshot parameters
    */
-  public static String toString(HBaseProtos.SnapshotDescription ssd) {
+  public static String toString(SnapshotProtos.SnapshotDescription ssd) {
     if (ssd == null) {
       return null;
     }