HDFS-10324. Trash directory in an encryption zone should be pre-created with correct permissions. Contributed by Wei-Chiu Chuang.

(cherry picked from commit dacd1f50fe)
This commit is contained in:
Xiaoyu Yao 2016-05-05 18:07:47 -07:00
parent d18a991817
commit 35859872b7
13 changed files with 518 additions and 73 deletions

View File

@ -56,7 +56,6 @@ public class TrashPolicyDefault extends TrashPolicy {
LogFactory.getLog(TrashPolicyDefault.class); LogFactory.getLog(TrashPolicyDefault.class);
private static final Path CURRENT = new Path("Current"); private static final Path CURRENT = new Path("Current");
private static final Path TRASH = new Path(".Trash/");
private static final FsPermission PERMISSION = private static final FsPermission PERMISSION =
new FsPermission(FsAction.ALL, FsAction.NONE, FsAction.NONE); new FsPermission(FsAction.ALL, FsAction.NONE, FsAction.NONE);

View File

@ -29,7 +29,6 @@ import java.nio.ByteBuffer;
import java.util.EnumSet; import java.util.EnumSet;
import org.apache.hadoop.crypto.key.JavaKeyStoreProvider; import org.apache.hadoop.crypto.key.JavaKeyStoreProvider;
import org.apache.hadoop.crypto.key.KeyProviderFactory;
import org.apache.hadoop.fs.CommonConfigurationKeys; import org.apache.hadoop.fs.CommonConfigurationKeys;
import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystemTestHelper; import org.apache.hadoop.fs.FileSystemTestHelper;
@ -38,6 +37,7 @@ import org.apache.hadoop.hdfs.DFSConfigKeys;
import org.apache.hadoop.hdfs.DFSTestUtil; import org.apache.hadoop.hdfs.DFSTestUtil;
import org.apache.hadoop.hdfs.DistributedFileSystem; import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.MiniDFSCluster; import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.client.CreateEncryptionZoneFlag;
import org.apache.hadoop.hdfs.client.HdfsAdmin; import org.apache.hadoop.hdfs.client.HdfsAdmin;
import org.apache.hadoop.hdfs.nfs.conf.NfsConfigKeys; import org.apache.hadoop.hdfs.nfs.conf.NfsConfigKeys;
import org.apache.hadoop.hdfs.nfs.conf.NfsConfiguration; import org.apache.hadoop.hdfs.nfs.conf.NfsConfiguration;
@ -118,6 +118,8 @@ public class TestRpcProgramNfs3 {
private static final String TEST_KEY = "test_key"; private static final String TEST_KEY = "test_key";
private static FileSystemTestHelper fsHelper; private static FileSystemTestHelper fsHelper;
private static File testRootDir; private static File testRootDir;
private static final EnumSet<CreateEncryptionZoneFlag> NO_TRASH =
EnumSet.of(CreateEncryptionZoneFlag.NO_TRASH);
@BeforeClass @BeforeClass
public static void setup() throws Exception { public static void setup() throws Exception {
@ -340,7 +342,7 @@ public class TestRpcProgramNfs3 {
final Path zone = new Path("/zone"); final Path zone = new Path("/zone");
hdfs.mkdirs(zone); hdfs.mkdirs(zone);
dfsAdmin.createEncryptionZone(zone, TEST_KEY); dfsAdmin.createEncryptionZone(zone, TEST_KEY, NO_TRASH);
final byte[] buffer = new byte[len]; final byte[] buffer = new byte[len];
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {

View File

@ -0,0 +1,71 @@
/**
* 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.hdfs.client;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
/**
* CreateEncryptionZoneFlag is used in
* {@link HdfsAdmin#createEncryptionZone(Path, String, EnumSet)} to indicate
* what should be done when creating an encryption zone.
*
* Use CreateEncryptionZoneFlag as follows:
* <ol>
* <li>PROVISION_TRASH - provision a trash directory for the encryption zone
* to support soft delete.</li>
* </ol>
*/
@InterfaceAudience.Public
@InterfaceStability.Evolving
public enum CreateEncryptionZoneFlag {
/**
* Do not provision a trash directory in the encryption zone.
*
* @see CreateEncryptionZoneFlag#NO_TRASH
*/
NO_TRASH((short) 0x00),
/**
* Provision a trash directory .Trash/ in the
* encryption zone.
*
* @see CreateEncryptionZoneFlag#PROVISION_TRASH
*/
PROVISION_TRASH((short) 0x01);
private final short mode;
CreateEncryptionZoneFlag(short mode) {
this.mode = mode;
}
public static CreateEncryptionZoneFlag valueOf(short mode) {
for (CreateEncryptionZoneFlag flag : CreateEncryptionZoneFlag.values()) {
if (flag.getMode() == mode) {
return flag;
}
}
return null;
}
public short getMode() {
return mode;
}
}

View File

@ -22,14 +22,18 @@ import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.util.EnumSet; import java.util.EnumSet;
import org.apache.hadoop.HadoopIllegalArgumentException;
import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CacheFlag; import org.apache.hadoop.fs.CacheFlag;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator; import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.fs.StorageType; import org.apache.hadoop.fs.StorageType;
import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.DFSInotifyEventInputStream; import org.apache.hadoop.hdfs.DFSInotifyEventInputStream;
import org.apache.hadoop.hdfs.DistributedFileSystem; import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.protocol.CacheDirectiveEntry; import org.apache.hadoop.hdfs.protocol.CacheDirectiveEntry;
@ -55,6 +59,8 @@ import org.apache.hadoop.hdfs.tools.DFSAdmin;
public class HdfsAdmin { public class HdfsAdmin {
private DistributedFileSystem dfs; private DistributedFileSystem dfs;
private static final FsPermission TRASH_PERMISSION = new FsPermission(
FsAction.ALL, FsAction.ALL, FsAction.ALL, true);
/** /**
* Create a new HdfsAdmin client. * Create a new HdfsAdmin client.
@ -269,11 +275,53 @@ public class HdfsAdmin {
* @throws AccessControlException if the caller does not have access to path * @throws AccessControlException if the caller does not have access to path
* @throws FileNotFoundException if the path does not exist * @throws FileNotFoundException if the path does not exist
*/ */
@Deprecated
public void createEncryptionZone(Path path, String keyName) public void createEncryptionZone(Path path, String keyName)
throws IOException, AccessControlException, FileNotFoundException { throws IOException, AccessControlException, FileNotFoundException {
dfs.createEncryptionZone(path, keyName); dfs.createEncryptionZone(path, keyName);
} }
/**
* Create an encryption zone rooted at an empty existing directory, using the
* specified encryption key. An encryption zone has an associated encryption
* key used when reading and writing files within the zone.
*
* Additional options, such as provisioning the trash directory, can be
* specified using {@link CreateEncryptionZoneFlag} flags.
*
* @param path The path of the root of the encryption zone. Must refer to
* an empty, existing directory.
* @param keyName Name of key available at the KeyProvider.
* @param flags flags for this operation.
* @throws IOException if there was a general IO exception
* @throws AccessControlException if the caller does not have access to path
* @throws FileNotFoundException if the path does not exist
* @throws HadoopIllegalArgumentException if the flags are invalid
*/
public void createEncryptionZone(Path path, String keyName,
EnumSet<CreateEncryptionZoneFlag> flags)
throws IOException, AccessControlException, FileNotFoundException,
HadoopIllegalArgumentException{
dfs.createEncryptionZone(path, keyName);
if (flags.contains(CreateEncryptionZoneFlag.PROVISION_TRASH)) {
if (flags.contains(CreateEncryptionZoneFlag.NO_TRASH)) {
throw new HadoopIllegalArgumentException(
"can not have both PROVISION_TRASH and NO_TRASH flags");
}
this.provisionEZTrash(path);
}
}
/**
* Provision a trash directory for a given encryption zone.
* @param path the root of the encryption zone
* @throws IOException if the trash directory can not be created.
*/
public void provisionEncryptionZoneTrash(Path path) throws IOException {
this.provisionEZTrash(path);
}
/** /**
* Get the path of the encryption zone for a given file or directory. * Get the path of the encryption zone for a given file or directory.
* *
@ -363,4 +411,42 @@ public class HdfsAdmin {
throws IOException { throws IOException {
dfs.setStoragePolicy(src, policyName); dfs.setStoragePolicy(src, policyName);
} }
private void provisionEZTrash(Path path) throws IOException {
// make sure the path is an EZ
EncryptionZone ez = dfs.getEZForPath(path);
if (ez == null) {
throw new IllegalArgumentException(path + " is not an encryption zone.");
}
String ezPath = ez.getPath();
if (!path.toString().equals(ezPath)) {
throw new IllegalArgumentException(path + " is not the root of an " +
"encryption zone. Do you mean " + ez.getPath() + "?");
}
// check if the trash directory exists
Path trashPath = new Path(ez.getPath(), FileSystem.TRASH_PREFIX);
if (dfs.exists(trashPath)) {
String errMessage = "Will not provision new trash directory for " +
"encryption zone " + ez.getPath() + ". Path already exists.";
FileStatus trashFileStatus = dfs.getFileStatus(trashPath);
if (!trashFileStatus.isDirectory()) {
errMessage += "\r\n" +
"Warning: " + trashPath.toString() + " is not a directory";
}
if (!trashFileStatus.getPermission().equals(TRASH_PERMISSION)) {
errMessage += "\r\n" +
"Warning: the permission of " +
trashPath.toString() + " is not " + TRASH_PERMISSION;
}
throw new IOException(errMessage);
}
// Update the permission bits
dfs.mkdir(trashPath, TRASH_PERMISSION);
dfs.setPermission(trashPath, TRASH_PERMISSION);
}
} }

View File

@ -0,0 +1,27 @@
/*
* 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.
*/
/**
* This package provides the administrative APIs for HDFS.
*/
@InterfaceAudience.Public
@InterfaceStability.Evolving
package org.apache.hadoop.hdfs.client;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;

View File

@ -18,15 +18,18 @@
package org.apache.hadoop.hdfs.tools; package org.apache.hadoop.hdfs.tools;
import java.io.IOException; import java.io.IOException;
import java.util.EnumSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured; import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator; import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.hdfs.DistributedFileSystem; import org.apache.hadoop.hdfs.client.CreateEncryptionZoneFlag;
import org.apache.hadoop.hdfs.client.HdfsAdmin;
import org.apache.hadoop.hdfs.protocol.EncryptionZone; import org.apache.hadoop.hdfs.protocol.EncryptionZone;
import org.apache.hadoop.tools.TableListing; import org.apache.hadoop.tools.TableListing;
import org.apache.hadoop.util.StringUtils; import org.apache.hadoop.util.StringUtils;
@ -103,7 +106,8 @@ public class CryptoAdmin extends Configured implements Tool {
public String getLongUsage() { public String getLongUsage() {
final TableListing listing = AdminHelper.getOptionDescriptionListing(); final TableListing listing = AdminHelper.getOptionDescriptionListing();
listing.addRow("<path>", "The path of the encryption zone to create. " + listing.addRow("<path>", "The path of the encryption zone to create. " +
"It must be an empty directory."); "It must be an empty directory. A trash directory is provisioned " +
"under this path.");
listing.addRow("<keyName>", "Name of the key to use for the " + listing.addRow("<keyName>", "Name of the key to use for the " +
"encryption zone."); "encryption zone.");
return getShortUsage() + "\n" + return getShortUsage() + "\n" +
@ -131,15 +135,16 @@ public class CryptoAdmin extends Configured implements Tool {
return 1; return 1;
} }
final DistributedFileSystem dfs = AdminHelper.getDFS(conf); HdfsAdmin admin = new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
EnumSet<CreateEncryptionZoneFlag> flags =
EnumSet.of(CreateEncryptionZoneFlag.PROVISION_TRASH);
try { try {
dfs.createEncryptionZone(new Path(path), keyName); admin.createEncryptionZone(new Path(path), keyName, flags);
System.out.println("Added encryption zone " + path); System.out.println("Added encryption zone " + path);
} catch (IOException e) { } catch (IOException e) {
System.err.println(prettifyException(e)); System.err.println(prettifyException(e));
return 2; return 2;
} }
return 0; return 0;
} }
} }
@ -168,12 +173,12 @@ public class CryptoAdmin extends Configured implements Tool {
return 1; return 1;
} }
final DistributedFileSystem dfs = AdminHelper.getDFS(conf); HdfsAdmin admin = new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
try { try {
final TableListing listing = new TableListing.Builder() final TableListing listing = new TableListing.Builder()
.addField("").addField("", true) .addField("").addField("", true)
.wrapWidth(AdminHelper.MAX_LINE_WIDTH).hideHeaders().build(); .wrapWidth(AdminHelper.MAX_LINE_WIDTH).hideHeaders().build();
final RemoteIterator<EncryptionZone> it = dfs.listEncryptionZones(); final RemoteIterator<EncryptionZone> it = admin.listEncryptionZones();
while (it.hasNext()) { while (it.hasNext()) {
EncryptionZone ez = it.next(); EncryptionZone ez = it.next();
listing.addRow(ez.getPath(), ez.getKeyName()); listing.addRow(ez.getPath(), ez.getKeyName());
@ -188,8 +193,50 @@ public class CryptoAdmin extends Configured implements Tool {
} }
} }
private static class ProvisionTrashCommand implements AdminHelper.Command {
@Override
public String getName() {
return "-provisionTrash";
}
@Override
public String getShortUsage() {
return "[" + getName() + " -path <path>]\n";
}
@Override
public String getLongUsage() {
final TableListing listing = AdminHelper.getOptionDescriptionListing();
listing.addRow("<path>", "The path to the root of the encryption zone. ");
return getShortUsage() + "\n" +
"Provision a trash directory for an encryption zone.\n\n" +
listing.toString();
}
@Override
public int run(Configuration conf, List<String> args) throws IOException {
final String path = StringUtils.popOptionWithArgument("-path", args);
if (!args.isEmpty()) {
System.err.println("Can't understand argument: " + args.get(0));
return 1;
}
HdfsAdmin admin = new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
try {
admin.provisionEncryptionZoneTrash(new Path(path));
System.out.println("Created a trash directory for " + path);
} catch (IOException ioe) {
System.err.println(prettifyException(ioe));
return 2;
}
return 0;
}
}
private static final AdminHelper.Command[] COMMANDS = { private static final AdminHelper.Command[] COMMANDS = {
new CreateZoneCommand(), new CreateZoneCommand(),
new ListZonesCommand() new ListZonesCommand(),
new ProvisionTrashCommand()
}; };
} }

View File

@ -329,6 +329,7 @@ Usage:
hdfs crypto -createZone -keyName <keyName> -path <path> hdfs crypto -createZone -keyName <keyName> -path <path>
hdfs crypto -listZones hdfs crypto -listZones
hdfs crypto -provisionTrash -path <path>
hdfs crypto -help <command-name> hdfs crypto -help <command-name>
See the [HDFS Transparent Encryption Documentation](./TransparentEncryption.html#crypto_command-line_interface) for more information. See the [HDFS Transparent Encryption Documentation](./TransparentEncryption.html#crypto_command-line_interface) for more information.

View File

@ -170,7 +170,7 @@ Create a new encryption zone.
| | | | | |
|:---- |:---- | |:---- |:---- |
| *path* | The path of the encryption zone to create. It must be an empty directory. | | *path* | The path of the encryption zone to create. It must be an empty directory. A trash directory is provisioned under this path.|
| *keyName* | Name of the key to use for the encryption zone. | | *keyName* | Name of the key to use for the encryption zone. |
### <a name="listZones"></a>listZones ### <a name="listZones"></a>listZones
@ -179,6 +179,16 @@ Usage: `[-listZones]`
List all encryption zones. Requires superuser permissions. List all encryption zones. Requires superuser permissions.
### <a name="provisionTrash"></a>provisionTrash
Usage: `[-provisionTrash -path <path>]`
Provision a trash directory for an encryption zone.
| | |
|:---- |:---- |
| *path* | The path to the root of the encryption zone. |
<a name="Example_usage"></a>Example usage <a name="Example_usage"></a>Example usage
------------- -------------
@ -222,6 +232,7 @@ This restriction enhances security and eases system management significantly. Al
To comply with the above rule, each encryption zone has its own `.Trash` directory under the "zone directory". E.g., after `hdfs dfs rm /zone/encryptedFile`, `encryptedFile` will be moved to `/zone/.Trash`, instead of the `.Trash` directory under the user's home directory. When the entire encryption zone is deleted, the "zone directory" will be moved to the `.Trash` directory under the user's home directory. To comply with the above rule, each encryption zone has its own `.Trash` directory under the "zone directory". E.g., after `hdfs dfs rm /zone/encryptedFile`, `encryptedFile` will be moved to `/zone/.Trash`, instead of the `.Trash` directory under the user's home directory. When the entire encryption zone is deleted, the "zone directory" will be moved to the `.Trash` directory under the user's home directory.
The `crypto` command before Hadoop 2.8.0 does not provision the `.Trash` directory automatically. If an encryption zone is created before Hadoop 2.8.0, and then the cluster is upgraded to Hadoop 2.8.0 or above, the trash directory can be provisioned using `-provisionTrash` option (e.g., `hdfs crypto -provisionTrash -path /zone`).
<a name="Attack_vectors"></a>Attack vectors <a name="Attack_vectors"></a>Attack vectors
-------------- --------------

View File

@ -29,6 +29,7 @@ import java.security.PrivilegedExceptionAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
@ -59,7 +60,9 @@ import org.apache.hadoop.fs.FileSystemTestWrapper;
import org.apache.hadoop.fs.FsShell; import org.apache.hadoop.fs.FsShell;
import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator; import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.client.CreateEncryptionZoneFlag;
import org.apache.hadoop.hdfs.client.HdfsAdmin; import org.apache.hadoop.hdfs.client.HdfsAdmin;
import org.apache.hadoop.hdfs.protocol.ClientProtocol; import org.apache.hadoop.hdfs.protocol.ClientProtocol;
import org.apache.hadoop.hdfs.protocol.EncryptionZone; import org.apache.hadoop.hdfs.protocol.EncryptionZone;
@ -70,6 +73,7 @@ import org.apache.hadoop.hdfs.server.namenode.EncryptionFaultInjector;
import org.apache.hadoop.hdfs.server.namenode.EncryptionZoneManager; import org.apache.hadoop.hdfs.server.namenode.EncryptionZoneManager;
import org.apache.hadoop.hdfs.server.namenode.FSImageTestUtil; import org.apache.hadoop.hdfs.server.namenode.FSImageTestUtil;
import org.apache.hadoop.hdfs.server.namenode.NamenodeFsck; import org.apache.hadoop.hdfs.server.namenode.NamenodeFsck;
import org.apache.hadoop.hdfs.tools.CryptoAdmin;
import org.apache.hadoop.hdfs.tools.DFSck; import org.apache.hadoop.hdfs.tools.DFSck;
import org.apache.hadoop.hdfs.tools.offlineImageViewer.PBImageXmlWriter; import org.apache.hadoop.hdfs.tools.offlineImageViewer.PBImageXmlWriter;
import org.apache.hadoop.hdfs.web.WebHdfsConstants; import org.apache.hadoop.hdfs.web.WebHdfsConstants;
@ -131,6 +135,9 @@ public class TestEncryptionZones {
protected FileSystemTestWrapper fsWrapper; protected FileSystemTestWrapper fsWrapper;
protected FileContextTestWrapper fcWrapper; protected FileContextTestWrapper fcWrapper;
protected static final EnumSet< CreateEncryptionZoneFlag > NO_TRASH =
EnumSet.of(CreateEncryptionZoneFlag.NO_TRASH);
protected String getKeyProviderURI() { protected String getKeyProviderURI() {
return JavaKeyStoreProvider.SCHEME_NAME + "://file" + return JavaKeyStoreProvider.SCHEME_NAME + "://file" +
new Path(testRootDir.toString(), "test.jks").toUri(); new Path(testRootDir.toString(), "test.jks").toUri();
@ -215,6 +222,106 @@ public class TestEncryptionZones {
); );
} }
/**
* Make sure hdfs crypto -createZone command creates a trash directory
* with sticky bits.
* @throws Exception
*/
@Test(timeout = 60000)
public void testTrashStickyBit() throws Exception {
// create an EZ /zones/zone1, make it world writable.
final Path zoneParent = new Path("/zones");
final Path zone1 = new Path(zoneParent, "zone1");
CryptoAdmin cryptoAdmin = new CryptoAdmin(conf);
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
fsWrapper.setPermission(zone1,
new FsPermission(FsAction.ALL, FsAction.ALL, FsAction.ALL));
String[] cryptoArgv = new String[]{"-createZone", "-keyName", TEST_KEY,
"-path", zone1.toUri().getPath()};
cryptoAdmin.run(cryptoArgv);
// create a file in EZ
final Path ezfile1 = new Path(zone1, "file1");
// Create the encrypted file in zone1
final int len = 8192;
DFSTestUtil.createFile(fs, ezfile1, len, (short) 1, 0xFEED);
// enable trash, delete /zones/zone1/file1,
// which moves the file to
// /zones/zone1/.Trash/$SUPERUSER/Current/zones/zone1/file1
Configuration clientConf = new Configuration(conf);
clientConf.setLong(FS_TRASH_INTERVAL_KEY, 1);
final FsShell shell = new FsShell(clientConf);
String[] argv = new String[]{"-rm", ezfile1.toString()};
int res = ToolRunner.run(shell, argv);
assertEquals("Can't remove a file in EZ as superuser", 0, res);
final Path trashDir = new Path(zone1, FileSystem.TRASH_PREFIX);
assertTrue(fsWrapper.exists(trashDir));
FileStatus trashFileStatus = fsWrapper.getFileStatus(trashDir);
assertTrue(trashFileStatus.getPermission().getStickyBit());
// create a non-privileged user
final UserGroupInformation user = UserGroupInformation.
createUserForTesting("user", new String[] { "mygroup" });
user.doAs(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
final Path ezfile2 = new Path(zone1, "file2");
final int len = 8192;
// create a file /zones/zone1/file2 in EZ
// this file is owned by user:mygroup
FileSystem fs2 = FileSystem.get(cluster.getConfiguration(0));
DFSTestUtil.createFile(fs2, ezfile2, len, (short) 1, 0xFEED);
// delete /zones/zone1/file2,
// which moves the file to
// /zones/zone1/.Trash/user/Current/zones/zone1/file2
String[] argv = new String[]{"-rm", ezfile2.toString()};
int res = ToolRunner.run(shell, argv);
assertEquals("Can't remove a file in EZ as user:mygroup", 0, res);
return null;
}
});
}
/**
* Make sure hdfs crypto -provisionTrash command creates a trash directory
* with sticky bits.
* @throws Exception
*/
@Test(timeout = 60000)
public void testProvisionTrash() throws Exception {
// create an EZ /zones/zone1
final Path zoneParent = new Path("/zones");
final Path zone1 = new Path(zoneParent, "zone1");
CryptoAdmin cryptoAdmin = new CryptoAdmin(conf);
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
String[] cryptoArgv = new String[]{"-createZone", "-keyName", TEST_KEY,
"-path", zone1.toUri().getPath()};
cryptoAdmin.run(cryptoArgv);
// remove the trash directory
Configuration clientConf = new Configuration(conf);
clientConf.setLong(FS_TRASH_INTERVAL_KEY, 1);
final FsShell shell = new FsShell(clientConf);
final Path trashDir = new Path(zone1, FileSystem.TRASH_PREFIX);
String[] argv = new String[]{"-rmdir", trashDir.toUri().getPath()};
int res = ToolRunner.run(shell, argv);
assertEquals("Unable to delete trash directory.", 0, res);
assertFalse(fsWrapper.exists(trashDir));
// execute -provisionTrash command option and make sure the trash
// directory has sticky bit.
String[] provisionTrashArgv = new String[]{"-provisionTrash", "-path",
zone1.toUri().getPath()};
cryptoAdmin.run(provisionTrashArgv);
assertTrue(fsWrapper.exists(trashDir));
FileStatus trashFileStatus = fsWrapper.getFileStatus(trashDir);
assertTrue(trashFileStatus.getPermission().getStickyBit());
}
@Test(timeout = 60000) @Test(timeout = 60000)
public void testBasicOperations() throws Exception { public void testBasicOperations() throws Exception {
@ -223,8 +330,9 @@ public class TestEncryptionZones {
/* Test failure of create EZ on a directory that doesn't exist. */ /* Test failure of create EZ on a directory that doesn't exist. */
final Path zoneParent = new Path("/zones"); final Path zoneParent = new Path("/zones");
final Path zone1 = new Path(zoneParent, "zone1"); final Path zone1 = new Path(zoneParent, "zone1");
try { try {
dfsAdmin.createEncryptionZone(zone1, TEST_KEY); dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
fail("expected /test doesn't exist"); fail("expected /test doesn't exist");
} catch (IOException e) { } catch (IOException e) {
assertExceptionContains("cannot find", e); assertExceptionContains("cannot find", e);
@ -232,20 +340,20 @@ public class TestEncryptionZones {
/* Normal creation of an EZ */ /* Normal creation of an EZ */
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true); fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY); dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
assertNumZones(++numZones); assertNumZones(++numZones);
assertZonePresent(null, zone1.toString()); assertZonePresent(null, zone1.toString());
/* Test failure of create EZ on a directory which is already an EZ. */ /* Test failure of create EZ on a directory which is already an EZ. */
try { try {
dfsAdmin.createEncryptionZone(zone1, TEST_KEY); dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
} catch (IOException e) { } catch (IOException e) {
assertExceptionContains("is already an encryption zone", e); assertExceptionContains("is already an encryption zone", e);
} }
/* create EZ on parent of an EZ should fail */ /* create EZ on parent of an EZ should fail */
try { try {
dfsAdmin.createEncryptionZone(zoneParent, TEST_KEY); dfsAdmin.createEncryptionZone(zoneParent, TEST_KEY, NO_TRASH);
fail("EZ over an EZ"); fail("EZ over an EZ");
} catch (IOException e) { } catch (IOException e) {
assertExceptionContains("encryption zone for a non-empty directory", e); assertExceptionContains("encryption zone for a non-empty directory", e);
@ -256,7 +364,7 @@ public class TestEncryptionZones {
final Path notEmptyChild = new Path(notEmpty, "child"); final Path notEmptyChild = new Path(notEmpty, "child");
fsWrapper.mkdir(notEmptyChild, FsPermission.getDirDefault(), true); fsWrapper.mkdir(notEmptyChild, FsPermission.getDirDefault(), true);
try { try {
dfsAdmin.createEncryptionZone(notEmpty, TEST_KEY); dfsAdmin.createEncryptionZone(notEmpty, TEST_KEY, NO_TRASH);
fail("Created EZ on an non-empty directory with folder"); fail("Created EZ on an non-empty directory with folder");
} catch (IOException e) { } catch (IOException e) {
assertExceptionContains("create an encryption zone", e); assertExceptionContains("create an encryption zone", e);
@ -266,7 +374,7 @@ public class TestEncryptionZones {
/* create EZ on a folder with a file fails */ /* create EZ on a folder with a file fails */
fsWrapper.createFile(notEmptyChild); fsWrapper.createFile(notEmptyChild);
try { try {
dfsAdmin.createEncryptionZone(notEmpty, TEST_KEY); dfsAdmin.createEncryptionZone(notEmpty, TEST_KEY, NO_TRASH);
fail("Created EZ on an non-empty directory with file"); fail("Created EZ on an non-empty directory with file");
} catch (IOException e) { } catch (IOException e) {
assertExceptionContains("create an encryption zone", e); assertExceptionContains("create an encryption zone", e);
@ -274,7 +382,7 @@ public class TestEncryptionZones {
/* Test failure of create EZ on a file. */ /* Test failure of create EZ on a file. */
try { try {
dfsAdmin.createEncryptionZone(notEmptyChild, TEST_KEY); dfsAdmin.createEncryptionZone(notEmptyChild, TEST_KEY, NO_TRASH);
fail("Created EZ on a file"); fail("Created EZ on a file");
} catch (IOException e) { } catch (IOException e) {
assertExceptionContains("create an encryption zone for a file.", e); assertExceptionContains("create an encryption zone for a file.", e);
@ -285,7 +393,7 @@ public class TestEncryptionZones {
fsWrapper.mkdir(zone2, FsPermission.getDirDefault(), false); fsWrapper.mkdir(zone2, FsPermission.getDirDefault(), false);
final String myKeyName = "mykeyname"; final String myKeyName = "mykeyname";
try { try {
dfsAdmin.createEncryptionZone(zone2, myKeyName); dfsAdmin.createEncryptionZone(zone2, myKeyName, NO_TRASH);
fail("expected key doesn't exist"); fail("expected key doesn't exist");
} catch (IOException e) { } catch (IOException e) {
assertExceptionContains("doesn't exist.", e); assertExceptionContains("doesn't exist.", e);
@ -293,13 +401,13 @@ public class TestEncryptionZones {
/* Test failure of empty and null key name */ /* Test failure of empty and null key name */
try { try {
dfsAdmin.createEncryptionZone(zone2, ""); dfsAdmin.createEncryptionZone(zone2, "", NO_TRASH);
fail("created a zone with empty key name"); fail("created a zone with empty key name");
} catch (IOException e) { } catch (IOException e) {
assertExceptionContains("Must specify a key name when creating", e); assertExceptionContains("Must specify a key name when creating", e);
} }
try { try {
dfsAdmin.createEncryptionZone(zone2, null); dfsAdmin.createEncryptionZone(zone2, null, NO_TRASH);
fail("created a zone with null key name"); fail("created a zone with null key name");
} catch (IOException e) { } catch (IOException e) {
assertExceptionContains("Must specify a key name when creating", e); assertExceptionContains("Must specify a key name when creating", e);
@ -309,7 +417,7 @@ public class TestEncryptionZones {
/* Test success of creating an EZ when they key exists. */ /* Test success of creating an EZ when they key exists. */
DFSTestUtil.createKey(myKeyName, cluster, conf); DFSTestUtil.createKey(myKeyName, cluster, conf);
dfsAdmin.createEncryptionZone(zone2, myKeyName); dfsAdmin.createEncryptionZone(zone2, myKeyName, NO_TRASH);
assertNumZones(++numZones); assertNumZones(++numZones);
assertZonePresent(myKeyName, zone2.toString()); assertZonePresent(myKeyName, zone2.toString());
@ -325,7 +433,7 @@ public class TestEncryptionZones {
final HdfsAdmin userAdmin = final HdfsAdmin userAdmin =
new HdfsAdmin(FileSystem.getDefaultUri(conf), conf); new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
try { try {
userAdmin.createEncryptionZone(nonSuper, TEST_KEY); userAdmin.createEncryptionZone(nonSuper, TEST_KEY, NO_TRASH);
fail("createEncryptionZone is superuser-only operation"); fail("createEncryptionZone is superuser-only operation");
} catch (AccessControlException e) { } catch (AccessControlException e) {
assertExceptionContains("Superuser privilege is required", e); assertExceptionContains("Superuser privilege is required", e);
@ -337,7 +445,7 @@ public class TestEncryptionZones {
// Test success of creating an encryption zone a few levels down. // Test success of creating an encryption zone a few levels down.
Path deepZone = new Path("/d/e/e/p/zone"); Path deepZone = new Path("/d/e/e/p/zone");
fsWrapper.mkdir(deepZone, FsPermission.getDirDefault(), true); fsWrapper.mkdir(deepZone, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(deepZone, TEST_KEY); dfsAdmin.createEncryptionZone(deepZone, TEST_KEY, NO_TRASH);
assertNumZones(++numZones); assertNumZones(++numZones);
assertZonePresent(null, deepZone.toString()); assertZonePresent(null, deepZone.toString());
@ -345,7 +453,7 @@ public class TestEncryptionZones {
for (int i=1; i<6; i++) { for (int i=1; i<6; i++) {
final Path zonePath = new Path("/listZone" + i); final Path zonePath = new Path("/listZone" + i);
fsWrapper.mkdir(zonePath, FsPermission.getDirDefault(), false); fsWrapper.mkdir(zonePath, FsPermission.getDirDefault(), false);
dfsAdmin.createEncryptionZone(zonePath, TEST_KEY); dfsAdmin.createEncryptionZone(zonePath, TEST_KEY, NO_TRASH);
numZones++; numZones++;
assertNumZones(numZones); assertNumZones(numZones);
assertZonePresent(null, zonePath.toString()); assertZonePresent(null, zonePath.toString());
@ -365,7 +473,7 @@ public class TestEncryptionZones {
// without persisting the namespace. // without persisting the namespace.
Path nonpersistZone = new Path("/nonpersistZone"); Path nonpersistZone = new Path("/nonpersistZone");
fsWrapper.mkdir(nonpersistZone, FsPermission.getDirDefault(), false); fsWrapper.mkdir(nonpersistZone, FsPermission.getDirDefault(), false);
dfsAdmin.createEncryptionZone(nonpersistZone, TEST_KEY); dfsAdmin.createEncryptionZone(nonpersistZone, TEST_KEY, NO_TRASH);
numZones++; numZones++;
cluster.restartNameNode(true); cluster.restartNameNode(true);
assertNumZones(numZones); assertNumZones(numZones);
@ -379,7 +487,7 @@ public class TestEncryptionZones {
final Path zone1 = new Path(rootDir, "zone1"); final Path zone1 = new Path(rootDir, "zone1");
/* Normal creation of an EZ on rootDir */ /* Normal creation of an EZ on rootDir */
dfsAdmin.createEncryptionZone(rootDir, TEST_KEY); dfsAdmin.createEncryptionZone(rootDir, TEST_KEY, NO_TRASH);
assertNumZones(++numZones); assertNumZones(++numZones);
assertZonePresent(null, rootDir.toString()); assertZonePresent(null, rootDir.toString());
@ -407,10 +515,10 @@ public class TestEncryptionZones {
final Path allPath = new Path(testRoot, "accessall"); final Path allPath = new Path(testRoot, "accessall");
fsWrapper.mkdir(superPath, new FsPermission((short) 0700), true); fsWrapper.mkdir(superPath, new FsPermission((short) 0700), true);
dfsAdmin.createEncryptionZone(superPath, TEST_KEY); dfsAdmin.createEncryptionZone(superPath, TEST_KEY, NO_TRASH);
fsWrapper.mkdir(allPath, new FsPermission((short) 0707), true); fsWrapper.mkdir(allPath, new FsPermission((short) 0707), true);
dfsAdmin.createEncryptionZone(allPath, TEST_KEY); dfsAdmin.createEncryptionZone(allPath, TEST_KEY, NO_TRASH);
user.doAs(new PrivilegedExceptionAction<Object>() { user.doAs(new PrivilegedExceptionAction<Object>() {
@Override @Override
@ -450,8 +558,8 @@ public class TestEncryptionZones {
fsWrapper.mkdir(superPath, new FsPermission((short) 0700), false); fsWrapper.mkdir(superPath, new FsPermission((short) 0700), false);
fsWrapper.mkdir(allPath, new FsPermission((short) 0777), false); fsWrapper.mkdir(allPath, new FsPermission((short) 0777), false);
fsWrapper.mkdir(nonEZDir, new FsPermission((short) 0777), false); fsWrapper.mkdir(nonEZDir, new FsPermission((short) 0777), false);
dfsAdmin.createEncryptionZone(superPath, TEST_KEY); dfsAdmin.createEncryptionZone(superPath, TEST_KEY, NO_TRASH);
dfsAdmin.createEncryptionZone(allPath, TEST_KEY); dfsAdmin.createEncryptionZone(allPath, TEST_KEY, NO_TRASH);
dfsAdmin.allowSnapshot(new Path("/")); dfsAdmin.allowSnapshot(new Path("/"));
final Path newSnap = fs.createSnapshot(new Path("/")); final Path newSnap = fs.createSnapshot(new Path("/"));
DFSTestUtil.createFile(fs, superPathFile, len, (short) 1, 0xFEED); DFSTestUtil.createFile(fs, superPathFile, len, (short) 1, 0xFEED);
@ -556,7 +664,7 @@ public class TestEncryptionZones {
final Path pathFooBarFile = new Path(pathFooBar, "file"); final Path pathFooBarFile = new Path(pathFooBar, "file");
final int len = 8192; final int len = 8192;
wrapper.mkdir(pathFoo, FsPermission.getDirDefault(), true); wrapper.mkdir(pathFoo, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(pathFoo, TEST_KEY); dfsAdmin.createEncryptionZone(pathFoo, TEST_KEY, NO_TRASH);
wrapper.mkdir(pathFooBaz, FsPermission.getDirDefault(), true); wrapper.mkdir(pathFooBaz, FsPermission.getDirDefault(), true);
DFSTestUtil.createFile(fs, pathFooBazFile, len, (short) 1, 0xFEED); DFSTestUtil.createFile(fs, pathFooBazFile, len, (short) 1, 0xFEED);
String contents = DFSTestUtil.readFile(fs, pathFooBazFile); String contents = DFSTestUtil.readFile(fs, pathFooBazFile);
@ -615,7 +723,7 @@ public class TestEncryptionZones {
// Create the first enc file // Create the first enc file
final Path zone = new Path("/zone"); final Path zone = new Path("/zone");
fs.mkdirs(zone); fs.mkdirs(zone);
dfsAdmin.createEncryptionZone(zone, TEST_KEY); dfsAdmin.createEncryptionZone(zone, TEST_KEY, NO_TRASH);
final Path encFile1 = new Path(zone, "myfile"); final Path encFile1 = new Path(zone, "myfile");
DFSTestUtil.createFile(fs, encFile1, len, (short) 1, 0xFEED); DFSTestUtil.createFile(fs, encFile1, len, (short) 1, 0xFEED);
// Read them back in and compare byte-by-byte // Read them back in and compare byte-by-byte
@ -650,7 +758,7 @@ public class TestEncryptionZones {
final Path zone = new Path("/zone"); final Path zone = new Path("/zone");
fs.mkdirs(zone); fs.mkdirs(zone);
dfsAdmin.createEncryptionZone(zone, TEST_KEY); dfsAdmin.createEncryptionZone(zone, TEST_KEY, NO_TRASH);
/* Create an unencrypted file for comparison purposes. */ /* Create an unencrypted file for comparison purposes. */
final Path unencFile = new Path("/unenc"); final Path unencFile = new Path("/unenc");
@ -696,7 +804,7 @@ public class TestEncryptionZones {
new HdfsAdmin(FileSystem.getDefaultUri(conf), conf); new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
final Path zone = new Path("/zone"); final Path zone = new Path("/zone");
fs.mkdirs(zone); fs.mkdirs(zone);
dfsAdmin.createEncryptionZone(zone, TEST_KEY); dfsAdmin.createEncryptionZone(zone, TEST_KEY, NO_TRASH);
// Create a file in an EZ, which should succeed // Create a file in an EZ, which should succeed
DFSTestUtil DFSTestUtil
.createFile(fs, new Path(zone, "success1"), 0, (short) 1, 0xFEED); .createFile(fs, new Path(zone, "success1"), 0, (short) 1, 0xFEED);
@ -827,7 +935,7 @@ public class TestEncryptionZones {
final Path zone1 = new Path("/zone1"); final Path zone1 = new Path("/zone1");
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true); fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
try { try {
dfsAdmin.createEncryptionZone(zone1, TEST_KEY); dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
fail("expected exception"); fail("expected exception");
} catch (IOException e) { } catch (IOException e) {
assertExceptionContains("since no key provider is available", e); assertExceptionContains("since no key provider is available", e);
@ -869,7 +977,7 @@ public class TestEncryptionZones {
// Create an encrypted file to check isEncrypted returns true // Create an encrypted file to check isEncrypted returns true
final Path zone = new Path(prefix, "zone"); final Path zone = new Path(prefix, "zone");
fsWrapper.mkdir(zone, FsPermission.getDirDefault(), true); fsWrapper.mkdir(zone, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(zone, TEST_KEY); dfsAdmin.createEncryptionZone(zone, TEST_KEY, NO_TRASH);
final Path encFile = new Path(zone, "encfile"); final Path encFile = new Path(zone, "encfile");
fsWrapper.createFile(encFile); fsWrapper.createFile(encFile);
stat = fsWrapper.getFileStatus(encFile); stat = fsWrapper.getFileStatus(encFile);
@ -1010,7 +1118,7 @@ public class TestEncryptionZones {
executor.submit(new InjectFaultTask() { executor.submit(new InjectFaultTask() {
@Override @Override
public void doFault() throws Exception { public void doFault() throws Exception {
dfsAdmin.createEncryptionZone(zone1, TEST_KEY); dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
} }
@Override @Override
public void doCleanup() throws Exception { public void doCleanup() throws Exception {
@ -1036,14 +1144,14 @@ public class TestEncryptionZones {
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true); fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
final String otherKey = "other_key"; final String otherKey = "other_key";
DFSTestUtil.createKey(otherKey, cluster, conf); DFSTestUtil.createKey(otherKey, cluster, conf);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY); dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
executor.submit(new InjectFaultTask() { executor.submit(new InjectFaultTask() {
@Override @Override
public void doFault() throws Exception { public void doFault() throws Exception {
fsWrapper.delete(zone1, true); fsWrapper.delete(zone1, true);
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true); fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(zone1, otherKey); dfsAdmin.createEncryptionZone(zone1, otherKey, NO_TRASH);
} }
@Override @Override
public void doCleanup() throws Exception { public void doCleanup() throws Exception {
@ -1056,7 +1164,7 @@ public class TestEncryptionZones {
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true); fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
final String anotherKey = "another_key"; final String anotherKey = "another_key";
DFSTestUtil.createKey(anotherKey, cluster, conf); DFSTestUtil.createKey(anotherKey, cluster, conf);
dfsAdmin.createEncryptionZone(zone1, anotherKey); dfsAdmin.createEncryptionZone(zone1, anotherKey, NO_TRASH);
String keyToUse = otherKey; String keyToUse = otherKey;
MyInjector injector = new MyInjector(); MyInjector injector = new MyInjector();
@ -1068,7 +1176,7 @@ public class TestEncryptionZones {
injector.ready.await(); injector.ready.await();
fsWrapper.delete(zone1, true); fsWrapper.delete(zone1, true);
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true); fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(zone1, keyToUse); dfsAdmin.createEncryptionZone(zone1, keyToUse, NO_TRASH);
if (keyToUse == otherKey) { if (keyToUse == otherKey) {
keyToUse = anotherKey; keyToUse = anotherKey;
} else { } else {
@ -1129,7 +1237,7 @@ public class TestEncryptionZones {
final Path zone1 = new Path(zoneParent, "zone1"); final Path zone1 = new Path(zoneParent, "zone1");
final Path zone1File = new Path(zone1, "file"); final Path zone1File = new Path(zone1, "file");
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true); fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY); dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
DFSTestUtil.createFile(fs, zone1File, len, (short) 1, 0xFEED); DFSTestUtil.createFile(fs, zone1File, len, (short) 1, 0xFEED);
ByteArrayOutputStream bStream = new ByteArrayOutputStream(); ByteArrayOutputStream bStream = new ByteArrayOutputStream();
PrintStream out = new PrintStream(bStream, true); PrintStream out = new PrintStream(bStream, true);
@ -1164,7 +1272,7 @@ public class TestEncryptionZones {
final Path zoneFile = new Path(zone, "zoneFile"); final Path zoneFile = new Path(zone, "zoneFile");
fsWrapper.mkdir(zone, FsPermission.getDirDefault(), true); fsWrapper.mkdir(zone, FsPermission.getDirDefault(), true);
dfsAdmin.allowSnapshot(zoneParent); dfsAdmin.allowSnapshot(zoneParent);
dfsAdmin.createEncryptionZone(zone, TEST_KEY); dfsAdmin.createEncryptionZone(zone, TEST_KEY, NO_TRASH);
DFSTestUtil.createFile(fs, zoneFile, len, (short) 1, 0xFEED); DFSTestUtil.createFile(fs, zoneFile, len, (short) 1, 0xFEED);
String contents = DFSTestUtil.readFile(fs, zoneFile); String contents = DFSTestUtil.readFile(fs, zoneFile);
final Path snap1 = fs.createSnapshot(zoneParent, "snap1"); final Path snap1 = fs.createSnapshot(zoneParent, "snap1");
@ -1182,7 +1290,7 @@ public class TestEncryptionZones {
dfsAdmin.getEncryptionZoneForPath(snap2Zone)); dfsAdmin.getEncryptionZoneForPath(snap2Zone));
// Create the encryption zone again // Create the encryption zone again
dfsAdmin.createEncryptionZone(zone, TEST_KEY2); dfsAdmin.createEncryptionZone(zone, TEST_KEY2, NO_TRASH);
final Path snap3 = fs.createSnapshot(zoneParent, "snap3"); final Path snap3 = fs.createSnapshot(zoneParent, "snap3");
final Path snap3Zone = new Path(snap3, zone.getName()); final Path snap3Zone = new Path(snap3, zone.getName());
// Check that snap3's EZ has the correct settings // Check that snap3's EZ has the correct settings
@ -1245,7 +1353,7 @@ public class TestEncryptionZones {
final Path link = new Path(linkParent, "link"); final Path link = new Path(linkParent, "link");
final Path target = new Path(targetParent, "target"); final Path target = new Path(targetParent, "target");
fs.mkdirs(parent); fs.mkdirs(parent);
dfsAdmin.createEncryptionZone(parent, TEST_KEY); dfsAdmin.createEncryptionZone(parent, TEST_KEY, NO_TRASH);
fs.mkdirs(linkParent); fs.mkdirs(linkParent);
fs.mkdirs(targetParent); fs.mkdirs(targetParent);
DFSTestUtil.createFile(fs, target, len, (short)1, 0xFEED); DFSTestUtil.createFile(fs, target, len, (short)1, 0xFEED);
@ -1259,8 +1367,8 @@ public class TestEncryptionZones {
// encryption zones // encryption zones
fs.mkdirs(linkParent); fs.mkdirs(linkParent);
fs.mkdirs(targetParent); fs.mkdirs(targetParent);
dfsAdmin.createEncryptionZone(linkParent, TEST_KEY); dfsAdmin.createEncryptionZone(linkParent, TEST_KEY, NO_TRASH);
dfsAdmin.createEncryptionZone(targetParent, TEST_KEY); dfsAdmin.createEncryptionZone(targetParent, TEST_KEY, NO_TRASH);
DFSTestUtil.createFile(fs, target, len, (short)1, 0xFEED); DFSTestUtil.createFile(fs, target, len, (short)1, 0xFEED);
content = DFSTestUtil.readFile(fs, target); content = DFSTestUtil.readFile(fs, target);
fs.createSymlink(target, link, false); fs.createSymlink(target, link, false);
@ -1275,7 +1383,7 @@ public class TestEncryptionZones {
final int len = 8192; final int len = 8192;
final Path ez = new Path("/ez"); final Path ez = new Path("/ez");
fs.mkdirs(ez); fs.mkdirs(ez);
dfsAdmin.createEncryptionZone(ez, TEST_KEY); dfsAdmin.createEncryptionZone(ez, TEST_KEY, NO_TRASH);
final Path src1 = new Path(ez, "src1"); final Path src1 = new Path(ez, "src1");
final Path src2 = new Path(ez, "src2"); final Path src2 = new Path(ez, "src2");
final Path target = new Path(ez, "target"); final Path target = new Path(ez, "target");
@ -1302,7 +1410,7 @@ public class TestEncryptionZones {
final Path zone1 = new Path(zoneParent, "zone1"); final Path zone1 = new Path(zoneParent, "zone1");
final Path zone1File = new Path(zone1, "file"); final Path zone1File = new Path(zone1, "file");
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true); fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY); dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
DFSTestUtil.createFile(fs, zone1File, len, (short) 1, 0xFEED); DFSTestUtil.createFile(fs, zone1File, len, (short) 1, 0xFEED);
fs.setSafeMode(SafeModeAction.SAFEMODE_ENTER, false); fs.setSafeMode(SafeModeAction.SAFEMODE_ENTER, false);
fs.saveNamespace(); fs.saveNamespace();
@ -1332,7 +1440,7 @@ public class TestEncryptionZones {
final Path rootDir = new Path("/"); final Path rootDir = new Path("/");
final Path zoneFile = new Path(rootDir, "file"); final Path zoneFile = new Path(rootDir, "file");
final Path rawFile = new Path("/.reserved/raw/file"); final Path rawFile = new Path("/.reserved/raw/file");
dfsAdmin.createEncryptionZone(rootDir, TEST_KEY); dfsAdmin.createEncryptionZone(rootDir, TEST_KEY, NO_TRASH);
DFSTestUtil.createFile(fs, zoneFile, len, (short) 1, 0xFEED); DFSTestUtil.createFile(fs, zoneFile, len, (short) 1, 0xFEED);
assertEquals("File can be created on the root encryption zone " + assertEquals("File can be created on the root encryption zone " +
@ -1353,7 +1461,7 @@ public class TestEncryptionZones {
final Path zoneFile = new Path("file"); final Path zoneFile = new Path("file");
fs.setWorkingDirectory(baseDir); fs.setWorkingDirectory(baseDir);
fs.mkdirs(zoneDir); fs.mkdirs(zoneDir);
dfsAdmin.createEncryptionZone(zoneDir, TEST_KEY); dfsAdmin.createEncryptionZone(zoneDir, TEST_KEY, NO_TRASH);
DFSTestUtil.createFile(fs, zoneFile, len, (short) 1, 0xFEED); DFSTestUtil.createFile(fs, zoneFile, len, (short) 1, 0xFEED);
assertNumZones(1); assertNumZones(1);
@ -1367,7 +1475,7 @@ public class TestEncryptionZones {
public void testGetEncryptionZoneOnANonExistentZoneFile() throws Exception { public void testGetEncryptionZoneOnANonExistentZoneFile() throws Exception {
final Path ez = new Path("/ez"); final Path ez = new Path("/ez");
fs.mkdirs(ez); fs.mkdirs(ez);
dfsAdmin.createEncryptionZone(ez, TEST_KEY); dfsAdmin.createEncryptionZone(ez, TEST_KEY, NO_TRASH);
Path zoneFile = new Path(ez, "file"); Path zoneFile = new Path(ez, "file");
try { try {
fs.getEZForPath(zoneFile); fs.getEZForPath(zoneFile);
@ -1392,7 +1500,7 @@ public class TestEncryptionZones {
new HdfsAdmin(FileSystem.getDefaultUri(conf), conf); new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
final Path zone1 = new Path("/zone1"); final Path zone1 = new Path("/zone1");
fs.mkdirs(zone1); fs.mkdirs(zone1);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY); dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
// Create the encrypted file in zone1 // Create the encrypted file in zone1
final Path encFile1 = new Path(zone1, "encFile1"); final Path encFile1 = new Path(zone1, "encFile1");
@ -1413,12 +1521,12 @@ public class TestEncryptionZones {
final Path topEZ = new Path("/topEZ"); final Path topEZ = new Path("/topEZ");
fs.mkdirs(topEZ); fs.mkdirs(topEZ);
dfsAdmin.createEncryptionZone(topEZ, TEST_KEY); dfsAdmin.createEncryptionZone(topEZ, TEST_KEY, NO_TRASH);
final String NESTED_EZ_TEST_KEY = "nested_ez_test_key"; final String NESTED_EZ_TEST_KEY = "nested_ez_test_key";
DFSTestUtil.createKey(NESTED_EZ_TEST_KEY, cluster, conf); DFSTestUtil.createKey(NESTED_EZ_TEST_KEY, cluster, conf);
final Path nestedEZ = new Path(topEZ, "nestedEZ"); final Path nestedEZ = new Path(topEZ, "nestedEZ");
fs.mkdirs(nestedEZ); fs.mkdirs(nestedEZ);
dfsAdmin.createEncryptionZone(nestedEZ, NESTED_EZ_TEST_KEY); dfsAdmin.createEncryptionZone(nestedEZ, NESTED_EZ_TEST_KEY, NO_TRASH);
final Path topEZFile = new Path(topEZ, "file"); final Path topEZFile = new Path(topEZ, "file");
final Path nestedEZFile = new Path(nestedEZ, "file"); final Path nestedEZFile = new Path(nestedEZ, "file");
DFSTestUtil.createFile(fs, topEZFile, len, (short) 1, 0xFEED); DFSTestUtil.createFile(fs, topEZFile, len, (short) 1, 0xFEED);
@ -1433,7 +1541,7 @@ public class TestEncryptionZones {
public void testRootDirEZTrash() throws Exception { public void testRootDirEZTrash() throws Exception {
final HdfsAdmin dfsAdmin = final HdfsAdmin dfsAdmin =
new HdfsAdmin(FileSystem.getDefaultUri(conf), conf); new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
dfsAdmin.createEncryptionZone(new Path("/"), TEST_KEY); dfsAdmin.createEncryptionZone(new Path("/"), TEST_KEY, NO_TRASH);
final Path encFile = new Path("/encFile"); final Path encFile = new Path("/encFile");
final int len = 8192; final int len = 8192;
DFSTestUtil.createFile(fs, encFile, len, (short) 1, 0xFEED); DFSTestUtil.createFile(fs, encFile, len, (short) 1, 0xFEED);
@ -1449,13 +1557,13 @@ public class TestEncryptionZones {
new HdfsAdmin(FileSystem.getDefaultUri(conf), conf); new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
Path ezRoot1 = new Path("/ez1"); Path ezRoot1 = new Path("/ez1");
fs.mkdirs(ezRoot1); fs.mkdirs(ezRoot1);
dfsAdmin.createEncryptionZone(ezRoot1, TEST_KEY); dfsAdmin.createEncryptionZone(ezRoot1, TEST_KEY, NO_TRASH);
Path ezRoot2 = new Path("/ez2"); Path ezRoot2 = new Path("/ez2");
fs.mkdirs(ezRoot2); fs.mkdirs(ezRoot2);
dfsAdmin.createEncryptionZone(ezRoot2, TEST_KEY); dfsAdmin.createEncryptionZone(ezRoot2, TEST_KEY, NO_TRASH);
Path ezRoot3 = new Path("/ez3"); Path ezRoot3 = new Path("/ez3");
fs.mkdirs(ezRoot3); fs.mkdirs(ezRoot3);
dfsAdmin.createEncryptionZone(ezRoot3, TEST_KEY); dfsAdmin.createEncryptionZone(ezRoot3, TEST_KEY, NO_TRASH);
Collection<FileStatus> trashRootsBegin = fs.getTrashRoots(true); Collection<FileStatus> trashRootsBegin = fs.getTrashRoots(true);
assertEquals("Unexpected getTrashRoots result", 0, trashRootsBegin.size()); assertEquals("Unexpected getTrashRoots result", 0, trashRootsBegin.size());

View File

@ -23,6 +23,7 @@ import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.fs.FileSystemTestHelper; import org.apache.hadoop.fs.FileSystemTestHelper;
import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.client.CreateEncryptionZoneFlag;
import org.apache.hadoop.hdfs.server.namenode.ha.HATestUtil; import org.apache.hadoop.hdfs.server.namenode.ha.HATestUtil;
import org.apache.hadoop.hdfs.client.HdfsAdmin; import org.apache.hadoop.hdfs.client.HdfsAdmin;
import org.apache.hadoop.hdfs.server.namenode.NameNode; import org.apache.hadoop.hdfs.server.namenode.NameNode;
@ -33,6 +34,7 @@ import org.junit.Test;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.EnumSet;
/** /**
* Tests interaction of encryption zones with HA failover. * Tests interaction of encryption zones with HA failover.
@ -49,7 +51,8 @@ public class TestEncryptionZonesWithHA {
private File testRootDir; private File testRootDir;
private final String TEST_KEY = "test_key"; private final String TEST_KEY = "test_key";
protected static final EnumSet< CreateEncryptionZoneFlag > NO_TRASH =
EnumSet.of(CreateEncryptionZoneFlag.NO_TRASH);
@Before @Before
public void setupCluster() throws Exception { public void setupCluster() throws Exception {
@ -101,7 +104,7 @@ public class TestEncryptionZonesWithHA {
final Path dirChild = new Path(dir, "child"); final Path dirChild = new Path(dir, "child");
final Path dirFile = new Path(dir, "file"); final Path dirFile = new Path(dir, "file");
fs.mkdir(dir, FsPermission.getDirDefault()); fs.mkdir(dir, FsPermission.getDirDefault());
dfsAdmin0.createEncryptionZone(dir, TEST_KEY); dfsAdmin0.createEncryptionZone(dir, TEST_KEY, NO_TRASH);
fs.mkdir(dirChild, FsPermission.getDirDefault()); fs.mkdir(dirChild, FsPermission.getDirDefault());
DFSTestUtil.createFile(fs, dirFile, len, (short) 1, 0xFEED); DFSTestUtil.createFile(fs, dirFile, len, (short) 1, 0xFEED);
String contents = DFSTestUtil.readFile(fs, dirFile); String contents = DFSTestUtil.readFile(fs, dirFile);

View File

@ -73,7 +73,7 @@ public class TestEncryptionZonesWithKMS extends TestEncryptionZones {
public void testCreateEZPopulatesEDEKCache() throws Exception { public void testCreateEZPopulatesEDEKCache() throws Exception {
final Path zonePath = new Path("/TestEncryptionZone"); final Path zonePath = new Path("/TestEncryptionZone");
fsWrapper.mkdir(zonePath, FsPermission.getDirDefault(), false); fsWrapper.mkdir(zonePath, FsPermission.getDirDefault(), false);
dfsAdmin.createEncryptionZone(zonePath, TEST_KEY); dfsAdmin.createEncryptionZone(zonePath, TEST_KEY, NO_TRASH);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
KMSClientProvider kcp = (KMSClientProvider) Whitebox KMSClientProvider kcp = (KMSClientProvider) Whitebox
.getInternalState(cluster.getNamesystem().getProvider(), "extension"); .getInternalState(cluster.getNamesystem().getProvider(), "extension");
@ -102,7 +102,7 @@ public class TestEncryptionZonesWithKMS extends TestEncryptionZones {
public void testWarmupEDEKCacheOnStartup() throws Exception { public void testWarmupEDEKCacheOnStartup() throws Exception {
final Path zonePath = new Path("/TestEncryptionZone"); final Path zonePath = new Path("/TestEncryptionZone");
fsWrapper.mkdir(zonePath, FsPermission.getDirDefault(), false); fsWrapper.mkdir(zonePath, FsPermission.getDirDefault(), false);
dfsAdmin.createEncryptionZone(zonePath, TEST_KEY); dfsAdmin.createEncryptionZone(zonePath, TEST_KEY, NO_TRASH);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
KMSClientProvider spy = (KMSClientProvider) Whitebox KMSClientProvider spy = (KMSClientProvider) Whitebox

View File

@ -21,6 +21,7 @@ import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.util.EnumSet;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.crypto.key.JavaKeyStoreProvider; import org.apache.hadoop.crypto.key.JavaKeyStoreProvider;
@ -31,6 +32,7 @@ import org.apache.hadoop.fs.FileSystemTestHelper;
import org.apache.hadoop.fs.FileSystemTestWrapper; import org.apache.hadoop.fs.FileSystemTestWrapper;
import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.client.CreateEncryptionZoneFlag;
import org.apache.hadoop.hdfs.client.HdfsAdmin; import org.apache.hadoop.hdfs.client.HdfsAdmin;
import org.apache.hadoop.hdfs.server.namenode.EncryptionZoneManager; import org.apache.hadoop.hdfs.server.namenode.EncryptionZoneManager;
import org.apache.hadoop.hdfs.server.namenode.FSDirectory; import org.apache.hadoop.hdfs.server.namenode.FSDirectory;
@ -61,6 +63,8 @@ public class TestReservedRawPaths {
protected FileSystemTestWrapper fsWrapper; protected FileSystemTestWrapper fsWrapper;
protected FileContextTestWrapper fcWrapper; protected FileContextTestWrapper fcWrapper;
protected static final EnumSet< CreateEncryptionZoneFlag > NO_TRASH =
EnumSet.of(CreateEncryptionZoneFlag.NO_TRASH);
@Before @Before
public void setup() throws Exception { public void setup() throws Exception {
@ -114,7 +118,7 @@ public class TestReservedRawPaths {
// Create the first enc file // Create the first enc file
final Path zone = new Path("/zone"); final Path zone = new Path("/zone");
fs.mkdirs(zone); fs.mkdirs(zone);
dfsAdmin.createEncryptionZone(zone, TEST_KEY); dfsAdmin.createEncryptionZone(zone, TEST_KEY, NO_TRASH);
final Path encFile1 = new Path(zone, "myfile"); final Path encFile1 = new Path(zone, "myfile");
DFSTestUtil.createFile(fs, encFile1, len, (short) 1, 0xFEED); DFSTestUtil.createFile(fs, encFile1, len, (short) 1, 0xFEED);
// Read them back in and compare byte-by-byte // Read them back in and compare byte-by-byte
@ -154,7 +158,7 @@ public class TestReservedRawPaths {
final Path zone = new Path("zone"); final Path zone = new Path("zone");
final Path slashZone = new Path("/", zone); final Path slashZone = new Path("/", zone);
fs.mkdirs(slashZone); fs.mkdirs(slashZone);
dfsAdmin.createEncryptionZone(slashZone, TEST_KEY); dfsAdmin.createEncryptionZone(slashZone, TEST_KEY, NO_TRASH);
final Path base = new Path("base"); final Path base = new Path("base");
final Path reservedRaw = new Path("/.reserved/raw"); final Path reservedRaw = new Path("/.reserved/raw");
@ -186,7 +190,7 @@ public class TestReservedRawPaths {
final Path zone = new Path("zone"); final Path zone = new Path("zone");
final Path slashZone = new Path("/", zone); final Path slashZone = new Path("/", zone);
fs.mkdirs(slashZone); fs.mkdirs(slashZone);
dfsAdmin.createEncryptionZone(slashZone, TEST_KEY); dfsAdmin.createEncryptionZone(slashZone, TEST_KEY, NO_TRASH);
final Path rawRoot = new Path("/.reserved/raw"); final Path rawRoot = new Path("/.reserved/raw");
final Path dir1 = new Path("dir1"); final Path dir1 = new Path("dir1");
final Path rawDir1 = new Path(rawRoot, dir1); final Path rawDir1 = new Path(rawRoot, dir1);
@ -224,7 +228,7 @@ public class TestReservedRawPaths {
final Path zone = new Path("zone"); final Path zone = new Path("zone");
final Path slashZone = new Path("/", zone); final Path slashZone = new Path("/", zone);
fs.mkdirs(slashZone); fs.mkdirs(slashZone);
dfsAdmin.createEncryptionZone(slashZone, TEST_KEY); dfsAdmin.createEncryptionZone(slashZone, TEST_KEY, NO_TRASH);
final Path base = new Path("base"); final Path base = new Path("base");
final Path reservedRaw = new Path("/.reserved/raw"); final Path reservedRaw = new Path("/.reserved/raw");
final int len = 8192; final int len = 8192;

View File

@ -68,6 +68,7 @@
<command>-fs NAMENODE -mkdir /foo</command> <command>-fs NAMENODE -mkdir /foo</command>
<command>-fs NAMENODE -ls /</command>- <command>-fs NAMENODE -ls /</command>-
<crypto-admin-command>-createZone -path /foo -keyName myKey</crypto-admin-command> <crypto-admin-command>-createZone -path /foo -keyName myKey</crypto-admin-command>
<command>-fs NAMENODE -rmdir /foo/.Trash</command>
<crypto-admin-command>-createZone -path /foo -keyName myKey</crypto-admin-command> <crypto-admin-command>-createZone -path /foo -keyName myKey</crypto-admin-command>
</test-commands> </test-commands>
<cleanup-commands> <cleanup-commands>
@ -91,7 +92,9 @@
<crypto-admin-command>-createZone -keyName myKey -path /foo/bar</crypto-admin-command> <crypto-admin-command>-createZone -keyName myKey -path /foo/bar</crypto-admin-command>
</test-commands> </test-commands>
<cleanup-commands> <cleanup-commands>
<command>-fs NAMENODE -rmdir /foo/bar/.Trash</command>
<command>-fs NAMENODE -rmdir /foo/bar</command> <command>-fs NAMENODE -rmdir /foo/bar</command>
<command>-fs NAMENODE -rmdir /foo/.Trash</command>
<command>-fs NAMENODE -rmdir /foo</command> <command>-fs NAMENODE -rmdir /foo</command>
</cleanup-commands> </cleanup-commands>
<comparators> <comparators>
@ -180,6 +183,7 @@
<crypto-admin-command>-createZone -path /foo/bar/baz -keyName myKey</crypto-admin-command> <crypto-admin-command>-createZone -path /foo/bar/baz -keyName myKey</crypto-admin-command>
</test-commands> </test-commands>
<cleanup-commands> <cleanup-commands>
<command>-fs NAMENODE -rmdir /foo/bar/baz/.Trash</command>
<command>-fs NAMENODE -rmdir /foo/bar/baz</command> <command>-fs NAMENODE -rmdir /foo/bar/baz</command>
<command>-fs NAMENODE -rmdir /foo/bar</command> <command>-fs NAMENODE -rmdir /foo/bar</command>
<command>-fs NAMENODE -rmdir /foo/</command> <command>-fs NAMENODE -rmdir /foo/</command>
@ -205,7 +209,9 @@
</test-commands> </test-commands>
<cleanup-commands> <cleanup-commands>
<command>-fs NAMENODE -rmdir /src/subdir</command> <command>-fs NAMENODE -rmdir /src/subdir</command>
<command>-fs NAMENODE -rmdir /src/.Trash</command>
<command>-fs NAMENODE -rmdir /src</command> <command>-fs NAMENODE -rmdir /src</command>
<command>-fs NAMENODE -rmdir /dst/.Trash</command>
<command>-fs NAMENODE -rmdir /dst</command> <command>-fs NAMENODE -rmdir /dst</command>
</cleanup-commands> </cleanup-commands>
<comparators> <comparators>
@ -227,6 +233,7 @@
</test-commands> </test-commands>
<cleanup-commands> <cleanup-commands>
<command>-fs NAMENODE -rmdir /src</command> <command>-fs NAMENODE -rmdir /src</command>
<command>-fs NAMENODE -rmdir /dst/.Trash</command>
<command>-fs NAMENODE -rmdir /dst</command> <command>-fs NAMENODE -rmdir /dst</command>
</cleanup-commands> </cleanup-commands>
<comparators> <comparators>
@ -249,6 +256,7 @@
</test-commands> </test-commands>
<cleanup-commands> <cleanup-commands>
<command>-fs NAMENODE -rm /src/foo</command> <command>-fs NAMENODE -rm /src/foo</command>
<command>-fs NAMENODE -rmdir /src/.Trash</command>
<command>-fs NAMENODE -rmdir /src</command> <command>-fs NAMENODE -rmdir /src</command>
<command>-fs NAMENODE -rmdir /dst</command> <command>-fs NAMENODE -rmdir /dst</command>
</cleanup-commands> </cleanup-commands>
@ -269,6 +277,7 @@
<command>-fs NAMENODE -ls /</command>- <command>-fs NAMENODE -ls /</command>-
</test-commands> </test-commands>
<cleanup-commands> <cleanup-commands>
<command>-fs NAMENODE -rmdir /src/.Trash</command>
<command>-fs NAMENODE -rmdir /src</command> <command>-fs NAMENODE -rmdir /src</command>
<command>-fs NAMENODE -rmdir /dst</command> <command>-fs NAMENODE -rmdir /dst</command>
</cleanup-commands> </cleanup-commands>
@ -292,6 +301,7 @@
<cleanup-commands> <cleanup-commands>
<command>-fs NAMENODE -rmdir /src/subdir2/subdir1</command> <command>-fs NAMENODE -rmdir /src/subdir2/subdir1</command>
<command>-fs NAMENODE -rmdir /src/subdir2</command> <command>-fs NAMENODE -rmdir /src/subdir2</command>
<command>-fs NAMENODE -rmdir /src/.Trash</command>
<command>-fs NAMENODE -rmdir /src</command> <command>-fs NAMENODE -rmdir /src</command>
</cleanup-commands> </cleanup-commands>
<comparators> <comparators>
@ -302,5 +312,81 @@
</comparators> </comparators>
</test> </test>
<test>
<description>Test failure of provisioning a trash dir if the EZ does not exist</description>
<test-commands>
<command>-fs NAMENODE -mkdir /src</command>
<crypto-admin-command>-provisionTrash -path /src</crypto-admin-command>-
</test-commands>
<cleanup-commands>
<command>-fs NAMENODE -rmdir /src</command>
</cleanup-commands>
<comparators>
<comparator>
<type>SubstringComparator</type>
<expected-output>/src is not an encryption zone.</expected-output>
</comparator>
</comparators>
</test>
<test>
<description>Test failure of provisioning a trash dir if .Trash exists</description>
<test-commands>
<command>-fs NAMENODE -mkdir /src</command>
<crypto-admin-command>-createZone -path /src -keyName myKey</crypto-admin-command>
<crypto-admin-command>-provisionTrash -path /src</crypto-admin-command>-
</test-commands>
<cleanup-commands>
<command>-fs NAMENODE -rm /src/.Trash</command>
<command>-fs NAMENODE -rmdir /src</command>
</cleanup-commands>
<comparators>
<comparator>
<type>SubstringComparator</type>
<expected-output>Will not provision new trash directory for encryption zone /src. Path already exists.</expected-output>
</comparator>
</comparators>
</test>
<test>
<description>Test success of provisioning a trash dir</description>
<test-commands>
<command>-fs NAMENODE -mkdir /src</command>
<crypto-admin-command>-createZone -path /src -keyName myKey</crypto-admin-command>
<command>-fs NAMENODE -rmdir /src/.Trash</command>
<crypto-admin-command>-provisionTrash -path /src</crypto-admin-command>-
</test-commands>
<cleanup-commands>
<command>-fs NAMENODE -rmdir /src/.Trash</command>
<command>-fs NAMENODE -rmdir /src</command>
</cleanup-commands>
<comparators>
<comparator>
<type>SubstringComparator</type>
<expected-output>Created a trash directory for /src</expected-output>
</comparator>
</comparators>
</test>
<test>
<description>Test failure of provisioning a trash dir for incorrect EZ directory</description>
<test-commands>
<command>-fs NAMENODE -mkdir /src</command>
<crypto-admin-command>-createZone -path /src -keyName myKey</crypto-admin-command>
<command>-fs NAMENODE -mkdir /src/dir1</command>
<crypto-admin-command>-provisionTrash -path /src/dir1</crypto-admin-command>-
</test-commands>
<cleanup-commands>
<command>-fs NAMENODE -rmdir /src/dir1</command>
<command>-fs NAMENODE -rmdir /src/.Trash</command>
<command>-fs NAMENODE -rmdir /src</command>
</cleanup-commands>
<comparators>
<comparator>
<type>SubstringComparator</type>
<expected-output>/src/dir1 is not the root of an encryption zone.</expected-output>
</comparator>
</comparators>
</test>
</tests> </tests>
</configuration> </configuration>