| /** |
| * 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 |
| * <p> |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * <p> |
| * 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.client.rpc; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.time.Instant; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.BitSet; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Optional; |
| import java.util.TreeMap; |
| import java.util.UUID; |
| import java.util.concurrent.CountDownLatch; |
| import java.util.concurrent.TimeUnit; |
| import java.util.concurrent.atomic.AtomicInteger; |
| |
| import org.apache.hadoop.conf.StorageUnit; |
| import org.apache.hadoop.hdds.client.OzoneQuota; |
| import org.apache.hadoop.hdds.client.ReplicationFactor; |
| import org.apache.hadoop.hdds.client.ReplicationType; |
| import org.apache.hadoop.hdds.conf.OzoneConfiguration; |
| import org.apache.hadoop.hdds.protocol.DatanodeDetails; |
| import org.apache.hadoop.hdds.protocol.StorageType; |
| import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos; |
| import org.apache.hadoop.hdds.protocol.proto.HddsProtos; |
| import org.apache.hadoop.hdds.scm.OzoneClientConfig; |
| import org.apache.hadoop.hdds.scm.client.HddsClientUtils; |
| import org.apache.hadoop.hdds.scm.container.ContainerID; |
| import org.apache.hadoop.hdds.scm.container.ContainerInfo; |
| import org.apache.hadoop.hdds.scm.pipeline.Pipeline; |
| import org.apache.hadoop.hdds.scm.protocolPB.StorageContainerLocationProtocolClientSideTranslatorPB; |
| import org.apache.hadoop.ozone.HddsDatanodeService; |
| import org.apache.hadoop.ozone.MiniOzoneCluster; |
| import org.apache.hadoop.ozone.OmUtils; |
| import org.apache.hadoop.ozone.OzoneAcl; |
| import org.apache.hadoop.ozone.OzoneConsts; |
| import org.apache.hadoop.ozone.OzoneTestUtils; |
| import org.apache.hadoop.ozone.client.BucketArgs; |
| import org.apache.hadoop.ozone.client.ObjectStore; |
| import org.apache.hadoop.ozone.client.OzoneBucket; |
| import org.apache.hadoop.ozone.client.OzoneClient; |
| import org.apache.hadoop.ozone.client.OzoneClientException; |
| import org.apache.hadoop.ozone.client.OzoneClientFactory; |
| import org.apache.hadoop.ozone.client.OzoneKey; |
| import org.apache.hadoop.ozone.client.OzoneKeyDetails; |
| import org.apache.hadoop.ozone.client.OzoneKeyLocation; |
| import org.apache.hadoop.ozone.client.OzoneMultipartUploadPartListParts; |
| import org.apache.hadoop.ozone.client.OzoneVolume; |
| import org.apache.hadoop.ozone.client.VolumeArgs; |
| import org.apache.hadoop.ozone.client.io.OzoneInputStream; |
| import org.apache.hadoop.ozone.client.io.OzoneOutputStream; |
| import org.apache.hadoop.ozone.client.protocol.ClientProtocol; |
| import org.apache.hadoop.ozone.common.OzoneChecksumException; |
| import org.apache.hadoop.ozone.container.common.helpers.BlockData; |
| import org.apache.hadoop.ozone.container.common.interfaces.BlockIterator; |
| import org.apache.hadoop.ozone.container.common.interfaces.Container; |
| import org.apache.hadoop.ozone.container.common.utils.ReferenceCountedDB; |
| import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData; |
| import org.apache.hadoop.ozone.container.keyvalue.helpers.BlockUtils; |
| import org.apache.hadoop.ozone.container.keyvalue.helpers.KeyValueContainerLocationUtil; |
| import org.apache.hadoop.ozone.om.OMMetadataManager; |
| import org.apache.hadoop.ozone.om.OmFailoverProxyUtil; |
| import org.apache.hadoop.ozone.om.OzoneManager; |
| import org.apache.hadoop.ozone.om.exceptions.OMException; |
| import org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes; |
| import org.apache.hadoop.ozone.om.ha.OMFailoverProxyProvider; |
| import org.apache.hadoop.ozone.om.ha.OMProxyInfo; |
| import org.apache.hadoop.ozone.om.helpers.OmKeyArgs; |
| import org.apache.hadoop.ozone.om.helpers.OmKeyInfo; |
| import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo; |
| import org.apache.hadoop.ozone.om.helpers.OmMultipartCommitUploadPartInfo; |
| import org.apache.hadoop.ozone.om.helpers.OmMultipartInfo; |
| import org.apache.hadoop.ozone.om.helpers.OmMultipartUploadCompleteInfo; |
| import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs; |
| import org.apache.hadoop.ozone.om.helpers.RepeatedOmKeyInfo; |
| import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType; |
| import org.apache.hadoop.ozone.security.acl.OzoneAclConfig; |
| import org.apache.hadoop.ozone.security.acl.OzoneObj; |
| import org.apache.hadoop.ozone.security.acl.OzoneObjInfo; |
| import org.apache.hadoop.security.UserGroupInformation; |
| import org.apache.hadoop.test.GenericTestUtils; |
| import org.apache.hadoop.test.LambdaTestUtils; |
| |
| import static java.nio.charset.StandardCharsets.UTF_8; |
| import org.apache.commons.io.FileUtils; |
| import org.apache.commons.lang3.RandomStringUtils; |
| import org.apache.commons.lang3.RandomUtils; |
| import org.apache.commons.lang3.StringUtils; |
| import static org.apache.hadoop.hdds.StringUtils.string2Bytes; |
| import static org.apache.hadoop.hdds.client.ReplicationFactor.ONE; |
| import static org.apache.hadoop.hdds.client.ReplicationFactor.THREE; |
| import static org.apache.hadoop.hdds.client.ReplicationType.STAND_ALONE; |
| import static org.apache.hadoop.ozone.OmUtils.MAX_TRXN_ID; |
| import static org.apache.hadoop.ozone.OzoneAcl.AclScope.ACCESS; |
| import static org.apache.hadoop.ozone.OzoneAcl.AclScope.DEFAULT; |
| 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.OzoneConsts.DEFAULT_OM_UPDATE_ID; |
| import static org.apache.hadoop.ozone.OzoneConsts.GB; |
| import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.KEY_NOT_FOUND; |
| import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.NO_SUCH_MULTIPART_UPLOAD_ERROR; |
| import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.PARTIAL_RENAME; |
| import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLIdentityType.GROUP; |
| import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLIdentityType.USER; |
| import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.READ; |
| import org.junit.Assert; |
| |
| import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.WRITE; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| import org.junit.Test; |
| |
| /** |
| * This is an abstract class to test all the public facing APIs of Ozone |
| * Client, w/o OM Ratis server. |
| * {@link TestOzoneRpcClient} tests the Ozone Client by submitting the |
| * requests directly to OzoneManager. {@link TestOzoneRpcClientWithRatis} |
| * tests the Ozone Client by submitting requests to OM's Ratis server. |
| */ |
| public abstract class TestOzoneRpcClientAbstract { |
| |
| private static MiniOzoneCluster cluster = null; |
| private static OzoneClient ozClient = null; |
| private static ObjectStore store = null; |
| private static OzoneManager ozoneManager; |
| private static StorageContainerLocationProtocolClientSideTranslatorPB |
| storageContainerLocationClient; |
| private static String remoteUserName = "remoteUser"; |
| private static String remoteGroupName = "remoteGroup"; |
| private static OzoneAcl defaultUserAcl = new OzoneAcl(USER, remoteUserName, |
| READ, DEFAULT); |
| private static OzoneAcl defaultGroupAcl = new OzoneAcl(GROUP, remoteGroupName, |
| READ, DEFAULT); |
| private static OzoneAcl inheritedUserAcl = new OzoneAcl(USER, remoteUserName, |
| READ, ACCESS); |
| private static OzoneAcl inheritedGroupAcl = new OzoneAcl(GROUP, |
| remoteGroupName, READ, ACCESS); |
| |
| private static String scmId = UUID.randomUUID().toString(); |
| |
| /** |
| * Create a MiniOzoneCluster for testing. |
| * @param conf Configurations to start the cluster. |
| * @throws Exception |
| */ |
| static void startCluster(OzoneConfiguration conf) throws Exception { |
| cluster = MiniOzoneCluster.newBuilder(conf) |
| .setNumDatanodes(3) |
| .setTotalPipelineNumLimit(10) |
| .setScmId(scmId) |
| .build(); |
| cluster.waitForClusterToBeReady(); |
| ozClient = OzoneClientFactory.getRpcClient(conf); |
| store = ozClient.getObjectStore(); |
| storageContainerLocationClient = |
| cluster.getStorageContainerLocationClient(); |
| ozoneManager = cluster.getOzoneManager(); |
| } |
| |
| /** |
| * Close OzoneClient and shutdown MiniOzoneCluster. |
| */ |
| static void shutdownCluster() throws IOException { |
| if(ozClient != null) { |
| ozClient.close(); |
| } |
| |
| if (storageContainerLocationClient != null) { |
| storageContainerLocationClient.close(); |
| } |
| |
| if (cluster != null) { |
| cluster.shutdown(); |
| } |
| } |
| |
| public static void setCluster(MiniOzoneCluster cluster) { |
| TestOzoneRpcClientAbstract.cluster = cluster; |
| } |
| |
| public static void setOzClient(OzoneClient ozClient) { |
| TestOzoneRpcClientAbstract.ozClient = ozClient; |
| } |
| |
| public static void setOzoneManager(OzoneManager ozoneManager){ |
| TestOzoneRpcClientAbstract.ozoneManager = ozoneManager; |
| } |
| |
| public static void setStorageContainerLocationClient( |
| StorageContainerLocationProtocolClientSideTranslatorPB |
| storageContainerLocationClient) { |
| TestOzoneRpcClientAbstract.storageContainerLocationClient = |
| storageContainerLocationClient; |
| } |
| |
| public static void setStore(ObjectStore store) { |
| TestOzoneRpcClientAbstract.store = store; |
| } |
| |
| public static ObjectStore getStore() { |
| return TestOzoneRpcClientAbstract.store; |
| } |
| |
| public static void setScmId(String scmId) { |
| TestOzoneRpcClientAbstract.scmId = scmId; |
| } |
| |
| /** |
| * Test OM Proxy Provider. |
| */ |
| @Test |
| public void testOMClientProxyProvider() { |
| |
| OMFailoverProxyProvider omFailoverProxyProvider = |
| OmFailoverProxyUtil.getFailoverProxyProvider(store.getClientProxy()); |
| |
| List<OMProxyInfo> omProxies = omFailoverProxyProvider.getOMProxyInfos(); |
| |
| // For a non-HA OM service, there should be only one OM proxy. |
| Assert.assertEquals(1, omProxies.size()); |
| // The address in OMProxyInfo object, which client will connect to, |
| // should match the OM's RPC address. |
| Assert.assertTrue(omProxies.get(0).getAddress().equals( |
| ozoneManager.getOmRpcServerAddr())); |
| } |
| |
| @Test |
| public void testDefaultS3GVolumeExists() throws Exception { |
| String s3VolumeName = HddsClientUtils.getS3VolumeName(cluster.getConf()); |
| OzoneVolume ozoneVolume = store.getVolume(s3VolumeName); |
| Assert.assertEquals(ozoneVolume.getName(), s3VolumeName); |
| OMMetadataManager omMetadataManager = |
| cluster.getOzoneManager().getMetadataManager(); |
| long transactionID = MAX_TRXN_ID + 1; |
| long objectID = OmUtils.addEpochToTxId(omMetadataManager.getOmEpoch(), |
| transactionID); |
| OmVolumeArgs omVolumeArgs = |
| cluster.getOzoneManager().getMetadataManager().getVolumeTable().get( |
| omMetadataManager.getVolumeKey(s3VolumeName)); |
| Assert.assertEquals(objectID, omVolumeArgs.getObjectID()); |
| Assert.assertEquals(DEFAULT_OM_UPDATE_ID, omVolumeArgs.getUpdateID()); |
| } |
| |
| @Test |
| public void testVolumeSetOwner() throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| store.createVolume(volumeName); |
| |
| String ownerName = "someRandomUser1"; |
| |
| ClientProtocol proxy = store.getClientProxy(); |
| proxy.setVolumeOwner(volumeName, ownerName); |
| // Set owner again |
| proxy.setVolumeOwner(volumeName, ownerName); |
| } |
| |
| @Test |
| public void testSetAndClrQuota() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String value = "sample value"; |
| int valueLength = value.getBytes().length; |
| OzoneVolume volume = null; |
| store.createVolume(volumeName); |
| |
| store.getVolume(volumeName).setQuota(OzoneQuota.parseQuota( |
| "0GB", 0L)); |
| volume = store.getVolume(volumeName); |
| Assert.assertEquals(OzoneConsts.QUOTA_RESET, volume.getQuotaInBytes()); |
| Assert.assertEquals(OzoneConsts.QUOTA_RESET, volume.getQuotaInNamespace()); |
| |
| store.getVolume(volumeName).setQuota(OzoneQuota.parseQuota( |
| "10GB", 10000L)); |
| store.getVolume(volumeName).createBucket(bucketName); |
| volume = store.getVolume(volumeName); |
| Assert.assertEquals(10 * GB, volume.getQuotaInBytes()); |
| Assert.assertEquals(10000L, volume.getQuotaInNamespace()); |
| OzoneBucket bucket = store.getVolume(volumeName).getBucket(bucketName); |
| Assert.assertEquals(OzoneConsts.QUOTA_RESET, bucket.getQuotaInBytes()); |
| Assert.assertEquals(OzoneConsts.QUOTA_RESET, bucket.getQuotaInNamespace()); |
| |
| store.getVolume(volumeName).getBucket(bucketName).setQuota( |
| OzoneQuota.parseQuota("0GB", 0)); |
| Assert.assertEquals(OzoneConsts.QUOTA_RESET, bucket.getQuotaInBytes()); |
| Assert.assertEquals(OzoneConsts.QUOTA_RESET, bucket.getQuotaInNamespace()); |
| |
| store.getVolume(volumeName).getBucket(bucketName).setQuota( |
| OzoneQuota.parseQuota("1GB", 1000L)); |
| OzoneBucket ozoneBucket = store.getVolume(volumeName).getBucket(bucketName); |
| Assert.assertEquals(1024 * 1024 * 1024, |
| ozoneBucket.getQuotaInBytes()); |
| Assert.assertEquals(1000L, ozoneBucket.getQuotaInNamespace()); |
| |
| LambdaTestUtils.intercept(IOException.class, "Can not clear bucket" + |
| " spaceQuota because volume spaceQuota is not cleared.", |
| () -> ozoneBucket.clearSpaceQuota()); |
| |
| writeKey(bucket, UUID.randomUUID().toString(), ONE, value, valueLength); |
| Assert.assertEquals(1L, |
| store.getVolume(volumeName).getBucket(bucketName).getUsedNamespace()); |
| Assert.assertEquals(valueLength, |
| store.getVolume(volumeName).getBucket(bucketName).getUsedBytes()); |
| Assert.assertEquals(1L, |
| store.getVolume(volumeName).getUsedNamespace()); |
| |
| store.getVolume(volumeName).clearSpaceQuota(); |
| store.getVolume(volumeName).clearNamespaceQuota(); |
| OzoneVolume clrVolume = store.getVolume(volumeName); |
| Assert.assertEquals(OzoneConsts.QUOTA_RESET, clrVolume.getQuotaInBytes()); |
| Assert.assertEquals(OzoneConsts.QUOTA_RESET, |
| clrVolume.getQuotaInNamespace()); |
| |
| ozoneBucket.clearSpaceQuota(); |
| ozoneBucket.clearNamespaceQuota(); |
| OzoneBucket clrBucket = store.getVolume(volumeName).getBucket(bucketName); |
| Assert.assertEquals(OzoneConsts.QUOTA_RESET, clrBucket.getQuotaInBytes()); |
| Assert.assertEquals(OzoneConsts.QUOTA_RESET, |
| clrBucket.getQuotaInNamespace()); |
| Assert.assertEquals(1L, |
| store.getVolume(volumeName).getBucket(bucketName).getUsedNamespace()); |
| Assert.assertEquals(valueLength, |
| store.getVolume(volumeName).getBucket(bucketName).getUsedBytes()); |
| Assert.assertEquals(1L, |
| store.getVolume(volumeName).getUsedNamespace()); |
| } |
| |
| @Test |
| public void testSetBucketQuotaIllegal() throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| store.createVolume(volumeName); |
| store.getVolume(volumeName).setQuota(OzoneQuota.parseQuota( |
| "10GB", 1000L)); |
| store.getVolume(volumeName).createBucket(bucketName); |
| |
| int countException = 0; |
| try { |
| store.getVolume(volumeName).getBucket(bucketName).setQuota( |
| OzoneQuota.parseQuota("1GB", -100L)); |
| } catch (IllegalArgumentException ex) { |
| countException++; |
| GenericTestUtils.assertExceptionContains( |
| "Invalid values for quota", ex); |
| } |
| // The unit should be legal. |
| try { |
| store.getVolume(volumeName).getBucket(bucketName).setQuota( |
| OzoneQuota.parseQuota("1TEST", 100L)); |
| } catch (IllegalArgumentException ex) { |
| countException++; |
| GenericTestUtils.assertExceptionContains( |
| "Invalid values for quota", ex); |
| } |
| |
| // The setting value cannot be greater than LONG.MAX_VALUE BYTES. |
| try { |
| store.getVolume(volumeName).getBucket(bucketName).setQuota( |
| OzoneQuota.parseQuota("9223372036854775808 BYTES", 100L)); |
| } catch (IllegalArgumentException ex) { |
| countException++; |
| GenericTestUtils.assertExceptionContains( |
| "Invalid values for quota", ex); |
| } |
| |
| // The value cannot be negative. |
| try { |
| store.getVolume(volumeName).getBucket(bucketName).setQuota( |
| OzoneQuota.parseQuota("-10GB", 100L)); |
| } catch (IllegalArgumentException ex) { |
| countException++; |
| GenericTestUtils.assertExceptionContains( |
| "Quota cannot be negative.", ex); |
| } |
| |
| Assert.assertEquals(4, countException); |
| } |
| |
| @Test |
| public void testSetVolumeQuota() throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| store.createVolume(volumeName); |
| Assert.assertEquals(OzoneConsts.QUOTA_RESET, |
| store.getVolume(volumeName).getQuotaInBytes()); |
| Assert.assertEquals(OzoneConsts.QUOTA_RESET, |
| store.getVolume(volumeName).getQuotaInNamespace()); |
| store.getVolume(volumeName).setQuota(OzoneQuota.parseQuota("1GB", 1000L)); |
| OzoneVolume volume = store.getVolume(volumeName); |
| Assert.assertEquals(1024 * 1024 * 1024, |
| volume.getQuotaInBytes()); |
| Assert.assertEquals(1000L, volume.getQuotaInNamespace()); |
| } |
| |
| @Test |
| public void testSetVolumeQuotaIllegal() |
| throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| store.createVolume(volumeName); |
| int countException = 0; |
| // The unit should be legal. |
| try { |
| store.getVolume(volumeName).setQuota(OzoneQuota.parseQuota( |
| "1TEST", 1000L)); |
| } catch (IllegalArgumentException ex) { |
| countException++; |
| GenericTestUtils.assertExceptionContains( |
| "Invalid values for quota", ex); |
| } |
| |
| // The setting value cannot be greater than LONG.MAX_VALUE BYTES. |
| try { |
| store.getVolume(volumeName).setQuota(OzoneQuota.parseQuota( |
| "9223372036854775808 BYTES", 1000L)); |
| } catch (IllegalArgumentException ex) { |
| countException++; |
| GenericTestUtils.assertExceptionContains( |
| "Invalid values for quota", ex); |
| } |
| |
| // The value cannot be negative. |
| try { |
| store.getVolume(volumeName).setQuota(OzoneQuota.parseQuota( |
| "-10GB", 1000L)); |
| } catch (IllegalArgumentException ex) { |
| countException++; |
| GenericTestUtils.assertExceptionContains( |
| "Quota cannot be negative.", ex); |
| } |
| Assert.assertEquals(3, countException); |
| } |
| |
| @Test |
| public void testDeleteVolume() |
| throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| Assert.assertNotNull(volume); |
| store.deleteVolume(volumeName); |
| OzoneTestUtils.expectOmException(ResultCodes.VOLUME_NOT_FOUND, |
| () -> store.getVolume(volumeName)); |
| |
| } |
| |
| @Test |
| public void testCreateVolumeWithMetadata() |
| throws IOException, OzoneClientException { |
| String volumeName = UUID.randomUUID().toString(); |
| VolumeArgs volumeArgs = VolumeArgs.newBuilder() |
| .addMetadata("key1", "val1") |
| .build(); |
| store.createVolume(volumeName, volumeArgs); |
| OzoneVolume volume = store.getVolume(volumeName); |
| |
| Assert.assertEquals("val1", volume.getMetadata().get("key1")); |
| Assert.assertEquals(volumeName, volume.getName()); |
| } |
| |
| @Test |
| public void testCreateBucketWithMetadata() |
| throws IOException, OzoneClientException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| BucketArgs args = BucketArgs.newBuilder() |
| .addMetadata("key1", "value1").build(); |
| volume.createBucket(bucketName, args); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| Assert.assertEquals(bucketName, bucket.getName()); |
| Assert.assertNotNull(bucket.getMetadata()); |
| Assert.assertEquals("value1", bucket.getMetadata().get("key1")); |
| |
| } |
| |
| |
| @Test |
| public void testCreateBucket() |
| throws IOException { |
| Instant testStartTime = Instant.now(); |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| Assert.assertEquals(bucketName, bucket.getName()); |
| Assert.assertFalse(bucket.getCreationTime().isBefore(testStartTime)); |
| Assert.assertFalse(volume.getCreationTime().isBefore(testStartTime)); |
| } |
| |
| @Test |
| public void testCreateS3Bucket() |
| throws IOException { |
| Instant testStartTime = Instant.now(); |
| String bucketName = UUID.randomUUID().toString(); |
| store.createS3Bucket(bucketName); |
| OzoneBucket bucket = store.getS3Bucket(bucketName); |
| Assert.assertEquals(bucketName, bucket.getName()); |
| Assert.assertFalse(bucket.getCreationTime().isBefore(testStartTime)); |
| } |
| |
| @Test |
| public void testDeleteS3Bucket() |
| throws Exception { |
| Instant testStartTime = Instant.now(); |
| String bucketName = UUID.randomUUID().toString(); |
| store.createS3Bucket(bucketName); |
| OzoneBucket bucket = store.getS3Bucket(bucketName); |
| Assert.assertEquals(bucketName, bucket.getName()); |
| Assert.assertFalse(bucket.getCreationTime().isBefore(testStartTime)); |
| store.deleteS3Bucket(bucketName); |
| |
| OzoneTestUtils.expectOmException(ResultCodes.BUCKET_NOT_FOUND, |
| () -> store.getS3Bucket(bucketName)); |
| } |
| |
| @Test |
| public void testDeleteS3NonExistingBucket() { |
| try { |
| store.deleteS3Bucket(UUID.randomUUID().toString()); |
| } catch (IOException ex) { |
| GenericTestUtils.assertExceptionContains("NOT_FOUND", ex); |
| } |
| } |
| |
| @Test |
| public void testCreateBucketWithVersioning() |
| throws IOException, OzoneClientException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| BucketArgs.Builder builder = BucketArgs.newBuilder(); |
| builder.setVersioning(true); |
| volume.createBucket(bucketName, builder.build()); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| Assert.assertEquals(bucketName, bucket.getName()); |
| Assert.assertEquals(true, bucket.getVersioning()); |
| } |
| |
| @Test |
| public void testCreateBucketWithStorageType() |
| throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| BucketArgs.Builder builder = BucketArgs.newBuilder(); |
| builder.setStorageType(StorageType.SSD); |
| volume.createBucket(bucketName, builder.build()); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| Assert.assertEquals(bucketName, bucket.getName()); |
| Assert.assertEquals(StorageType.SSD, bucket.getStorageType()); |
| } |
| |
| @Test |
| public void testCreateBucketWithAcls() |
| throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| OzoneAcl userAcl = new OzoneAcl(USER, "test", |
| READ, ACCESS); |
| List<OzoneAcl> acls = new ArrayList<>(); |
| acls.add(userAcl); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| BucketArgs.Builder builder = BucketArgs.newBuilder(); |
| builder.setAcls(acls); |
| volume.createBucket(bucketName, builder.build()); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| Assert.assertEquals(bucketName, bucket.getName()); |
| Assert.assertTrue(bucket.getAcls().contains(userAcl)); |
| } |
| |
| @Test |
| public void testCreateBucketWithAllArgument() |
| throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| OzoneAcl userAcl = new OzoneAcl(USER, "test", |
| ACLType.ALL, ACCESS); |
| List<OzoneAcl> acls = new ArrayList<>(); |
| acls.add(userAcl); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| BucketArgs.Builder builder = BucketArgs.newBuilder(); |
| builder.setVersioning(true) |
| .setStorageType(StorageType.SSD) |
| .setAcls(acls); |
| volume.createBucket(bucketName, builder.build()); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| Assert.assertEquals(bucketName, bucket.getName()); |
| Assert.assertEquals(true, bucket.getVersioning()); |
| Assert.assertEquals(StorageType.SSD, bucket.getStorageType()); |
| Assert.assertTrue(bucket.getAcls().contains(userAcl)); |
| } |
| |
| @Test |
| public void testInvalidBucketCreation() throws Exception { |
| |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = "invalid#bucket"; |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| LambdaTestUtils.intercept(OMException.class, |
| "Bucket or Volume name has an unsupported" + |
| " character : #", |
| () -> volume.createBucket(bucketName)); |
| |
| } |
| |
| @Test |
| public void testAddBucketAcl() |
| throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| List<OzoneAcl> acls = new ArrayList<>(); |
| acls.add(new OzoneAcl(USER, "test", ACLType.ALL, ACCESS)); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| for (OzoneAcl acl : acls) { |
| assertTrue(bucket.addAcls(acl)); |
| } |
| OzoneBucket newBucket = volume.getBucket(bucketName); |
| Assert.assertEquals(bucketName, newBucket.getName()); |
| Assert.assertTrue(bucket.getAcls().contains(acls.get(0))); |
| } |
| |
| @Test |
| public void testRemoveBucketAcl() |
| throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| OzoneAcl userAcl = new OzoneAcl(USER, "test", |
| ACLType.ALL, ACCESS); |
| List<OzoneAcl> acls = new ArrayList<>(); |
| acls.add(userAcl); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| BucketArgs.Builder builder = BucketArgs.newBuilder(); |
| builder.setAcls(acls); |
| volume.createBucket(bucketName, builder.build()); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| for (OzoneAcl acl : acls) { |
| assertTrue(bucket.removeAcls(acl)); |
| } |
| OzoneBucket newBucket = volume.getBucket(bucketName); |
| Assert.assertEquals(bucketName, newBucket.getName()); |
| Assert.assertTrue(!bucket.getAcls().contains(acls.get(0))); |
| } |
| |
| @Test |
| public void testRemoveBucketAclUsingRpcClientRemoveAcl() |
| throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| OzoneAcl userAcl = new OzoneAcl(USER, "test", |
| ACLType.ALL, ACCESS); |
| List<OzoneAcl> acls = new ArrayList<>(); |
| acls.add(userAcl); |
| acls.add(new OzoneAcl(USER, "test1", |
| ACLType.ALL, ACCESS)); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| BucketArgs.Builder builder = BucketArgs.newBuilder(); |
| builder.setAcls(acls); |
| volume.createBucket(bucketName, builder.build()); |
| OzoneObj ozoneObj = OzoneObjInfo.Builder.newBuilder() |
| .setBucketName(bucketName) |
| .setVolumeName(volumeName) |
| .setStoreType(OzoneObj.StoreType.OZONE) |
| .setResType(OzoneObj.ResourceType.BUCKET).build(); |
| |
| // Remove the 2nd acl added to the list. |
| boolean remove = store.removeAcl(ozoneObj, acls.get(1)); |
| Assert.assertTrue(remove); |
| Assert.assertFalse(store.getAcl(ozoneObj).contains(acls.get(1))); |
| |
| remove = store.removeAcl(ozoneObj, acls.get(0)); |
| Assert.assertTrue(remove); |
| Assert.assertFalse(store.getAcl(ozoneObj).contains(acls.get(0))); |
| } |
| |
| @Test |
| public void testSetBucketVersioning() |
| throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| bucket.setVersioning(true); |
| OzoneBucket newBucket = volume.getBucket(bucketName); |
| Assert.assertEquals(bucketName, newBucket.getName()); |
| Assert.assertEquals(true, newBucket.getVersioning()); |
| } |
| |
| @Test |
| public void testAclsAfterCallingSetBucketProperty() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| |
| OzoneBucket ozoneBucket = volume.getBucket(bucketName); |
| List<OzoneAcl> currentAcls = ozoneBucket.getAcls(); |
| |
| ozoneBucket.setVersioning(true); |
| |
| OzoneBucket newBucket = volume.getBucket(bucketName); |
| Assert.assertEquals(bucketName, newBucket.getName()); |
| Assert.assertEquals(true, newBucket.getVersioning()); |
| |
| List<OzoneAcl> aclsAfterSet = newBucket.getAcls(); |
| Assert.assertEquals(currentAcls, aclsAfterSet); |
| |
| } |
| |
| @Test |
| public void testSetBucketStorageType() |
| throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| bucket.setStorageType(StorageType.SSD); |
| OzoneBucket newBucket = volume.getBucket(bucketName); |
| Assert.assertEquals(bucketName, newBucket.getName()); |
| Assert.assertEquals(StorageType.SSD, newBucket.getStorageType()); |
| } |
| |
| |
| @Test |
| public void testDeleteBucket() |
| throws Exception { |
| |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| Assert.assertNotNull(bucket); |
| volume.deleteBucket(bucketName); |
| |
| OzoneTestUtils.expectOmException(ResultCodes.BUCKET_NOT_FOUND, |
| () -> volume.getBucket(bucketName) |
| ); |
| } |
| |
| private boolean verifyRatisReplication(String volumeName, String bucketName, |
| String keyName, ReplicationType type, ReplicationFactor factor) |
| throws IOException { |
| OmKeyArgs keyArgs = new OmKeyArgs.Builder() |
| .setVolumeName(volumeName) |
| .setBucketName(bucketName) |
| .setKeyName(keyName) |
| .setRefreshPipeline(true) |
| .build(); |
| HddsProtos.ReplicationType replicationType = |
| HddsProtos.ReplicationType.valueOf(type.toString()); |
| HddsProtos.ReplicationFactor replicationFactor = |
| HddsProtos.ReplicationFactor.valueOf(factor.getValue()); |
| OmKeyInfo keyInfo = ozoneManager.lookupKey(keyArgs); |
| for (OmKeyLocationInfo info: |
| keyInfo.getLatestVersionLocations().getLocationList()) { |
| ContainerInfo container = |
| storageContainerLocationClient.getContainer(info.getContainerID()); |
| if (!container.getReplicationFactor().equals(replicationFactor) || ( |
| container.getReplicationType() != replicationType)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @Test |
| public void testPutKey() throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| Instant testStartTime = Instant.now(); |
| |
| String value = "sample value"; |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| for (int i = 0; i < 10; i++) { |
| String keyName = UUID.randomUUID().toString(); |
| |
| OzoneOutputStream out = bucket.createKey(keyName, |
| value.getBytes().length, STAND_ALONE, |
| ONE, new HashMap<>()); |
| out.write(value.getBytes()); |
| out.close(); |
| OzoneKey key = bucket.getKey(keyName); |
| Assert.assertEquals(keyName, key.getName()); |
| OzoneInputStream is = bucket.readKey(keyName); |
| byte[] fileContent = new byte[value.getBytes().length]; |
| is.read(fileContent); |
| Assert.assertTrue(verifyRatisReplication(volumeName, bucketName, |
| keyName, STAND_ALONE, |
| ONE)); |
| Assert.assertEquals(value, new String(fileContent)); |
| Assert.assertFalse(key.getCreationTime().isBefore(testStartTime)); |
| Assert.assertFalse(key.getModificationTime().isBefore(testStartTime)); |
| } |
| } |
| |
| @Test |
| public void testCheckUsedBytesQuota() throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| OzoneVolume volume = null; |
| |
| String value = "sample value"; |
| int blockSize = (int) ozoneManager.getConfiguration().getStorageSize( |
| OZONE_SCM_BLOCK_SIZE, OZONE_SCM_BLOCK_SIZE_DEFAULT, StorageUnit.BYTES); |
| int valueLength = value.getBytes().length; |
| int countException = 0; |
| |
| store.createVolume(volumeName); |
| volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| // Test bucket quota. |
| store.getVolume(volumeName).setQuota( |
| OzoneQuota.parseQuota(Long.MAX_VALUE + " Bytes", 100)); |
| bucketName = UUID.randomUUID().toString(); |
| volume.createBucket(bucketName); |
| bucket = volume.getBucket(bucketName); |
| bucket.setQuota(OzoneQuota.parseQuota("1 Bytes", 100)); |
| |
| // Test bucket quota: write key. |
| // The remaining quota does not satisfy a block size, so the write fails. |
| try { |
| writeKey(bucket, UUID.randomUUID().toString(), ONE, value, valueLength); |
| } catch (IOException ex) { |
| countException++; |
| GenericTestUtils.assertExceptionContains("QUOTA_EXCEEDED", ex); |
| } |
| // Write failed, bucket usedBytes should be 0 |
| Assert.assertEquals(0L, |
| store.getVolume(volumeName).getBucket(bucketName).getUsedBytes()); |
| |
| // Test bucket quota: write file. |
| // The remaining quota does not satisfy a block size, so the write fails. |
| try { |
| writeFile(bucket, UUID.randomUUID().toString(), ONE, value, 0); |
| } catch (IOException ex) { |
| countException++; |
| GenericTestUtils.assertExceptionContains("QUOTA_EXCEEDED", ex); |
| } |
| // Write failed, bucket usedBytes should be 0 |
| Assert.assertEquals(0L, |
| store.getVolume(volumeName).getBucket(bucketName).getUsedBytes()); |
| |
| // Test bucket quota: write large key(with five blocks), the first four |
| // blocks will succeed,while the later block will fail. |
| bucket.setQuota(OzoneQuota.parseQuota( |
| 4 * blockSize + " Bytes", 100)); |
| try { |
| OzoneOutputStream out = bucket.createKey(UUID.randomUUID().toString(), |
| valueLength, STAND_ALONE, ONE, new HashMap<>()); |
| for (int i = 0; i <= (4 * blockSize) / value.length(); i++) { |
| out.write(value.getBytes()); |
| } |
| out.close(); |
| } catch (IOException ex) { |
| countException++; |
| GenericTestUtils.assertExceptionContains("QUOTA_EXCEEDED", ex); |
| } |
| // AllocateBlock failed, bucket usedBytes should be 4 * blockSize |
| Assert.assertEquals(4 * blockSize, |
| store.getVolume(volumeName).getBucket(bucketName).getUsedBytes()); |
| |
| // Reset bucket quota, the original usedBytes needs to remain the same |
| bucket.setQuota(OzoneQuota.parseQuota( |
| 100 + " GB", 100)); |
| Assert.assertEquals(4 * blockSize, |
| store.getVolume(volumeName).getBucket(bucketName).getUsedBytes()); |
| |
| Assert.assertEquals(3, countException); |
| } |
| |
| @Test |
| public void testVolumeUsedNamespace() throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String bucketName2 = UUID.randomUUID().toString(); |
| OzoneVolume volume = null; |
| |
| // set Volume namespace quota as 1 |
| store.createVolume(volumeName, |
| VolumeArgs.newBuilder().setQuotaInNamespace(1L).build()); |
| volume = store.getVolume(volumeName); |
| // The initial value should be 0 |
| Assert.assertEquals(0L, volume.getUsedNamespace()); |
| volume.createBucket(bucketName); |
| // Used namespace should be 1 |
| volume = store.getVolume(volumeName); |
| Assert.assertEquals(1L, volume.getUsedNamespace()); |
| |
| try { |
| volume.createBucket(bucketName2); |
| } catch (IOException ex) { |
| GenericTestUtils.assertExceptionContains("QUOTA_EXCEEDED", ex); |
| } |
| |
| // test linked bucket |
| String targetVolName = UUID.randomUUID().toString(); |
| store.createVolume(targetVolName); |
| OzoneVolume volumeWithLinkedBucket = store.getVolume(targetVolName); |
| String targetBucketName = UUID.randomUUID().toString(); |
| BucketArgs.Builder argsBuilder = new BucketArgs.Builder() |
| .setStorageType(StorageType.DEFAULT) |
| .setVersioning(false) |
| .setSourceVolume(volumeName) |
| .setSourceBucket(bucketName); |
| volumeWithLinkedBucket.createBucket(targetBucketName, argsBuilder.build()); |
| // Used namespace should be 0 because linked bucket does not consume |
| // namespace quota |
| Assert.assertEquals(0L, volumeWithLinkedBucket.getUsedNamespace()); |
| |
| // Reset volume quota, the original usedNamespace needs to remain the same |
| store.getVolume(volumeName).setQuota(OzoneQuota.parseQuota( |
| 100 + " GB", 100)); |
| Assert.assertEquals(1L, |
| store.getVolume(volumeName).getUsedNamespace()); |
| |
| volume.deleteBucket(bucketName); |
| // Used namespace should be 0 |
| volume = store.getVolume(volumeName); |
| Assert.assertEquals(0L, volume.getUsedNamespace()); |
| } |
| |
| @Test |
| public void testBucketUsedNamespace() throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String key1 = UUID.randomUUID().toString(); |
| String key2 = UUID.randomUUID().toString(); |
| String key3 = UUID.randomUUID().toString(); |
| OzoneVolume volume = null; |
| OzoneBucket bucket = null; |
| |
| String value = "sample value"; |
| |
| store.createVolume(volumeName); |
| volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| bucket = volume.getBucket(bucketName); |
| bucket.setQuota(OzoneQuota.parseQuota(Long.MAX_VALUE + " Bytes", 2)); |
| |
| writeKey(bucket, key1, ONE, value, value.length()); |
| Assert.assertEquals(1L, |
| store.getVolume(volumeName).getBucket(bucketName).getUsedNamespace()); |
| |
| writeKey(bucket, key2, ONE, value, value.length()); |
| Assert.assertEquals(2L, |
| store.getVolume(volumeName).getBucket(bucketName).getUsedNamespace()); |
| |
| try { |
| writeKey(bucket, key3, ONE, value, value.length()); |
| Assert.fail("Write key should be failed"); |
| } catch (IOException ex) { |
| GenericTestUtils.assertExceptionContains("QUOTA_EXCEEDED", ex); |
| } |
| |
| // Write failed, bucket usedNamespace should remain as 2 |
| Assert.assertEquals(2L, |
| store.getVolume(volumeName).getBucket(bucketName).getUsedNamespace()); |
| |
| // Reset bucket quota, the original usedNamespace needs to remain the same |
| bucket.setQuota(OzoneQuota.parseQuota(Long.MAX_VALUE + " Bytes", 100)); |
| Assert.assertEquals(2L, |
| store.getVolume(volumeName).getBucket(bucketName).getUsedNamespace()); |
| |
| bucket.deleteKeys(Arrays.asList(key1, key2)); |
| Assert.assertEquals(0L, |
| store.getVolume(volumeName).getBucket(bucketName).getUsedNamespace()); |
| } |
| |
| private void writeKey(OzoneBucket bucket, String keyName, |
| ReplicationFactor replication, String value, int valueLength) |
| throws IOException{ |
| OzoneOutputStream out = bucket.createKey(keyName, valueLength, STAND_ALONE, |
| replication, new HashMap<>()); |
| out.write(value.getBytes()); |
| out.close(); |
| } |
| |
| private void writeFile(OzoneBucket bucket, String keyName, |
| ReplicationFactor replication, String value, int valueLength) |
| throws IOException{ |
| OzoneOutputStream out = bucket.createFile(keyName, valueLength, STAND_ALONE, |
| replication, true, true); |
| out.write(value.getBytes()); |
| out.close(); |
| } |
| |
| @Test |
| public void testUsedBytesWithUploadPart() throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| int blockSize = (int) ozoneManager.getConfiguration().getStorageSize( |
| OZONE_SCM_BLOCK_SIZE, OZONE_SCM_BLOCK_SIZE_DEFAULT, StorageUnit.BYTES); |
| String sampleData = generateData(blockSize + 100, |
| (byte) RandomUtils.nextLong()).toString(); |
| int valueLength = sampleData.getBytes().length; |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| OmMultipartInfo multipartInfo = bucket.initiateMultipartUpload(keyName, |
| STAND_ALONE, ONE); |
| |
| assertNotNull(multipartInfo); |
| String uploadID = multipartInfo.getUploadID(); |
| Assert.assertEquals(volumeName, multipartInfo.getVolumeName()); |
| Assert.assertEquals(bucketName, multipartInfo.getBucketName()); |
| Assert.assertEquals(keyName, multipartInfo.getKeyName()); |
| assertNotNull(multipartInfo.getUploadID()); |
| |
| OzoneOutputStream ozoneOutputStream = bucket.createMultipartKey(keyName, |
| sampleData.length(), 1, uploadID); |
| ozoneOutputStream.write(string2Bytes(sampleData), 0, |
| sampleData.length()); |
| ozoneOutputStream.close(); |
| |
| Assert.assertEquals(valueLength, store.getVolume(volumeName) |
| .getBucket(bucketName).getUsedBytes()); |
| |
| // Abort uploaded partKey and the usedBytes of bucket should be 0. |
| bucket.abortMultipartUpload(keyName, uploadID); |
| Assert.assertEquals(0, store.getVolume(volumeName) |
| .getBucket(bucketName).getUsedBytes()); |
| } |
| |
| @Test |
| public void testValidateBlockLengthWithCommitKey() throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| |
| String value = RandomStringUtils.random(RandomUtils.nextInt(0, 1024)); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| String keyName = UUID.randomUUID().toString(); |
| |
| // create the initial key with size 0, write will allocate the first block. |
| OzoneOutputStream out = bucket.createKey(keyName, 0, |
| STAND_ALONE, ONE, new HashMap<>()); |
| out.write(value.getBytes()); |
| out.close(); |
| OmKeyArgs.Builder builder = new OmKeyArgs.Builder(); |
| builder.setVolumeName(volumeName).setBucketName(bucketName) |
| .setKeyName(keyName).setRefreshPipeline(true); |
| OmKeyInfo keyInfo = ozoneManager.lookupKey(builder.build()); |
| |
| List<OmKeyLocationInfo> locationInfoList = |
| keyInfo.getLatestVersionLocations().getBlocksLatestVersionOnly(); |
| // LocationList should have only 1 block |
| Assert.assertEquals(1, locationInfoList.size()); |
| // make sure the data block size is updated |
| Assert.assertEquals(value.getBytes().length, |
| locationInfoList.get(0).getLength()); |
| // make sure the total data size is set correctly |
| Assert.assertEquals(value.getBytes().length, keyInfo.getDataSize()); |
| } |
| |
| @Test |
| public void testPutKeyRatisOneNode() throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| Instant testStartTime = Instant.now(); |
| |
| String value = "sample value"; |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| for (int i = 0; i < 10; i++) { |
| String keyName = UUID.randomUUID().toString(); |
| |
| OzoneOutputStream out = bucket.createKey(keyName, |
| value.getBytes().length, ReplicationType.RATIS, |
| ONE, new HashMap<>()); |
| out.write(value.getBytes()); |
| out.close(); |
| OzoneKey key = bucket.getKey(keyName); |
| Assert.assertEquals(keyName, key.getName()); |
| OzoneInputStream is = bucket.readKey(keyName); |
| byte[] fileContent = new byte[value.getBytes().length]; |
| is.read(fileContent); |
| is.close(); |
| Assert.assertTrue(verifyRatisReplication(volumeName, bucketName, |
| keyName, ReplicationType.RATIS, ONE)); |
| Assert.assertEquals(value, new String(fileContent)); |
| Assert.assertFalse(key.getCreationTime().isBefore(testStartTime)); |
| Assert.assertFalse(key.getModificationTime().isBefore(testStartTime)); |
| } |
| } |
| |
| @Test |
| public void testPutKeyRatisThreeNodes() throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| Instant testStartTime = Instant.now(); |
| |
| String value = "sample value"; |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| for (int i = 0; i < 10; i++) { |
| String keyName = UUID.randomUUID().toString(); |
| |
| OzoneOutputStream out = bucket.createKey(keyName, |
| value.getBytes().length, ReplicationType.RATIS, |
| THREE, new HashMap<>()); |
| out.write(value.getBytes()); |
| out.close(); |
| OzoneKey key = bucket.getKey(keyName); |
| Assert.assertEquals(keyName, key.getName()); |
| OzoneInputStream is = bucket.readKey(keyName); |
| byte[] fileContent = new byte[value.getBytes().length]; |
| is.read(fileContent); |
| is.close(); |
| Assert.assertTrue(verifyRatisReplication(volumeName, bucketName, |
| keyName, ReplicationType.RATIS, |
| THREE)); |
| Assert.assertEquals(value, new String(fileContent)); |
| Assert.assertFalse(key.getCreationTime().isBefore(testStartTime)); |
| Assert.assertFalse(key.getModificationTime().isBefore(testStartTime)); |
| } |
| } |
| |
| |
| @Test |
| public void testPutKeyRatisThreeNodesParallel() throws IOException, |
| InterruptedException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| Instant testStartTime = Instant.now(); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| CountDownLatch latch = new CountDownLatch(2); |
| AtomicInteger failCount = new AtomicInteger(0); |
| |
| Runnable r = () -> { |
| try { |
| for (int i = 0; i < 5; i++) { |
| String keyName = UUID.randomUUID().toString(); |
| String data = generateData(5 * 1024 * 1024, |
| (byte) RandomUtils.nextLong()).toString(); |
| OzoneOutputStream out = bucket.createKey(keyName, |
| data.getBytes().length, ReplicationType.RATIS, |
| THREE, new HashMap<>()); |
| out.write(data.getBytes()); |
| out.close(); |
| OzoneKey key = bucket.getKey(keyName); |
| Assert.assertEquals(keyName, key.getName()); |
| OzoneInputStream is = bucket.readKey(keyName); |
| byte[] fileContent = new byte[data.getBytes().length]; |
| is.read(fileContent); |
| is.close(); |
| Assert.assertTrue(verifyRatisReplication(volumeName, bucketName, |
| keyName, ReplicationType.RATIS, |
| THREE)); |
| Assert.assertEquals(data, new String(fileContent)); |
| Assert.assertFalse(key.getCreationTime().isBefore(testStartTime)); |
| Assert.assertFalse(key.getModificationTime().isBefore(testStartTime)); |
| } |
| latch.countDown(); |
| } catch (IOException ex) { |
| latch.countDown(); |
| failCount.incrementAndGet(); |
| } |
| }; |
| |
| Thread thread1 = new Thread(r); |
| Thread thread2 = new Thread(r); |
| |
| thread1.start(); |
| thread2.start(); |
| |
| latch.await(600, TimeUnit.SECONDS); |
| |
| if (failCount.get() > 0) { |
| fail("testPutKeyRatisThreeNodesParallel failed"); |
| } |
| |
| } |
| |
| |
| @Test |
| public void testReadKeyWithVerifyChecksumFlagEnable() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| // Create and corrupt key |
| createAndCorruptKey(volumeName, bucketName, keyName); |
| |
| // read corrupt key with verify checksum enabled |
| readCorruptedKey(volumeName, bucketName, keyName, true); |
| |
| } |
| |
| |
| @Test |
| public void testReadKeyWithVerifyChecksumFlagDisable() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| // Create and corrupt key |
| createAndCorruptKey(volumeName, bucketName, keyName); |
| |
| // read corrupt key with verify checksum enabled |
| readCorruptedKey(volumeName, bucketName, keyName, false); |
| |
| } |
| |
| private void createAndCorruptKey(String volumeName, String bucketName, |
| String keyName) throws IOException { |
| String value = "sample value"; |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| // Write data into a key |
| OzoneOutputStream out = bucket.createKey(keyName, |
| value.getBytes().length, ReplicationType.RATIS, |
| ONE, new HashMap<>()); |
| out.write(value.getBytes()); |
| out.close(); |
| |
| // We need to find the location of the chunk file corresponding to the |
| // data we just wrote. |
| OzoneKey key = bucket.getKey(keyName); |
| long containerID = ((OzoneKeyDetails) key).getOzoneKeyLocations().get(0) |
| .getContainerID(); |
| |
| // Get the container by traversing the datanodes. Atleast one of the |
| // datanode must have this container. |
| Container container = null; |
| for (HddsDatanodeService hddsDatanode : cluster.getHddsDatanodes()) { |
| container = hddsDatanode.getDatanodeStateMachine().getContainer() |
| .getContainerSet().getContainer(containerID); |
| if (container != null) { |
| break; |
| } |
| } |
| Assert.assertNotNull("Container not found", container); |
| corruptData(container, key); |
| } |
| |
| |
| private void readCorruptedKey(String volumeName, String bucketName, |
| String keyName, boolean verifyChecksum) { |
| try { |
| |
| OzoneConfiguration configuration = cluster.getConf(); |
| |
| final OzoneClientConfig clientConfig = |
| configuration.getObject(OzoneClientConfig.class); |
| clientConfig.setChecksumVerify(verifyChecksum); |
| configuration.setFromObject(clientConfig); |
| |
| RpcClient client = new RpcClient(configuration, null); |
| OzoneInputStream is = client.getKey(volumeName, bucketName, keyName); |
| is.read(new byte[100]); |
| is.close(); |
| if (verifyChecksum) { |
| fail("Reading corrupted data should fail, as verify checksum is " + |
| "enabled"); |
| } |
| } catch (IOException e) { |
| if (!verifyChecksum) { |
| fail("Reading corrupted data should not fail, as verify checksum is " + |
| "disabled"); |
| } |
| } |
| } |
| |
| |
| private void readKey(OzoneBucket bucket, String keyName, String data) |
| throws IOException { |
| OzoneKey key = bucket.getKey(keyName); |
| Assert.assertEquals(keyName, key.getName()); |
| OzoneInputStream is = bucket.readKey(keyName); |
| byte[] fileContent = new byte[data.getBytes().length]; |
| is.read(fileContent); |
| is.close(); |
| } |
| |
| @Test |
| public void testGetKeyDetails() throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| String keyName = UUID.randomUUID().toString(); |
| String keyValue = RandomStringUtils.random(128); |
| //String keyValue = "this is a test value.glx"; |
| // create the initial key with size 0, write will allocate the first block. |
| OzoneOutputStream out = bucket.createKey(keyName, |
| keyValue.getBytes().length, STAND_ALONE, |
| ONE, new HashMap<>()); |
| out.write(keyValue.getBytes()); |
| out.close(); |
| |
| OzoneInputStream is = bucket.readKey(keyName); |
| byte[] fileContent = new byte[32]; |
| is.read(fileContent); |
| |
| // First, confirm the key info from the client matches the info in OM. |
| OmKeyArgs.Builder builder = new OmKeyArgs.Builder(); |
| builder.setVolumeName(volumeName).setBucketName(bucketName) |
| .setKeyName(keyName).setRefreshPipeline(true); |
| OmKeyLocationInfo keyInfo = ozoneManager.lookupKey(builder.build()). |
| getKeyLocationVersions().get(0).getBlocksLatestVersionOnly().get(0); |
| long containerID = keyInfo.getContainerID(); |
| long localID = keyInfo.getLocalID(); |
| OzoneKeyDetails keyDetails = (OzoneKeyDetails)bucket.getKey(keyName); |
| Assert.assertEquals(keyName, keyDetails.getName()); |
| |
| List<OzoneKeyLocation> keyLocations = keyDetails.getOzoneKeyLocations(); |
| Assert.assertEquals(1, keyLocations.size()); |
| Assert.assertEquals(containerID, keyLocations.get(0).getContainerID()); |
| Assert.assertEquals(localID, keyLocations.get(0).getLocalID()); |
| |
| // Make sure that the data size matched. |
| Assert.assertEquals(keyValue.getBytes().length, |
| keyLocations.get(0).getLength()); |
| |
| // Second, sum the data size from chunks in Container via containerID |
| // and localID, make sure the size equals to the size from keyDetails. |
| ContainerInfo container = cluster.getStorageContainerManager() |
| .getContainerManager().getContainer(ContainerID.valueof(containerID)); |
| Pipeline pipeline = cluster.getStorageContainerManager() |
| .getPipelineManager().getPipeline(container.getPipelineID()); |
| List<DatanodeDetails> datanodes = pipeline.getNodes(); |
| Assert.assertEquals(datanodes.size(), 1); |
| |
| DatanodeDetails datanodeDetails = datanodes.get(0); |
| Assert.assertNotNull(datanodeDetails); |
| HddsDatanodeService datanodeService = null; |
| for (HddsDatanodeService datanodeServiceItr : cluster.getHddsDatanodes()) { |
| if (datanodeDetails.equals(datanodeServiceItr.getDatanodeDetails())) { |
| datanodeService = datanodeServiceItr; |
| break; |
| } |
| } |
| KeyValueContainerData containerData = |
| (KeyValueContainerData)(datanodeService.getDatanodeStateMachine() |
| .getContainer().getContainerSet().getContainer(containerID) |
| .getContainerData()); |
| try (ReferenceCountedDB db = BlockUtils.getDB(containerData, |
| cluster.getConf()); |
| BlockIterator<BlockData> keyValueBlockIterator = |
| db.getStore().getBlockIterator()) { |
| while (keyValueBlockIterator.hasNext()) { |
| BlockData blockData = keyValueBlockIterator.nextBlock(); |
| if (blockData.getBlockID().getLocalID() == localID) { |
| long length = 0; |
| List<ContainerProtos.ChunkInfo> chunks = blockData.getChunks(); |
| for (ContainerProtos.ChunkInfo chunk : chunks) { |
| length += chunk.getLen(); |
| } |
| Assert.assertEquals(length, keyValue.getBytes().length); |
| break; |
| } |
| } |
| } |
| } |
| |
| /** |
| * Tests reading a corrputed chunk file throws checksum exception. |
| * @throws IOException |
| */ |
| @Test |
| public void testReadKeyWithCorruptedData() throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| |
| String value = "sample value"; |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| String keyName = UUID.randomUUID().toString(); |
| |
| // Write data into a key |
| OzoneOutputStream out = bucket.createKey(keyName, |
| value.getBytes().length, ReplicationType.RATIS, |
| ONE, new HashMap<>()); |
| out.write(value.getBytes()); |
| out.close(); |
| |
| // We need to find the location of the chunk file corresponding to the |
| // data we just wrote. |
| OzoneKey key = bucket.getKey(keyName); |
| long containerID = ((OzoneKeyDetails) key).getOzoneKeyLocations().get(0) |
| .getContainerID(); |
| |
| // Get the container by traversing the datanodes. Atleast one of the |
| // datanode must have this container. |
| Container container = null; |
| for (HddsDatanodeService hddsDatanode : cluster.getHddsDatanodes()) { |
| container = hddsDatanode.getDatanodeStateMachine().getContainer() |
| .getContainerSet().getContainer(containerID); |
| if (container != null) { |
| break; |
| } |
| } |
| Assert.assertNotNull("Container not found", container); |
| corruptData(container, key); |
| |
| // Try reading the key. Since the chunk file is corrupted, it should |
| // throw a checksum mismatch exception. |
| try { |
| OzoneInputStream is = bucket.readKey(keyName); |
| is.read(new byte[100]); |
| fail("Reading corrupted data should fail."); |
| } catch (IOException e) { |
| GenericTestUtils.assertExceptionContains("Checksum mismatch", e); |
| } |
| } |
| |
| /** |
| * Tests reading a corrputed chunk file throws checksum exception. |
| * @throws IOException |
| */ |
| @Test |
| public void testReadKeyWithCorruptedDataWithMutiNodes() throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| |
| String value = "sample value"; |
| byte[] data = value.getBytes(); |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| String keyName = UUID.randomUUID().toString(); |
| |
| // Write data into a key |
| OzoneOutputStream out = bucket.createKey(keyName, |
| value.getBytes().length, ReplicationType.RATIS, |
| THREE, new HashMap<>()); |
| out.write(value.getBytes()); |
| out.close(); |
| |
| // We need to find the location of the chunk file corresponding to the |
| // data we just wrote. |
| OzoneKey key = bucket.getKey(keyName); |
| List<OzoneKeyLocation> keyLocation = |
| ((OzoneKeyDetails) key).getOzoneKeyLocations(); |
| Assert.assertTrue("Key location not found in OM", !keyLocation.isEmpty()); |
| long containerID = ((OzoneKeyDetails) key).getOzoneKeyLocations().get(0) |
| .getContainerID(); |
| |
| // Get the container by traversing the datanodes. |
| List<Container> containerList = new ArrayList<>(); |
| Container container; |
| for (HddsDatanodeService hddsDatanode : cluster.getHddsDatanodes()) { |
| container = hddsDatanode.getDatanodeStateMachine().getContainer() |
| .getContainerSet().getContainer(containerID); |
| if (container != null) { |
| containerList.add(container); |
| if (containerList.size() == 3) { |
| break; |
| } |
| } |
| } |
| Assert.assertTrue("Container not found", !containerList.isEmpty()); |
| corruptData(containerList.get(0), key); |
| // Try reading the key. Read will fail on the first node and will eventually |
| // failover to next replica |
| try { |
| OzoneInputStream is = bucket.readKey(keyName); |
| byte[] b = new byte[data.length]; |
| is.read(b); |
| Assert.assertTrue(Arrays.equals(b, data)); |
| } catch (OzoneChecksumException e) { |
| fail("Reading corrupted data should not fail."); |
| } |
| corruptData(containerList.get(1), key); |
| // Try reading the key. Read will fail on the first node and will eventually |
| // failover to next replica |
| try { |
| OzoneInputStream is = bucket.readKey(keyName); |
| byte[] b = new byte[data.length]; |
| is.read(b); |
| Assert.assertTrue(Arrays.equals(b, data)); |
| } catch (OzoneChecksumException e) { |
| fail("Reading corrupted data should not fail."); |
| } |
| corruptData(containerList.get(2), key); |
| // Try reading the key. Read will fail here as all the replica are corrupt |
| try { |
| OzoneInputStream is = bucket.readKey(keyName); |
| byte[] b = new byte[data.length]; |
| is.read(b); |
| fail("Reading corrupted data should fail."); |
| } catch (IOException e) { |
| GenericTestUtils.assertExceptionContains("Checksum mismatch", e); |
| } |
| } |
| |
| private void corruptData(Container container, OzoneKey key) |
| throws IOException { |
| long containerID = ((OzoneKeyDetails) key).getOzoneKeyLocations().get(0) |
| .getContainerID(); |
| long localID = ((OzoneKeyDetails) key).getOzoneKeyLocations().get(0) |
| .getLocalID(); |
| // From the containerData, get the block iterator for all the blocks in |
| // the container. |
| KeyValueContainerData containerData = |
| (KeyValueContainerData) container.getContainerData(); |
| try (ReferenceCountedDB db = BlockUtils.getDB(containerData, |
| cluster.getConf()); |
| BlockIterator<BlockData> keyValueBlockIterator = |
| db.getStore().getBlockIterator()) { |
| // Find the block corresponding to the key we put. We use the localID of |
| // the BlockData to identify out key. |
| BlockData blockData = null; |
| while (keyValueBlockIterator.hasNext()) { |
| blockData = keyValueBlockIterator.nextBlock(); |
| if (blockData.getBlockID().getLocalID() == localID) { |
| break; |
| } |
| } |
| Assert.assertNotNull("Block not found", blockData); |
| |
| // Get the location of the chunk file |
| String containreBaseDir = |
| container.getContainerData().getVolume().getHddsRootDir().getPath(); |
| File chunksLocationPath = KeyValueContainerLocationUtil |
| .getChunksLocationPath(containreBaseDir, scmId, containerID); |
| byte[] corruptData = "corrupted data".getBytes(); |
| // Corrupt the contents of chunk files |
| for (File file : FileUtils.listFiles(chunksLocationPath, null, false)) { |
| FileUtils.writeByteArrayToFile(file, corruptData); |
| } |
| } |
| } |
| |
| @Test |
| public void testDeleteKey() |
| throws Exception { |
| |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| String value = "sample value"; |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| OzoneOutputStream out = bucket.createKey(keyName, |
| value.getBytes().length, STAND_ALONE, |
| ONE, new HashMap<>()); |
| out.write(value.getBytes()); |
| out.close(); |
| OzoneKey key = bucket.getKey(keyName); |
| Assert.assertEquals(keyName, key.getName()); |
| bucket.deleteKey(keyName); |
| |
| OzoneTestUtils.expectOmException(KEY_NOT_FOUND, |
| () -> bucket.getKey(keyName)); |
| } |
| |
| @Test |
| public void testRenameKey() |
| throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String fromKeyName = UUID.randomUUID().toString(); |
| String value = "sample value"; |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| createTestKey(bucket, fromKeyName, value); |
| |
| // Rename to empty string should fail. |
| OMException oe = null; |
| String toKeyName = ""; |
| try { |
| bucket.renameKey(fromKeyName, toKeyName); |
| } catch (OMException e) { |
| oe = e; |
| } |
| Assert.assertEquals(ResultCodes.INVALID_KEY_NAME, oe.getResult()); |
| |
| toKeyName = UUID.randomUUID().toString(); |
| bucket.renameKey(fromKeyName, toKeyName); |
| |
| // Lookup for old key should fail. |
| try { |
| bucket.getKey(fromKeyName); |
| } catch (OMException e) { |
| oe = e; |
| } |
| Assert.assertEquals(KEY_NOT_FOUND, oe.getResult()); |
| |
| OzoneKey key = bucket.getKey(toKeyName); |
| Assert.assertEquals(toKeyName, key.getName()); |
| } |
| |
| @Test |
| public void testKeysRename() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName1 = "dir/file1"; |
| String keyName2 = "dir/file2"; |
| |
| String newKeyName1 = "dir/key1"; |
| String newKeyName2 = "dir/key2"; |
| |
| String value = "sample value"; |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| createTestKey(bucket, keyName1, value); |
| createTestKey(bucket, keyName2, value); |
| |
| Map<String, String> keyMap = new HashMap(); |
| keyMap.put(keyName1, newKeyName1); |
| keyMap.put(keyName2, newKeyName2); |
| bucket.renameKeys(keyMap); |
| |
| // new key should exist |
| Assert.assertEquals(newKeyName1, bucket.getKey(newKeyName1).getName()); |
| Assert.assertEquals(newKeyName2, bucket.getKey(newKeyName2).getName()); |
| |
| // old key should not exist |
| assertKeyRenamedEx(bucket, keyName1); |
| assertKeyRenamedEx(bucket, keyName2); |
| } |
| |
| @Test |
| public void testKeysRenameFail() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName1 = "dir/file1"; |
| String keyName2 = "dir/file2"; |
| |
| String newKeyName1 = "dir/key1"; |
| String newKeyName2 = "dir/key2"; |
| |
| String value = "sample value"; |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| // Create only keyName1 to test the partial failure of renameKeys. |
| createTestKey(bucket, keyName1, value); |
| |
| Map<String, String> keyMap = new HashMap(); |
| keyMap.put(keyName1, newKeyName1); |
| keyMap.put(keyName2, newKeyName2); |
| |
| try { |
| bucket.renameKeys(keyMap); |
| } catch (OMException ex) { |
| Assert.assertEquals(PARTIAL_RENAME, ex.getResult()); |
| } |
| |
| // newKeyName1 should exist |
| Assert.assertEquals(newKeyName1, bucket.getKey(newKeyName1).getName()); |
| // newKeyName2 should not exist |
| assertKeyRenamedEx(bucket, keyName2); |
| } |
| |
| @Test |
| public void testListVolume() throws IOException { |
| String volBase = "vol-" + RandomStringUtils.randomNumeric(3); |
| //Create 10 volume vol-<random>-a-0-<random> to vol-<random>-a-9-<random> |
| String volBaseNameA = volBase + "-a-"; |
| for(int i = 0; i < 10; i++) { |
| store.createVolume( |
| volBaseNameA + i + "-" + RandomStringUtils.randomNumeric(5)); |
| } |
| //Create 10 volume vol-<random>-b-0-<random> to vol-<random>-b-9-<random> |
| String volBaseNameB = volBase + "-b-"; |
| for(int i = 0; i < 10; i++) { |
| store.createVolume( |
| volBaseNameB + i + "-" + RandomStringUtils.randomNumeric(5)); |
| } |
| Iterator<? extends OzoneVolume> volIterator = store.listVolumes(volBase); |
| int totalVolumeCount = 0; |
| while(volIterator.hasNext()) { |
| volIterator.next(); |
| totalVolumeCount++; |
| } |
| Assert.assertEquals(20, totalVolumeCount); |
| Iterator<? extends OzoneVolume> volAIterator = store.listVolumes( |
| volBaseNameA); |
| for(int i = 0; i < 10; i++) { |
| Assert.assertTrue(volAIterator.next().getName() |
| .startsWith(volBaseNameA + i + "-")); |
| } |
| Assert.assertFalse(volAIterator.hasNext()); |
| Iterator<? extends OzoneVolume> volBIterator = store.listVolumes( |
| volBaseNameB); |
| for(int i = 0; i < 10; i++) { |
| Assert.assertTrue(volBIterator.next().getName() |
| .startsWith(volBaseNameB + i + "-")); |
| } |
| Assert.assertFalse(volBIterator.hasNext()); |
| Iterator<? extends OzoneVolume> iter = store.listVolumes(volBaseNameA + |
| "1-"); |
| Assert.assertTrue(iter.next().getName().startsWith(volBaseNameA + "1-")); |
| Assert.assertFalse(iter.hasNext()); |
| } |
| |
| @Test |
| public void testListBucket() |
| throws IOException { |
| String volumeA = "vol-a-" + RandomStringUtils.randomNumeric(5); |
| String volumeB = "vol-b-" + RandomStringUtils.randomNumeric(5); |
| store.createVolume(volumeA); |
| store.createVolume(volumeB); |
| OzoneVolume volA = store.getVolume(volumeA); |
| OzoneVolume volB = store.getVolume(volumeB); |
| |
| //Create 10 buckets in vol-a-<random> and 10 in vol-b-<random> |
| String bucketBaseNameA = "bucket-a-"; |
| for(int i = 0; i < 10; i++) { |
| volA.createBucket( |
| bucketBaseNameA + i + "-" + RandomStringUtils.randomNumeric(5)); |
| volB.createBucket( |
| bucketBaseNameA + i + "-" + RandomStringUtils.randomNumeric(5)); |
| } |
| //Create 10 buckets in vol-a-<random> and 10 in vol-b-<random> |
| String bucketBaseNameB = "bucket-b-"; |
| for(int i = 0; i < 10; i++) { |
| volA.createBucket( |
| bucketBaseNameB + i + "-" + RandomStringUtils.randomNumeric(5)); |
| volB.createBucket( |
| bucketBaseNameB + i + "-" + RandomStringUtils.randomNumeric(5)); |
| } |
| Iterator<? extends OzoneBucket> volABucketIter = |
| volA.listBuckets("bucket-"); |
| int volABucketCount = 0; |
| while(volABucketIter.hasNext()) { |
| volABucketIter.next(); |
| volABucketCount++; |
| } |
| Assert.assertEquals(20, volABucketCount); |
| Iterator<? extends OzoneBucket> volBBucketIter = |
| volA.listBuckets("bucket-"); |
| int volBBucketCount = 0; |
| while(volBBucketIter.hasNext()) { |
| volBBucketIter.next(); |
| volBBucketCount++; |
| } |
| Assert.assertEquals(20, volBBucketCount); |
| |
| Iterator<? extends OzoneBucket> volABucketAIter = |
| volA.listBuckets("bucket-a-"); |
| int volABucketACount = 0; |
| while(volABucketAIter.hasNext()) { |
| volABucketAIter.next(); |
| volABucketACount++; |
| } |
| Assert.assertEquals(10, volABucketACount); |
| Iterator<? extends OzoneBucket> volBBucketBIter = |
| volA.listBuckets("bucket-b-"); |
| int volBBucketBCount = 0; |
| while(volBBucketBIter.hasNext()) { |
| volBBucketBIter.next(); |
| volBBucketBCount++; |
| } |
| Assert.assertEquals(10, volBBucketBCount); |
| Iterator<? extends OzoneBucket> volABucketBIter = volA.listBuckets( |
| "bucket-b-"); |
| for(int i = 0; i < 10; i++) { |
| Assert.assertTrue(volABucketBIter.next().getName() |
| .startsWith(bucketBaseNameB + i + "-")); |
| } |
| Assert.assertFalse(volABucketBIter.hasNext()); |
| Iterator<? extends OzoneBucket> volBBucketAIter = volB.listBuckets( |
| "bucket-a-"); |
| for(int i = 0; i < 10; i++) { |
| Assert.assertTrue(volBBucketAIter.next().getName() |
| .startsWith(bucketBaseNameA + i + "-")); |
| } |
| Assert.assertFalse(volBBucketAIter.hasNext()); |
| |
| } |
| |
| @Test |
| public void testListBucketsOnEmptyVolume() |
| throws IOException { |
| String volume = "vol-" + RandomStringUtils.randomNumeric(5); |
| store.createVolume(volume); |
| OzoneVolume vol = store.getVolume(volume); |
| Iterator<? extends OzoneBucket> buckets = vol.listBuckets(""); |
| while(buckets.hasNext()) { |
| fail(); |
| } |
| } |
| |
| @Test |
| public void testListKey() |
| throws IOException { |
| String volumeA = "vol-a-" + RandomStringUtils.randomNumeric(5); |
| String volumeB = "vol-b-" + RandomStringUtils.randomNumeric(5); |
| String bucketA = "buc-a-" + RandomStringUtils.randomNumeric(5); |
| String bucketB = "buc-b-" + RandomStringUtils.randomNumeric(5); |
| store.createVolume(volumeA); |
| store.createVolume(volumeB); |
| OzoneVolume volA = store.getVolume(volumeA); |
| OzoneVolume volB = store.getVolume(volumeB); |
| volA.createBucket(bucketA); |
| volA.createBucket(bucketB); |
| volB.createBucket(bucketA); |
| volB.createBucket(bucketB); |
| OzoneBucket volAbucketA = volA.getBucket(bucketA); |
| OzoneBucket volAbucketB = volA.getBucket(bucketB); |
| OzoneBucket volBbucketA = volB.getBucket(bucketA); |
| OzoneBucket volBbucketB = volB.getBucket(bucketB); |
| |
| /* |
| Create 10 keys in vol-a-<random>/buc-a-<random>, |
| vol-a-<random>/buc-b-<random>, vol-b-<random>/buc-a-<random> and |
| vol-b-<random>/buc-b-<random> |
| */ |
| String keyBaseA = "key-a-"; |
| for (int i = 0; i < 10; i++) { |
| byte[] value = RandomStringUtils.randomAscii(10240).getBytes(); |
| OzoneOutputStream one = volAbucketA.createKey( |
| keyBaseA + i + "-" + RandomStringUtils.randomNumeric(5), |
| value.length, STAND_ALONE, ONE, |
| new HashMap<>()); |
| one.write(value); |
| one.close(); |
| OzoneOutputStream two = volAbucketB.createKey( |
| keyBaseA + i + "-" + RandomStringUtils.randomNumeric(5), |
| value.length, STAND_ALONE, ONE, |
| new HashMap<>()); |
| two.write(value); |
| two.close(); |
| OzoneOutputStream three = volBbucketA.createKey( |
| keyBaseA + i + "-" + RandomStringUtils.randomNumeric(5), |
| value.length, STAND_ALONE, ONE, |
| new HashMap<>()); |
| three.write(value); |
| three.close(); |
| OzoneOutputStream four = volBbucketB.createKey( |
| keyBaseA + i + "-" + RandomStringUtils.randomNumeric(5), |
| value.length, STAND_ALONE, ONE, |
| new HashMap<>()); |
| four.write(value); |
| four.close(); |
| } |
| /* |
| Create 10 keys in vol-a-<random>/buc-a-<random>, |
| vol-a-<random>/buc-b-<random>, vol-b-<random>/buc-a-<random> and |
| vol-b-<random>/buc-b-<random> |
| */ |
| String keyBaseB = "key-b-"; |
| for (int i = 0; i < 10; i++) { |
| byte[] value = RandomStringUtils.randomAscii(10240).getBytes(); |
| OzoneOutputStream one = volAbucketA.createKey( |
| keyBaseB + i + "-" + RandomStringUtils.randomNumeric(5), |
| value.length, STAND_ALONE, ONE, |
| new HashMap<>()); |
| one.write(value); |
| one.close(); |
| OzoneOutputStream two = volAbucketB.createKey( |
| keyBaseB + i + "-" + RandomStringUtils.randomNumeric(5), |
| value.length, STAND_ALONE, ONE, |
| new HashMap<>()); |
| two.write(value); |
| two.close(); |
| OzoneOutputStream three = volBbucketA.createKey( |
| keyBaseB + i + "-" + RandomStringUtils.randomNumeric(5), |
| value.length, STAND_ALONE, ONE, |
| new HashMap<>()); |
| three.write(value); |
| three.close(); |
| OzoneOutputStream four = volBbucketB.createKey( |
| keyBaseB + i + "-" + RandomStringUtils.randomNumeric(5), |
| value.length, STAND_ALONE, ONE, |
| new HashMap<>()); |
| four.write(value); |
| four.close(); |
| } |
| Iterator<? extends OzoneKey> volABucketAIter = |
| volAbucketA.listKeys("key-"); |
| int volABucketAKeyCount = 0; |
| while(volABucketAIter.hasNext()) { |
| volABucketAIter.next(); |
| volABucketAKeyCount++; |
| } |
| Assert.assertEquals(20, volABucketAKeyCount); |
| Iterator<? extends OzoneKey> volABucketBIter = |
| volAbucketB.listKeys("key-"); |
| int volABucketBKeyCount = 0; |
| while(volABucketBIter.hasNext()) { |
| volABucketBIter.next(); |
| volABucketBKeyCount++; |
| } |
| Assert.assertEquals(20, volABucketBKeyCount); |
| Iterator<? extends OzoneKey> volBBucketAIter = |
| volBbucketA.listKeys("key-"); |
| int volBBucketAKeyCount = 0; |
| while(volBBucketAIter.hasNext()) { |
| volBBucketAIter.next(); |
| volBBucketAKeyCount++; |
| } |
| Assert.assertEquals(20, volBBucketAKeyCount); |
| Iterator<? extends OzoneKey> volBBucketBIter = |
| volBbucketB.listKeys("key-"); |
| int volBBucketBKeyCount = 0; |
| while(volBBucketBIter.hasNext()) { |
| volBBucketBIter.next(); |
| volBBucketBKeyCount++; |
| } |
| Assert.assertEquals(20, volBBucketBKeyCount); |
| Iterator<? extends OzoneKey> volABucketAKeyAIter = |
| volAbucketA.listKeys("key-a-"); |
| int volABucketAKeyACount = 0; |
| while(volABucketAKeyAIter.hasNext()) { |
| volABucketAKeyAIter.next(); |
| volABucketAKeyACount++; |
| } |
| Assert.assertEquals(10, volABucketAKeyACount); |
| Iterator<? extends OzoneKey> volABucketAKeyBIter = |
| volAbucketA.listKeys("key-b-"); |
| for(int i = 0; i < 10; i++) { |
| Assert.assertTrue(volABucketAKeyBIter.next().getName() |
| .startsWith("key-b-" + i + "-")); |
| } |
| Assert.assertFalse(volABucketBIter.hasNext()); |
| } |
| |
| @Test |
| public void testListKeyOnEmptyBucket() |
| throws IOException { |
| String volume = "vol-" + RandomStringUtils.randomNumeric(5); |
| String bucket = "buc-" + RandomStringUtils.randomNumeric(5); |
| store.createVolume(volume); |
| OzoneVolume vol = store.getVolume(volume); |
| vol.createBucket(bucket); |
| OzoneBucket buc = vol.getBucket(bucket); |
| Iterator<? extends OzoneKey> keys = buc.listKeys(""); |
| while(keys.hasNext()) { |
| fail(); |
| } |
| } |
| |
| @Test |
| public void testInitiateMultipartUploadWithReplicationInformationSet() throws |
| IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| OmMultipartInfo multipartInfo = bucket.initiateMultipartUpload(keyName, |
| STAND_ALONE, ONE); |
| |
| assertNotNull(multipartInfo); |
| String uploadID = multipartInfo.getUploadID(); |
| Assert.assertEquals(volumeName, multipartInfo.getVolumeName()); |
| Assert.assertEquals(bucketName, multipartInfo.getBucketName()); |
| Assert.assertEquals(keyName, multipartInfo.getKeyName()); |
| assertNotNull(multipartInfo.getUploadID()); |
| |
| // Call initiate multipart upload for the same key again, this should |
| // generate a new uploadID. |
| multipartInfo = bucket.initiateMultipartUpload(keyName, |
| STAND_ALONE, ONE); |
| |
| assertNotNull(multipartInfo); |
| Assert.assertEquals(volumeName, multipartInfo.getVolumeName()); |
| Assert.assertEquals(bucketName, multipartInfo.getBucketName()); |
| Assert.assertEquals(keyName, multipartInfo.getKeyName()); |
| assertNotEquals(multipartInfo.getUploadID(), uploadID); |
| assertNotNull(multipartInfo.getUploadID()); |
| } |
| |
| |
| @Test |
| public void testInitiateMultipartUploadWithDefaultReplication() throws |
| IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| OmMultipartInfo multipartInfo = bucket.initiateMultipartUpload(keyName); |
| |
| assertNotNull(multipartInfo); |
| String uploadID = multipartInfo.getUploadID(); |
| Assert.assertEquals(volumeName, multipartInfo.getVolumeName()); |
| Assert.assertEquals(bucketName, multipartInfo.getBucketName()); |
| Assert.assertEquals(keyName, multipartInfo.getKeyName()); |
| assertNotNull(multipartInfo.getUploadID()); |
| |
| // Call initiate multipart upload for the same key again, this should |
| // generate a new uploadID. |
| multipartInfo = bucket.initiateMultipartUpload(keyName); |
| |
| assertNotNull(multipartInfo); |
| Assert.assertEquals(volumeName, multipartInfo.getVolumeName()); |
| Assert.assertEquals(bucketName, multipartInfo.getBucketName()); |
| Assert.assertEquals(keyName, multipartInfo.getKeyName()); |
| assertNotEquals(multipartInfo.getUploadID(), uploadID); |
| assertNotNull(multipartInfo.getUploadID()); |
| } |
| |
| @Test |
| public void testUploadPartWithNoOverride() throws IOException { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| String sampleData = "sample Value"; |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| OmMultipartInfo multipartInfo = bucket.initiateMultipartUpload(keyName, |
| STAND_ALONE, ONE); |
| |
| assertNotNull(multipartInfo); |
| String uploadID = multipartInfo.getUploadID(); |
| Assert.assertEquals(volumeName, multipartInfo.getVolumeName()); |
| Assert.assertEquals(bucketName, multipartInfo.getBucketName()); |
| Assert.assertEquals(keyName, multipartInfo.getKeyName()); |
| assertNotNull(multipartInfo.getUploadID()); |
| |
| OzoneOutputStream ozoneOutputStream = bucket.createMultipartKey(keyName, |
| sampleData.length(), 1, uploadID); |
| ozoneOutputStream.write(string2Bytes(sampleData), 0, sampleData.length()); |
| ozoneOutputStream.close(); |
| |
| OmMultipartCommitUploadPartInfo commitUploadPartInfo = ozoneOutputStream |
| .getCommitUploadPartInfo(); |
| |
| assertNotNull(commitUploadPartInfo); |
| String partName = commitUploadPartInfo.getPartName(); |
| assertNotNull(commitUploadPartInfo.getPartName()); |
| |
| } |
| |
| @Test |
| public void testUploadPartOverrideWithStandAlone() throws IOException { |
| |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| String sampleData = "sample Value"; |
| int partNumber = 1; |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| OmMultipartInfo multipartInfo = bucket.initiateMultipartUpload(keyName, |
| STAND_ALONE, ONE); |
| |
| assertNotNull(multipartInfo); |
| String uploadID = multipartInfo.getUploadID(); |
| Assert.assertEquals(volumeName, multipartInfo.getVolumeName()); |
| Assert.assertEquals(bucketName, multipartInfo.getBucketName()); |
| Assert.assertEquals(keyName, multipartInfo.getKeyName()); |
| assertNotNull(multipartInfo.getUploadID()); |
| |
| OzoneOutputStream ozoneOutputStream = bucket.createMultipartKey(keyName, |
| sampleData.length(), partNumber, uploadID); |
| ozoneOutputStream.write(string2Bytes(sampleData), 0, sampleData.length()); |
| ozoneOutputStream.close(); |
| |
| OmMultipartCommitUploadPartInfo commitUploadPartInfo = ozoneOutputStream |
| .getCommitUploadPartInfo(); |
| |
| assertNotNull(commitUploadPartInfo); |
| String partName = commitUploadPartInfo.getPartName(); |
| assertNotNull(commitUploadPartInfo.getPartName()); |
| |
| //Overwrite the part by creating part key with same part number. |
| sampleData = "sample Data Changed"; |
| ozoneOutputStream = bucket.createMultipartKey(keyName, |
| sampleData.length(), partNumber, uploadID); |
| ozoneOutputStream.write(string2Bytes(sampleData), 0, "name".length()); |
| ozoneOutputStream.close(); |
| |
| commitUploadPartInfo = ozoneOutputStream |
| .getCommitUploadPartInfo(); |
| |
| assertNotNull(commitUploadPartInfo); |
| assertNotNull(commitUploadPartInfo.getPartName()); |
| |
| // PartName should be different from old part Name. |
| assertNotEquals("Part names should be different", partName, |
| commitUploadPartInfo.getPartName()); |
| } |
| |
| @Test |
| public void testUploadPartOverrideWithRatis() throws IOException { |
| |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| String sampleData = "sample Value"; |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| OmMultipartInfo multipartInfo = bucket.initiateMultipartUpload(keyName, |
| ReplicationType.RATIS, THREE); |
| |
| assertNotNull(multipartInfo); |
| String uploadID = multipartInfo.getUploadID(); |
| Assert.assertEquals(volumeName, multipartInfo.getVolumeName()); |
| Assert.assertEquals(bucketName, multipartInfo.getBucketName()); |
| Assert.assertEquals(keyName, multipartInfo.getKeyName()); |
| assertNotNull(multipartInfo.getUploadID()); |
| |
| int partNumber = 1; |
| |
| OzoneOutputStream ozoneOutputStream = bucket.createMultipartKey(keyName, |
| sampleData.length(), partNumber, uploadID); |
| ozoneOutputStream.write(string2Bytes(sampleData), 0, sampleData.length()); |
| ozoneOutputStream.close(); |
| |
| OmMultipartCommitUploadPartInfo commitUploadPartInfo = ozoneOutputStream |
| .getCommitUploadPartInfo(); |
| |
| assertNotNull(commitUploadPartInfo); |
| String partName = commitUploadPartInfo.getPartName(); |
| assertNotNull(commitUploadPartInfo.getPartName()); |
| |
| //Overwrite the part by creating part key with same part number. |
| sampleData = "sample Data Changed"; |
| ozoneOutputStream = bucket.createMultipartKey(keyName, |
| sampleData.length(), partNumber, uploadID); |
| ozoneOutputStream.write(string2Bytes(sampleData), 0, "name".length()); |
| ozoneOutputStream.close(); |
| |
| commitUploadPartInfo = ozoneOutputStream |
| .getCommitUploadPartInfo(); |
| |
| assertNotNull(commitUploadPartInfo); |
| assertNotNull(commitUploadPartInfo.getPartName()); |
| |
| // PartName should be different from old part Name. |
| assertNotEquals("Part names should be different", partName, |
| commitUploadPartInfo.getPartName()); |
| } |
| |
| @Test |
| public void testNoSuchUploadError() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| String sampleData = "sample Value"; |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| String uploadID = "random"; |
| OzoneTestUtils |
| .expectOmException(NO_SUCH_MULTIPART_UPLOAD_ERROR, () -> |
| bucket |
| .createMultipartKey(keyName, sampleData.length(), 1, uploadID)); |
| } |
| |
| @Test |
| public void testMultipartUpload() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| doMultipartUpload(bucket, keyName, (byte)98); |
| } |
| |
| |
| @Test |
| public void testMultipartUploadOverride() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| doMultipartUpload(bucket, keyName, (byte)96); |
| |
| // Initiate Multipart upload again, now we should read latest version, as |
| // read always reads latest blocks. |
| doMultipartUpload(bucket, keyName, (byte)97); |
| |
| } |
| |
| |
| @Test |
| public void testMultipartUploadWithPartsLessThanMinSize() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| // Initiate multipart upload |
| String uploadID = initiateMultipartUpload(bucket, keyName, STAND_ALONE, |
| ONE); |
| |
| // Upload Parts |
| Map<Integer, String> partsMap = new TreeMap<>(); |
| // Uploading part 1 with less than min size |
| String partName = uploadPart(bucket, keyName, uploadID, 1, |
| "data".getBytes(UTF_8)); |
| partsMap.put(1, partName); |
| |
| partName = uploadPart(bucket, keyName, uploadID, 2, |
| "data".getBytes(UTF_8)); |
| partsMap.put(2, partName); |
| |
| |
| // Complete multipart upload |
| |
| OzoneTestUtils.expectOmException(ResultCodes.ENTITY_TOO_SMALL, |
| () -> completeMultipartUpload(bucket, keyName, uploadID, partsMap)); |
| |
| } |
| @Test |
| public void testMultipartUploadWithPartsMisMatchWithListSizeDifferent() |
| throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| String uploadID = initiateMultipartUpload(bucket, keyName, STAND_ALONE, |
| ONE); |
| |
| // We have not uploaded any parts, but passing some list it should throw |
| // error. |
| TreeMap<Integer, String> partsMap = new TreeMap<>(); |
| partsMap.put(1, UUID.randomUUID().toString()); |
| |
| OzoneTestUtils.expectOmException(ResultCodes.INVALID_PART, |
| () -> completeMultipartUpload(bucket, keyName, uploadID, partsMap)); |
| |
| } |
| |
| @Test |
| public void testMultipartUploadWithPartsMisMatchWithIncorrectPartName() |
| throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| String uploadID = initiateMultipartUpload(bucket, keyName, STAND_ALONE, |
| ONE); |
| |
| uploadPart(bucket, keyName, uploadID, 1, "data".getBytes(UTF_8)); |
| // We have not uploaded any parts, but passing some list it should throw |
| // error. |
| TreeMap<Integer, String> partsMap = new TreeMap<>(); |
| partsMap.put(1, UUID.randomUUID().toString()); |
| |
| OzoneTestUtils.expectOmException(ResultCodes.INVALID_PART, |
| () -> completeMultipartUpload(bucket, keyName, uploadID, partsMap)); |
| |
| } |
| |
| @Test |
| public void testMultipartUploadWithMissingParts() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| String uploadID = initiateMultipartUpload(bucket, keyName, STAND_ALONE, |
| ONE); |
| |
| uploadPart(bucket, keyName, uploadID, 1, "data".getBytes(UTF_8)); |
| // We have not uploaded any parts, but passing some list it should throw |
| // error. |
| TreeMap<Integer, String> partsMap = new TreeMap<>(); |
| partsMap.put(3, "random"); |
| |
| OzoneTestUtils.expectOmException(ResultCodes.INVALID_PART, |
| () -> completeMultipartUpload(bucket, keyName, uploadID, partsMap)); |
| } |
| |
| @Test |
| public void testAbortUploadFail() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| OzoneTestUtils.expectOmException(NO_SUCH_MULTIPART_UPLOAD_ERROR, |
| () -> bucket.abortMultipartUpload(keyName, "random")); |
| } |
| |
| @Test |
| public void testAbortUploadFailWithInProgressPartUpload() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| OmMultipartInfo omMultipartInfo = bucket.initiateMultipartUpload(keyName, |
| STAND_ALONE, ONE); |
| |
| Assert.assertNotNull(omMultipartInfo.getUploadID()); |
| |
| // Do not close output stream. |
| byte[] data = "data".getBytes(UTF_8); |
| OzoneOutputStream ozoneOutputStream = bucket.createMultipartKey(keyName, |
| data.length, 1, omMultipartInfo.getUploadID()); |
| ozoneOutputStream.write(data, 0, data.length); |
| |
| // Abort before completing part upload. |
| bucket.abortMultipartUpload(keyName, omMultipartInfo.getUploadID()); |
| |
| try { |
| ozoneOutputStream.close(); |
| fail("testAbortUploadFailWithInProgressPartUpload failed"); |
| } catch (IOException ex) { |
| assertTrue(ex instanceof OMException); |
| assertEquals(NO_SUCH_MULTIPART_UPLOAD_ERROR, |
| ((OMException) ex).getResult()); |
| } |
| } |
| |
| @Test |
| public void testCommitPartAfterCompleteUpload() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| OmMultipartInfo omMultipartInfo = bucket.initiateMultipartUpload(keyName, |
| STAND_ALONE, ONE); |
| |
| Assert.assertNotNull(omMultipartInfo.getUploadID()); |
| |
| String uploadID = omMultipartInfo.getUploadID(); |
| |
| // upload part 1. |
| byte[] data = generateData(5 * 1024 * 1024, |
| (byte) RandomUtils.nextLong()); |
| OzoneOutputStream ozoneOutputStream = bucket.createMultipartKey(keyName, |
| data.length, 1, uploadID); |
| ozoneOutputStream.write(data, 0, data.length); |
| ozoneOutputStream.close(); |
| |
| OmMultipartCommitUploadPartInfo omMultipartCommitUploadPartInfo = |
| ozoneOutputStream.getCommitUploadPartInfo(); |
| |
| // Do not close output stream for part 2. |
| ozoneOutputStream = bucket.createMultipartKey(keyName, |
| data.length, 2, omMultipartInfo.getUploadID()); |
| ozoneOutputStream.write(data, 0, data.length); |
| |
| Map<Integer, String> partsMap = new LinkedHashMap<>(); |
| partsMap.put(1, omMultipartCommitUploadPartInfo.getPartName()); |
| OmMultipartUploadCompleteInfo omMultipartUploadCompleteInfo = |
| bucket.completeMultipartUpload(keyName, |
| uploadID, partsMap); |
| |
| Assert.assertNotNull(omMultipartCommitUploadPartInfo); |
| |
| byte[] fileContent = new byte[data.length]; |
| OzoneInputStream inputStream = bucket.readKey(keyName); |
| inputStream.read(fileContent); |
| StringBuilder sb = new StringBuilder(data.length); |
| |
| // Combine all parts data, and check is it matching with get key data. |
| String part1 = new String(data); |
| sb.append(part1); |
| Assert.assertEquals(sb.toString(), new String(fileContent)); |
| |
| try { |
| ozoneOutputStream.close(); |
| fail("testCommitPartAfterCompleteUpload failed"); |
| } catch (IOException ex) { |
| assertTrue(ex instanceof OMException); |
| assertEquals(NO_SUCH_MULTIPART_UPLOAD_ERROR, |
| ((OMException) ex).getResult()); |
| } |
| } |
| |
| |
| @Test |
| public void testAbortUploadSuccessWithOutAnyParts() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| String uploadID = initiateMultipartUpload(bucket, keyName, STAND_ALONE, |
| ONE); |
| bucket.abortMultipartUpload(keyName, uploadID); |
| } |
| |
| @Test |
| public void testAbortUploadSuccessWithParts() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| String uploadID = initiateMultipartUpload(bucket, keyName, STAND_ALONE, |
| ONE); |
| uploadPart(bucket, keyName, uploadID, 1, "data".getBytes(UTF_8)); |
| bucket.abortMultipartUpload(keyName, uploadID); |
| } |
| |
| @Test |
| public void testListMultipartUploadParts() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| Map<Integer, String> partsMap = new TreeMap<>(); |
| String uploadID = initiateMultipartUpload(bucket, keyName, STAND_ALONE, |
| ONE); |
| String partName1 = uploadPart(bucket, keyName, uploadID, 1, |
| generateData(OzoneConsts.OM_MULTIPART_MIN_SIZE, (byte)97)); |
| partsMap.put(1, partName1); |
| |
| String partName2 =uploadPart(bucket, keyName, uploadID, 2, |
| generateData(OzoneConsts.OM_MULTIPART_MIN_SIZE, (byte)97)); |
| partsMap.put(2, partName2); |
| |
| String partName3 =uploadPart(bucket, keyName, uploadID, 3, |
| generateData(OzoneConsts.OM_MULTIPART_MIN_SIZE, (byte)97)); |
| partsMap.put(3, partName3); |
| |
| OzoneMultipartUploadPartListParts ozoneMultipartUploadPartListParts = |
| bucket.listParts(keyName, uploadID, 0, 3); |
| |
| Assert.assertEquals(STAND_ALONE, |
| ozoneMultipartUploadPartListParts.getReplicationType()); |
| Assert.assertEquals(3, |
| ozoneMultipartUploadPartListParts.getPartInfoList().size()); |
| |
| Assert.assertEquals(partsMap.get(ozoneMultipartUploadPartListParts |
| .getPartInfoList().get(0).getPartNumber()), |
| ozoneMultipartUploadPartListParts.getPartInfoList().get(0) |
| .getPartName()); |
| Assert.assertEquals(partsMap.get(ozoneMultipartUploadPartListParts |
| .getPartInfoList().get(1).getPartNumber()), |
| ozoneMultipartUploadPartListParts.getPartInfoList().get(1) |
| .getPartName()); |
| Assert.assertEquals(partsMap.get(ozoneMultipartUploadPartListParts |
| .getPartInfoList().get(2).getPartNumber()), |
| ozoneMultipartUploadPartListParts.getPartInfoList().get(2) |
| .getPartName()); |
| |
| Assert.assertFalse(ozoneMultipartUploadPartListParts.isTruncated()); |
| } |
| |
| @Test |
| public void testListMultipartUploadPartsWithContinuation() |
| throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| Map<Integer, String> partsMap = new TreeMap<>(); |
| String uploadID = initiateMultipartUpload(bucket, keyName, STAND_ALONE, |
| ONE); |
| String partName1 = uploadPart(bucket, keyName, uploadID, 1, |
| generateData(OzoneConsts.OM_MULTIPART_MIN_SIZE, (byte)97)); |
| partsMap.put(1, partName1); |
| |
| String partName2 =uploadPart(bucket, keyName, uploadID, 2, |
| generateData(OzoneConsts.OM_MULTIPART_MIN_SIZE, (byte)97)); |
| partsMap.put(2, partName2); |
| |
| String partName3 =uploadPart(bucket, keyName, uploadID, 3, |
| generateData(OzoneConsts.OM_MULTIPART_MIN_SIZE, (byte)97)); |
| partsMap.put(3, partName3); |
| |
| OzoneMultipartUploadPartListParts ozoneMultipartUploadPartListParts = |
| bucket.listParts(keyName, uploadID, 0, 2); |
| |
| Assert.assertEquals(STAND_ALONE, |
| ozoneMultipartUploadPartListParts.getReplicationType()); |
| |
| Assert.assertEquals(2, |
| ozoneMultipartUploadPartListParts.getPartInfoList().size()); |
| |
| Assert.assertEquals(partsMap.get(ozoneMultipartUploadPartListParts |
| .getPartInfoList().get(0).getPartNumber()), |
| ozoneMultipartUploadPartListParts.getPartInfoList().get(0) |
| .getPartName()); |
| Assert.assertEquals(partsMap.get(ozoneMultipartUploadPartListParts |
| .getPartInfoList().get(1).getPartNumber()), |
| ozoneMultipartUploadPartListParts.getPartInfoList().get(1) |
| .getPartName()); |
| |
| // Get remaining |
| Assert.assertTrue(ozoneMultipartUploadPartListParts.isTruncated()); |
| ozoneMultipartUploadPartListParts = bucket.listParts(keyName, uploadID, |
| ozoneMultipartUploadPartListParts.getNextPartNumberMarker(), 2); |
| |
| Assert.assertEquals(1, |
| ozoneMultipartUploadPartListParts.getPartInfoList().size()); |
| Assert.assertEquals(partsMap.get(ozoneMultipartUploadPartListParts |
| .getPartInfoList().get(0).getPartNumber()), |
| ozoneMultipartUploadPartListParts.getPartInfoList().get(0) |
| .getPartName()); |
| |
| |
| // As we don't have any parts for this, we should get false here |
| Assert.assertFalse(ozoneMultipartUploadPartListParts.isTruncated()); |
| |
| } |
| |
| @Test |
| public void testListPartsInvalidPartMarker() throws Exception { |
| try { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| |
| OzoneMultipartUploadPartListParts ozoneMultipartUploadPartListParts = |
| bucket.listParts(keyName, "random", -1, 2); |
| } catch (IllegalArgumentException ex) { |
| GenericTestUtils.assertExceptionContains("Should be greater than or " + |
| "equal to zero", ex); |
| } |
| } |
| |
| @Test |
| public void testListPartsInvalidMaxParts() throws Exception { |
| try { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| |
| OzoneMultipartUploadPartListParts ozoneMultipartUploadPartListParts = |
| bucket.listParts(keyName, "random", 1, -1); |
| } catch (IllegalArgumentException ex) { |
| GenericTestUtils.assertExceptionContains("Max Parts Should be greater " + |
| "than zero", ex); |
| } |
| } |
| |
| @Test |
| public void testListPartsWithPartMarkerGreaterThanPartCount() |
| throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| |
| |
| String uploadID = initiateMultipartUpload(bucket, keyName, STAND_ALONE, |
| ONE); |
| uploadPart(bucket, keyName, uploadID, 1, |
| generateData(OzoneConsts.OM_MULTIPART_MIN_SIZE, (byte)97)); |
| |
| |
| OzoneMultipartUploadPartListParts ozoneMultipartUploadPartListParts = |
| bucket.listParts(keyName, uploadID, 100, 2); |
| |
| // Should return empty |
| |
| Assert.assertEquals(0, |
| ozoneMultipartUploadPartListParts.getPartInfoList().size()); |
| Assert.assertEquals(STAND_ALONE, |
| ozoneMultipartUploadPartListParts.getReplicationType()); |
| |
| // As we don't have any parts with greater than partNumberMarker and list |
| // is not truncated, so it should return false here. |
| Assert.assertFalse(ozoneMultipartUploadPartListParts.isTruncated()); |
| |
| } |
| |
| @Test |
| public void testListPartsWithInvalidUploadID() throws Exception { |
| OzoneTestUtils |
| .expectOmException(NO_SUCH_MULTIPART_UPLOAD_ERROR, () -> { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| OzoneMultipartUploadPartListParts ozoneMultipartUploadPartListParts = |
| bucket.listParts(keyName, "random", 100, 2); |
| }); |
| } |
| |
| @Test |
| public void testNativeAclsForVolume() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| store.createVolume(volumeName); |
| |
| OzoneObj ozObj = new OzoneObjInfo.Builder() |
| .setVolumeName(volumeName) |
| .setResType(OzoneObj.ResourceType.VOLUME) |
| .setStoreType(OzoneObj.StoreType.OZONE) |
| .build(); |
| |
| validateOzoneAccessAcl(ozObj); |
| } |
| |
| @Test |
| public void testNativeAclsForBucket() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| assertNotNull("Bucket creation failed", bucket); |
| |
| OzoneObj ozObj = new OzoneObjInfo.Builder() |
| .setVolumeName(volumeName) |
| .setBucketName(bucketName) |
| .setResType(OzoneObj.ResourceType.BUCKET) |
| .setStoreType(OzoneObj.StoreType.OZONE) |
| .build(); |
| |
| validateOzoneAccessAcl(ozObj); |
| |
| OzoneObj volObj = new OzoneObjInfo.Builder() |
| .setVolumeName(volumeName) |
| .setResType(OzoneObj.ResourceType.VOLUME) |
| .setStoreType(OzoneObj.StoreType.OZONE) |
| .build(); |
| validateDefaultAcls(volObj, ozObj, volume, null); |
| } |
| |
| private void validateDefaultAcls(OzoneObj parentObj, OzoneObj childObj, |
| OzoneVolume volume, OzoneBucket bucket) throws Exception { |
| assertTrue(store.addAcl(parentObj, defaultUserAcl)); |
| assertTrue(store.addAcl(parentObj, defaultGroupAcl)); |
| if (volume != null) { |
| volume.deleteBucket(childObj.getBucketName()); |
| volume.createBucket(childObj.getBucketName()); |
| } else { |
| if (childObj.getResourceType().equals(OzoneObj.ResourceType.KEY)) { |
| bucket.deleteKey(childObj.getKeyName()); |
| writeKey(childObj.getKeyName(), bucket); |
| } else { |
| store.setAcl(childObj, getAclList(new OzoneConfiguration())); |
| } |
| } |
| List<OzoneAcl> acls = store.getAcl(parentObj); |
| assertTrue("Current acls: " + StringUtils.join(",", acls) + |
| " inheritedUserAcl: " + inheritedUserAcl, |
| acls.contains(defaultUserAcl)); |
| assertTrue("Current acls: " + StringUtils.join(",", acls) + |
| " inheritedGroupAcl: " + inheritedGroupAcl, |
| acls.contains(defaultGroupAcl)); |
| |
| acls = store.getAcl(childObj); |
| assertTrue("Current acls:" + StringUtils.join(",", acls) + |
| " inheritedUserAcl:" + inheritedUserAcl, |
| acls.contains(inheritedUserAcl)); |
| assertTrue("Current acls:" + StringUtils.join(",", acls) + |
| " inheritedGroupAcl:" + inheritedGroupAcl, |
| acls.contains(inheritedGroupAcl)); |
| } |
| |
| @Test |
| public void testNativeAclsForKey() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String key1 = "dir1/dir2" + UUID.randomUUID().toString(); |
| String key2 = "dir1/dir2" + UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| assertNotNull("Bucket creation failed", bucket); |
| |
| writeKey(key1, bucket); |
| writeKey(key2, bucket); |
| |
| OzoneObj ozObj = new OzoneObjInfo.Builder() |
| .setVolumeName(volumeName) |
| .setBucketName(bucketName) |
| .setKeyName(key1) |
| .setResType(OzoneObj.ResourceType.KEY) |
| .setStoreType(OzoneObj.StoreType.OZONE) |
| .build(); |
| |
| // Validates access acls. |
| validateOzoneAccessAcl(ozObj); |
| |
| // Check default acls inherited from bucket. |
| OzoneObj buckObj = new OzoneObjInfo.Builder() |
| .setVolumeName(volumeName) |
| .setBucketName(bucketName) |
| .setKeyName(key1) |
| .setResType(OzoneObj.ResourceType.BUCKET) |
| .setStoreType(OzoneObj.StoreType.OZONE) |
| .build(); |
| |
| validateDefaultAcls(buckObj, ozObj, null, bucket); |
| |
| // Check default acls inherited from prefix. |
| OzoneObj prefixObj = new OzoneObjInfo.Builder() |
| .setVolumeName(volumeName) |
| .setBucketName(bucketName) |
| .setKeyName(key1) |
| .setPrefixName("dir1/") |
| .setResType(OzoneObj.ResourceType.PREFIX) |
| .setStoreType(OzoneObj.StoreType.OZONE) |
| .build(); |
| store.setAcl(prefixObj, getAclList(new OzoneConfiguration())); |
| // Prefix should inherit DEFAULT acl from bucket. |
| |
| List<OzoneAcl> acls = store.getAcl(prefixObj); |
| assertTrue("Current acls:" + StringUtils.join(",", acls), |
| acls.contains(inheritedUserAcl)); |
| assertTrue("Current acls:" + StringUtils.join(",", acls), |
| acls.contains(inheritedGroupAcl)); |
| // Remove inherited acls from prefix. |
| assertTrue(store.removeAcl(prefixObj, inheritedUserAcl)); |
| assertTrue(store.removeAcl(prefixObj, inheritedGroupAcl)); |
| |
| validateDefaultAcls(prefixObj, ozObj, null, bucket); |
| } |
| |
| @Test |
| public void testNativeAclsForPrefix() throws Exception { |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| |
| String prefix1 = "PF" + UUID.randomUUID().toString() + "/"; |
| String key1 = prefix1 + "KEY" + UUID.randomUUID().toString(); |
| |
| String prefix2 = "PF" + UUID.randomUUID().toString() + "/"; |
| String key2 = prefix2 + "KEY" + UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| volume.createBucket(bucketName); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| assertNotNull("Bucket creation failed", bucket); |
| |
| writeKey(key1, bucket); |
| writeKey(key2, bucket); |
| |
| OzoneObj prefixObj = new OzoneObjInfo.Builder() |
| .setVolumeName(volumeName) |
| .setBucketName(bucketName) |
| .setPrefixName(prefix1) |
| .setResType(OzoneObj.ResourceType.PREFIX) |
| .setStoreType(OzoneObj.StoreType.OZONE) |
| .build(); |
| |
| OzoneObj prefixObj2 = new OzoneObjInfo.Builder() |
| .setVolumeName(volumeName) |
| .setBucketName(bucketName) |
| .setPrefixName(prefix2) |
| .setResType(OzoneObj.ResourceType.PREFIX) |
| .setStoreType(OzoneObj.StoreType.OZONE) |
| .build(); |
| |
| // add acl |
| BitSet aclRights1 = new BitSet(); |
| aclRights1.set(READ.ordinal()); |
| OzoneAcl user1Acl = new OzoneAcl(USER, |
| "user1", aclRights1, ACCESS); |
| assertTrue(store.addAcl(prefixObj, user1Acl)); |
| |
| // get acl |
| List<OzoneAcl> aclsGet = store.getAcl(prefixObj); |
| Assert.assertEquals(1, aclsGet.size()); |
| Assert.assertEquals(user1Acl, aclsGet.get(0)); |
| |
| // remove acl |
| Assert.assertTrue(store.removeAcl(prefixObj, user1Acl)); |
| aclsGet = store.getAcl(prefixObj); |
| Assert.assertEquals(0, aclsGet.size()); |
| |
| // set acl |
| BitSet aclRights2 = new BitSet(); |
| aclRights2.set(ACLType.ALL.ordinal()); |
| OzoneAcl group1Acl = new OzoneAcl(GROUP, |
| "group1", aclRights2, ACCESS); |
| List<OzoneAcl> acls = new ArrayList<>(); |
| acls.add(user1Acl); |
| acls.add(group1Acl); |
| Assert.assertTrue(store.setAcl(prefixObj, acls)); |
| |
| // get acl |
| aclsGet = store.getAcl(prefixObj); |
| Assert.assertEquals(2, aclsGet.size()); |
| |
| OzoneObj keyObj = new OzoneObjInfo.Builder() |
| .setVolumeName(volumeName) |
| .setBucketName(bucketName) |
| .setKeyName(key1) |
| .setResType(OzoneObj.ResourceType.KEY) |
| .setStoreType(OzoneObj.StoreType.OZONE) |
| .build(); |
| |
| // Check default acls inherited from prefix. |
| validateDefaultAcls(prefixObj, keyObj, null, bucket); |
| |
| // Check default acls inherited from bucket when prefix does not exist. |
| validateDefaultAcls(prefixObj2, keyObj, null, bucket); |
| } |
| |
| /** |
| * Helper function to get default acl list for current user. |
| * |
| * @return list of default Acls. |
| * @throws IOException |
| * */ |
| private List<OzoneAcl> getAclList(OzoneConfiguration conf) |
| throws IOException { |
| List<OzoneAcl> listOfAcls = new ArrayList<>(); |
| //User ACL |
| UserGroupInformation ugi = UserGroupInformation.getCurrentUser(); |
| OzoneAclConfig aclConfig = conf.getObject(OzoneAclConfig.class); |
| ACLType userRights = aclConfig.getUserDefaultRights(); |
| ACLType groupRights = aclConfig.getGroupDefaultRights(); |
| |
| listOfAcls.add(new OzoneAcl(USER, |
| ugi.getUserName(), userRights, ACCESS)); |
| //Group ACLs of the User |
| List<String> userGroups = Arrays.asList(ugi.getGroupNames()); |
| userGroups.stream().forEach((group) -> listOfAcls.add( |
| new OzoneAcl(GROUP, group, groupRights, ACCESS))); |
| return listOfAcls; |
| } |
| |
| /** |
| * Helper function to validate ozone Acl for given object. |
| * @param ozObj |
| * */ |
| private void validateOzoneAccessAcl(OzoneObj ozObj) throws IOException { |
| // Get acls for volume. |
| List<OzoneAcl> expectedAcls = getAclList(new OzoneConfiguration()); |
| |
| // Case:1 Add new acl permission to existing acl. |
| if(expectedAcls.size()>0) { |
| OzoneAcl oldAcl = expectedAcls.get(0); |
| OzoneAcl newAcl = new OzoneAcl(oldAcl.getType(), oldAcl.getName(), |
| ACLType.READ_ACL, ACCESS); |
| // Verify that operation successful. |
| assertTrue(store.addAcl(ozObj, newAcl)); |
| |
| assertEquals(expectedAcls.size(), store.getAcl(ozObj).size()); |
| final Optional<OzoneAcl> readAcl = store.getAcl(ozObj).stream() |
| .filter(acl -> acl.getName().equals(newAcl.getName()) |
| && acl.getType().equals(newAcl.getType())) |
| .findFirst(); |
| assertTrue("New acl expected but not found.", readAcl.isPresent()); |
| assertTrue("READ_ACL should exist in current acls:" |
| + readAcl.get(), |
| readAcl.get().getAclList().contains(ACLType.READ_ACL)); |
| |
| |
| // Case:2 Remove newly added acl permission. |
| assertTrue(store.removeAcl(ozObj, newAcl)); |
| |
| assertEquals(expectedAcls.size(), store.getAcl(ozObj).size()); |
| final Optional<OzoneAcl> nonReadAcl = store.getAcl(ozObj).stream() |
| .filter(acl -> acl.getName().equals(newAcl.getName()) |
| && acl.getType().equals(newAcl.getType())) |
| .findFirst(); |
| assertTrue("New acl expected but not found.", nonReadAcl.isPresent()); |
| assertFalse("READ_ACL should not exist in current acls:" |
| + nonReadAcl.get(), |
| nonReadAcl.get().getAclList().contains(ACLType.READ_ACL)); |
| } else { |
| fail("Default acl should not be empty."); |
| } |
| |
| List<OzoneAcl> keyAcls = store.getAcl(ozObj); |
| expectedAcls.forEach(a -> assertTrue(keyAcls.contains(a))); |
| |
| // Remove all acl's. |
| for (OzoneAcl a : expectedAcls) { |
| store.removeAcl(ozObj, a); |
| } |
| List<OzoneAcl> newAcls = store.getAcl(ozObj); |
| assertEquals(0, newAcls.size()); |
| |
| // Add acl's and then call getAcl. |
| int aclCount = 0; |
| for (OzoneAcl a : expectedAcls) { |
| aclCount++; |
| assertTrue(store.addAcl(ozObj, a)); |
| assertEquals(aclCount, store.getAcl(ozObj).size()); |
| } |
| newAcls = store.getAcl(ozObj); |
| assertEquals(expectedAcls.size(), newAcls.size()); |
| List<OzoneAcl> finalNewAcls = newAcls; |
| expectedAcls.forEach(a -> assertTrue(finalNewAcls.contains(a))); |
| |
| // Reset acl's. |
| OzoneAcl ua = new OzoneAcl(USER, "userx", |
| ACLType.READ_ACL, ACCESS); |
| OzoneAcl ug = new OzoneAcl(GROUP, "userx", |
| ACLType.ALL, ACCESS); |
| store.setAcl(ozObj, Arrays.asList(ua, ug)); |
| newAcls = store.getAcl(ozObj); |
| assertEquals(2, newAcls.size()); |
| assertTrue(newAcls.contains(ua)); |
| assertTrue(newAcls.contains(ug)); |
| } |
| |
| private void writeKey(String key1, OzoneBucket bucket) throws IOException { |
| OzoneOutputStream out = bucket.createKey(key1, 1024, STAND_ALONE, |
| ONE, new HashMap<>()); |
| out.write(RandomStringUtils.random(1024).getBytes()); |
| out.close(); |
| } |
| |
| private byte[] generateData(int size, byte val) { |
| byte[] chars = new byte[size]; |
| Arrays.fill(chars, val); |
| return chars; |
| } |
| |
| |
| private void doMultipartUpload(OzoneBucket bucket, String keyName, byte val) |
| throws Exception { |
| // Initiate Multipart upload request |
| String uploadID = initiateMultipartUpload(bucket, keyName, ReplicationType |
| .RATIS, THREE); |
| |
| // Upload parts |
| Map<Integer, String> partsMap = new TreeMap<>(); |
| |
| // get 5mb data, as each part should be of min 5mb, last part can be less |
| // than 5mb |
| int length = 0; |
| byte[] data = generateData(OzoneConsts.OM_MULTIPART_MIN_SIZE, val); |
| String partName = uploadPart(bucket, keyName, uploadID, 1, data); |
| partsMap.put(1, partName); |
| length += data.length; |
| |
| |
| partName = uploadPart(bucket, keyName, uploadID, 2, data); |
| partsMap.put(2, partName); |
| length += data.length; |
| |
| String part3 = UUID.randomUUID().toString(); |
| partName = uploadPart(bucket, keyName, uploadID, 3, part3.getBytes( |
| UTF_8)); |
| partsMap.put(3, partName); |
| length += part3.getBytes(UTF_8).length; |
| |
| |
| // Complete multipart upload request |
| completeMultipartUpload(bucket, keyName, uploadID, partsMap); |
| |
| |
| //Now Read the key which has been completed multipart upload. |
| byte[] fileContent = new byte[data.length + data.length + part3.getBytes( |
| UTF_8).length]; |
| OzoneInputStream inputStream = bucket.readKey(keyName); |
| inputStream.read(fileContent); |
| |
| Assert.assertTrue(verifyRatisReplication(bucket.getVolumeName(), |
| bucket.getName(), keyName, ReplicationType.RATIS, |
| THREE)); |
| |
| StringBuilder sb = new StringBuilder(length); |
| |
| // Combine all parts data, and check is it matching with get key data. |
| String part1 = new String(data); |
| String part2 = new String(data); |
| sb.append(part1); |
| sb.append(part2); |
| sb.append(part3); |
| Assert.assertEquals(sb.toString(), new String(fileContent)); |
| } |
| |
| |
| private String initiateMultipartUpload(OzoneBucket bucket, String keyName, |
| ReplicationType replicationType, ReplicationFactor replicationFactor) |
| throws Exception { |
| OmMultipartInfo multipartInfo = bucket.initiateMultipartUpload(keyName, |
| replicationType, replicationFactor); |
| |
| String uploadID = multipartInfo.getUploadID(); |
| Assert.assertNotNull(uploadID); |
| return uploadID; |
| } |
| |
| private String uploadPart(OzoneBucket bucket, String keyName, String |
| uploadID, int partNumber, byte[] data) throws Exception { |
| OzoneOutputStream ozoneOutputStream = bucket.createMultipartKey(keyName, |
| data.length, partNumber, uploadID); |
| ozoneOutputStream.write(data, 0, |
| data.length); |
| ozoneOutputStream.close(); |
| |
| OmMultipartCommitUploadPartInfo omMultipartCommitUploadPartInfo = |
| ozoneOutputStream.getCommitUploadPartInfo(); |
| |
| Assert.assertNotNull(omMultipartCommitUploadPartInfo); |
| Assert.assertNotNull(omMultipartCommitUploadPartInfo.getPartName()); |
| return omMultipartCommitUploadPartInfo.getPartName(); |
| |
| } |
| |
| private void completeMultipartUpload(OzoneBucket bucket, String keyName, |
| String uploadID, Map<Integer, String> partsMap) throws Exception { |
| OmMultipartUploadCompleteInfo omMultipartUploadCompleteInfo = bucket |
| .completeMultipartUpload(keyName, uploadID, partsMap); |
| |
| Assert.assertNotNull(omMultipartUploadCompleteInfo); |
| Assert.assertEquals(omMultipartUploadCompleteInfo.getBucket(), bucket |
| .getName()); |
| Assert.assertEquals(omMultipartUploadCompleteInfo.getVolume(), bucket |
| .getVolumeName()); |
| Assert.assertEquals(omMultipartUploadCompleteInfo.getKey(), keyName); |
| Assert.assertNotNull(omMultipartUploadCompleteInfo.getHash()); |
| } |
| |
| private void createTestKey(OzoneBucket bucket, String keyName, |
| String keyValue) throws IOException { |
| OzoneOutputStream out = bucket.createKey(keyName, |
| keyValue.getBytes().length, STAND_ALONE, |
| ONE, new HashMap<>()); |
| out.write(keyValue.getBytes()); |
| out.close(); |
| OzoneKey key = bucket.getKey(keyName); |
| Assert.assertEquals(keyName, key.getName()); |
| } |
| |
| private void assertKeyRenamedEx(OzoneBucket bucket, String keyName) |
| throws Exception { |
| OMException oe = null; |
| try { |
| bucket.getKey(keyName); |
| } catch (OMException e) { |
| oe = e; |
| } |
| Assert.assertEquals(KEY_NOT_FOUND, oe.getResult()); |
| } |
| |
| /** |
| * Tests GDPR encryption/decryption. |
| * 1. Create GDPR Enabled bucket. |
| * 2. Create a Key in this bucket so it gets encrypted via GDPRSymmetricKey. |
| * 3. Read key and validate the content/metadata is as expected because the |
| * readKey will decrypt using the GDPR Symmetric Key with details from KeyInfo |
| * Metadata. |
| * 4. To check encryption, we forcibly update KeyInfo Metadata and remove the |
| * gdprEnabled flag |
| * 5. When we now read the key, {@link RpcClient} checks for GDPR Flag in |
| * method createInputStream. If the gdprEnabled flag in metadata is set to |
| * true, it decrypts using the GDPRSymmetricKey. Since we removed that flag |
| * from metadata for this key, if will read the encrypted data as-is. |
| * 6. Thus, when we compare this content with expected text, it should |
| * not match as the decryption has not been performed. |
| * @throws Exception |
| */ |
| @Test |
| public void testKeyReadWriteForGDPR() throws Exception { |
| //Step 1 |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| BucketArgs args = BucketArgs.newBuilder() |
| .addMetadata(OzoneConsts.GDPR_FLAG, "true").build(); |
| volume.createBucket(bucketName, args); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| Assert.assertEquals(bucketName, bucket.getName()); |
| Assert.assertNotNull(bucket.getMetadata()); |
| Assert.assertEquals("true", |
| bucket.getMetadata().get(OzoneConsts.GDPR_FLAG)); |
| |
| //Step 2 |
| String text = "hello world"; |
| Map<String, String> keyMetadata = new HashMap<>(); |
| keyMetadata.put(OzoneConsts.GDPR_FLAG, "true"); |
| OzoneOutputStream out = bucket.createKey(keyName, |
| text.getBytes().length, STAND_ALONE, ONE, keyMetadata); |
| out.write(text.getBytes()); |
| out.close(); |
| Assert.assertNull(keyMetadata.get(OzoneConsts.GDPR_SECRET)); |
| |
| //Step 3 |
| OzoneKeyDetails key = bucket.getKey(keyName); |
| |
| Assert.assertEquals(keyName, key.getName()); |
| Assert.assertEquals("true", key.getMetadata().get(OzoneConsts.GDPR_FLAG)); |
| Assert.assertEquals("AES", |
| key.getMetadata().get(OzoneConsts.GDPR_ALGORITHM)); |
| Assert.assertNotNull(key.getMetadata().get(OzoneConsts.GDPR_SECRET)); |
| |
| OzoneInputStream is = bucket.readKey(keyName); |
| byte[] fileContent = new byte[text.getBytes().length]; |
| is.read(fileContent); |
| Assert.assertTrue(verifyRatisReplication(volumeName, bucketName, |
| keyName, STAND_ALONE, |
| ONE)); |
| Assert.assertEquals(text, new String(fileContent)); |
| |
| //Step 4 |
| OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager(); |
| OmKeyInfo omKeyInfo = |
| omMetadataManager.getKeyTable().get(omMetadataManager.getOzoneKey( |
| volumeName, bucketName, keyName)); |
| |
| omKeyInfo.getMetadata().remove(OzoneConsts.GDPR_FLAG); |
| |
| omMetadataManager.getKeyTable().put(omMetadataManager.getOzoneKey( |
| volumeName, bucketName, keyName), omKeyInfo); |
| |
| //Step 5 |
| key = bucket.getKey(keyName); |
| Assert.assertEquals(keyName, key.getName()); |
| Assert.assertNull(key.getMetadata().get(OzoneConsts.GDPR_FLAG)); |
| is = bucket.readKey(keyName); |
| fileContent = new byte[text.getBytes().length]; |
| is.read(fileContent); |
| |
| //Step 6 |
| Assert.assertNotEquals(text, new String(fileContent)); |
| |
| } |
| |
| /** |
| * Tests deletedKey for GDPR. |
| * 1. Create GDPR Enabled bucket. |
| * 2. Create a Key in this bucket so it gets encrypted via GDPRSymmetricKey. |
| * 3. Read key and validate the content/metadata is as expected because the |
| * readKey will decrypt using the GDPR Symmetric Key with details from KeyInfo |
| * Metadata. |
| * 4. Delete this key in GDPR enabled bucket |
| * 5. Confirm the deleted key metadata in deletedTable does not contain the |
| * GDPR encryption details (flag, secret, algorithm). |
| * @throws Exception |
| */ |
| @Test |
| public void testDeletedKeyForGDPR() throws Exception { |
| //Step 1 |
| String volumeName = UUID.randomUUID().toString(); |
| String bucketName = UUID.randomUUID().toString(); |
| String keyName = UUID.randomUUID().toString(); |
| |
| store.createVolume(volumeName); |
| OzoneVolume volume = store.getVolume(volumeName); |
| BucketArgs args = BucketArgs.newBuilder() |
| .addMetadata(OzoneConsts.GDPR_FLAG, "true").build(); |
| volume.createBucket(bucketName, args); |
| OzoneBucket bucket = volume.getBucket(bucketName); |
| Assert.assertEquals(bucketName, bucket.getName()); |
| Assert.assertNotNull(bucket.getMetadata()); |
| Assert.assertEquals("true", |
| bucket.getMetadata().get(OzoneConsts.GDPR_FLAG)); |
| |
| //Step 2 |
| String text = "hello world"; |
| Map<String, String> keyMetadata = new HashMap<>(); |
| keyMetadata.put(OzoneConsts.GDPR_FLAG, "true"); |
| OzoneOutputStream out = bucket.createKey(keyName, |
| text.getBytes().length, STAND_ALONE, ONE, keyMetadata); |
| out.write(text.getBytes()); |
| out.close(); |
| |
| //Step 3 |
| OzoneKeyDetails key = bucket.getKey(keyName); |
| |
| Assert.assertEquals(keyName, key.getName()); |
| Assert.assertEquals("true", key.getMetadata().get(OzoneConsts.GDPR_FLAG)); |
| Assert.assertEquals("AES", |
| key.getMetadata().get(OzoneConsts.GDPR_ALGORITHM)); |
| Assert.assertTrue(key.getMetadata().get(OzoneConsts.GDPR_SECRET) != null); |
| |
| OzoneInputStream is = bucket.readKey(keyName); |
| byte[] fileContent = new byte[text.getBytes().length]; |
| is.read(fileContent); |
| Assert.assertTrue(verifyRatisReplication(volumeName, bucketName, |
| keyName, STAND_ALONE, |
| ONE)); |
| Assert.assertEquals(text, new String(fileContent)); |
| |
| //Step 4 |
| bucket.deleteKey(keyName); |
| |
| //Step 5 |
| OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager(); |
| String objectKey = omMetadataManager.getOzoneKey(volumeName, bucketName, |
| keyName); |
| RepeatedOmKeyInfo deletedKeys = |
| omMetadataManager.getDeletedTable().get(objectKey); |
| if (deletedKeys != null) { |
| Map<String, String> deletedKeyMetadata = |
| deletedKeys.getOmKeyInfoList().get(0).getMetadata(); |
| Assert.assertFalse(deletedKeyMetadata.containsKey(OzoneConsts.GDPR_FLAG)); |
| Assert.assertFalse( |
| deletedKeyMetadata.containsKey(OzoneConsts.GDPR_SECRET)); |
| Assert.assertFalse( |
| deletedKeyMetadata.containsKey(OzoneConsts.GDPR_ALGORITHM)); |
| } |
| } |
| |
| |
| @Test |
| public void setS3VolumeAcl() throws Exception { |
| OzoneObj s3vVolume = new OzoneObjInfo.Builder() |
| .setVolumeName(HddsClientUtils.getS3VolumeName(cluster.getConf())) |
| .setResType(OzoneObj.ResourceType.VOLUME) |
| .setStoreType(OzoneObj.StoreType.OZONE) |
| .build(); |
| |
| OzoneAcl ozoneAcl = new OzoneAcl(USER, remoteUserName, WRITE, DEFAULT); |
| |
| boolean result = store.addAcl(s3vVolume, ozoneAcl); |
| |
| Assert.assertTrue("SetAcl on default s3v failed", result); |
| |
| List<OzoneAcl> ozoneAclList = store.getAcl(s3vVolume); |
| |
| Assert.assertTrue(ozoneAclList.contains(ozoneAcl)); |
| } |
| } |