blob: f309715608e11927bb8aa97f2719d471669c9666 [file] [log] [blame]
/**
* 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.om;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.hadoop.fs.StorageType;
import org.apache.hadoop.hdds.scm.client.HddsClientUtils;
import org.apache.hadoop.hdfs.DFSUtil;
import org.apache.hadoop.hdfs.server.datanode.ObjectStoreHandler;
import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.ozone.MiniOzoneCluster;
import org.apache.hadoop.ozone.OzoneConfigKeys;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.ozone.OzoneConsts;
import org.apache.hadoop.ozone.common.BlockGroup;
import org.apache.hadoop.ozone.client.rest.OzoneException;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.hdds.scm.server.SCMStorage;
import org.apache.hadoop.ozone.om.helpers.ServiceInfo;
import org.apache.hadoop.ozone.protocol.proto
.OzoneManagerProtocolProtos.ServicePort;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.ozone.web.handlers.BucketArgs;
import org.apache.hadoop.ozone.web.handlers.KeyArgs;
import org.apache.hadoop.ozone.web.handlers.UserArgs;
import org.apache.hadoop.ozone.web.handlers.VolumeArgs;
import org.apache.hadoop.ozone.web.interfaces.StorageHandler;
import org.apache.hadoop.ozone.OzoneAcl;
import org.apache.hadoop.ozone.web.request.OzoneQuota;
import org.apache.hadoop.ozone.web.response.BucketInfo;
import org.apache.hadoop.ozone.web.response.KeyInfo;
import org.apache.hadoop.ozone.web.response.VolumeInfo;
import org.apache.hadoop.ozone.web.utils.OzoneUtils;
import org.apache.hadoop.hdds.scm.ScmConfigKeys;
import org.apache.hadoop.hdds.scm.ScmInfo;
import org.apache.hadoop.test.GenericTestUtils;
import org.apache.hadoop.ozone.protocol.proto
.OzoneManagerProtocolProtos.Status;
import org.apache.hadoop.ozone.web.handlers.ListArgs;
import org.apache.hadoop.ozone.web.response.ListBuckets;
import org.apache.hadoop.ozone.web.response.ListKeys;
import org.apache.hadoop.ozone.web.response.ListVolumes;
import org.apache.hadoop.util.Time;
import org.apache.hadoop.utils.db.Table;
import org.apache.hadoop.utils.db.TableIterator;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.net.InetSocketAddress;
import java.text.ParseException;
import java.util.LinkedList;
import java.util.Random;
import java.util.Set;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.apache.hadoop.ozone.OzoneConfigKeys
.OZONE_OPEN_KEY_EXPIRE_THRESHOLD_SECONDS;
import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_ADDRESS_KEY;
import static org.apache.hadoop.hdds.scm.ScmConfigKeys
.OZONE_SCM_CLIENT_ADDRESS_KEY;
/**
* Test Ozone Manager operation in distributed handler scenario.
*/
public class TestOzoneManager {
private static MiniOzoneCluster cluster = null;
private static StorageHandler storageHandler;
private static UserArgs userArgs;
private static OMMetrics omMetrics;
private static OzoneConfiguration conf;
private static String clusterId;
private static String scmId;
private static String omId;
@Rule
public ExpectedException exception = ExpectedException.none();
/**
* Create a MiniDFSCluster for testing.
* <p>
* Ozone is made active by setting OZONE_ENABLED = true
*
* @throws IOException
*/
@BeforeClass
public static void init() throws Exception {
conf = new OzoneConfiguration();
clusterId = UUID.randomUUID().toString();
scmId = UUID.randomUUID().toString();
omId = UUID.randomUUID().toString();
conf.setInt(OZONE_OPEN_KEY_EXPIRE_THRESHOLD_SECONDS, 2);
cluster = MiniOzoneCluster.newBuilder(conf)
.setClusterId(clusterId)
.setScmId(scmId)
.setOmId(omId)
.build();
cluster.waitForClusterToBeReady();
storageHandler = new ObjectStoreHandler(conf).getStorageHandler();
userArgs = new UserArgs(null, OzoneUtils.getRequestID(),
null, null, null, null);
omMetrics = cluster.getOzoneManager().getMetrics();
}
/**
* Shutdown MiniDFSCluster.
*/
@AfterClass
public static void shutdown() {
if (cluster != null) {
cluster.shutdown();
}
}
// Create a volume and test its attribute after creating them
@Test(timeout = 60000)
public void testCreateVolume() throws IOException, OzoneException {
long volumeCreateFailCount = omMetrics.getNumVolumeCreateFails();
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
VolumeArgs createVolumeArgs = new VolumeArgs(volumeName, userArgs);
createVolumeArgs.setUserName(userName);
createVolumeArgs.setAdminName(adminName);
storageHandler.createVolume(createVolumeArgs);
VolumeArgs getVolumeArgs = new VolumeArgs(volumeName, userArgs);
VolumeInfo retVolumeinfo = storageHandler.getVolumeInfo(getVolumeArgs);
Assert.assertTrue(retVolumeinfo.getVolumeName().equals(volumeName));
Assert.assertTrue(retVolumeinfo.getOwner().getName().equals(userName));
Assert.assertEquals(volumeCreateFailCount,
omMetrics.getNumVolumeCreateFails());
}
// Create a volume and modify the volume owner and then test its attributes
@Test(timeout = 60000)
public void testChangeVolumeOwner() throws IOException, OzoneException {
long volumeCreateFailCount = omMetrics.getNumVolumeCreateFails();
long volumeInfoFailCount = omMetrics.getNumVolumeInfoFails();
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
VolumeArgs createVolumeArgs = new VolumeArgs(volumeName, userArgs);
createVolumeArgs.setUserName(userName);
createVolumeArgs.setAdminName(adminName);
storageHandler.createVolume(createVolumeArgs);
String newUserName = "user" + RandomStringUtils.randomNumeric(5);
createVolumeArgs.setUserName(newUserName);
storageHandler.setVolumeOwner(createVolumeArgs);
VolumeArgs getVolumeArgs = new VolumeArgs(volumeName, userArgs);
VolumeInfo retVolumeInfo = storageHandler.getVolumeInfo(getVolumeArgs);
Assert.assertTrue(retVolumeInfo.getVolumeName().equals(volumeName));
Assert.assertFalse(retVolumeInfo.getOwner().getName().equals(userName));
Assert.assertTrue(retVolumeInfo.getOwner().getName().equals(newUserName));
Assert.assertEquals(volumeCreateFailCount,
omMetrics.getNumVolumeCreateFails());
Assert.assertEquals(volumeInfoFailCount,
omMetrics.getNumVolumeInfoFails());
}
// Create a volume and modify the volume owner and then test its attributes
@Test(timeout = 60000)
public void testChangeVolumeQuota() throws IOException, OzoneException {
long numVolumeCreateFail = omMetrics.getNumVolumeCreateFails();
long numVolumeInfoFail = omMetrics.getNumVolumeInfoFails();
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
Random rand = new Random();
// Create a new volume with a quota
OzoneQuota createQuota =
new OzoneQuota(rand.nextInt(100), OzoneQuota.Units.GB);
VolumeArgs createVolumeArgs = new VolumeArgs(volumeName, userArgs);
createVolumeArgs.setUserName(userName);
createVolumeArgs.setAdminName(adminName);
createVolumeArgs.setQuota(createQuota);
storageHandler.createVolume(createVolumeArgs);
VolumeArgs getVolumeArgs = new VolumeArgs(volumeName, userArgs);
VolumeInfo retVolumeInfo = storageHandler.getVolumeInfo(getVolumeArgs);
Assert.assertEquals(createQuota.sizeInBytes(),
retVolumeInfo.getQuota().sizeInBytes());
// Set a new quota and test it
OzoneQuota setQuota =
new OzoneQuota(rand.nextInt(100), OzoneQuota.Units.GB);
createVolumeArgs.setQuota(setQuota);
storageHandler.setVolumeQuota(createVolumeArgs, false);
getVolumeArgs = new VolumeArgs(volumeName, userArgs);
retVolumeInfo = storageHandler.getVolumeInfo(getVolumeArgs);
Assert.assertEquals(setQuota.sizeInBytes(),
retVolumeInfo.getQuota().sizeInBytes());
// Remove the quota and test it again
storageHandler.setVolumeQuota(createVolumeArgs, true);
getVolumeArgs = new VolumeArgs(volumeName, userArgs);
retVolumeInfo = storageHandler.getVolumeInfo(getVolumeArgs);
Assert.assertEquals(OzoneConsts.MAX_QUOTA_IN_BYTES,
retVolumeInfo.getQuota().sizeInBytes());
Assert.assertEquals(numVolumeCreateFail,
omMetrics.getNumVolumeCreateFails());
Assert.assertEquals(numVolumeInfoFail,
omMetrics.getNumVolumeInfoFails());
}
// Create a volume and then delete it and then check for deletion
@Test(timeout = 60000)
public void testDeleteVolume() throws IOException, OzoneException {
long volumeCreateFailCount = omMetrics.getNumVolumeCreateFails();
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
String volumeName1 = volumeName + "_A";
String volumeName2 = volumeName + "_AA";
VolumeArgs volumeArgs = null;
VolumeInfo volumeInfo = null;
// Create 2 empty volumes with same prefix.
volumeArgs = new VolumeArgs(volumeName1, userArgs);
volumeArgs.setUserName(userName);
volumeArgs.setAdminName(adminName);
storageHandler.createVolume(volumeArgs);
volumeArgs = new VolumeArgs(volumeName2, userArgs);
volumeArgs.setUserName(userName);
volumeArgs.setAdminName(adminName);
storageHandler.createVolume(volumeArgs);
volumeArgs = new VolumeArgs(volumeName1, userArgs);
volumeInfo = storageHandler.getVolumeInfo(volumeArgs);
Assert.assertTrue(volumeInfo.getVolumeName().equals(volumeName1));
Assert.assertTrue(volumeInfo.getOwner().getName().equals(userName));
Assert.assertEquals(volumeCreateFailCount,
omMetrics.getNumVolumeCreateFails());
// Volume with _A should be able to delete as it is empty.
storageHandler.deleteVolume(volumeArgs);
// Make sure volume with _AA suffix still exists.
volumeArgs = new VolumeArgs(volumeName2, userArgs);
volumeInfo = storageHandler.getVolumeInfo(volumeArgs);
Assert.assertTrue(volumeInfo.getVolumeName().equals(volumeName2));
// Make sure volume with _A suffix is successfully deleted.
try {
volumeArgs = new VolumeArgs(volumeName1, userArgs);
storageHandler.getVolumeInfo(volumeArgs);
Assert.fail("Volume is not deleted");
} catch (IOException ex) {
Assert.assertEquals("Info Volume failed, error:VOLUME_NOT_FOUND",
ex.getMessage());
}
//delete the _AA volume, too
storageHandler.deleteVolume(new VolumeArgs(volumeName2, userArgs));
//Make sure there is no volume information for the specific user
OMMetadataManager metadataManager =
cluster.getOzoneManager().getMetadataManager();
byte[] userKey = metadataManager.getUserKey(userName);
byte[] volumes = metadataManager.getUserTable().get(userKey);
//that was the last volume of the user, shouldn't be any record here
Assert.assertNull(volumes);
}
// Create a volume and a bucket inside the volume,
// then delete it and then check for deletion failure
@Test(timeout = 60000)
public void testFailedDeleteVolume() throws IOException, OzoneException {
long numVolumeCreateFails = omMetrics.getNumVolumeCreateFails();
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
String bucketName = "bucket" + RandomStringUtils.randomNumeric(5);
VolumeArgs createVolumeArgs = new VolumeArgs(volumeName, userArgs);
createVolumeArgs.setUserName(userName);
createVolumeArgs.setAdminName(adminName);
storageHandler.createVolume(createVolumeArgs);
VolumeArgs getVolumeArgs = new VolumeArgs(volumeName, userArgs);
VolumeInfo retVolumeInfo = storageHandler.getVolumeInfo(getVolumeArgs);
Assert.assertTrue(retVolumeInfo.getVolumeName().equals(volumeName));
Assert.assertTrue(retVolumeInfo.getOwner().getName().equals(userName));
Assert.assertEquals(numVolumeCreateFails,
omMetrics.getNumVolumeCreateFails());
BucketArgs bucketArgs = new BucketArgs(volumeName, bucketName, userArgs);
storageHandler.createBucket(bucketArgs);
try {
storageHandler.deleteVolume(createVolumeArgs);
Assert.fail("Expecting deletion should fail "
+ "because volume is not empty");
} catch (IOException ex) {
Assert.assertEquals(ex.getMessage(),
"Delete Volume failed, error:VOLUME_NOT_EMPTY");
}
retVolumeInfo = storageHandler.getVolumeInfo(getVolumeArgs);
Assert.assertTrue(retVolumeInfo.getVolumeName().equals(volumeName));
Assert.assertTrue(retVolumeInfo.getOwner().getName().equals(userName));
}
// Create a volume and test Volume access for a different user
@Test(timeout = 60000)
public void testAccessVolume() throws IOException, OzoneException {
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
String[] groupName =
{"group" + RandomStringUtils.randomNumeric(5)};
VolumeArgs createVolumeArgs = new VolumeArgs(volumeName, userArgs);
createVolumeArgs.setUserName(userName);
createVolumeArgs.setAdminName(adminName);
createVolumeArgs.setGroups(groupName);
storageHandler.createVolume(createVolumeArgs);
OzoneAcl userAcl = new OzoneAcl(OzoneAcl.OzoneACLType.USER, userName,
OzoneAcl.OzoneACLRights.READ_WRITE);
Assert.assertTrue(storageHandler.checkVolumeAccess(volumeName, userAcl));
OzoneAcl group = new OzoneAcl(OzoneAcl.OzoneACLType.GROUP, groupName[0],
OzoneAcl.OzoneACLRights.READ);
Assert.assertTrue(storageHandler.checkVolumeAccess(volumeName, group));
// Create a different user and access should fail
String falseUserName = "user" + RandomStringUtils.randomNumeric(5);
OzoneAcl falseUserAcl =
new OzoneAcl(OzoneAcl.OzoneACLType.USER, falseUserName,
OzoneAcl.OzoneACLRights.READ_WRITE);
Assert.assertFalse(storageHandler
.checkVolumeAccess(volumeName, falseUserAcl));
// Checking access with user name and Group Type should fail
OzoneAcl falseGroupAcl = new OzoneAcl(OzoneAcl.OzoneACLType.GROUP, userName,
OzoneAcl.OzoneACLRights.READ_WRITE);
Assert.assertFalse(storageHandler
.checkVolumeAccess(volumeName, falseGroupAcl));
// Access for acl type world should also fail
OzoneAcl worldAcl =
new OzoneAcl(OzoneAcl.OzoneACLType.WORLD, "",
OzoneAcl.OzoneACLRights.READ);
Assert.assertFalse(storageHandler.checkVolumeAccess(volumeName, worldAcl));
Assert.assertEquals(0, omMetrics.getNumVolumeCheckAccessFails());
Assert.assertEquals(0, omMetrics.getNumVolumeCreateFails());
}
@Test(timeout = 60000)
public void testCreateBucket() throws IOException, OzoneException {
long numVolumeCreateFail = omMetrics.getNumVolumeCreateFails();
long numBucketCreateFail = omMetrics.getNumBucketCreateFails();
long numBucketInfoFail = omMetrics.getNumBucketInfoFails();
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
String bucketName = "bucket" + RandomStringUtils.randomNumeric(5);
VolumeArgs volumeArgs = new VolumeArgs(volumeName, userArgs);
volumeArgs.setUserName(userName);
volumeArgs.setAdminName(adminName);
storageHandler.createVolume(volumeArgs);
BucketArgs bucketArgs = new BucketArgs(volumeName, bucketName, userArgs);
storageHandler.createBucket(bucketArgs);
BucketArgs getBucketArgs = new BucketArgs(volumeName, bucketName,
userArgs);
BucketInfo bucketInfo = storageHandler.getBucketInfo(getBucketArgs);
Assert.assertTrue(bucketInfo.getVolumeName().equals(volumeName));
Assert.assertTrue(bucketInfo.getBucketName().equals(bucketName));
Assert.assertEquals(numVolumeCreateFail,
omMetrics.getNumVolumeCreateFails());
Assert.assertEquals(numBucketCreateFail,
omMetrics.getNumBucketCreateFails());
Assert.assertEquals(numBucketInfoFail,
omMetrics.getNumBucketInfoFails());
}
@Test(timeout = 60000)
public void testDeleteBucket() throws IOException, OzoneException {
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
String bucketName = "bucket" + RandomStringUtils.randomNumeric(5);
VolumeArgs volumeArgs = new VolumeArgs(volumeName, userArgs);
volumeArgs.setUserName(userName);
volumeArgs.setAdminName(adminName);
storageHandler.createVolume(volumeArgs);
BucketArgs bucketArgs = new BucketArgs(volumeName, bucketName, userArgs);
storageHandler.createBucket(bucketArgs);
BucketArgs getBucketArgs = new BucketArgs(volumeName, bucketName,
userArgs);
BucketInfo bucketInfo = storageHandler.getBucketInfo(getBucketArgs);
Assert.assertTrue(bucketInfo.getVolumeName().equals(volumeName));
Assert.assertTrue(bucketInfo.getBucketName().equals(bucketName));
storageHandler.deleteBucket(bucketArgs);
exception.expect(IOException.class);
exception.expectMessage("Info Bucket failed, error: BUCKET_NOT_FOUND");
storageHandler.getBucketInfo(getBucketArgs);
}
@Test(timeout = 60000)
public void testDeleteNonExistingBucket() throws IOException, OzoneException {
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
String bucketName = "bucket" + RandomStringUtils.randomNumeric(5);
VolumeArgs volumeArgs = new VolumeArgs(volumeName, userArgs);
volumeArgs.setUserName(userName);
volumeArgs.setAdminName(adminName);
storageHandler.createVolume(volumeArgs);
BucketArgs bucketArgs = new BucketArgs(volumeName, bucketName, userArgs);
storageHandler.createBucket(bucketArgs);
BucketArgs getBucketArgs = new BucketArgs(volumeName, bucketName,
userArgs);
BucketInfo bucketInfo = storageHandler.getBucketInfo(getBucketArgs);
Assert.assertTrue(bucketInfo.getVolumeName().equals(volumeName));
Assert.assertTrue(bucketInfo.getBucketName().equals(bucketName));
BucketArgs newBucketArgs = new BucketArgs(
volumeName, bucketName + "_invalid", userArgs);
exception.expect(IOException.class);
exception.expectMessage("Delete Bucket failed, error:BUCKET_NOT_FOUND");
storageHandler.deleteBucket(newBucketArgs);
}
@Test(timeout = 60000)
public void testDeleteNonEmptyBucket() throws IOException, OzoneException {
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
String bucketName = "bucket" + RandomStringUtils.randomNumeric(5);
String keyName = "key" + RandomStringUtils.randomNumeric(5);
VolumeArgs volumeArgs = new VolumeArgs(volumeName, userArgs);
volumeArgs.setUserName(userName);
volumeArgs.setAdminName(adminName);
storageHandler.createVolume(volumeArgs);
BucketArgs bucketArgs = new BucketArgs(volumeName, bucketName, userArgs);
storageHandler.createBucket(bucketArgs);
BucketArgs getBucketArgs = new BucketArgs(volumeName, bucketName,
userArgs);
BucketInfo bucketInfo = storageHandler.getBucketInfo(getBucketArgs);
Assert.assertTrue(bucketInfo.getVolumeName().equals(volumeName));
Assert.assertTrue(bucketInfo.getBucketName().equals(bucketName));
String dataString = RandomStringUtils.randomAscii(100);
KeyArgs keyArgs = new KeyArgs(volumeName, bucketName, keyName, userArgs);
keyArgs.setSize(100);
try (OutputStream stream = storageHandler.newKeyWriter(keyArgs)) {
stream.write(dataString.getBytes());
}
exception.expect(IOException.class);
exception.expectMessage("Delete Bucket failed, error:BUCKET_NOT_EMPTY");
storageHandler.deleteBucket(bucketArgs);
}
/**
* Basic test of both putKey and getKey from OM, as one can not be tested
* without the other.
*
* @throws IOException
* @throws OzoneException
*/
@Test
public void testGetKeyWriterReader() throws IOException, OzoneException {
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
String bucketName = "bucket" + RandomStringUtils.randomNumeric(5);
String keyName = "key" + RandomStringUtils.randomNumeric(5);
long numKeyAllocates = omMetrics.getNumKeyAllocates();
long numKeyLookups = omMetrics.getNumKeyLookups();
VolumeArgs createVolumeArgs = new VolumeArgs(volumeName, userArgs);
createVolumeArgs.setUserName(userName);
createVolumeArgs.setAdminName(adminName);
storageHandler.createVolume(createVolumeArgs);
BucketArgs bucketArgs = new BucketArgs(bucketName, createVolumeArgs);
bucketArgs.setAddAcls(new LinkedList<>());
bucketArgs.setRemoveAcls(new LinkedList<>());
bucketArgs.setStorageType(StorageType.DISK);
storageHandler.createBucket(bucketArgs);
String dataString = RandomStringUtils.randomAscii(100);
KeyArgs keyArgs = new KeyArgs(volumeName, bucketName, keyName, userArgs);
keyArgs.setSize(100);
try (OutputStream stream = storageHandler.newKeyWriter(keyArgs)) {
stream.write(dataString.getBytes());
}
Assert.assertEquals(1 + numKeyAllocates, omMetrics.getNumKeyAllocates());
byte[] data = new byte[dataString.length()];
try (InputStream in = storageHandler.newKeyReader(keyArgs)) {
in.read(data);
}
Assert.assertEquals(dataString, DFSUtil.bytes2String(data));
Assert.assertEquals(1 + numKeyLookups, omMetrics.getNumKeyLookups());
}
/**
* Test write the same key twice, the second write should fail, as currently
* key overwrite is not supported.
*
* @throws IOException
* @throws OzoneException
*/
@Test
public void testKeyOverwrite() throws IOException, OzoneException {
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
String bucketName = "bucket" + RandomStringUtils.randomNumeric(5);
String keyName = "key" + RandomStringUtils.randomNumeric(5);
long numKeyAllocateFails = omMetrics.getNumKeyAllocateFails();
VolumeArgs createVolumeArgs = new VolumeArgs(volumeName, userArgs);
createVolumeArgs.setUserName(userName);
createVolumeArgs.setAdminName(adminName);
storageHandler.createVolume(createVolumeArgs);
BucketArgs bucketArgs = new BucketArgs(bucketName, createVolumeArgs);
bucketArgs.setAddAcls(new LinkedList<>());
bucketArgs.setRemoveAcls(new LinkedList<>());
bucketArgs.setStorageType(StorageType.DISK);
storageHandler.createBucket(bucketArgs);
KeyArgs keyArgs = new KeyArgs(volumeName, bucketName, keyName, userArgs);
keyArgs.setSize(100);
String dataString = RandomStringUtils.randomAscii(100);
try (OutputStream stream = storageHandler.newKeyWriter(keyArgs)) {
stream.write(dataString.getBytes());
}
// We allow the key overwrite to be successful. Please note : Till
// HDFS-11922 is fixed this causes a data block leak on the data node side.
// That is this overwrite only overwrites the keys on OM. We need to
// garbage collect those blocks from datanode.
KeyArgs keyArgs2 = new KeyArgs(volumeName, bucketName, keyName, userArgs);
storageHandler.newKeyWriter(keyArgs2);
Assert
.assertEquals(numKeyAllocateFails, omMetrics.getNumKeyAllocateFails());
}
/**
* Test get a non-exiting key.
*
* @throws IOException
* @throws OzoneException
*/
@Test
public void testGetNonExistKey() throws IOException, OzoneException {
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
String bucketName = "bucket" + RandomStringUtils.randomNumeric(5);
String keyName = "key" + RandomStringUtils.randomNumeric(5);
long numKeyLookupFails = omMetrics.getNumKeyLookupFails();
VolumeArgs createVolumeArgs = new VolumeArgs(volumeName, userArgs);
createVolumeArgs.setUserName(userName);
createVolumeArgs.setAdminName(adminName);
storageHandler.createVolume(createVolumeArgs);
BucketArgs bucketArgs = new BucketArgs(bucketName, createVolumeArgs);
bucketArgs.setAddAcls(new LinkedList<>());
bucketArgs.setRemoveAcls(new LinkedList<>());
bucketArgs.setStorageType(StorageType.DISK);
storageHandler.createBucket(bucketArgs);
KeyArgs keyArgs = new KeyArgs(volumeName, bucketName, keyName, userArgs);
// try to get the key, should fail as it hasn't been created
exception.expect(IOException.class);
exception.expectMessage("KEY_NOT_FOUND");
storageHandler.newKeyReader(keyArgs);
Assert.assertEquals(1 + numKeyLookupFails,
omMetrics.getNumKeyLookupFails());
}
/**
* Test delete keys for om.
*
* @throws IOException
* @throws OzoneException
*/
@Test
public void testDeleteKey() throws IOException, OzoneException {
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
String bucketName = "bucket" + RandomStringUtils.randomNumeric(5);
String keyName = "key" + RandomStringUtils.randomNumeric(5);
long numKeyDeletes = omMetrics.getNumKeyDeletes();
long numKeyDeleteFails = omMetrics.getNumKeyDeletesFails();
VolumeArgs createVolumeArgs = new VolumeArgs(volumeName, userArgs);
createVolumeArgs.setUserName(userName);
createVolumeArgs.setAdminName(adminName);
storageHandler.createVolume(createVolumeArgs);
BucketArgs bucketArgs = new BucketArgs(bucketName, createVolumeArgs);
storageHandler.createBucket(bucketArgs);
KeyArgs keyArgs = new KeyArgs(keyName, bucketArgs);
keyArgs.setSize(100);
String dataString = RandomStringUtils.randomAscii(100);
try (OutputStream stream = storageHandler.newKeyWriter(keyArgs)) {
stream.write(dataString.getBytes());
}
storageHandler.deleteKey(keyArgs);
Assert.assertEquals(1 + numKeyDeletes, omMetrics.getNumKeyDeletes());
// Make sure the deleted key has been moved to the deleted table.
OMMetadataManager manager = cluster.getOzoneManager().
getMetadataManager();
try(TableIterator<Table.KeyValue> iter =
manager.getDeletedTable().iterator()) {
iter.seekToFirst();
Table.KeyValue kv = iter.next();
Assert.assertNotNull(kv);
}
// Delete the key again to test deleting non-existing key.
try {
storageHandler.deleteKey(keyArgs);
Assert.fail("Expected exception not thrown.");
} catch (IOException ioe) {
Assert.assertTrue(ioe.getMessage().contains("KEY_NOT_FOUND"));
}
Assert.assertEquals(1 + numKeyDeleteFails,
omMetrics.getNumKeyDeletesFails());
}
/**
* Test rename key for om.
*
* @throws IOException
* @throws OzoneException
*/
@Test
public void testRenameKey() throws IOException, OzoneException {
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
String bucketName = "bucket" + RandomStringUtils.randomNumeric(5);
String keyName = "key" + RandomStringUtils.randomNumeric(5);
long numKeyRenames = omMetrics.getNumKeyRenames();
long numKeyRenameFails = omMetrics.getNumKeyRenameFails();
int testRenameFails = 0;
int testRenames = 0;
IOException ioe = null;
VolumeArgs createVolumeArgs = new VolumeArgs(volumeName, userArgs);
createVolumeArgs.setUserName(userName);
createVolumeArgs.setAdminName(adminName);
storageHandler.createVolume(createVolumeArgs);
BucketArgs bucketArgs = new BucketArgs(bucketName, createVolumeArgs);
storageHandler.createBucket(bucketArgs);
KeyArgs keyArgs = new KeyArgs(keyName, bucketArgs);
keyArgs.setSize(100);
String toKeyName = "key" + RandomStringUtils.randomNumeric(5);
// Rename from non-existent key should fail
try {
testRenames++;
storageHandler.renameKey(keyArgs, toKeyName);
} catch (IOException e) {
testRenameFails++;
ioe = e;
}
Assert.assertTrue(ioe.getMessage().contains("Rename key failed, error"));
// Write the contents of the key to be renamed
String dataString = RandomStringUtils.randomAscii(100);
try (OutputStream stream = storageHandler.newKeyWriter(keyArgs)) {
stream.write(dataString.getBytes());
}
// Rename the key
toKeyName = "key" + RandomStringUtils.randomNumeric(5);
testRenames++;
storageHandler.renameKey(keyArgs, toKeyName);
Assert.assertEquals(numKeyRenames + testRenames,
omMetrics.getNumKeyRenames());
Assert.assertEquals(numKeyRenameFails + testRenameFails,
omMetrics.getNumKeyRenameFails());
// Try to get the key, should fail as it has been renamed
try {
storageHandler.newKeyReader(keyArgs);
} catch (IOException e) {
ioe = e;
}
Assert.assertTrue(ioe.getMessage().contains("KEY_NOT_FOUND"));
// Verify the contents of the renamed key
keyArgs = new KeyArgs(toKeyName, bucketArgs);
InputStream in = storageHandler.newKeyReader(keyArgs);
byte[] b = new byte[dataString.getBytes().length];
in.read(b);
Assert.assertEquals(new String(b), dataString);
// Rewrite the renamed key. Rename to key which already exists should fail.
keyArgs = new KeyArgs(keyName, bucketArgs);
keyArgs.setSize(100);
dataString = RandomStringUtils.randomAscii(100);
try (OutputStream stream = storageHandler.newKeyWriter(keyArgs)) {
stream.write(dataString.getBytes());
stream.close();
testRenames++;
storageHandler.renameKey(keyArgs, toKeyName);
} catch (IOException e) {
testRenameFails++;
ioe = e;
}
Assert.assertTrue(ioe.getMessage().contains("Rename key failed, error"));
// Rename to empty string should fail
toKeyName = "";
try {
testRenames++;
storageHandler.renameKey(keyArgs, toKeyName);
} catch (IOException e) {
testRenameFails++;
ioe = e;
}
Assert.assertTrue(ioe.getMessage().contains("Rename key failed, error"));
// Rename from empty string should fail
keyArgs = new KeyArgs("", bucketArgs);
toKeyName = "key" + RandomStringUtils.randomNumeric(5);
try {
testRenames++;
storageHandler.renameKey(keyArgs, toKeyName);
} catch (IOException e) {
testRenameFails++;
ioe = e;
}
Assert.assertTrue(ioe.getMessage().contains("Rename key failed, error"));
Assert.assertEquals(numKeyRenames + testRenames,
omMetrics.getNumKeyRenames());
Assert.assertEquals(numKeyRenameFails + testRenameFails,
omMetrics.getNumKeyRenameFails());
}
@Test(timeout = 60000)
public void testListBuckets() throws IOException, OzoneException {
ListBuckets result = null;
ListArgs listBucketArgs = null;
// Create volume - volA.
final String volAname = "volA";
VolumeArgs volAArgs = new VolumeArgs(volAname, userArgs);
volAArgs.setUserName("userA");
volAArgs.setAdminName("adminA");
storageHandler.createVolume(volAArgs);
// Create 20 buckets in volA for tests.
for (int i=0; i<10; i++) {
// Create "/volA/aBucket_0" to "/volA/aBucket_9" buckets in volA volume.
BucketArgs aBuckets = new BucketArgs(volAname,
"aBucket_" + i, userArgs);
if(i % 3 == 0) {
aBuckets.setStorageType(StorageType.ARCHIVE);
} else {
aBuckets.setStorageType(StorageType.DISK);
}
storageHandler.createBucket(aBuckets);
// Create "/volA/bBucket_0" to "/volA/bBucket_9" buckets in volA volume.
BucketArgs bBuckets = new BucketArgs(volAname,
"bBucket_" + i, userArgs);
if(i % 3 == 0) {
bBuckets.setStorageType(StorageType.RAM_DISK);
} else {
bBuckets.setStorageType(StorageType.SSD);
}
storageHandler.createBucket(bBuckets);
}
VolumeArgs volArgs = new VolumeArgs(volAname, userArgs);
// List all buckets in volA.
listBucketArgs = new ListArgs(volArgs, null, 100, null);
result = storageHandler.listBuckets(listBucketArgs);
Assert.assertEquals(20, result.getBuckets().size());
List<BucketInfo> archiveBuckets = result.getBuckets().stream()
.filter(item -> item.getStorageType() == StorageType.ARCHIVE)
.collect(Collectors.toList());
Assert.assertEquals(4, archiveBuckets.size());
// List buckets with prefix "aBucket".
listBucketArgs = new ListArgs(volArgs, "aBucket", 100, null);
result = storageHandler.listBuckets(listBucketArgs);
Assert.assertEquals(10, result.getBuckets().size());
Assert.assertTrue(result.getBuckets().stream()
.allMatch(entry -> entry.getBucketName().startsWith("aBucket")));
// List a certain number of buckets.
listBucketArgs = new ListArgs(volArgs, null, 3, null);
result = storageHandler.listBuckets(listBucketArgs);
Assert.assertEquals(3, result.getBuckets().size());
Assert.assertEquals("aBucket_0",
result.getBuckets().get(0).getBucketName());
Assert.assertEquals("aBucket_1",
result.getBuckets().get(1).getBucketName());
Assert.assertEquals("aBucket_2",
result.getBuckets().get(2).getBucketName());
// List a certain number of buckets from the startKey.
listBucketArgs = new ListArgs(volArgs, null, 2, "bBucket_3");
result = storageHandler.listBuckets(listBucketArgs);
Assert.assertEquals(2, result.getBuckets().size());
Assert.assertEquals("bBucket_4",
result.getBuckets().get(0).getBucketName());
Assert.assertEquals("bBucket_5",
result.getBuckets().get(1).getBucketName());
// Provide an invalid bucket name as start key.
listBucketArgs = new ListArgs(volArgs, null, 100, "unknown_bucket_name");
ListBuckets buckets = storageHandler.listBuckets(listBucketArgs);
Assert.assertEquals(buckets.getBuckets().size(), 0);
// Use all arguments.
listBucketArgs = new ListArgs(volArgs, "b", 5, "bBucket_7");
result = storageHandler.listBuckets(listBucketArgs);
Assert.assertEquals(2, result.getBuckets().size());
Assert.assertEquals("bBucket_8",
result.getBuckets().get(0).getBucketName());
Assert.assertEquals("bBucket_9",
result.getBuckets().get(1).getBucketName());
// Provide an invalid maxKeys argument.
try {
listBucketArgs = new ListArgs(volArgs, null, -1, null);
storageHandler.listBuckets(listBucketArgs);
Assert.fail("Expecting an error when the given"
+ " maxKeys argument is invalid.");
} catch (Exception e) {
Assert.assertTrue(e.getMessage()
.contains(String.format("the value must be in range (0, %d]",
OzoneConsts.MAX_LISTBUCKETS_SIZE)));
}
// Provide an invalid volume name.
VolumeArgs invalidVolArgs = new VolumeArgs("invalid_name", userArgs);
try {
listBucketArgs = new ListArgs(invalidVolArgs, null, 100, null);
storageHandler.listBuckets(listBucketArgs);
Assert.fail("Expecting an error when the given volume name is invalid.");
} catch (Exception e) {
Assert.assertTrue(e instanceof IOException);
Assert.assertTrue(e.getMessage()
.contains(Status.VOLUME_NOT_FOUND.name()));
}
}
/**
* Test list keys.
* @throws IOException
* @throws OzoneException
*/
@Test
public void testListKeys() throws IOException, OzoneException {
ListKeys result = null;
ListArgs listKeyArgs = null;
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
String bucketName = "bucket" + RandomStringUtils.randomNumeric(5);
VolumeArgs createVolumeArgs = new VolumeArgs(volumeName, userArgs);
createVolumeArgs.setUserName(userName);
createVolumeArgs.setAdminName(adminName);
storageHandler.createVolume(createVolumeArgs);
BucketArgs bucketArgs = new BucketArgs(bucketName, createVolumeArgs);
bucketArgs.setAddAcls(new LinkedList<>());
bucketArgs.setRemoveAcls(new LinkedList<>());
bucketArgs.setStorageType(StorageType.DISK);
storageHandler.createBucket(bucketArgs);
// Write 20 keys in bucket.
int numKeys = 20;
String keyName = "Key";
KeyArgs keyArgs = null;
for (int i = 0; i < numKeys; i++) {
if (i % 2 == 0) {
// Create /volume/bucket/aKey[0,2,4,...,18] in bucket.
keyArgs = new KeyArgs("a" + keyName + i, bucketArgs);
} else {
// Create /volume/bucket/bKey[1,3,5,...,19] in bucket.
keyArgs = new KeyArgs("b" + keyName + i, bucketArgs);
}
keyArgs.setSize(4096);
// Just for testing list keys call, so no need to write real data.
OutputStream stream = storageHandler.newKeyWriter(keyArgs);
stream.close();
}
// List all keys in bucket.
bucketArgs = new BucketArgs(volumeName, bucketName, userArgs);
listKeyArgs = new ListArgs(bucketArgs, null, 100, null);
result = storageHandler.listKeys(listKeyArgs);
Assert.assertEquals(numKeys, result.getKeyList().size());
// List keys with prefix "aKey".
listKeyArgs = new ListArgs(bucketArgs, "aKey", 100, null);
result = storageHandler.listKeys(listKeyArgs);
Assert.assertEquals(numKeys / 2, result.getKeyList().size());
Assert.assertTrue(result.getKeyList().stream()
.allMatch(entry -> entry.getKeyName().startsWith("aKey")));
// List a certain number of keys.
listKeyArgs = new ListArgs(bucketArgs, null, 3, null);
result = storageHandler.listKeys(listKeyArgs);
Assert.assertEquals(3, result.getKeyList().size());
Assert.assertEquals("aKey0",
result.getKeyList().get(0).getKeyName());
Assert.assertEquals("aKey10",
result.getKeyList().get(1).getKeyName());
Assert.assertEquals("aKey12",
result.getKeyList().get(2).getKeyName());
// List a certain number of keys from the startKey.
listKeyArgs = new ListArgs(bucketArgs, null, 2, "bKey1");
result = storageHandler.listKeys(listKeyArgs);
Assert.assertEquals(2, result.getKeyList().size());
Assert.assertEquals("bKey11",
result.getKeyList().get(0).getKeyName());
Assert.assertEquals("bKey13",
result.getKeyList().get(1).getKeyName());
// Provide an invalid key name as start key.
listKeyArgs = new ListArgs(bucketArgs, null, 100, "invalid_start_key");
ListKeys keys = storageHandler.listKeys(listKeyArgs);
Assert.assertEquals(keys.getKeyList().size(), 0);
// Provide an invalid maxKeys argument.
try {
listKeyArgs = new ListArgs(bucketArgs, null, -1, null);
storageHandler.listBuckets(listKeyArgs);
Assert.fail("Expecting an error when the given"
+ " maxKeys argument is invalid.");
} catch (Exception e) {
GenericTestUtils.assertExceptionContains(
String.format("the value must be in range (0, %d]",
OzoneConsts.MAX_LISTKEYS_SIZE), e);
}
// Provide an invalid bucket name.
bucketArgs = new BucketArgs("invalid_bucket", createVolumeArgs);
try {
listKeyArgs = new ListArgs(bucketArgs, null, numKeys, null);
storageHandler.listKeys(listKeyArgs);
Assert.fail(
"Expecting an error when the given bucket name is invalid.");
} catch (IOException e) {
GenericTestUtils.assertExceptionContains(
Status.BUCKET_NOT_FOUND.name(), e);
}
}
@Test
public void testListVolumes() throws IOException, OzoneException {
String user0 = "testListVolumes-user-0";
String user1 = "testListVolumes-user-1";
String adminUser = "testListVolumes-admin";
ListArgs listVolumeArgs;
ListVolumes volumes;
// Create 10 volumes by user0 and user1
String[] user0vols = new String[10];
String[] user1vols = new String[10];
for (int i =0; i<10; i++) {
VolumeArgs createVolumeArgs;
String user0VolName = "Vol-" + user0 + "-" + i;
user0vols[i] = user0VolName;
createVolumeArgs = new VolumeArgs(user0VolName, userArgs);
createVolumeArgs.setUserName(user0);
createVolumeArgs.setAdminName(adminUser);
createVolumeArgs.setQuota(new OzoneQuota(i, OzoneQuota.Units.GB));
storageHandler.createVolume(createVolumeArgs);
String user1VolName = "Vol-" + user1 + "-" + i;
user1vols[i] = user1VolName;
createVolumeArgs = new VolumeArgs(user1VolName, userArgs);
createVolumeArgs.setUserName(user1);
createVolumeArgs.setAdminName(adminUser);
createVolumeArgs.setQuota(new OzoneQuota(i, OzoneQuota.Units.GB));
storageHandler.createVolume(createVolumeArgs);
}
// Test list all volumes - Removed Support for this operation for time
// being. TODO: we will need to bring this back if needed.
UserArgs userArgs0 = new UserArgs(user0, OzoneUtils.getRequestID(),
null, null, null, null);
//listVolumeArgs = new ListArgs(userArgs0,"Vol-testListVolumes", 100, null);
// listVolumeArgs.setRootScan(true);
// volumes = storageHandler.listVolumes(listVolumeArgs);
// Assert.assertEquals(20, volumes.getVolumes().size());
// Test list all volumes belongs to an user
listVolumeArgs = new ListArgs(userArgs0, null, 100, null);
listVolumeArgs.setRootScan(false);
volumes = storageHandler.listVolumes(listVolumeArgs);
Assert.assertEquals(10, volumes.getVolumes().size());
// Test prefix
listVolumeArgs = new ListArgs(userArgs0,
"Vol-" + user0 + "-3", 100, null);
volumes = storageHandler.listVolumes(listVolumeArgs);
Assert.assertEquals(1, volumes.getVolumes().size());
Assert.assertEquals(user0vols[3],
volumes.getVolumes().get(0).getVolumeName());
Assert.assertEquals(user0,
volumes.getVolumes().get(0).getOwner().getName());
// Test list volumes by user
UserArgs userArgs1 = new UserArgs(user1, OzoneUtils.getRequestID(),
null, null, null, null);
listVolumeArgs = new ListArgs(userArgs1, null, 100, null);
listVolumeArgs.setRootScan(false);
volumes = storageHandler.listVolumes(listVolumeArgs);
Assert.assertEquals(10, volumes.getVolumes().size());
Assert.assertEquals(user1,
volumes.getVolumes().get(3).getOwner().getName());
// Make sure all available fields are returned
final String user0vol4 = "Vol-" + user0 + "-4";
final String user0vol5 = "Vol-" + user0 + "-5";
listVolumeArgs = new ListArgs(userArgs0, null, 1, user0vol4);
listVolumeArgs.setRootScan(false);
volumes = storageHandler.listVolumes(listVolumeArgs);
Assert.assertEquals(1, volumes.getVolumes().size());
Assert.assertEquals(user0,
volumes.getVolumes().get(0).getOwner().getName());
Assert.assertEquals(user0vol5,
volumes.getVolumes().get(0).getVolumeName());
Assert.assertEquals(5,
volumes.getVolumes().get(0).getQuota().getSize());
Assert.assertEquals(OzoneQuota.Units.GB,
volumes.getVolumes().get(0).getQuota().getUnit());
// User doesn't have volumes
UserArgs userArgsX = new UserArgs("unknwonUser", OzoneUtils.getRequestID(),
null, null, null, null);
listVolumeArgs = new ListArgs(userArgsX, null, 100, null);
listVolumeArgs.setRootScan(false);
volumes = storageHandler.listVolumes(listVolumeArgs);
Assert.assertEquals(0, volumes.getVolumes().size());
}
/**
* Test get key information.
*
* @throws IOException
* @throws OzoneException
*/
@Test
public void testGetKeyInfo() throws IOException,
OzoneException, ParseException {
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
String bucketName = "bucket" + RandomStringUtils.randomNumeric(5);
long currentTime = Time.now();
VolumeArgs createVolumeArgs = new VolumeArgs(volumeName, userArgs);
createVolumeArgs.setUserName(userName);
createVolumeArgs.setAdminName(adminName);
storageHandler.createVolume(createVolumeArgs);
BucketArgs bucketArgs = new BucketArgs(bucketName, createVolumeArgs);
bucketArgs.setAddAcls(new LinkedList<>());
bucketArgs.setRemoveAcls(new LinkedList<>());
bucketArgs.setStorageType(StorageType.DISK);
storageHandler.createBucket(bucketArgs);
String keyName = "testKey";
KeyArgs keyArgs = new KeyArgs(keyName, bucketArgs);
keyArgs.setSize(4096);
OutputStream stream = storageHandler.newKeyWriter(keyArgs);
stream.close();
KeyInfo keyInfo = storageHandler.getKeyInfo(keyArgs);
// Compare the time in second unit since the date string reparsed to
// millisecond will lose precision.
Assert.assertTrue(
(HddsClientUtils.formatDateTime(keyInfo.getCreatedOn()) / 1000) >= (
currentTime / 1000));
Assert.assertTrue(
(HddsClientUtils.formatDateTime(keyInfo.getModifiedOn()) / 1000) >= (
currentTime / 1000));
Assert.assertEquals(keyName, keyInfo.getKeyName());
// with out data written, the size would be 0
Assert.assertEquals(0, keyInfo.getSize());
}
/**
* Test that the write can proceed without having to set the right size.
*
* @throws IOException
*/
@Test
public void testWriteSize() throws IOException, OzoneException {
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
String bucketName = "bucket" + RandomStringUtils.randomNumeric(5);
VolumeArgs createVolumeArgs = new VolumeArgs(volumeName, userArgs);
createVolumeArgs.setUserName(userName);
createVolumeArgs.setAdminName(adminName);
storageHandler.createVolume(createVolumeArgs);
BucketArgs bucketArgs = new BucketArgs(bucketName, createVolumeArgs);
bucketArgs.setAddAcls(new LinkedList<>());
bucketArgs.setRemoveAcls(new LinkedList<>());
bucketArgs.setStorageType(StorageType.DISK);
storageHandler.createBucket(bucketArgs);
String dataString = RandomStringUtils.randomAscii(100);
// write a key without specifying size at all
String keyName = "testKey";
KeyArgs keyArgs = new KeyArgs(keyName, bucketArgs);
try (OutputStream stream = storageHandler.newKeyWriter(keyArgs)) {
stream.write(dataString.getBytes());
}
byte[] data = new byte[dataString.length()];
try (InputStream in = storageHandler.newKeyReader(keyArgs)) {
in.read(data);
}
Assert.assertEquals(dataString, DFSUtil.bytes2String(data));
// write a key with a size, but write above it.
String keyName1 = "testKey1";
KeyArgs keyArgs1 = new KeyArgs(keyName1, bucketArgs);
keyArgs1.setSize(30);
try (OutputStream stream = storageHandler.newKeyWriter(keyArgs1)) {
stream.write(dataString.getBytes());
}
byte[] data1 = new byte[dataString.length()];
try (InputStream in = storageHandler.newKeyReader(keyArgs1)) {
in.read(data1);
}
Assert.assertEquals(dataString, DFSUtil.bytes2String(data1));
}
/**
* Tests the RPC call for getting scmId and clusterId from SCM.
* @throws IOException
*/
@Test
public void testGetScmInfo() throws IOException {
ScmInfo info = cluster.getOzoneManager().getScmInfo();
Assert.assertEquals(clusterId, info.getClusterId());
Assert.assertEquals(scmId, info.getScmId());
}
//Disabling this test
@Ignore("Disabling this test until Open Key is fixed.")
public void testExpiredOpenKey() throws Exception {
// BackgroundService openKeyCleanUpService = ((KeyManagerImpl)cluster
// .getOzoneManager().getKeyManager()).getOpenKeyCleanupService();
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
String bucketName = "bucket" + RandomStringUtils.randomNumeric(5);
VolumeArgs createVolumeArgs = new VolumeArgs(volumeName, userArgs);
createVolumeArgs.setUserName(userName);
createVolumeArgs.setAdminName(adminName);
storageHandler.createVolume(createVolumeArgs);
BucketArgs bucketArgs = new BucketArgs(bucketName, createVolumeArgs);
bucketArgs.setAddAcls(new LinkedList<>());
bucketArgs.setRemoveAcls(new LinkedList<>());
bucketArgs.setStorageType(StorageType.DISK);
storageHandler.createBucket(bucketArgs);
// open some keys.
KeyArgs keyArgs1 = new KeyArgs("testKey1", bucketArgs);
KeyArgs keyArgs2 = new KeyArgs("testKey2", bucketArgs);
KeyArgs keyArgs3 = new KeyArgs("testKey3", bucketArgs);
KeyArgs keyArgs4 = new KeyArgs("testKey4", bucketArgs);
List<BlockGroup> openKeys;
storageHandler.newKeyWriter(keyArgs1);
storageHandler.newKeyWriter(keyArgs2);
storageHandler.newKeyWriter(keyArgs3);
storageHandler.newKeyWriter(keyArgs4);
Set<String> expected = Stream.of(
"testKey1", "testKey2", "testKey3", "testKey4")
.collect(Collectors.toSet());
// Now all k1-k4 should be in open state, so ExpiredOpenKeys should not
// contain these values.
openKeys = cluster.getOzoneManager()
.getMetadataManager().getExpiredOpenKeys();
for (BlockGroup bg : openKeys) {
String[] subs = bg.getGroupID().split("/");
String keyName = subs[subs.length - 1];
Assert.assertFalse(expected.contains(keyName));
}
Thread.sleep(2000);
// Now all k1-k4 should be in ExpiredOpenKeys
openKeys = cluster.getOzoneManager()
.getMetadataManager().getExpiredOpenKeys();
for (BlockGroup bg : openKeys) {
String[] subs = bg.getGroupID().split("/");
String keyName = subs[subs.length - 1];
if (expected.contains(keyName)) {
expected.remove(keyName);
}
}
Assert.assertEquals(0, expected.size());
KeyArgs keyArgs5 = new KeyArgs("testKey5", bucketArgs);
storageHandler.newKeyWriter(keyArgs5);
//openKeyCleanUpService.triggerBackgroundTaskForTesting();
Thread.sleep(2000);
// now all k1-k4 should have been removed by the clean-up task, only k5
// should be present in ExpiredOpenKeys.
openKeys =
cluster.getOzoneManager().getMetadataManager().getExpiredOpenKeys();
System.out.println(openKeys);
boolean key5found = false;
Set<String> removed = Stream.of(
"testKey1", "testKey2", "testKey3", "testKey4")
.collect(Collectors.toSet());
for (BlockGroup bg : openKeys) {
String[] subs = bg.getGroupID().split("/");
String keyName = subs[subs.length - 1];
Assert.assertFalse(removed.contains(keyName));
if (keyName.equals("testKey5")) {
key5found = true;
}
}
Assert.assertTrue(key5found);
}
/**
* Tests the OM Initialization.
* @throws IOException
*/
@Test
public void testOmInitialization() throws IOException {
// Read the version file info from OM version file
OMStorage omStorage = cluster.getOzoneManager().getOmStorage();
SCMStorage scmStorage = new SCMStorage(conf);
// asserts whether cluster Id and SCM ID are properly set in SCM Version
// file.
Assert.assertEquals(clusterId, scmStorage.getClusterID());
Assert.assertEquals(scmId, scmStorage.getScmId());
// asserts whether OM Id is properly set in OM Version file.
Assert.assertEquals(omId, omStorage.getOmId());
// asserts whether the SCM info is correct in OM Version file.
Assert.assertEquals(clusterId, omStorage.getClusterID());
Assert.assertEquals(scmId, omStorage.getScmId());
}
/**
* Tests the OM Initialization Failure.
* @throws IOException
*/
@Test
public void testOmInitializationFailure() throws Exception {
OzoneConfiguration config = new OzoneConfiguration();
final String path =
GenericTestUtils.getTempPath(UUID.randomUUID().toString());
Path metaDirPath = Paths.get(path, "om-meta");
config.set(OzoneConfigKeys.OZONE_METADATA_DIRS, metaDirPath.toString());
config.setBoolean(OzoneConfigKeys.OZONE_ENABLED, true);
config.set(ScmConfigKeys.OZONE_SCM_CLIENT_ADDRESS_KEY, "127.0.0.1:0");
config.set(ScmConfigKeys.OZONE_SCM_BLOCK_CLIENT_ADDRESS_KEY,
conf.get(ScmConfigKeys.OZONE_SCM_BLOCK_CLIENT_ADDRESS_KEY));
exception.expect(OMException.class);
exception.expectMessage("OM not initialized.");
OzoneManager.createOm(null, config);
OMStorage omStore = new OMStorage(config);
omStore.setClusterId("testClusterId");
omStore.setScmId("testScmId");
// writes the version file properties
omStore.initialize();
exception.expect(OMException.class);
exception.expectMessage("SCM version info mismatch.");
OzoneManager.createOm(null, conf);
}
@Test
public void testGetServiceList() throws IOException {
long numGetServiceListCalls = omMetrics.getNumGetServiceLists();
List<ServiceInfo> services = cluster.getOzoneManager().getServiceList();
Assert.assertEquals(numGetServiceListCalls + 1,
omMetrics.getNumGetServiceLists());
ServiceInfo omInfo = services.stream().filter(
a -> a.getNodeType().equals(HddsProtos.NodeType.OM))
.collect(Collectors.toList()).get(0);
InetSocketAddress omAddress = new InetSocketAddress(omInfo.getHostname(),
omInfo.getPort(ServicePort.Type.RPC));
Assert.assertEquals(NetUtils.createSocketAddr(
conf.get(OZONE_OM_ADDRESS_KEY)), omAddress);
ServiceInfo scmInfo = services.stream().filter(
a -> a.getNodeType().equals(HddsProtos.NodeType.SCM))
.collect(Collectors.toList()).get(0);
InetSocketAddress scmAddress = new InetSocketAddress(scmInfo.getHostname(),
scmInfo.getPort(ServicePort.Type.RPC));
Assert.assertEquals(NetUtils.createSocketAddr(
conf.get(OZONE_SCM_CLIENT_ADDRESS_KEY)), scmAddress);
}
}