getAcl(OzoneObj obj) throws IOException {
return bucketManager.getAcl(obj);
case KEY:
return keyManager.getAcl(obj);
+ case PREFIX:
+ return prefixManager.getAcl(obj);
+
default:
throw new OMException("Unexpected resource type: " +
obj.getResourceType(), INVALID_REQUEST);
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/PrefixManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/PrefixManager.java
new file mode 100644
index 00000000000..a505b8d7fc0
--- /dev/null
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/PrefixManager.java
@@ -0,0 +1,45 @@
+/**
+ * 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.ozone.om;
+
+import org.apache.hadoop.ozone.om.helpers.OmPrefixInfo;
+
+import java.util.List;
+
+/**
+ * Handles prefix commands.
+ * //TODO: support OzoneManagerFS for ozfs optimization using prefix tree.
+ */
+public interface PrefixManager extends IOzoneAcl {
+
+ /**
+ * Returns the metadataManager.
+ * @return OMMetadataManager.
+ */
+ OMMetadataManager getMetadataManager();
+
+ /**
+ * Get the list of path components that match with obj's path.
+ * longest prefix.
+ * Note: the number of the entries include a root "/"
+ * so if you have a longtest prefix path /a/b/c/
+ * the returned list will be ["/", "a", "b", "c"]
+ * @param path ozone object path
+ * @return list of longest path components that matches obj's path.
+ */
+ List getLongestPrefixPath(String path);
+}
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/PrefixManagerImpl.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/PrefixManagerImpl.java
new file mode 100644
index 00000000000..b9aff890982
--- /dev/null
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/PrefixManagerImpl.java
@@ -0,0 +1,316 @@
+/**
+ * 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.ozone.om;
+
+import com.google.common.base.Strings;
+import org.apache.hadoop.ozone.OzoneAcl;
+import org.apache.hadoop.ozone.om.exceptions.OMException;
+import org.apache.hadoop.ozone.om.helpers.OmPrefixInfo;
+import org.apache.hadoop.ozone.security.acl.OzoneObj;
+import org.apache.hadoop.ozone.util.RadixNode;
+import org.apache.hadoop.ozone.util.RadixTree;
+import org.apache.hadoop.utils.db.*;
+import org.apache.hadoop.utils.db.Table.KeyValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.BUCKET_NOT_FOUND;
+import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.PREFIX_NOT_FOUND;
+import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.VOLUME_NOT_FOUND;
+import static org.apache.hadoop.ozone.security.acl.OzoneObj.ResourceType.PREFIX;
+
+/**
+ * Implementation of PreManager.
+ */
+public class PrefixManagerImpl implements PrefixManager {
+ private static final Logger LOG =
+ LoggerFactory.getLogger(PrefixManagerImpl.class);
+
+ private static final List EMPTY_ACL_LIST = new ArrayList<>();
+ private final OMMetadataManager metadataManager;
+
+ // In-memory prefix tree to optimize ACL evaluation
+ private RadixTree prefixTree;
+
+ public PrefixManagerImpl(OMMetadataManager metadataManager) {
+ this.metadataManager = metadataManager;
+ loadPrefixTree();
+ }
+
+ private void loadPrefixTree() {
+ prefixTree = new RadixTree<>();
+ try (TableIterator> iterator =
+ getMetadataManager().getPrefixTable().iterator()) {
+ iterator.seekToFirst();
+ while (iterator.hasNext()) {
+ KeyValue kv = iterator.next();
+ prefixTree.insert(kv.getKey(), kv.getValue());
+ }
+ } catch (IOException ex) {
+ LOG.error("Fail to load prefix tree");
+ }
+ }
+
+
+ @Override
+ public OMMetadataManager getMetadataManager() {
+ return metadataManager;
+ }
+
+ /**
+ * Add acl for Ozone object. Return true if acl is added successfully else
+ * false.
+ *
+ * @param obj Ozone object for which acl should be added.
+ * @param acl ozone acl top be added.
+ * @throws IOException if there is error.
+ */
+ @Override
+ public boolean addAcl(OzoneObj obj, OzoneAcl acl) throws IOException {
+ validateOzoneObj(obj);
+
+ String prefixPath = obj.getPath();
+ metadataManager.getLock().acquirePrefixLock(prefixPath);
+ try {
+ OmPrefixInfo prefixInfo =
+ metadataManager.getPrefixTable().get(prefixPath);
+ List list = null;
+ if (prefixInfo != null) {
+ list = prefixInfo.getAcls();
+ }
+
+ if (list == null) {
+ list = new ArrayList<>();
+ list.add(acl);
+ } else {
+ boolean found = false;
+ for (OzoneAcl a: list) {
+ if (a.getName().equals(acl.getName()) &&
+ a.getType() == acl.getType()) {
+ found = true;
+ a.getAclBitSet().or(acl.getAclBitSet());
+ break;
+ }
+ }
+ if (!found) {
+ list.add(acl);
+ }
+ }
+
+ OmPrefixInfo.Builder upiBuilder = OmPrefixInfo.newBuilder();
+ upiBuilder.setName(prefixPath).setAcls(list);
+ if (prefixInfo != null && prefixInfo.getMetadata() != null) {
+ upiBuilder.addAllMetadata(prefixInfo.getMetadata());
+ }
+ prefixInfo = upiBuilder.build();
+ // Persist into prefix table first
+ metadataManager.getPrefixTable().put(prefixPath, prefixInfo);
+ // update the in-memory prefix tree
+ prefixTree.insert(prefixPath, prefixInfo);
+ } catch (IOException ex) {
+ if (!(ex instanceof OMException)) {
+ LOG.error("Add acl operation failed for prefix path:{} acl:{}",
+ prefixPath, acl, ex);
+ }
+ throw ex;
+ } finally {
+ metadataManager.getLock().releasePrefixLock(prefixPath);
+ }
+ return true;
+ }
+
+ /**
+ * Remove acl for Ozone object. Return true if acl is removed successfully
+ * else false.
+ *
+ * @param obj Ozone object.
+ * @param acl Ozone acl to be removed.
+ * @throws IOException if there is error.
+ */
+ @Override
+ public boolean removeAcl(OzoneObj obj, OzoneAcl acl) throws IOException {
+ validateOzoneObj(obj);
+ String prefixPath = obj.getPath();
+ metadataManager.getLock().acquirePrefixLock(prefixPath);
+ try {
+ OmPrefixInfo prefixInfo =
+ metadataManager.getPrefixTable().get(prefixPath);
+ List list = null;
+ if (prefixInfo != null) {
+ list = prefixInfo.getAcls();
+ }
+
+ if (list == null) {
+ LOG.debug("acl {} does not exist for prefix path {}", acl, prefixPath);
+ return false;
+ }
+
+ boolean found = false;
+ for (OzoneAcl a: list) {
+ if (a.getName().equals(acl.getName())
+ && a.getType() == acl.getType()) {
+ found = true;
+ a.getAclBitSet().andNot(acl.getAclBitSet());
+ if (a.getAclBitSet().isEmpty()) {
+ list.remove(a);
+ }
+ break;
+ }
+ }
+ if (!found) {
+ LOG.debug("acl {} does not exist for prefix path {}", acl, prefixPath);
+ return false;
+ }
+
+ if (!list.isEmpty()) {
+ OmPrefixInfo.Builder upiBuilder = OmPrefixInfo.newBuilder();
+ upiBuilder.setName(prefixPath).setAcls(list);
+ if (prefixInfo != null && prefixInfo.getMetadata() != null) {
+ upiBuilder.addAllMetadata(prefixInfo.getMetadata());
+ }
+ prefixInfo = upiBuilder.build();
+ metadataManager.getPrefixTable().put(prefixPath, prefixInfo);
+ prefixTree.insert(prefixPath, prefixInfo);
+ } else {
+ // Remove prefix entry in table and prefix tree if the # of acls is 0
+ metadataManager.getPrefixTable().delete(prefixPath);
+ prefixTree.removePrefixPath(prefixPath);
+ }
+
+ } catch (IOException ex) {
+ if (!(ex instanceof OMException)) {
+ LOG.error("Remove prefix acl operation failed for prefix path:{}" +
+ " acl:{}", prefixPath, acl, ex);
+ }
+ throw ex;
+ } finally {
+ metadataManager.getLock().releasePrefixLock(prefixPath);
+ }
+ return true;
+ }
+
+ /**
+ * Acls to be set for given Ozone object. This operations reset ACL for given
+ * object to list of ACLs provided in argument.
+ *
+ * @param obj Ozone object.
+ * @param acls List of acls.
+ * @throws IOException if there is error.
+ */
+ @Override
+ public boolean setAcl(OzoneObj obj, List acls) throws IOException {
+ validateOzoneObj(obj);
+ String prefixPath = obj.getPath();
+ metadataManager.getLock().acquirePrefixLock(prefixPath);
+ try {
+ OmPrefixInfo prefixInfo =
+ metadataManager.getPrefixTable().get(prefixPath);
+ OmPrefixInfo.Builder upiBuilder = OmPrefixInfo.newBuilder();
+ upiBuilder.setName(prefixPath).setAcls(acls);
+ if (prefixInfo != null && prefixInfo.getMetadata() != null) {
+ upiBuilder.addAllMetadata(prefixInfo.getMetadata());
+ }
+ prefixInfo = upiBuilder.build();
+ prefixTree.insert(prefixPath, prefixInfo);
+ metadataManager.getPrefixTable().put(prefixPath, prefixInfo);
+ } catch (IOException ex) {
+ if (!(ex instanceof OMException)) {
+ LOG.error("Set prefix acl operation failed for prefix path:{} acls:{}",
+ prefixPath, acls, ex);
+ }
+ throw ex;
+ } finally {
+ metadataManager.getLock().releasePrefixLock(prefixPath);
+ }
+ return true;
+ }
+
+ /**
+ * Returns list of ACLs for given Ozone object.
+ *
+ * @param obj Ozone object.
+ * @throws IOException if there is error.
+ */
+ @Override
+ public List getAcl(OzoneObj obj) throws IOException {
+ validateOzoneObj(obj);
+ String prefixPath = obj.getPath();
+ metadataManager.getLock().acquirePrefixLock(prefixPath);
+ try {
+ String longestPrefix = prefixTree.getLongestPrefix(prefixPath);
+ if (prefixPath.equals(longestPrefix)) {
+ RadixNode lastNode =
+ prefixTree.getLastNodeInPrefixPath(prefixPath);
+ if (lastNode != null && lastNode.getValue() != null) {
+ return lastNode.getValue().getAcls();
+ }
+ }
+ } finally {
+ metadataManager.getLock().releasePrefixLock(prefixPath);
+ }
+ return EMPTY_ACL_LIST;
+ }
+
+ @Override
+ public List getLongestPrefixPath(String path) {
+ String prefixPath = prefixTree.getLongestPrefix(path);
+ metadataManager.getLock().acquirePrefixLock(prefixPath);
+ try {
+ return prefixTree.getLongestPrefixPath(prefixPath).stream()
+ .map(c -> c.getValue()).collect(Collectors.toList());
+ } finally {
+ metadataManager.getLock().releasePrefixLock(prefixPath);
+ }
+ }
+
+ /**
+ * Helper method to validate ozone object.
+ * @param obj
+ * */
+ private void validateOzoneObj(OzoneObj obj) throws OMException {
+ Objects.requireNonNull(obj);
+
+ if (!obj.getResourceType().equals(PREFIX)) {
+ throw new IllegalArgumentException("Unexpected argument passed to " +
+ "PrefixManager. OzoneObj type:" + obj.getResourceType());
+ }
+ String volume = obj.getVolumeName();
+ String bucket = obj.getBucketName();
+ String prefixName = obj.getPrefixName();
+
+ if (Strings.isNullOrEmpty(volume)) {
+ throw new OMException("Volume name is required.", VOLUME_NOT_FOUND);
+ }
+ if (Strings.isNullOrEmpty(bucket)) {
+ throw new OMException("Bucket name is required.", BUCKET_NOT_FOUND);
+ }
+ if (Strings.isNullOrEmpty(prefixName)) {
+ throw new OMException("Prefix name is required.", PREFIX_NOT_FOUND);
+ }
+ if (!prefixName.endsWith("/")) {
+ throw new OMException("Invalid prefix name: " + prefixName,
+ PREFIX_NOT_FOUND);
+ }
+ }
+}
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/fs/OzoneManagerFS.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/fs/OzoneManagerFS.java
index 46ba58dfe76..bff883dc7fe 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/fs/OzoneManagerFS.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/fs/OzoneManagerFS.java
@@ -18,6 +18,7 @@
package org.apache.hadoop.ozone.om.fs;
+import org.apache.hadoop.ozone.om.IOzoneAcl;
import org.apache.hadoop.ozone.om.helpers.OmKeyArgs;
import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
import org.apache.hadoop.ozone.om.helpers.OpenKeySession;
@@ -29,7 +30,7 @@
/**
* Ozone Manager FileSystem interface.
*/
-public interface OzoneManagerFS {
+public interface OzoneManagerFS extends IOzoneAcl {
OzoneFileStatus getFileStatus(OmKeyArgs args) throws IOException;
void createDirectory(OmKeyArgs args) throws IOException;
diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestKeyManagerImpl.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestKeyManagerImpl.java
index fb323fe0c63..e9e6b2504a8 100644
--- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestKeyManagerImpl.java
+++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestKeyManagerImpl.java
@@ -23,6 +23,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -47,21 +48,38 @@
import org.apache.hadoop.hdds.scm.protocol.ScmBlockLocationProtocol;
import org.apache.hadoop.hdds.scm.server.SCMConfigurator;
import org.apache.hadoop.hdds.scm.server.StorageContainerManager;
+import org.apache.hadoop.ozone.OzoneAcl;
import org.apache.hadoop.ozone.om.exceptions.OMException;
-import org.apache.hadoop.ozone.om.helpers.*;
+import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
+import org.apache.hadoop.ozone.om.helpers.OmKeyArgs;
+import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
+import org.apache.hadoop.ozone.om.helpers.OmPrefixInfo;
+import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
+import org.apache.hadoop.ozone.om.helpers.OpenKeySession;
+import org.apache.hadoop.ozone.om.helpers.OzoneFSUtils;
+import org.apache.hadoop.ozone.om.helpers.OzoneFileStatus;
+import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer;
+import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLIdentityType;
+import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType;
+import org.apache.hadoop.ozone.security.acl.OzoneObj;
+import org.apache.hadoop.ozone.security.acl.OzoneObjInfo;
import org.apache.hadoop.ozone.web.utils.OzoneUtils;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.test.GenericTestUtils;
import org.apache.hadoop.test.LambdaTestUtils;
import org.junit.After;
+import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
-import org.junit.AfterClass;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.mockito.Mockito;
-import static org.apache.hadoop.ozone.OzoneConfigKeys.*;
+import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_KEY_PREALLOCATION_BLOCKS_MAX;
+import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_SCM_BLOCK_SIZE;
+import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_SCM_BLOCK_SIZE_DEFAULT;
import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.ALL;
/**
@@ -69,6 +87,7 @@
*/
public class TestKeyManagerImpl {
+ private static PrefixManager prefixManager;
private static KeyManagerImpl keyManager;
private static VolumeManagerImpl volumeManager;
private static BucketManagerImpl bucketManager;
@@ -82,6 +101,9 @@ public class TestKeyManagerImpl {
private static final String BUCKET_NAME = "bucket1";
private static final String VOLUME_NAME = "vol1";
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
@BeforeClass
public static void setUp() throws Exception {
conf = new OzoneConfiguration();
@@ -105,6 +127,8 @@ public static void setUp() throws Exception {
keyManager =
new KeyManagerImpl(scm.getBlockProtocolServer(), metadataManager, conf,
"om1", null);
+ prefixManager = new PrefixManagerImpl(metadataManager);
+
Mockito.when(mockScmBlockLocationProtocol
.allocateBlock(Mockito.anyLong(), Mockito.anyInt(),
Mockito.any(ReplicationType.class),
@@ -323,6 +347,213 @@ public void testOpenFile() throws IOException {
}
}
+
+ @Test
+ public void testPrefixAclOps() throws IOException {
+ String volumeName = "vol1";
+ String bucketName = "bucket1";
+ String prefix1 = "pf1/";
+
+ OzoneObj ozPrefix1 = new OzoneObjInfo.Builder()
+ .setVolumeName(volumeName)
+ .setBucketName(bucketName)
+ .setPrefixName(prefix1)
+ .setResType(OzoneObj.ResourceType.PREFIX)
+ .setStoreType(OzoneObj.StoreType.OZONE)
+ .build();
+
+ OzoneAcl ozAcl1 = new OzoneAcl(ACLIdentityType.USER, "user1",
+ ACLType.READ);
+ prefixManager.addAcl(ozPrefix1, ozAcl1);
+
+ List ozAclGet = prefixManager.getAcl(ozPrefix1);
+ Assert.assertEquals(1, ozAclGet.size());
+ Assert.assertEquals(ozAcl1, ozAclGet.get(0));
+
+ List acls = new ArrayList<>();
+ OzoneAcl ozAcl2 = new OzoneAcl(ACLIdentityType.USER, "admin",
+ ACLType.ALL);
+
+ BitSet rwRights = new BitSet();
+ rwRights.set(IAccessAuthorizer.ACLType.WRITE.ordinal());
+ rwRights.set(IAccessAuthorizer.ACLType.READ.ordinal());
+ OzoneAcl ozAcl3 = new OzoneAcl(ACLIdentityType.GROUP, "dev",
+ rwRights);
+
+ BitSet wRights = new BitSet();
+ wRights.set(IAccessAuthorizer.ACLType.WRITE.ordinal());
+ OzoneAcl ozAcl4 = new OzoneAcl(ACLIdentityType.GROUP, "dev",
+ wRights);
+
+ BitSet rRights = new BitSet();
+ rRights.set(IAccessAuthorizer.ACLType.READ.ordinal());
+ OzoneAcl ozAcl5 = new OzoneAcl(ACLIdentityType.GROUP, "dev",
+ rRights);
+
+ acls.add(ozAcl2);
+ acls.add(ozAcl3);
+
+ prefixManager.setAcl(ozPrefix1, acls);
+ ozAclGet = prefixManager.getAcl(ozPrefix1);
+ Assert.assertEquals(2, ozAclGet.size());
+
+ int matchEntries = 0;
+ for (OzoneAcl acl : ozAclGet) {
+ if (acl.getType() == ACLIdentityType.GROUP) {
+ Assert.assertEquals(ozAcl3, acl);
+ matchEntries++;
+ }
+ if (acl.getType() == ACLIdentityType.USER) {
+ Assert.assertEquals(ozAcl2, acl);
+ matchEntries++;
+ }
+ }
+ Assert.assertEquals(2, matchEntries);
+
+ boolean result = prefixManager.removeAcl(ozPrefix1, ozAcl4);
+ Assert.assertEquals(true, result);
+
+ ozAclGet = prefixManager.getAcl(ozPrefix1);
+ Assert.assertEquals(2, ozAclGet.size());
+
+ result = prefixManager.removeAcl(ozPrefix1, ozAcl3);
+ Assert.assertEquals(true, result);
+ ozAclGet = prefixManager.getAcl(ozPrefix1);
+ Assert.assertEquals(1, ozAclGet.size());
+
+ Assert.assertEquals(ozAcl2, ozAclGet.get(0));
+
+ // add dev:w
+ prefixManager.addAcl(ozPrefix1, ozAcl4);
+ ozAclGet = prefixManager.getAcl(ozPrefix1);
+ Assert.assertEquals(2, ozAclGet.size());
+
+ // add dev:r and validate the acl bitset combined
+ prefixManager.addAcl(ozPrefix1, ozAcl5);
+ ozAclGet = prefixManager.getAcl(ozPrefix1);
+ Assert.assertEquals(2, ozAclGet.size());
+
+ matchEntries = 0;
+ for (OzoneAcl acl : ozAclGet) {
+ if (acl.getType() == ACLIdentityType.GROUP) {
+ Assert.assertEquals(ozAcl3, acl);
+ matchEntries++;
+ }
+ if (acl.getType() == ACLIdentityType.USER) {
+ Assert.assertEquals(ozAcl2, acl);
+ matchEntries++;
+ }
+ }
+ Assert.assertEquals(2, matchEntries);
+ }
+
+ @Test
+ public void testInvalidPrefixAcl() throws IOException {
+ String volumeName = "vol1";
+ String bucketName = "bucket1";
+ String prefix1 = "pf1/";
+
+ // Invalid prefix not ending with "/"
+ String invalidPrefix = "invalid/pf";
+ OzoneAcl ozAcl1 = new OzoneAcl(ACLIdentityType.USER, "user1",
+ ACLType.READ);
+
+ OzoneObj ozInvalidPrefix = new OzoneObjInfo.Builder()
+ .setVolumeName(volumeName)
+ .setBucketName(bucketName)
+ .setPrefixName(invalidPrefix)
+ .setResType(OzoneObj.ResourceType.PREFIX)
+ .setStoreType(OzoneObj.StoreType.OZONE)
+ .build();
+
+ // add acl with invalid prefix name
+ exception.expect(OMException.class);
+ exception.expectMessage("Invalid prefix name");
+ prefixManager.addAcl(ozInvalidPrefix, ozAcl1);
+
+ OzoneObj ozPrefix1 = new OzoneObjInfo.Builder()
+ .setVolumeName(volumeName)
+ .setBucketName(bucketName)
+ .setPrefixName(prefix1)
+ .setResType(OzoneObj.ResourceType.PREFIX)
+ .setStoreType(OzoneObj.StoreType.OZONE)
+ .build();
+
+
+ List ozAclGet = prefixManager.getAcl(ozPrefix1);
+ Assert.assertEquals(1, ozAclGet.size());
+ Assert.assertEquals(ozAcl1, ozAclGet.get(0));
+
+ // get acl with invalid prefix name
+ exception.expect(OMException.class);
+ exception.expectMessage("Invalid prefix name");
+ ozAclGet = prefixManager.getAcl(ozInvalidPrefix);
+ Assert.assertEquals(null, ozAcl1);
+
+ // set acl with invalid prefix name
+ List ozoneAcls = new ArrayList();
+ ozoneAcls.add(ozAcl1);
+ exception.expect(OMException.class);
+ exception.expectMessage("Invalid prefix name");
+ prefixManager.setAcl(ozInvalidPrefix, ozoneAcls);
+
+ // remove acl with invalid prefix name
+ exception.expect(OMException.class);
+ exception.expectMessage("Invalid prefix name");
+ prefixManager.removeAcl(ozInvalidPrefix, ozAcl1);
+ }
+
+ @Test
+ public void testLongestPrefixPath() throws IOException {
+ String volumeName = "vol1";
+ String bucketName = "bucket1";
+ String prefix1 = "pf1/pf11/pf111/pf1111/";
+ String file1 = "pf1/pf11/file1";
+ String file2 = "pf1/pf11/pf111/pf1111/file2";
+
+ OzoneObj ozPrefix1 = new OzoneObjInfo.Builder()
+ .setVolumeName(volumeName)
+ .setBucketName(bucketName)
+ .setPrefixName(prefix1)
+ .setResType(OzoneObj.ResourceType.PREFIX)
+ .setStoreType(OzoneObj.StoreType.OZONE)
+ .build();
+
+ OzoneAcl ozAcl1 = new OzoneAcl(ACLIdentityType.USER, "user1",
+ ACLType.READ);
+ prefixManager.addAcl(ozPrefix1, ozAcl1);
+
+ OzoneObj ozFile1 = new OzoneObjInfo.Builder()
+ .setVolumeName(volumeName)
+ .setBucketName(bucketName)
+ .setKeyName(file1)
+ .setResType(OzoneObj.ResourceType.KEY)
+ .setStoreType(OzoneObj.StoreType.OZONE)
+ .build();
+
+ List prefixInfos =
+ prefixManager.getLongestPrefixPath(ozFile1.getPath());
+ Assert.assertEquals(5, prefixInfos.size());
+
+ OzoneObj ozFile2 = new OzoneObjInfo.Builder()
+ .setVolumeName(volumeName)
+ .setBucketName(bucketName)
+ .setPrefixName(file2)
+ .setResType(OzoneObj.ResourceType.KEY)
+ .setStoreType(OzoneObj.StoreType.OZONE)
+ .build();
+
+ prefixInfos =
+ prefixManager.getLongestPrefixPath(ozFile2.getPath());
+ Assert.assertEquals(7, prefixInfos.size());
+ // Only the last node has acl on it
+ Assert.assertEquals(ozAcl1, prefixInfos.get(6).getAcls().get(0));
+ // All other nodes don't have acl value associate with it
+ for (int i = 0; i < 6; i++) {
+ Assert.assertEquals(null, prefixInfos.get(i));
+ }
+ }
+
@Test
public void testLookupFile() throws IOException {
String keyName = RandomStringUtils.randomAlphabetic(5);