|
@@ -27,6 +27,9 @@ import java.util.TreeMap;
|
|
|
|
|
|
import com.google.common.base.Preconditions;
|
|
|
import com.google.common.collect.Lists;
|
|
|
+import com.google.protobuf.InvalidProtocolBufferException;
|
|
|
+import org.apache.commons.lang.builder.EqualsBuilder;
|
|
|
+import org.apache.commons.lang.builder.HashCodeBuilder;
|
|
|
import org.apache.hadoop.conf.Configuration;
|
|
|
import org.apache.hadoop.crypto.CipherSuite;
|
|
|
import org.apache.hadoop.crypto.CryptoProtocolVersion;
|
|
@@ -40,6 +43,7 @@ import org.apache.hadoop.hdfs.protocol.SnapshotAccessControlException;
|
|
|
import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos;
|
|
|
import org.apache.hadoop.hdfs.protocolPB.PBHelperClient;
|
|
|
import org.apache.hadoop.hdfs.server.namenode.FSDirectory.DirOp;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.snapshot.Snapshot;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
@@ -94,6 +98,34 @@ public class EncryptionZoneManager {
|
|
|
String getKeyName() {
|
|
|
return keyName;
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean equals(Object o) {
|
|
|
+ if (this == o) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (!(o instanceof EncryptionZoneInt)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ EncryptionZoneInt b = (EncryptionZoneInt)o;
|
|
|
+ return new EqualsBuilder()
|
|
|
+ .append(inodeId, b.getINodeId())
|
|
|
+ .append(suite, b.getSuite())
|
|
|
+ .append(version, b.getVersion())
|
|
|
+ .append(keyName, b.getKeyName())
|
|
|
+ .isEquals();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int hashCode() {
|
|
|
+ return new HashCodeBuilder().
|
|
|
+ append(inodeId).
|
|
|
+ append(suite).
|
|
|
+ append(version).
|
|
|
+ append(keyName).
|
|
|
+ toHashCode();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private TreeMap<Long, EncryptionZoneInt> encryptionZones = null;
|
|
@@ -166,8 +198,8 @@ public class EncryptionZoneManager {
|
|
|
* <p/>
|
|
|
* Called while holding the FSDirectory lock.
|
|
|
*/
|
|
|
- boolean isInAnEZ(INodesInPath iip)
|
|
|
- throws UnresolvedLinkException, SnapshotAccessControlException {
|
|
|
+ boolean isInAnEZ(INodesInPath iip) throws UnresolvedLinkException,
|
|
|
+ SnapshotAccessControlException, IOException {
|
|
|
assert dir.hasReadLock();
|
|
|
return (getEncryptionZoneForPath(iip) != null);
|
|
|
}
|
|
@@ -188,7 +220,7 @@ public class EncryptionZoneManager {
|
|
|
* <p/>
|
|
|
* Called while holding the FSDirectory lock.
|
|
|
*/
|
|
|
- String getKeyName(final INodesInPath iip) {
|
|
|
+ String getKeyName(final INodesInPath iip) throws IOException {
|
|
|
assert dir.hasReadLock();
|
|
|
EncryptionZoneInt ezi = getEncryptionZoneForPath(iip);
|
|
|
if (ezi == null) {
|
|
@@ -203,19 +235,43 @@ public class EncryptionZoneManager {
|
|
|
* <p/>
|
|
|
* Called while holding the FSDirectory lock.
|
|
|
*/
|
|
|
- private EncryptionZoneInt getEncryptionZoneForPath(INodesInPath iip) {
|
|
|
+ private EncryptionZoneInt getEncryptionZoneForPath(INodesInPath iip)
|
|
|
+ throws IOException {
|
|
|
assert dir.hasReadLock();
|
|
|
Preconditions.checkNotNull(iip);
|
|
|
if (!hasCreatedEncryptionZone()) {
|
|
|
return null;
|
|
|
}
|
|
|
+
|
|
|
+ int snapshotID = iip.getPathSnapshotId();
|
|
|
for (int i = iip.length() - 1; i >= 0; i--) {
|
|
|
final INode inode = iip.getINode(i);
|
|
|
- if (inode != null) {
|
|
|
+ if (inode == null || !inode.isDirectory()) {
|
|
|
+ //not found or not a directory, encryption zone is supported on
|
|
|
+ //directory only.
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (snapshotID == Snapshot.CURRENT_STATE_ID) {
|
|
|
final EncryptionZoneInt ezi = encryptionZones.get(inode.getId());
|
|
|
if (ezi != null) {
|
|
|
return ezi;
|
|
|
}
|
|
|
+ } else {
|
|
|
+ XAttr xAttr = FSDirXAttrOp.unprotectedGetXAttrByPrefixedName(
|
|
|
+ inode, snapshotID, CRYPTO_XATTR_ENCRYPTION_ZONE);
|
|
|
+ if (xAttr != null) {
|
|
|
+ try {
|
|
|
+ final HdfsProtos.ZoneEncryptionInfoProto ezProto =
|
|
|
+ HdfsProtos.ZoneEncryptionInfoProto.parseFrom(xAttr.getValue());
|
|
|
+ return new EncryptionZoneInt(
|
|
|
+ inode.getId(), PBHelperClient.convert(ezProto.getSuite()),
|
|
|
+ PBHelperClient.convert(ezProto.getCryptoProtocolVersion()),
|
|
|
+ ezProto.getKeyName());
|
|
|
+ } catch (InvalidProtocolBufferException e) {
|
|
|
+ throw new IOException("Could not parse encryption zone for inode "
|
|
|
+ + iip.getPath(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
return null;
|
|
@@ -228,7 +284,8 @@ public class EncryptionZoneManager {
|
|
|
* <p/>
|
|
|
* Called while holding the FSDirectory lock.
|
|
|
*/
|
|
|
- private EncryptionZoneInt getParentEncryptionZoneForPath(INodesInPath iip) {
|
|
|
+ private EncryptionZoneInt getParentEncryptionZoneForPath(INodesInPath iip)
|
|
|
+ throws IOException {
|
|
|
assert dir.hasReadLock();
|
|
|
Preconditions.checkNotNull(iip);
|
|
|
INodesInPath parentIIP = iip.getParentINodesInPath();
|
|
@@ -242,7 +299,8 @@ public class EncryptionZoneManager {
|
|
|
* @param iip The INodesInPath of the path to check
|
|
|
* @return the EncryptionZone representing the ez for the path.
|
|
|
*/
|
|
|
- EncryptionZone getEZINodeForPath(INodesInPath iip) {
|
|
|
+ EncryptionZone getEZINodeForPath(INodesInPath iip)
|
|
|
+ throws IOException {
|
|
|
final EncryptionZoneInt ezi = getEncryptionZoneForPath(iip);
|
|
|
if (ezi == null) {
|
|
|
return null;
|
|
@@ -283,7 +341,7 @@ public class EncryptionZoneManager {
|
|
|
}
|
|
|
|
|
|
if (srcInEZ) {
|
|
|
- if (srcParentEZI != dstParentEZI) {
|
|
|
+ if (!srcParentEZI.equals(dstParentEZI)) {
|
|
|
final String srcEZPath = getFullPathName(srcParentEZI);
|
|
|
final String dstEZPath = getFullPathName(dstParentEZI);
|
|
|
final StringBuilder sb = new StringBuilder(srcIIP.getPath());
|