HDFS-12231. Ozone: KSM: Add creation time field in volume info. Contributed by Yiqun Lin.

This commit is contained in:
Anu Engineer 2017-08-04 19:50:48 -07:00 committed by Owen O'Malley
parent 6f83e9c51e
commit bb5f1c4228
7 changed files with 71 additions and 17 deletions

View File

@ -39,6 +39,7 @@ public final class KsmVolumeArgs {
private final String adminName; private final String adminName;
private final String ownerName; private final String ownerName;
private final String volume; private final String volume;
private final long creationTime;
private final long quotaInBytes; private final long quotaInBytes;
private final Map<String, String> keyValueMap; private final Map<String, String> keyValueMap;
private final KsmOzoneAclMap aclMap; private final KsmOzoneAclMap aclMap;
@ -51,16 +52,18 @@ public final class KsmVolumeArgs {
* @param quotaInBytes - Volume Quota in bytes. * @param quotaInBytes - Volume Quota in bytes.
* @param keyValueMap - keyValue map. * @param keyValueMap - keyValue map.
* @param aclMap - User to access rights map. * @param aclMap - User to access rights map.
* @param creationTime - Volume creation time.
*/ */
private KsmVolumeArgs(String adminName, String ownerName, String volume, private KsmVolumeArgs(String adminName, String ownerName, String volume,
long quotaInBytes, Map<String, String> keyValueMap, long quotaInBytes, Map<String, String> keyValueMap,
KsmOzoneAclMap aclMap) { KsmOzoneAclMap aclMap, long creationTime) {
this.adminName = adminName; this.adminName = adminName;
this.ownerName = ownerName; this.ownerName = ownerName;
this.volume = volume; this.volume = volume;
this.quotaInBytes = quotaInBytes; this.quotaInBytes = quotaInBytes;
this.keyValueMap = keyValueMap; this.keyValueMap = keyValueMap;
this.aclMap = aclMap; this.aclMap = aclMap;
this.creationTime = creationTime;
} }
/** /**
@ -87,6 +90,14 @@ public String getVolume() {
return volume; return volume;
} }
/**
* Returns creation time.
* @return long
*/
public long getCreationTime() {
return creationTime;
}
/** /**
* Returns Quota in Bytes. * Returns Quota in Bytes.
* @return long, Quota in bytes. * @return long, Quota in bytes.
@ -118,6 +129,7 @@ public static class Builder {
private String adminName; private String adminName;
private String ownerName; private String ownerName;
private String volume; private String volume;
private long creationTime;
private long quotaInBytes; private long quotaInBytes;
private Map<String, String> keyValueMap; private Map<String, String> keyValueMap;
private KsmOzoneAclMap aclMap; private KsmOzoneAclMap aclMap;
@ -145,6 +157,11 @@ public Builder setVolume(String volume) {
return this; return this;
} }
public Builder setCreationTime(long createdOn) {
this.creationTime = createdOn;
return this;
}
public Builder setQuotaInBytes(long quotaInBytes) { public Builder setQuotaInBytes(long quotaInBytes) {
this.quotaInBytes = quotaInBytes; this.quotaInBytes = quotaInBytes;
return this; return this;
@ -169,7 +186,7 @@ public KsmVolumeArgs build() {
Preconditions.checkNotNull(ownerName); Preconditions.checkNotNull(ownerName);
Preconditions.checkNotNull(volume); Preconditions.checkNotNull(volume);
return new KsmVolumeArgs(adminName, ownerName, volume, quotaInBytes, return new KsmVolumeArgs(adminName, ownerName, volume, quotaInBytes,
keyValueMap, aclMap); keyValueMap, aclMap, creationTime);
} }
} }
@ -188,6 +205,7 @@ public VolumeInfo getProtobuf() {
.setQuotaInBytes(quotaInBytes) .setQuotaInBytes(quotaInBytes)
.addAllMetadata(metadataList) .addAllMetadata(metadataList)
.addAllVolumeAcls(aclList) .addAllVolumeAcls(aclList)
.setCreationTime(creationTime)
.build(); .build();
} }
@ -199,6 +217,7 @@ public static KsmVolumeArgs getFromProtobuf(VolumeInfo volInfo) {
KsmOzoneAclMap.ozoneAclGetFromProtobuf(volInfo.getVolumeAclsList()); KsmOzoneAclMap.ozoneAclGetFromProtobuf(volInfo.getVolumeAclsList());
return new KsmVolumeArgs(volInfo.getAdminName(), volInfo.getOwnerName(), return new KsmVolumeArgs(volInfo.getAdminName(), volInfo.getOwnerName(),
volInfo.getVolume(), volInfo.getQuotaInBytes(), kvMap, aclMap); volInfo.getVolume(), volInfo.getQuotaInBytes(), kvMap, aclMap,
volInfo.getCreationTime());
} }
} }

View File

@ -62,6 +62,7 @@ message VolumeInfo {
optional uint64 quotaInBytes = 4; optional uint64 quotaInBytes = 4;
repeated KeyValue metadata = 5; repeated KeyValue metadata = 5;
repeated OzoneAclInfo volumeAcls = 6; repeated OzoneAclInfo volumeAcls = 6;
required uint64 creationTime = 7;
} }
/** /**

View File

@ -131,6 +131,15 @@ public OzoneQuota getQuota() {
return volumeInfo.getQuota(); return volumeInfo.getQuota();
} }
/**
* Returns creation time of Volume.
*
* @return String
*/
public String getCreatedOn() {
return volumeInfo.getCreatedOn();
}
/** /**
* Returns a Http header from the Last Volume related call. * Returns a Http header from the Last Volume related call.
* *

View File

@ -42,6 +42,7 @@
import org.apache.hadoop.scm.XceiverClientManager; import org.apache.hadoop.scm.XceiverClientManager;
import org.apache.hadoop.scm.protocolPB import org.apache.hadoop.scm.protocolPB
.StorageContainerLocationProtocolClientSideTranslatorPB; .StorageContainerLocationProtocolClientSideTranslatorPB;
import org.apache.hadoop.util.Time;
import org.apache.hadoop.ozone.web.exceptions.OzoneException; import org.apache.hadoop.ozone.web.exceptions.OzoneException;
import org.apache.hadoop.ozone.web.handlers.BucketArgs; import org.apache.hadoop.ozone.web.handlers.BucketArgs;
import org.apache.hadoop.ozone.web.handlers.KeyArgs; import org.apache.hadoop.ozone.web.handlers.KeyArgs;
@ -124,7 +125,8 @@ public void createVolume(VolumeArgs args) throws IOException, OzoneException {
.setOwnerName(args.getUserName()) .setOwnerName(args.getUserName())
.setVolume(args.getVolumeName()) .setVolume(args.getVolumeName())
.setQuotaInBytes(quota) .setQuotaInBytes(quota)
.addOzoneAcls(KSMPBHelper.convertOzoneAcl(userAcl)); .addOzoneAcls(KSMPBHelper.convertOzoneAcl(userAcl))
.setCreationTime(Time.now());
if (args.getGroups() != null) { if (args.getGroups() != null) {
for (String group : args.getGroups()) { for (String group : args.getGroups()) {
OzoneAcl groupAcl = OzoneAcl groupAcl =
@ -183,7 +185,7 @@ public ListVolumes listVolumes(ListArgs args)
args.getMaxKeys()); args.getMaxKeys());
} }
// TODO Add missing fields createdOn, createdBy, bucketCount and bytesUsed // TODO Add missing fields createdBy, bucketCount and bytesUsed
ListVolumes result = new ListVolumes(); ListVolumes result = new ListVolumes();
for (KsmVolumeArgs volumeArgs : listResult) { for (KsmVolumeArgs volumeArgs : listResult) {
VolumeInfo info = new VolumeInfo(); VolumeInfo info = new VolumeInfo();
@ -192,6 +194,7 @@ public ListVolumes listVolumes(ListArgs args)
info.setOwner(new VolumeOwner(infoProto.getOwnerName())); info.setOwner(new VolumeOwner(infoProto.getOwnerName()));
info.setQuota(OzoneQuota.getOzoneQuota(infoProto.getQuotaInBytes())); info.setQuota(OzoneQuota.getOzoneQuota(infoProto.getQuotaInBytes()));
info.setVolumeName(infoProto.getVolume()); info.setVolumeName(infoProto.getVolume());
info.setCreatedOn(OzoneUtils.formatTime(infoProto.getCreationTime()));
result.addVolume(info); result.addVolume(info);
} }
@ -215,6 +218,7 @@ public VolumeInfo getVolumeInfo(VolumeArgs args)
volumeArgs.getAdminName()); volumeArgs.getAdminName());
volInfo.setOwner(new VolumeOwner(volumeArgs.getOwnerName())); volInfo.setOwner(new VolumeOwner(volumeArgs.getOwnerName()));
volInfo.setQuota(OzoneQuota.getOzoneQuota(volumeArgs.getQuotaInBytes())); volInfo.setQuota(OzoneQuota.getOzoneQuota(volumeArgs.getQuotaInBytes()));
volInfo.setCreatedOn(OzoneUtils.formatTime(volumeArgs.getCreationTime()));
return volInfo; return volInfo;
} }

View File

@ -191,7 +191,11 @@ public void testInfoVolume() throws Exception {
String[] args = new String[] {"-infoVolume", url + "/" + volumeName, String[] args = new String[] {"-infoVolume", url + "/" + volumeName,
"-root"}; "-root"};
assertEquals(0, ToolRunner.run(shell, args)); assertEquals(0, ToolRunner.run(shell, args));
assertTrue(out.toString().contains(volumeName));
String output = out.toString();
assertTrue(output.contains(volumeName));
assertTrue(output.contains("createdOn")
&& output.contains(OzoneConsts.OZONE_TIME_ZONE));
// get info for non-exist volume // get info for non-exist volume
args = new String[] {"-infoVolume", url + "/invalid-volume", "-root"}; args = new String[] {"-infoVolume", url + "/invalid-volume", "-root"};
@ -270,12 +274,19 @@ public void testListVolume() throws Exception {
List<String> names = getValueLines("name", out.toString()); List<String> names = getValueLines("name", out.toString());
List<String> volumes = getValueLines("volumeName", out.toString()); List<String> volumes = getValueLines("volumeName", out.toString());
List<String> creationTimes = getValueLines("createdOn", out.toString());
assertEquals(10, volumes.size()); assertEquals(10, volumes.size());
assertEquals(10, names.size()); assertEquals(10, names.size());
assertEquals(10, creationTimes.size());
for (String user : names) { for (String user : names) {
assertTrue(user.contains(user1)); assertTrue(user.contains(user1));
} }
for (String time : creationTimes) {
assertTrue(time.contains(OzoneConsts.OZONE_TIME_ZONE));
}
out.reset(); out.reset();
args = new String[] {"-listVolume", url + "/", "-user", args = new String[] {"-listVolume", url + "/", "-user",
user1, "-length", "2"}; user1, "-length", "2"};

View File

@ -32,6 +32,7 @@
import org.apache.hadoop.ozone.web.request.OzoneQuota; import org.apache.hadoop.ozone.web.request.OzoneQuota;
import org.apache.hadoop.ozone.web.utils.OzoneUtils; import org.apache.hadoop.ozone.web.utils.OzoneUtils;
import org.apache.hadoop.test.GenericTestUtils; import org.apache.hadoop.test.GenericTestUtils;
import org.apache.hadoop.util.Time;
import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.log4j.Level; import org.apache.log4j.Level;
@ -41,10 +42,10 @@
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
@ -99,15 +100,16 @@ public static void shutdown() {
} }
@Test @Test
public void testCreateVolume() throws OzoneException, IOException { public void testCreateVolume() throws Exception {
runTestCreateVolume(ozoneRestClient); runTestCreateVolume(ozoneRestClient);
} }
static void runTestCreateVolume(OzoneRestClient client) static void runTestCreateVolume(OzoneRestClient client)
throws OzoneException, IOException { throws OzoneException, IOException, ParseException {
String volumeName = OzoneUtils.getRequestID().toLowerCase(); String volumeName = OzoneUtils.getRequestID().toLowerCase();
client.setUserAuth(OzoneConsts.OZONE_SIMPLE_HDFS_USER); client.setUserAuth(OzoneConsts.OZONE_SIMPLE_HDFS_USER);
long currentTime = Time.now();
OzoneRestClient mockClient = Mockito.spy(client); OzoneRestClient mockClient = Mockito.spy(client);
List<CloseableHttpClient> mockedClients = mockHttpClients(mockClient); List<CloseableHttpClient> mockedClients = mockHttpClients(mockClient);
OzoneVolume vol = mockClient.createVolume(volumeName, "bilbo", "100TB"); OzoneVolume vol = mockClient.createVolume(volumeName, "bilbo", "100TB");
@ -119,6 +121,10 @@ static void runTestCreateVolume(OzoneRestClient client)
assertEquals(vol.getOwnerName(), "bilbo"); assertEquals(vol.getOwnerName(), "bilbo");
assertEquals(vol.getQuota().getUnit(), OzoneQuota.Units.TB); assertEquals(vol.getQuota().getUnit(), OzoneQuota.Units.TB);
assertEquals(vol.getQuota().getSize(), 100); assertEquals(vol.getQuota().getSize(), 100);
// verify the key creation time
assertTrue((OzoneUtils.formatDate(vol.getCreatedOn())
/ 1000) >= (currentTime / 1000));
} }
@Test @Test
@ -270,16 +276,17 @@ static void runTestListAllVolumes(OzoneRestClient client)
} }
@Test @Test
public void testListVolumes() throws OzoneException, IOException { public void testListVolumes() throws Exception {
runTestListVolumes(ozoneRestClient); runTestListVolumes(ozoneRestClient);
} }
static void runTestListVolumes(OzoneRestClient client) static void runTestListVolumes(OzoneRestClient client)
throws OzoneException, IOException { throws OzoneException, IOException, ParseException {
final int volCount = 20; final int volCount = 20;
final String user1 = "test-user-a"; final String user1 = "test-user-a";
final String user2 = "test-user-b"; final String user2 = "test-user-b";
long currentTime = Time.now();
client.setUserAuth(OzoneConsts.OZONE_SIMPLE_HDFS_USER); client.setUserAuth(OzoneConsts.OZONE_SIMPLE_HDFS_USER);
// Create 20 volumes, 10 for user1 and another 10 for user2. // Create 20 volumes, 10 for user1 and another 10 for user2.
for (int x = 0; x < volCount; x++) { for (int x = 0; x < volCount; x++) {
@ -303,9 +310,12 @@ static void runTestListVolumes(OzoneRestClient client)
List<OzoneVolume> volumeList = client.listVolumes(user1, List<OzoneVolume> volumeList = client.listVolumes(user1,
null, 100, StringUtils.EMPTY); null, 100, StringUtils.EMPTY);
assertEquals(10, volumeList.size()); assertEquals(10, volumeList.size());
volumeList.stream() // verify the owner name and creation time of volume
.filter(item -> item.getOwnerName().equals(user1)) for (OzoneVolume vol : volumeList) {
.collect(Collectors.toList()); assertTrue(vol.getOwnerName().equals(user1));
assertTrue((OzoneUtils.formatDate(vol.getCreatedOn())
/ 1000) >= (currentTime / 1000));
}
// test max key parameter of listing volumes // test max key parameter of listing volumes
volumeList = client.listVolumes(user1, null, 2, StringUtils.EMPTY); volumeList = client.listVolumes(user1, null, 2, StringUtils.EMPTY);

View File

@ -47,7 +47,7 @@ public static void shutdown() {
} }
@Test @Test
public void testCreateVolume() throws OzoneException, IOException { public void testCreateVolume() throws Exception {
TestVolume.runTestCreateVolume(ozoneClient); TestVolume.runTestCreateVolume(ozoneClient);
} }
@ -88,12 +88,12 @@ public void testListVolumePagination() throws OzoneException, IOException {
// TODO: remove @Ignore below once the problem has been resolved. // TODO: remove @Ignore below once the problem has been resolved.
@Ignore("See TestVolume.testListAllVolumes()") @Ignore("See TestVolume.testListAllVolumes()")
@Test @Test
public void testListAllVolumes() throws OzoneException, IOException { public void testListAllVolumes() throws Exception {
TestVolume.runTestListAllVolumes(ozoneClient); TestVolume.runTestListAllVolumes(ozoneClient);
} }
@Test @Test
public void testListVolumes() throws OzoneException, IOException { public void testListVolumes() throws Exception {
TestVolume.runTestListVolumes(ozoneClient); TestVolume.runTestListVolumes(ozoneClient);
} }
} }