Skip to content

Commit 062a831

Browse files
mymeiyiApache9
authored andcommitted
HBASE-22776 Rename config names in user scan snapshot feature (apache#440)
1 parent 5ac33a7 commit 062a831

File tree

5 files changed

+570
-276
lines changed

5 files changed

+570
-276
lines changed

hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/SnapshotManager.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@
7070
import org.apache.hadoop.hbase.security.AccessDeniedException;
7171
import org.apache.hadoop.hbase.security.User;
7272
import org.apache.hadoop.hbase.security.access.AccessChecker;
73+
import org.apache.hadoop.hbase.security.access.SnapshotScannerHDFSAclCleaner;
74+
import org.apache.hadoop.hbase.security.access.SnapshotScannerHDFSAclHelper;
7375
import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
7476
import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException;
7577
import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException;
@@ -1140,6 +1142,10 @@ private void checkSnapshotSupport(final Configuration conf, final MasterFileSyst
11401142
// Inject snapshot cleaners, if snapshot.enable is true
11411143
hfileCleaners.add(SnapshotHFileCleaner.class.getName());
11421144
hfileCleaners.add(HFileLinkCleaner.class.getName());
1145+
// If sync acl to HDFS feature is enabled, then inject the cleaner
1146+
if (SnapshotScannerHDFSAclHelper.isAclSyncToHdfsEnabled(conf)) {
1147+
hfileCleaners.add(SnapshotScannerHDFSAclCleaner.class.getName());
1148+
}
11431149

11441150
// Set cleaners conf
11451151
conf.setStrings(HFileCleaner.MASTER_HFILE_CLEANER_PLUGINS,

hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/SnapshotScannerHDFSAclCleaner.java

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import org.apache.hadoop.hbase.HConstants;
2828
import org.apache.hadoop.hbase.MetaTableAccessor;
2929
import org.apache.hadoop.hbase.TableName;
30-
import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
3130
import org.apache.hadoop.hbase.master.HMaster;
3231
import org.apache.hadoop.hbase.master.cleaner.BaseHFileCleanerDelegate;
3332
import org.apache.yetus.audience.InterfaceAudience;
@@ -59,7 +58,7 @@ public void init(Map<String, Object> params) {
5958
@Override
6059
public void setConf(Configuration conf) {
6160
super.setConf(conf);
62-
userScanSnapshotEnabled = isUserScanSnapshotEnabled(conf);
61+
userScanSnapshotEnabled = SnapshotScannerHDFSAclHelper.isAclSyncToHdfsEnabled(conf);
6362
}
6463

6564
@Override
@@ -82,13 +81,6 @@ public boolean isEmptyDirDeletable(Path dir) {
8281
return true;
8382
}
8483

85-
private boolean isUserScanSnapshotEnabled(Configuration conf) {
86-
String masterCoprocessors = conf.get(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY);
87-
return conf.getBoolean(SnapshotScannerHDFSAclHelper.USER_SCAN_SNAPSHOT_ENABLE, false)
88-
&& masterCoprocessors.contains(SnapshotScannerHDFSAclController.class.getName())
89-
&& masterCoprocessors.contains(AccessController.class.getName());
90-
}
91-
9284
private boolean isEmptyArchiveDirDeletable(Path dir) {
9385
try {
9486
if (isArchiveDataDir(dir)) {

hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/SnapshotScannerHDFSAclController.java

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ public Optional<MasterObserver> getMasterObserver() {
119119
public void preMasterInitialization(ObserverContext<MasterCoprocessorEnvironment> c)
120120
throws IOException {
121121
if (c.getEnvironment().getConfiguration()
122-
.getBoolean(SnapshotScannerHDFSAclHelper.USER_SCAN_SNAPSHOT_ENABLE, false)) {
122+
.getBoolean(SnapshotScannerHDFSAclHelper.ACL_SYNC_TO_HDFS_ENABLE, false)) {
123123
MasterCoprocessorEnvironment mEnv = c.getEnvironment();
124124
if (!(mEnv instanceof HasMasterServices)) {
125125
throw new IOException("Does not implement HMasterServices");
@@ -133,7 +133,7 @@ public void preMasterInitialization(ObserverContext<MasterCoprocessorEnvironment
133133
userProvider = UserProvider.instantiate(c.getEnvironment().getConfiguration());
134134
} else {
135135
LOG.warn("Try to initialize the coprocessor SnapshotScannerHDFSAclController but failure "
136-
+ "because the config " + SnapshotScannerHDFSAclHelper.USER_SCAN_SNAPSHOT_ENABLE
136+
+ "because the config " + SnapshotScannerHDFSAclHelper.ACL_SYNC_TO_HDFS_ENABLE
137137
+ " is false.");
138138
}
139139
}
@@ -213,7 +213,9 @@ public void postCompletedSnapshotAction(ObserverContext<MasterCoprocessorEnviron
213213
public void postCompletedTruncateTableAction(ObserverContext<MasterCoprocessorEnvironment> c,
214214
TableName tableName) throws IOException {
215215
if (needHandleTableHdfsAcl(tableName, "truncateTable " + tableName)) {
216-
// Since the table directories is recreated, so add HDFS acls again
216+
// 1. create tmp table directories
217+
hdfsAclHelper.createTableDirectories(tableName);
218+
// 2. Since the table directories is recreated, so add HDFS acls again
217219
Set<String> users = hdfsAclHelper.getUsersWithTableReadAction(tableName, false, false);
218220
hdfsAclHelper.addTableAcl(tableName, users, "truncate");
219221
}
@@ -233,9 +235,11 @@ public void postDeleteTable(ObserverContext<MasterCoprocessorEnvironment> ctx,
233235
try (Table aclTable =
234236
ctx.getEnvironment().getConnection().getTable(PermissionStorage.ACL_TABLE_NAME)) {
235237
Set<String> users = SnapshotScannerHDFSAclStorage.getTableUsers(aclTable, tableName);
236-
// 1. Delete table owner permission is synced to HDFS in acl table
238+
// 1. Remove table archive directory default ACLs
239+
hdfsAclHelper.removeTableDefaultAcl(tableName, users);
240+
// 2. Delete table owner permission is synced to HDFS in acl table
237241
SnapshotScannerHDFSAclStorage.deleteTableHdfsAcl(aclTable, tableName);
238-
// 2. Remove namespace access acls
242+
// 3. Remove namespace access acls
239243
Set<String> removeUsers = filterUsersToRemoveNsAccessAcl(aclTable, tableName, users);
240244
if (removeUsers.size() > 0) {
241245
hdfsAclHelper.removeNamespaceAccessAcl(tableName, removeUsers, "delete");
@@ -251,7 +255,7 @@ public void postModifyTable(ObserverContext<MasterCoprocessorEnvironment> ctx,
251255
try (Table aclTable =
252256
ctx.getEnvironment().getConnection().getTable(PermissionStorage.ACL_TABLE_NAME)) {
253257
if (needHandleTableHdfsAcl(currentDescriptor, "modifyTable " + tableName)
254-
&& !hdfsAclHelper.isTableUserScanSnapshotEnabled(oldDescriptor)) {
258+
&& !hdfsAclHelper.isAclSyncToHdfsEnabled(oldDescriptor)) {
255259
// 1. Create table directories used for acl inherited
256260
hdfsAclHelper.createTableDirectories(tableName);
257261
// 2. Add table users HDFS acls
@@ -264,7 +268,7 @@ public void postModifyTable(ObserverContext<MasterCoprocessorEnvironment> ctx,
264268
SnapshotScannerHDFSAclStorage.addUserTableHdfsAcl(ctx.getEnvironment().getConnection(),
265269
tableUsers, tableName);
266270
} else if (needHandleTableHdfsAcl(oldDescriptor, "modifyTable " + tableName)
267-
&& !hdfsAclHelper.isTableUserScanSnapshotEnabled(currentDescriptor)) {
271+
&& !hdfsAclHelper.isAclSyncToHdfsEnabled(currentDescriptor)) {
268272
// 1. Remove empty table directories
269273
List<Path> tableRootPaths = hdfsAclHelper.getTableRootPaths(tableName, false);
270274
for (Path path : tableRootPaths) {
@@ -290,17 +294,24 @@ public void postModifyTable(ObserverContext<MasterCoprocessorEnvironment> ctx,
290294
public void postDeleteNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx,
291295
String namespace) throws IOException {
292296
if (checkInitialized("deleteNamespace " + namespace)) {
293-
// 1. Record namespace user acl is not synced to HDFS
294-
SnapshotScannerHDFSAclStorage.deleteNamespaceHdfsAcl(ctx.getEnvironment().getConnection(),
295-
namespace);
296-
// 2. Delete tmp namespace directory
297-
/**
298-
* Delete namespace tmp directory because it's created by this coprocessor when namespace is
299-
* created to make namespace default acl can be inherited by tables. The namespace data
300-
* directory is deleted by DeleteNamespaceProcedure, the namespace archive directory is
301-
* deleted by HFileCleaner.
302-
*/
303-
hdfsAclHelper.deleteEmptyDir(pathHelper.getTmpNsDir(namespace));
297+
try (Table aclTable =
298+
ctx.getEnvironment().getConnection().getTable(PermissionStorage.ACL_TABLE_NAME)) {
299+
// 1. Delete namespace archive dir default ACLs
300+
Set<String> users = SnapshotScannerHDFSAclStorage.getEntryUsers(aclTable,
301+
PermissionStorage.toNamespaceEntry(Bytes.toBytes(namespace)));
302+
hdfsAclHelper.removeNamespaceDefaultAcl(namespace, users);
303+
// 2. Record namespace user acl is not synced to HDFS
304+
SnapshotScannerHDFSAclStorage.deleteNamespaceHdfsAcl(ctx.getEnvironment().getConnection(),
305+
namespace);
306+
// 3. Delete tmp namespace directory
307+
/**
308+
* Delete namespace tmp directory because it's created by this coprocessor when namespace is
309+
* created to make namespace default acl can be inherited by tables. The namespace data
310+
* directory is deleted by DeleteNamespaceProcedure, the namespace archive directory is
311+
* deleted by HFileCleaner.
312+
*/
313+
hdfsAclHelper.deleteEmptyDir(pathHelper.getTmpNsDir(namespace));
314+
}
304315
}
305316
}
306317

@@ -364,7 +375,9 @@ public void postGrant(ObserverContext<MasterCoprocessorEnvironment> c,
364375
UserPermission tPerm = getUserTablePermission(conf, userName, tableName);
365376
if (tPerm != null && hdfsAclHelper.containReadAction(tPerm)) {
366377
if (!isHdfsAclSet(aclTable, userName, tableName)) {
367-
// 1. Add HDFS acl
378+
// 1. create table dirs
379+
hdfsAclHelper.createTableDirectories(tableName);
380+
// 2. Add HDFS acl
368381
hdfsAclHelper.grantAcl(userPermission, new HashSet<>(0), new HashSet<>(0));
369382
}
370383
// 2. Record table acl is synced to HDFS
@@ -547,13 +560,13 @@ private boolean needHandleTableHdfsAcl(TablePermission tablePermission) throws I
547560

548561
private boolean needHandleTableHdfsAcl(TableName tableName, String operation) throws IOException {
549562
return !tableName.isSystemTable() && checkInitialized(operation) && hdfsAclHelper
550-
.isTableUserScanSnapshotEnabled(masterServices.getTableDescriptors().get(tableName));
563+
.isAclSyncToHdfsEnabled(masterServices.getTableDescriptors().get(tableName));
551564
}
552565

553566
private boolean needHandleTableHdfsAcl(TableDescriptor tableDescriptor, String operation) {
554567
TableName tableName = tableDescriptor.getTableName();
555568
return !tableName.isSystemTable() && checkInitialized(operation)
556-
&& hdfsAclHelper.isTableUserScanSnapshotEnabled(tableDescriptor);
569+
&& hdfsAclHelper.isAclSyncToHdfsEnabled(tableDescriptor);
557570
}
558571

559572
private User getActiveUser(ObserverContext<?> ctx) throws IOException {

hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/SnapshotScannerHDFSAclHelper.java

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.io.FileNotFoundException;
2929
import java.io.IOException;
3030
import java.util.ArrayList;
31+
import java.util.Collections;
3132
import java.util.HashSet;
3233
import java.util.List;
3334
import java.util.Map;
@@ -52,6 +53,7 @@
5253
import org.apache.hadoop.hbase.client.Connection;
5354
import org.apache.hadoop.hbase.client.SnapshotDescription;
5455
import org.apache.hadoop.hbase.client.TableDescriptor;
56+
import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
5557
import org.apache.hadoop.hbase.mob.MobUtils;
5658
import org.apache.hadoop.hbase.util.Bytes;
5759
import org.apache.yetus.audience.InterfaceAudience;
@@ -70,23 +72,23 @@
7072
public class SnapshotScannerHDFSAclHelper implements Closeable {
7173
private static final Logger LOG = LoggerFactory.getLogger(SnapshotScannerHDFSAclHelper.class);
7274

73-
public static final String USER_SCAN_SNAPSHOT_ENABLE = "hbase.user.scan.snapshot.enable";
74-
public static final String USER_SCAN_SNAPSHOT_THREAD_NUMBER =
75-
"hbase.user.scan.snapshot.thread.number";
75+
public static final String ACL_SYNC_TO_HDFS_ENABLE = "hbase.acl.sync.to.hdfs.enable";
76+
public static final String ACL_SYNC_TO_HDFS_THREAD_NUMBER =
77+
"hbase.acl.sync.to.hdfs.thread.number";
7678
// The tmp directory to restore snapshot, it can not be a sub directory of HBase root dir
7779
public static final String SNAPSHOT_RESTORE_TMP_DIR = "hbase.snapshot.restore.tmp.dir";
7880
public static final String SNAPSHOT_RESTORE_TMP_DIR_DEFAULT =
7981
"/hbase/.tmpdir-to-restore-snapshot";
8082
// The default permission of the common directories if the feature is enabled.
8183
public static final String COMMON_DIRECTORY_PERMISSION =
82-
"hbase.user.scan.snapshot.common.directory.permission";
84+
"hbase.acl.sync.to.hdfs.common.directory.permission";
8385
// The secure HBase permission is 700, 751 means all others have execute access and the mask is
8486
// set to read-execute to make the extended access ACL entries can work. Be cautious to set
8587
// this value.
8688
public static final String COMMON_DIRECTORY_PERMISSION_DEFAULT = "751";
8789
// The default permission of the snapshot restore directories if the feature is enabled.
8890
public static final String SNAPSHOT_RESTORE_DIRECTORY_PERMISSION =
89-
"hbase.user.scan.snapshot.restore.directory.permission";
91+
"hbase.acl.sync.to.hdfs.restore.directory.permission";
9092
// 753 means all others have write-execute access.
9193
public static final String SNAPSHOT_RESTORE_DIRECTORY_PERMISSION_DEFAULT = "753";
9294

@@ -101,7 +103,7 @@ public SnapshotScannerHDFSAclHelper(Configuration configuration, Connection conn
101103
this.conf = configuration;
102104
this.pathHelper = new PathHelper(conf);
103105
this.fs = pathHelper.getFileSystem();
104-
this.pool = Executors.newFixedThreadPool(conf.getInt(USER_SCAN_SNAPSHOT_THREAD_NUMBER, 10),
106+
this.pool = Executors.newFixedThreadPool(conf.getInt(ACL_SYNC_TO_HDFS_THREAD_NUMBER, 10),
105107
new ThreadFactoryBuilder().setNameFormat("hdfs-acl-thread-%d").setDaemon(true).build());
106108
this.admin = connection.getAdmin();
107109
}
@@ -233,6 +235,50 @@ public boolean removeNamespaceAccessAcl(TableName tableName, Set<String> removeU
233235
}
234236
}
235237

238+
/**
239+
* Remove default acl from namespace archive dir when delete namespace
240+
* @param namespace the namespace
241+
* @param removeUsers the users whose default acl will be removed
242+
* @return false if an error occurred, otherwise true
243+
*/
244+
public boolean removeNamespaceDefaultAcl(String namespace, Set<String> removeUsers) {
245+
try {
246+
long start = System.currentTimeMillis();
247+
Path archiveNsDir = pathHelper.getArchiveNsDir(namespace);
248+
HDFSAclOperation operation = new HDFSAclOperation(fs, archiveNsDir, removeUsers,
249+
HDFSAclOperation.OperationType.REMOVE, false, HDFSAclOperation.AclType.DEFAULT);
250+
operation.handleAcl();
251+
LOG.info("Remove HDFS acl when delete namespace {}, cost {} ms", namespace,
252+
System.currentTimeMillis() - start);
253+
return true;
254+
} catch (Exception e) {
255+
LOG.error("Remove HDFS acl error when delete namespace {}", namespace, e);
256+
return false;
257+
}
258+
}
259+
260+
/**
261+
* Remove default acl from table archive dir when delete table
262+
* @param tableName the table name
263+
* @param removeUsers the users whose default acl will be removed
264+
* @return false if an error occurred, otherwise true
265+
*/
266+
public boolean removeTableDefaultAcl(TableName tableName, Set<String> removeUsers) {
267+
try {
268+
long start = System.currentTimeMillis();
269+
Path archiveTableDir = pathHelper.getArchiveTableDir(tableName);
270+
HDFSAclOperation operation = new HDFSAclOperation(fs, archiveTableDir, removeUsers,
271+
HDFSAclOperation.OperationType.REMOVE, false, HDFSAclOperation.AclType.DEFAULT);
272+
operation.handleAcl();
273+
LOG.info("Remove HDFS acl when delete table {}, cost {} ms", tableName,
274+
System.currentTimeMillis() - start);
275+
return true;
276+
} catch (Exception e) {
277+
LOG.error("Remove HDFS acl error when delete table {}", tableName, e);
278+
return false;
279+
}
280+
}
281+
236282
/**
237283
* Add table user acls
238284
* @param tableName the table
@@ -352,7 +398,7 @@ private void handleNamespaceAcl(Set<String> namespaces, Set<String> users,
352398
Set<TableName> tables = new HashSet<>();
353399
for (String namespace : namespaces) {
354400
tables.addAll(admin.listTableDescriptorsByNamespace(Bytes.toBytes(namespace)).stream()
355-
.filter(this::isTableUserScanSnapshotEnabled).map(TableDescriptor::getTableName)
401+
.filter(this::isAclSyncToHdfsEnabled).map(TableDescriptor::getTableName)
356402
.collect(Collectors.toSet()));
357403
}
358404
handleTableAcl(tables, users, skipNamespaces, skipTables, operationType);
@@ -406,7 +452,7 @@ void createTableDirectories(TableName tableName) throws IOException {
406452
* return paths that user will global permission will visit
407453
* @return the path list
408454
*/
409-
private List<Path> getGlobalRootPaths() {
455+
List<Path> getGlobalRootPaths() {
410456
return Lists.newArrayList(pathHelper.getTmpDataDir(), pathHelper.getDataDir(),
411457
pathHelper.getMobDataDir(), pathHelper.getArchiveDataDir(), pathHelper.getSnapshotRootDir());
412458
}
@@ -514,9 +560,20 @@ boolean isNotFamilyOrQualifierPermission(TablePermission tablePermission) {
514560
return !tablePermission.hasFamily() && !tablePermission.hasQualifier();
515561
}
516562

517-
boolean isTableUserScanSnapshotEnabled(TableDescriptor tableDescriptor) {
563+
public static boolean isAclSyncToHdfsEnabled(Configuration conf) {
564+
String[] masterCoprocessors = conf.getStrings(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY);
565+
Set<String> masterCoprocessorSet = new HashSet<>();
566+
if (masterCoprocessors != null) {
567+
Collections.addAll(masterCoprocessorSet, masterCoprocessors);
568+
}
569+
return conf.getBoolean(SnapshotScannerHDFSAclHelper.ACL_SYNC_TO_HDFS_ENABLE, false)
570+
&& masterCoprocessorSet.contains(SnapshotScannerHDFSAclController.class.getName())
571+
&& masterCoprocessorSet.contains(AccessController.class.getName());
572+
}
573+
574+
boolean isAclSyncToHdfsEnabled(TableDescriptor tableDescriptor) {
518575
return tableDescriptor == null ? false
519-
: Boolean.valueOf(tableDescriptor.getValue(USER_SCAN_SNAPSHOT_ENABLE));
576+
: Boolean.valueOf(tableDescriptor.getValue(ACL_SYNC_TO_HDFS_ENABLE));
520577
}
521578

522579
PathHelper getPathHelper() {

0 commit comments

Comments
 (0)