|
@@ -42,6 +42,7 @@ import java.security.NoSuchAlgorithmException;
|
|
|
import java.security.PrivilegedExceptionAction;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
+import java.util.Collection;
|
|
|
import java.util.Collections;
|
|
|
import java.util.EnumSet;
|
|
|
import java.util.HashSet;
|
|
@@ -2144,4 +2145,301 @@ public class TestDistributedFileSystem {
|
|
|
LambdaTestUtils.intercept(IOException.class, "", () -> str.close());
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testGetTrashRoot() throws IOException {
|
|
|
+ Configuration conf = getTestConfiguration();
|
|
|
+ conf.setBoolean("dfs.namenode.snapshot.trashroot.enabled", true);
|
|
|
+ MiniDFSCluster cluster =
|
|
|
+ new MiniDFSCluster.Builder(conf).numDataNodes(1).build();
|
|
|
+ try {
|
|
|
+ DistributedFileSystem dfs = cluster.getFileSystem();
|
|
|
+ Path testDir = new Path("/ssgtr/test1/");
|
|
|
+ Path file0path = new Path(testDir, "file-0");
|
|
|
+ dfs.create(file0path);
|
|
|
+
|
|
|
+ Path trBeforeAllowSnapshot = dfs.getTrashRoot(file0path);
|
|
|
+ String trBeforeAllowSnapshotStr = trBeforeAllowSnapshot.toUri().getPath();
|
|
|
+ // The trash root should be in user home directory
|
|
|
+ String homeDirStr = dfs.getHomeDirectory().toUri().getPath();
|
|
|
+ assertTrue(trBeforeAllowSnapshotStr.startsWith(homeDirStr));
|
|
|
+
|
|
|
+ dfs.allowSnapshot(testDir);
|
|
|
+
|
|
|
+ Path trAfterAllowSnapshot = dfs.getTrashRoot(file0path);
|
|
|
+ String trAfterAllowSnapshotStr = trAfterAllowSnapshot.toUri().getPath();
|
|
|
+ // The trash root should now be in the snapshot root
|
|
|
+ String testDirStr = testDir.toUri().getPath();
|
|
|
+ assertTrue(trAfterAllowSnapshotStr.startsWith(testDirStr));
|
|
|
+
|
|
|
+ // Cleanup
|
|
|
+ dfs.disallowSnapshot(testDir);
|
|
|
+ dfs.delete(testDir, true);
|
|
|
+ } finally {
|
|
|
+ if (cluster != null) {
|
|
|
+ cluster.shutdown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isPathInUserHome(String pathStr, DistributedFileSystem dfs) {
|
|
|
+ String homeDirStr = dfs.getHomeDirectory().toUri().getPath();
|
|
|
+ return pathStr.startsWith(homeDirStr);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testGetTrashRoots() throws IOException {
|
|
|
+ Configuration conf = getTestConfiguration();
|
|
|
+ conf.setBoolean("dfs.namenode.snapshot.trashroot.enabled", true);
|
|
|
+ MiniDFSCluster cluster =
|
|
|
+ new MiniDFSCluster.Builder(conf).numDataNodes(1).build();
|
|
|
+ try {
|
|
|
+ DistributedFileSystem dfs = cluster.getFileSystem();
|
|
|
+ Path testDir = new Path("/ssgtr/test1/");
|
|
|
+ Path file0path = new Path(testDir, "file-0");
|
|
|
+ dfs.create(file0path);
|
|
|
+ // Create user trash
|
|
|
+ Path currUserHome = dfs.getHomeDirectory();
|
|
|
+ Path currUserTrash = new Path(currUserHome, FileSystem.TRASH_PREFIX);
|
|
|
+ dfs.mkdirs(currUserTrash);
|
|
|
+ // Create trash inside test directory
|
|
|
+ Path testDirTrash = new Path(testDir, FileSystem.TRASH_PREFIX);
|
|
|
+ Path testDirTrashCurrUser = new Path(testDirTrash,
|
|
|
+ UserGroupInformation.getCurrentUser().getShortUserName());
|
|
|
+ dfs.mkdirs(testDirTrashCurrUser);
|
|
|
+
|
|
|
+ Collection<FileStatus> trashRoots = dfs.getTrashRoots(false);
|
|
|
+ // getTrashRoots should only return 1 empty user trash in the home dir now
|
|
|
+ assertEquals(1, trashRoots.size());
|
|
|
+ FileStatus firstFileStatus = trashRoots.iterator().next();
|
|
|
+ String pathStr = firstFileStatus.getPath().toUri().getPath();
|
|
|
+ assertTrue(isPathInUserHome(pathStr, dfs));
|
|
|
+ // allUsers should not make a difference for now because we have one user
|
|
|
+ Collection<FileStatus> trashRootsAllUsers = dfs.getTrashRoots(true);
|
|
|
+ assertEquals(trashRoots, trashRootsAllUsers);
|
|
|
+
|
|
|
+ dfs.allowSnapshot(testDir);
|
|
|
+
|
|
|
+ Collection<FileStatus> trashRootsAfter = dfs.getTrashRoots(false);
|
|
|
+ // getTrashRoots should return 1 more trash root inside snapshottable dir
|
|
|
+ assertEquals(trashRoots.size() + 1, trashRootsAfter.size());
|
|
|
+ boolean foundUserHomeTrash = false;
|
|
|
+ boolean foundSnapDirUserTrash = false;
|
|
|
+ String testDirStr = testDir.toUri().getPath();
|
|
|
+ for (FileStatus fileStatus : trashRootsAfter) {
|
|
|
+ String currPathStr = fileStatus.getPath().toUri().getPath();
|
|
|
+ if (isPathInUserHome(currPathStr, dfs)) {
|
|
|
+ foundUserHomeTrash = true;
|
|
|
+ } else if (currPathStr.startsWith(testDirStr)) {
|
|
|
+ foundSnapDirUserTrash = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ assertTrue(foundUserHomeTrash);
|
|
|
+ assertTrue(foundSnapDirUserTrash);
|
|
|
+ // allUsers should not make a difference for now because we have one user
|
|
|
+ Collection<FileStatus> trashRootsAfterAllUsers = dfs.getTrashRoots(true);
|
|
|
+ assertEquals(trashRootsAfter, trashRootsAfterAllUsers);
|
|
|
+
|
|
|
+ // Create trash root for user0
|
|
|
+ UserGroupInformation ugi = UserGroupInformation.createRemoteUser("user0");
|
|
|
+ String user0HomeStr = DFSUtilClient.getHomeDirectory(conf, ugi);
|
|
|
+ Path user0Trash = new Path(user0HomeStr, FileSystem.TRASH_PREFIX);
|
|
|
+ dfs.mkdirs(user0Trash);
|
|
|
+ // allUsers flag set to false should be unaffected
|
|
|
+ Collection<FileStatus> trashRootsAfter2 = dfs.getTrashRoots(false);
|
|
|
+ assertEquals(trashRootsAfter, trashRootsAfter2);
|
|
|
+ // allUsers flag set to true should include new user's trash
|
|
|
+ trashRootsAfter2 = dfs.getTrashRoots(true);
|
|
|
+ assertEquals(trashRootsAfter.size() + 1, trashRootsAfter2.size());
|
|
|
+
|
|
|
+ // Create trash root inside the snapshottable directory for user0
|
|
|
+ Path testDirTrashUser0 = new Path(testDirTrash, ugi.getShortUserName());
|
|
|
+ dfs.mkdirs(testDirTrashUser0);
|
|
|
+ Collection<FileStatus> trashRootsAfter3 = dfs.getTrashRoots(true);
|
|
|
+ assertEquals(trashRootsAfter2.size() + 1, trashRootsAfter3.size());
|
|
|
+
|
|
|
+ // Cleanup
|
|
|
+ dfs.disallowSnapshot(testDir);
|
|
|
+ dfs.delete(testDir, true);
|
|
|
+ } finally {
|
|
|
+ if (cluster != null) {
|
|
|
+ cluster.shutdown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testGetTrashRootsOnSnapshottableDirWithEZ()
|
|
|
+ throws IOException, NoSuchAlgorithmException {
|
|
|
+ Configuration conf = getTestConfiguration();
|
|
|
+ conf.setBoolean("dfs.namenode.snapshot.trashroot.enabled", true);
|
|
|
+ // Set encryption zone config
|
|
|
+ File tmpDir = GenericTestUtils.getTestDir(UUID.randomUUID().toString());
|
|
|
+ final Path jksPath = new Path(tmpDir.toString(), "test.jks");
|
|
|
+ conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_KEY_PROVIDER_PATH,
|
|
|
+ JavaKeyStoreProvider.SCHEME_NAME + "://file" + jksPath.toUri());
|
|
|
+ MiniDFSCluster cluster =
|
|
|
+ new MiniDFSCluster.Builder(conf).numDataNodes(1).build();
|
|
|
+ // Create key for EZ
|
|
|
+ final KeyProvider provider =
|
|
|
+ cluster.getNameNode().getNamesystem().getProvider();
|
|
|
+ final KeyProvider.Options options = KeyProvider.options(conf);
|
|
|
+ provider.createKey("key", options);
|
|
|
+ provider.flush();
|
|
|
+
|
|
|
+ try {
|
|
|
+ DistributedFileSystem dfs = cluster.getFileSystem();
|
|
|
+ Path testDir = new Path("/ssgtr/test2/");
|
|
|
+ dfs.mkdirs(testDir);
|
|
|
+ dfs.createEncryptionZone(testDir, "key");
|
|
|
+
|
|
|
+ // Create trash inside test directory
|
|
|
+ Path testDirTrash = new Path(testDir, FileSystem.TRASH_PREFIX);
|
|
|
+ Path testDirTrashCurrUser = new Path(testDirTrash,
|
|
|
+ UserGroupInformation.getCurrentUser().getShortUserName());
|
|
|
+ dfs.mkdirs(testDirTrashCurrUser);
|
|
|
+
|
|
|
+ Collection<FileStatus> trashRoots = dfs.getTrashRoots(false);
|
|
|
+ assertEquals(1, trashRoots.size());
|
|
|
+ FileStatus firstFileStatus = trashRoots.iterator().next();
|
|
|
+ String pathStr = firstFileStatus.getPath().toUri().getPath();
|
|
|
+ String testDirStr = testDir.toUri().getPath();
|
|
|
+ assertTrue(pathStr.startsWith(testDirStr));
|
|
|
+
|
|
|
+ dfs.allowSnapshot(testDir);
|
|
|
+
|
|
|
+ Collection<FileStatus> trashRootsAfter = dfs.getTrashRoots(false);
|
|
|
+ // getTrashRoots should give the same result
|
|
|
+ assertEquals(trashRoots, trashRootsAfter);
|
|
|
+
|
|
|
+ // Cleanup
|
|
|
+ dfs.disallowSnapshot(testDir);
|
|
|
+ dfs.delete(testDir, true);
|
|
|
+ } finally {
|
|
|
+ if (cluster != null) {
|
|
|
+ cluster.shutdown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testGetTrashRootOnSnapshottableDirInEZ()
|
|
|
+ throws IOException, NoSuchAlgorithmException {
|
|
|
+ Configuration conf = getTestConfiguration();
|
|
|
+ conf.setBoolean("dfs.namenode.snapshot.trashroot.enabled", true);
|
|
|
+ // Set EZ config
|
|
|
+ File tmpDir = GenericTestUtils.getTestDir(UUID.randomUUID().toString());
|
|
|
+ final Path jksPath = new Path(tmpDir.toString(), "test.jks");
|
|
|
+ conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_KEY_PROVIDER_PATH,
|
|
|
+ JavaKeyStoreProvider.SCHEME_NAME + "://file" + jksPath.toUri());
|
|
|
+ MiniDFSCluster cluster =
|
|
|
+ new MiniDFSCluster.Builder(conf).numDataNodes(1).build();
|
|
|
+ // Create key for EZ
|
|
|
+ final KeyProvider provider =
|
|
|
+ cluster.getNameNode().getNamesystem().getProvider();
|
|
|
+ final KeyProvider.Options options = KeyProvider.options(conf);
|
|
|
+ provider.createKey("key", options);
|
|
|
+ provider.flush();
|
|
|
+
|
|
|
+ try {
|
|
|
+ DistributedFileSystem dfs = cluster.getFileSystem();
|
|
|
+
|
|
|
+ Path testDir = new Path("/ssgtr/test3ez/");
|
|
|
+ dfs.mkdirs(testDir);
|
|
|
+ dfs.createEncryptionZone(testDir, "key");
|
|
|
+ Path testSubD = new Path(testDir, "sssubdir");
|
|
|
+ Path file1Path = new Path(testSubD, "file1");
|
|
|
+ dfs.create(file1Path);
|
|
|
+
|
|
|
+ final Path trBefore = dfs.getTrashRoot(file1Path);
|
|
|
+ final String trBeforeStr = trBefore.toUri().getPath();
|
|
|
+ // The trash root should be directly under testDir
|
|
|
+ final Path testDirTrash = new Path(testDir, FileSystem.TRASH_PREFIX);
|
|
|
+ final String testDirTrashStr = testDirTrash.toUri().getPath();
|
|
|
+ assertTrue(trBeforeStr.startsWith(testDirTrashStr));
|
|
|
+
|
|
|
+ dfs.allowSnapshot(testSubD);
|
|
|
+ final Path trAfter = dfs.getTrashRoot(file1Path);
|
|
|
+ final String trAfterStr = trAfter.toUri().getPath();
|
|
|
+ // The trash is now located in the dir inside
|
|
|
+ final Path testSubDirTrash = new Path(testSubD, FileSystem.TRASH_PREFIX);
|
|
|
+ UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
|
|
|
+ final Path testSubDirUserTrash = new Path(testSubDirTrash,
|
|
|
+ ugi.getShortUserName());
|
|
|
+ final String testSubDirUserTrashStr =
|
|
|
+ testSubDirUserTrash.toUri().getPath();
|
|
|
+ assertEquals(testSubDirUserTrashStr, trAfterStr);
|
|
|
+
|
|
|
+ // Cleanup
|
|
|
+ dfs.disallowSnapshot(testSubD);
|
|
|
+ dfs.delete(testDir, true);
|
|
|
+ } finally {
|
|
|
+ if (cluster != null) {
|
|
|
+ cluster.shutdown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testGetTrashRootOnEZInSnapshottableDir()
|
|
|
+ throws IOException, NoSuchAlgorithmException {
|
|
|
+ Configuration conf = getTestConfiguration();
|
|
|
+ conf.setBoolean("dfs.namenode.snapshot.trashroot.enabled", true);
|
|
|
+ // Set EZ config
|
|
|
+ File tmpDir = GenericTestUtils.getTestDir(UUID.randomUUID().toString());
|
|
|
+ final Path jksPath = new Path(tmpDir.toString(), "test.jks");
|
|
|
+ conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_KEY_PROVIDER_PATH,
|
|
|
+ JavaKeyStoreProvider.SCHEME_NAME + "://file" + jksPath.toUri());
|
|
|
+ MiniDFSCluster cluster =
|
|
|
+ new MiniDFSCluster.Builder(conf).numDataNodes(1).build();
|
|
|
+ // Create key for EZ
|
|
|
+ final KeyProvider provider =
|
|
|
+ cluster.getNameNode().getNamesystem().getProvider();
|
|
|
+ final KeyProvider.Options options = KeyProvider.options(conf);
|
|
|
+ provider.createKey("key", options);
|
|
|
+ provider.flush();
|
|
|
+
|
|
|
+ try {
|
|
|
+ DistributedFileSystem dfs = cluster.getFileSystem();
|
|
|
+
|
|
|
+ Path testDir = new Path("/ssgtr/test3ss/");
|
|
|
+ dfs.mkdirs(testDir);
|
|
|
+ dfs.allowSnapshot(testDir);
|
|
|
+ Path testSubD = new Path(testDir, "ezsubdir");
|
|
|
+ dfs.mkdirs(testSubD);
|
|
|
+ Path file1Path = new Path(testSubD, "file1");
|
|
|
+ dfs.create(file1Path);
|
|
|
+
|
|
|
+ final Path trBefore = dfs.getTrashRoot(file1Path);
|
|
|
+ final String trBeforeStr = trBefore.toUri().getPath();
|
|
|
+ // The trash root should be directly under testDir
|
|
|
+ final Path testDirTrash = new Path(testDir, FileSystem.TRASH_PREFIX);
|
|
|
+ final String testDirTrashStr = testDirTrash.toUri().getPath();
|
|
|
+ assertTrue(trBeforeStr.startsWith(testDirTrashStr));
|
|
|
+
|
|
|
+ // Need to remove the file inside the dir to establish EZ
|
|
|
+ dfs.delete(file1Path, false);
|
|
|
+ dfs.createEncryptionZone(testSubD, "key");
|
|
|
+ dfs.create(file1Path);
|
|
|
+
|
|
|
+ final Path trAfter = dfs.getTrashRoot(file1Path);
|
|
|
+ final String trAfterStr = trAfter.toUri().getPath();
|
|
|
+ // The trash is now located in the dir inside
|
|
|
+ final Path testSubDirTrash = new Path(testSubD, FileSystem.TRASH_PREFIX);
|
|
|
+ UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
|
|
|
+ final Path testSubDirUserTrash = new Path(testSubDirTrash,
|
|
|
+ ugi.getShortUserName());
|
|
|
+ final String testSubDirUserTrashStr =
|
|
|
+ testSubDirUserTrash.toUri().getPath();
|
|
|
+ assertEquals(testSubDirUserTrashStr, trAfterStr);
|
|
|
+
|
|
|
+ // Cleanup
|
|
|
+ dfs.disallowSnapshot(testDir);
|
|
|
+ dfs.delete(testDir, true);
|
|
|
+ } finally {
|
|
|
+ if (cluster != null) {
|
|
|
+ cluster.shutdown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|